├── topics ├── raspberrypi.md ├── config.md ├── compression.md ├── vm.md ├── caching.md ├── excel.md ├── security.md ├── vscode.md ├── systemd.md ├── rfid.md ├── tmux.md ├── babel.md ├── vagrant.md ├── algos.md ├── express.md ├── filesystem.md ├── ssh.md ├── webpack.md ├── users.md ├── vim.md ├── csharp.md ├── base.md ├── architecture.md ├── testing.md ├── arduino.md ├── ansible.md ├── css.md ├── bash.md ├── mssql.md ├── nodemcu.md ├── linux.md ├── fp.md ├── node.md ├── networking.md ├── docker.md ├── react.md ├── elm.md ├── dom.md ├── javascript.md ├── mobile.md ├── mysql.md ├── electronics.md ├── es6.md ├── restful.md ├── async.md ├── electron.md └── git.md ├── pics ├── grid.jpg ├── elm │ ├── TEA.png │ └── elm_arch.png ├── inherit.jpg ├── arduino_led.jpg ├── breadboard.png ├── js_event_loop.png ├── networking │ ├── OSI.png │ ├── TCPIP.jpg │ ├── http.jpg │ ├── ping.jpg │ ├── data_flow.jpg │ └── OSI_vs_TCPIP.jpg ├── sql │ └── pivot_unpivot.png ├── rfid_wiegand_arduino.jpg ├── electronics │ ├── khan_current.jpg │ └── khan_voltage.jpg └── architecture │ ├── architecture_c4model_maps.jpg │ └── architecture_c4model_scope.jpg └── README.md /topics/raspberrypi.md: -------------------------------------------------------------------------------- 1 | # Raspberry Pi 2 | 3 | It's a micro-computer. 4 | -------------------------------------------------------------------------------- /pics/grid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/grid.jpg -------------------------------------------------------------------------------- /pics/elm/TEA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/elm/TEA.png -------------------------------------------------------------------------------- /pics/inherit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/inherit.jpg -------------------------------------------------------------------------------- /pics/arduino_led.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/arduino_led.jpg -------------------------------------------------------------------------------- /pics/breadboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/breadboard.png -------------------------------------------------------------------------------- /pics/elm/elm_arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/elm/elm_arch.png -------------------------------------------------------------------------------- /pics/js_event_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/js_event_loop.png -------------------------------------------------------------------------------- /pics/networking/OSI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/networking/OSI.png -------------------------------------------------------------------------------- /pics/networking/TCPIP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/networking/TCPIP.jpg -------------------------------------------------------------------------------- /pics/networking/http.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/networking/http.jpg -------------------------------------------------------------------------------- /pics/networking/ping.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/networking/ping.jpg -------------------------------------------------------------------------------- /pics/sql/pivot_unpivot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/sql/pivot_unpivot.png -------------------------------------------------------------------------------- /pics/networking/data_flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/networking/data_flow.jpg -------------------------------------------------------------------------------- /pics/rfid_wiegand_arduino.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/rfid_wiegand_arduino.jpg -------------------------------------------------------------------------------- /pics/electronics/khan_current.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/electronics/khan_current.jpg -------------------------------------------------------------------------------- /pics/electronics/khan_voltage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/electronics/khan_voltage.jpg -------------------------------------------------------------------------------- /pics/networking/OSI_vs_TCPIP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/networking/OSI_vs_TCPIP.jpg -------------------------------------------------------------------------------- /pics/architecture/architecture_c4model_maps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/architecture/architecture_c4model_maps.jpg -------------------------------------------------------------------------------- /pics/architecture/architecture_c4model_scope.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-interview/notes/master/pics/architecture/architecture_c4model_scope.jpg -------------------------------------------------------------------------------- /topics/config.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | **Make a BACKUP before any edits** with `cp file file.ORIGINAL` 4 | 5 | All config files are located in `/etc/`. They are plain text files. 6 | 7 | Use the `less` program to view configuration files, instead of an editor. Ex. `less /etc/ssh/sshd_config`. 8 | 9 | `/`+`string` - Search inside **less** (case sensitive). 10 | `q` - Exit. 11 | -------------------------------------------------------------------------------- /topics/compression.md: -------------------------------------------------------------------------------- 1 | # gzip 2 | 3 | This package creates a `.gz` compressed file, much like `.rar` or `.zip`. 4 | 5 | ## Compression 6 | `gzip ` - Compress a file. *Deletes original file*. 7 | `gzip -k ` - Compress without deletion. 8 | 9 | `gzip -9 ` - Compression quality 1-9. *Default is 5*. 10 | 11 | 12 | ## Extraction 13 | `gzip -d ` or `gunzip `- Extract. 14 | -------------------------------------------------------------------------------- /topics/vm.md: -------------------------------------------------------------------------------- 1 | # Virtualbox 2 | 3 | 1. Create VM. 4 | 2. Mount and install Guest Additions. 5 | 3. **Reboot.** 6 | 4. Add clipboard settings. 7 | 5. Add host shared folder. It is under `/media/user/sf_folder_name`. 8 | 6. `sudo adduser username vboxsf` to access shared folder. 9 | 7. **Reboot.** 10 | 11 | # Packages 12 | 13 | ### Update 14 | 15 | ```bash 16 | # Update 17 | sudo apt update; 18 | 19 | # curl, vim, tmux. 20 | sudo apt install curl vim tmux; 21 | 22 | # Node 23 | sudo apt install nodejs git -y; 24 | 25 | # MySQL 26 | sudo apt install mysql-server -y && mysql_secure_installation; 27 | ``` 28 | -------------------------------------------------------------------------------- /topics/caching.md: -------------------------------------------------------------------------------- 1 | # Memcached 2 | 3 | It stores key-value pairs in memory for quick access. It doesn't persist data to disk as a database. 4 | 5 | Can be run on a separate machine, but usually it's on the app server. 6 | 7 | When an HTTP request hits the server, it first checks if memcached has the response stored and returns that. If not, it retireves the data from the database, generates the reposnse, and saves it in the cache for future use. 8 | 9 | ```bash 10 | sudo apt-get install memcached 11 | ``` 12 | 13 | ```bash 14 | # key (string) - value (string) 15 | set(key, value) 16 | get(key) 17 | delete(key) 18 | ``` -------------------------------------------------------------------------------- /topics/excel.md: -------------------------------------------------------------------------------- 1 | # Insert pictures 2 | 3 | ```vbnet 4 | Sub URLPictureInsert() 5 | Dim xCol As Long 6 | Dim xRg As Range 7 | Dim w As Integer 8 | Dim h As Integer 9 | On Error Resume Next 10 | Set Rng = ActiveSheet.Range("b1:b2") 11 | w = 100 12 | h = 100 13 | For Each cell In Rng 14 | xCol = cell.Column + 1 15 | Set xRg = Cells(cell.Row, xCol) 16 | xRg.ColumnWidth = 20 17 | xRg.RowHeight = 100 18 | ActiveSheet.Shapes.AddPicture Filename:=cell, LinkToFile:=msoFalse, SaveWithDocument:=msoCTrue, Left:=xRg.Left + (xRg.Width - w) / 2, Top:=xRg.Top + (xRg.Height - h) / 2, Width:=w, Height:=h 19 | Next 20 | End Sub 21 | ``` -------------------------------------------------------------------------------- /topics/security.md: -------------------------------------------------------------------------------- 1 | # Attacks 2 | 3 | ### XSS - Cross Site Scripting 4 | Javascript injection. 5 | 6 | ### CSRF / XSRF - Cross Site Request Forgery 7 | Executing requests on one website for another one while authenticated. 8 | 9 | #### Same-origin policy 10 | 11 | Prevents scripts from one origin to access private data on another origin. 12 | 13 | ### MITM 14 | Packet snooping. 15 | 16 | ### SQL Injection 17 | SQL injection. 18 | 19 | # Good Practices 20 | 21 | ### SSL 22 | Let's encrypt. 23 | 24 | ### Encryption 25 | Password hashing. 26 | 27 | ### JWT 28 | Tokens vs cookies. 29 | 30 | ### Reverse-proxy 31 | Localhost vs direct. 32 | 33 | ### User groups 34 | Linux permissions. 35 | -------------------------------------------------------------------------------- /topics/vscode.md: -------------------------------------------------------------------------------- 1 | # Shortcuts 2 | 3 | `CTRL` + `p` - Search files. 4 | `CTRL` + `Shift` + `p` - Commands. 5 | 6 | `CTRL` + `d` - Select duplicate values. 7 | 8 | `ALT` + `Up` or `Down` - Move line up or down. 9 | 10 | `ALT` + `SHIFT` + `Down` - Duplicate line. 11 | `ALT` + `SHIFT` + `Right` - Select everything between brackets. 12 | 13 | 14 | # Zen Coding 15 | 16 | ```html 17 | table.table.small>thead>tr>th*4 18 | ``` 19 | 20 | results in 21 | 22 | ```html 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | ``` 34 | -------------------------------------------------------------------------------- /topics/systemd.md: -------------------------------------------------------------------------------- 1 | # systemd 2 | 3 | This tool is used for managing services (units). 4 | 5 | Service/Daemon is an on-going process that provides a service, usually designed to interact with something outside of it. Ex. web server, monitoring tool, database... 6 | 7 | ## systemctl 8 | Manages services. 9 | 10 | `systemctl ` - Format. 11 | 12 | `status` - Shows the status and last lines of log. 13 | `start` - Starts a service. 14 | `stop` - Stops a service. 15 | 16 | `enable` - Enable start on BOOT. 17 | `disable` - Disable start on BOOT. 18 | 19 | `reload` - Re-read the configuration files. 20 | `restart` - Restart the service and re-read config files. 21 | 22 | ## journalctl 23 | Manages logs. 24 | 25 | `journalctl -u SERVICE` - Log from a service. 26 | `journalctl --since "10 min ago"` - Log from last 10 minutes. 27 | -------------------------------------------------------------------------------- /topics/rfid.md: -------------------------------------------------------------------------------- 1 | # Standards 2 | 3 | | Family | Frequency | Protocol| Storage | Writable | Reader 4 | |---|---|---|---|---|---| 5 | Low Frequency (LF) | 125/134 kHz | EM4100 | UID 4 bytes | No | RDM-6300 (Coil antenna) 6 | High Frequency (HF) | 13.56 MHz | Mifare Classic | UID 4 bytes | 1 KB | MFRC-522 (Loop antenna) 7 | Ultra High Frequency (UHF) | 868 MHz | 1386.00 | 8 | 9 | The UIDs are hard-coded by the manufacturer and cannot be changed. 10 | 11 | All cards contain a chip and an antenna. They are passive i.e. get the energy from the reader. 12 | 13 | # Wiegand 14 | 15 | This is a transmission protocol which connects the RFID reader with a controller. 16 | 17 | It transmits the UID in 2 formats: 18 | 19 | - W26 - Transports only first 3 bytes of the UID. 20 | - W34 - Transports the whole UID (4 bytes). Connect brown wire to ground to get this format. 21 | 22 | If the correct UIDs are not transported via serial, the D0 and D1 may need to be swapped. 23 | 24 | ![Sketch](../pics/rfid_wiegand_arduino.jpg) -------------------------------------------------------------------------------- /topics/tmux.md: -------------------------------------------------------------------------------- 1 | # tmux 2 | 3 | ## Basic 4 | `tmux` - Start tmux. 5 | `CTRL + B` - Command mode. 6 | 7 | ## Panes 8 | `%` - Split horizontally (left/right). 9 | `"` - Split vertically (top/bottom). 10 | `arrows` - Change pane. Resize if holding command. 11 | `x` - Close pane. 12 | 13 | ## Windows 14 | `c` - New window. 15 | `numbers` - Change window. 16 | `,` - Name window. 17 | `w` - List windows. 18 | `.` - Move window. Asks for a number. 19 | `&` - Close window. 20 | 21 | ## Misc 22 | `[` - Scrolling mode with arrows or PageUp/PageDown. Exit with `CTRL + C`. 23 | 24 | # Configuration 25 | In order to configurate tmux, a `tmux.conf` file is needed, as it doesn't exist. We can create this with `sudo touch /etc/tmux.conf`, or `sudo touch ~/.tmux.conf` for a user specific one. 26 | 27 | ```bash 28 | # Reload config file with CTRL + b + r 29 | bind r source-file /etc/tmux.conf 30 | 31 | # Activate mouse (Scrolling, selecting, re-sizing) 32 | set -g mouse on 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /topics/babel.md: -------------------------------------------------------------------------------- 1 | Babel is a transpiler (translator + compiler) and it converts modern code into old code, able to run in older browsers. 2 | 3 | ```bash 4 | npm install babel-cli babel-core babel-preset-env 5 | ``` 6 | 7 | `babel-cli` - Command line interface. Takes a js file and returns a transpiled one. 8 | `babel-core` - The transpiling logic. 9 | `babel-preset-env` - Each new javascript feature has a **separate** plugin. Intead of installing them one by one, we can install a preset containing all of them. 10 | 11 | To run the transpiler we can use: 12 | ```bash 13 | # Use the env preset to transpile index.js and put the output in the build folder in index.js. 14 | babel --presets env index.js -o build/index.js 15 | ``` 16 | This command is for one file. In order to transpile many files, a bundler like Webpack is needed. Here, every file is transpiler first, before being added to the bundle. 17 | 18 | We can add this in `package.json` for convenience: 19 | ```json 20 | { 21 | "scripts": { 22 | "babel": "babel --presets env index.js -o build/index.js" 23 | } 24 | } 25 | ``` -------------------------------------------------------------------------------- /topics/vagrant.md: -------------------------------------------------------------------------------- 1 | # Vagrant 2 | 3 | Vagrant is used to avoid the tedious provisioning of Virtual Machines. Instead of manually installing the OS for every machine, VMs can be spun up instantly by downloading an image (box) from the hub, and running it. 4 | 5 | Vagrant **is not** like Docker. Vagrant is used to start VMs fast, while Docker is used to containerize packages within the VMs. Vagrant avoids installing an OS, Docker avoids installing packages i.e. they just run them. This significantly speeds things up by allowing to quickly create and destroy whole environments. 6 | 7 | In other words, use Vagrant for just the OS and Docker install, and run everything else as a Docker container. 8 | 9 | **Host** = Main Machine. **Guest** = Virtual Machine. 10 | 11 | ## Install 12 | `wget "URL"` - Download Vagrant. 13 | `sudo dpkg -i FILENAME` - Install Vagrant. 14 | `sudo apt-get install virtualbox` - Download VirtualBox. 15 | 16 | ## Virtual Machine 17 | `vagrant box add BOX_NAME` - Download a box. 18 | `vagrant init BOX_NAME` - Create Vagrantfile i.e. VMs live here. 19 | `vagrant up` - Start a box (VM). 20 | -------------------------------------------------------------------------------- /topics/algos.md: -------------------------------------------------------------------------------- 1 | # Useful ALgorithmS 2 | 3 | ```javascript 4 | let data = [ 5 | { id: 1, name: "a" }, 6 | { id: 2, name: "b" }, 7 | { id: 3, name: "c" }, 8 | { id: 4, name: "d" }, 9 | { id: 5, name: "e" } 10 | ] 11 | ``` 12 | 13 | ## Shuffle array 14 | ```javascript 15 | function shuffleArray(array) { 16 | for (var i = array.length - 1; i > 0; i--) { 17 | var j = Math.floor(Math.random() * (i + 1)); 18 | var temp = array[i]; 19 | array[i] = array[j]; 20 | array[j] = temp; 21 | } 22 | return array; 23 | } 24 | 25 | let shuffled = shuffleArray(data); 26 | console.log(shuffled); 27 | ``` 28 | 29 | ## Sort array 30 | ```javascript 31 | // true desc, false asc 32 | let dynamicSort = function(field, reverse, primer){ 33 | 34 | let key = primer ? 35 | function(x) {return primer(x[field])} : 36 | function(x) {return x[field]}; 37 | 38 | reverse = !reverse ? 1 : -1; 39 | 40 | return function (a, b) { 41 | return a = key(a), b = key(b), reverse * ((a > b) - (b > a)); 42 | }; 43 | } 44 | 45 | let sorted = data.sort(dynamicSort("id", false)); 46 | console.log(sorted); 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /topics/express.md: -------------------------------------------------------------------------------- 1 | # JSON 2 | 3 | JSON is used to transfer data via a string. 4 | 5 | An object from one programming language can be transferred to another by encoding it in JSON and then decoding it, even though they cannot understand each others' objects. 6 | 7 | ```Javascript 8 | // Javascript object literal. 9 | var personObject = { 10 | firstName:"John", 11 | lastName:"Doe", 12 | age:50, 13 | eyeColor:"blue" 14 | }; 15 | 16 | // Convert object to JSON. 17 | var personJSON = JSON.stringify(personObject); 18 | 19 | // personJSON. 20 | { 21 | "firstName":"John", 22 | "lastName":"Doe", 23 | "age":50, 24 | "eyeColor":"blue" 25 | } 26 | 27 | // Convert JSON to object. 28 | JSON.stringify(personJSON); 29 | 30 | ``` 31 | 32 | # MSSQL 33 | 34 | ```Javascript 35 | // Callback 36 | sql.connect(db, function (err) { 37 | if (err) console.log(err); 38 | var request = new sql.Request(); 39 | request.query("SELECT * FROM product", function (err, recordset) { 40 | if (err) console.log(err) 41 | 42 | let rows = recordset.recordsets[0]; 43 | res.send(rows); 44 | sql.close(); // Important 45 | }); 46 | }); 47 | 48 | // Promises 49 | new sql.ConnectionPool(db).connect().then(pool => { 50 | return pool.request().query("SELECT * FROM product") 51 | }).then(result => { 52 | let rows = result.recordset 53 | res.setHeader('Access-Control-Allow-Origin', '*') 54 | res.status(200).json(rows); 55 | sql.close(); 56 | }).catch(err => { 57 | res.status(500).send({ message: "${err}"}) 58 | sql.close(); 59 | }); 60 | ``` 61 | 62 | 63 | -------------------------------------------------------------------------------- /topics/filesystem.md: -------------------------------------------------------------------------------- 1 | # Filesystem 2 | 3 | #### Directories 4 | 5 | **root** has the following directories: 6 | - **etc**. Configuration files. 7 | - **proc**. System information. 8 | - **home**. All the users. 9 | - **boot**. Operating system lives here. 10 | - **dev**. Where devices are mounted. `sda` is main disk, `sdaX` are partitions (Mounted as block files). 11 | 12 | `tree DIRECTORY` - Show directory tree. `tree .` for current. Needs to be donwloaded with `sudo apt-get install tree`. 13 | 14 | #### Files 15 | 16 | Plain text file > Compilation > Binary (.exe) i.e. package. Ubuntu is simply a collection (repository) of pre-compiled packages, running over a kernel (Big pile of software that knows how to make the hardware do stuff). 17 | 18 | **"On a UNIX system, everything is a file; if something is not a file, it is a process."** (directory is a file containing names of other files) 19 | 20 | File extensions are meaningless. They are there for the user's sake. 21 | 22 | There are 7 types of files, which can be recognized by using `ls -l` and looking at the first bit: 23 | 1. **Normal**. Images, text, config... 24 | 2. **Directory**. File pointing to files. 25 | 3. **Link**. Shortcut/Redirect. 26 | 4. **Pipe**. Use a process output as input for another. 27 | 5. **Character Device**. Input/Output files Ex. Teminal. 28 | 6. **Block**. Used for block devices. Ex. Hard Disk. 29 | 7. **Socket**. Used for Interprocess Communication. 30 | - **Unix Socket**. Local machine only (Superfast). Ex. Nginx communicates with a PHP interpreter. 31 | - **TCP Socket**. Exposed to network (Slower). Ex. Nginx communicates with a website visitor. 32 | 33 | #### Interprocess Communication (IPC) 34 | 35 | In Linux, **everything is a file**. There are special files like **sockets** that allow processes to communicate with each other without dangerously sharing memory. 36 | 37 | **Sockets** are files where processes can write stuff, and other processes can listen in real time. 38 | -------------------------------------------------------------------------------- /topics/ssh.md: -------------------------------------------------------------------------------- 1 | # Install 2 | 3 | ```bash 4 | sudo apt-get install openssh-server 5 | ``` 6 | 7 | # Connect 8 | 9 | ```bash 10 | ssh -p PORT USER@SERVER_IP 11 | 12 | # Execute one command and exit. 13 | ssh -p PORT USER@SERVER_IP ls 14 | ``` 15 | 16 | SSH in Virtual Machine needs a port forwarding rule in network settings for the VM. Name `ssh`, host port `3022`, guest port `22`. 17 | 18 | ```bash 19 | # SSH to local VM via port forwarding. 20 | ssh -p 3022 user@127.0.0.1 21 | ``` 22 | 23 | # Alias 24 | 25 | ```bash 26 | /etc/ssh/ssh_config # system-wide 27 | ~/.ssh/config # per user (better) 28 | 29 | # Add this in the config. 30 | Host server_name 31 | Port 22 32 | User user 33 | HostName 123.456.789.255 34 | 35 | # Connect with this now. 36 | ssh server_name 37 | ``` 38 | 39 | # SSH with RSA key 40 | 41 | This is used to log in without writing the password each time. Also, it is much more secure. 42 | 43 | This works by using a private `id_rsa` and public `id_rsa.pub` key pair. These keys can be generated by running `ssh-keygen`, and they are located in `~/.ssh` i.e. `/home/user/.ssh`. 44 | 45 | The `id_rsa` private key stays in the host machine in `~/.ssh`. The `id_rsa.pub` public key goes on the server in a `~/.ssh/authorized_keys` file. Simple as that, the next ssh is password-less. 46 | 47 | To transfer a public key, use this from `~`: 48 | 49 | ```bash 50 | rsync -av -e 'ssh -p 3022' ./.ssh/id_rsa.pub user@127.0.0.1:~/.ssh/ 51 | ``` 52 | 53 | # Transfer files over SSH with rsync 54 | 55 | Only trasnfer the files that have changes or are missing. Much faster and secure than FTP. 56 | 57 | `-a` - Recursion and preserve everything. 58 | `-v` - Transfer log. 59 | `-e` - Specify remote shell. 60 | 61 | ```bash 62 | # Transfer everything from the current directory to a new folder in the remote home directory. 63 | rsync -av -e 'ssh' . user@255.255.255.255:~/folder/ 64 | 65 | # Transfer folder1 and its content to remote home directory 66 | rsync -av -e 'ssh' ./folder1 user@255.255.255.255:~/ 67 | 68 | # Transfer everything from folder1 without the folder itself to remote folder2 in remote home directory. 69 | rsync -av -e 'ssh' ./folder1/ user@255.255.255.255:~/folder2/ 70 | 71 | # Transfer multiple files and folders. 72 | rsync -av -e 'ssh' ./file1 ./file2 ./folder1 user@255.255.255.255:~/folder2/ 73 | ``` 74 | 75 | ### To Virtual Machine 76 | 77 | ```bash 78 | rsync -av -e "ssh -p PORT_NUMBER" : 79 | 80 | rsync -av -e 'ssh -p 3022' . user@127.0.0.1:~/make-this_folder 81 | ``` 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Programming 2 | 3 | ### Javascript 4 | 5 | - [Javascript](./topics/javascript.md) 6 | - [ES6](./topics/es6.md) 7 | - [OOP](./topics/oop.md) 8 | - [DOM](./topics/dom.md) 9 | - [Async](./topics/async.md) 10 | - [FP](./topics/fp.md) 11 | 12 | ### Frontend 13 | 14 | - [CSS](./topics/css.md) 15 | - [React](./topics/react.md) 16 | - [Electron](./topics/electron.md) 17 | - Virtual DOM 18 | - [Elm](./topics/elm.md) 19 | 20 | ### Backend 21 | 22 | - [Node](./topics/node.md) 23 | - [Express](./topics/express.md) 24 | - [MySQL](./topics/mysql.md) 25 | - [SQL Server](./topics/mssql.md) 26 | - [nginx](./topics/nginx.md) 27 | - [C#](./topics/csharp.md) 28 | 29 | ### Version Control 30 | 31 | - [Git](./topics/git.md) 32 | 33 | ### Tooling 34 | 35 | - [Babel](./topics/babel.md) 36 | - [Webpack](./topics/webpack.md) 37 | - Typescript 38 | - [Caching](./topics/caching.md) 39 | 40 | ### Architecture 41 | - [Architecture](./topics/architecture.md) 42 | - Use Cases 43 | - [RESTful](./topics/restful.md) 44 | 45 | ### Concepts 46 | 47 | - File Organization 48 | - Authentication 49 | - [Security](./topics/security.md) 50 | - [Testing](./topics/testing.md) 51 | - [Binary base](./topics/base.md) 52 | 53 | ### Useful 54 | 55 | - [Algorithms](./topics/algos.md) 56 | - [Excel](./topics/excel.md) 57 | 58 | ### Mobile 59 | 60 | - [Overview](./topics/mobile.md) 61 | 62 | ### IDE 63 | 64 | - [VS Code](./topics/vscode.md) 65 | 66 | # Linux 67 | 68 | ### Administration 69 | 70 | - [basics](./topics/linux.md) 71 | - [filesystem](./topics/filesystem.md) 72 | - [users](./topics/users.md) 73 | - [config](./topics/config.md) 74 | - [systemd](./topics/systemd.md) 75 | 76 | ### Tools 77 | 78 | - [bash](./topics/bash.md) 79 | - [tmux](./topics/tmux.md) 80 | - [vim](./topics/vim.md) 81 | - [ssh](./topics/ssh.md) 82 | - [compression](./topics/compression.md) 83 | 84 | # DevOps 85 | 86 | ### Virtualization 87 | 88 | - [VM](./topics/vm.md) 89 | - [Vagrant](./topics/vagrant.md) 90 | 91 | ### Containerization 92 | 93 | - [Docker](./topics/docker.md) 94 | 95 | ### Configuration Management 96 | 97 | - [Ansible](./topics/ansible.md) 98 | 99 | # Networking 100 | 101 | - [Networking](./topics/networking.md) 102 | 103 | # Electronics 104 | 105 | ### Gadgets 106 | 107 | - [Raspberry Pi](./topics/raspberrypi.md) 108 | - [Arduino](./topics/arduino.md) 109 | - [NodeMCU](./topics/nodemcu.md) 110 | 111 | ### Theory 112 | 113 | - [Electronics](./topics/electronics.md) 114 | - [RFID](./topics/rfid.md) 115 | - [Electricity](./topics/electricity.md) 116 | -------------------------------------------------------------------------------- /topics/webpack.md: -------------------------------------------------------------------------------- 1 | Webpack is a bundler, which combines many javascript files into a single bundle file. 2 | 3 | It also uglifies (shortens identifier names) and minifies (gets rid of whitespace) the code. 4 | 5 | ```bash 6 | sudo npm install webpack --save-dev 7 | ``` 8 | 9 | ## Simple Example 10 | 11 | We need to add a webpack scripts in `package.json` with an entry and exit point. Webpack will start from `app.js`, get all the dependencies from it, and bundle all the code into one `bundle.js` file. 12 | 13 | Appending `-p` at the end of the script will use the production mode, which minifies the bundle. 14 | 15 | ```json 16 | { 17 | "scripts": { 18 | "build": "webpack src/js/app.js dist/bundle.js", 19 | "build:prod": "webpack src/js/app.js dist/bundle.js -p", 20 | }, 21 | "devDependencies": { 22 | "webpack": "4.x.x" 23 | } 24 | } 25 | ``` 26 | 27 | ## Configuration 28 | 29 | Instead of a `package.json` script, we can use a detailed `webpack.config.js` configuration file, which can be generated with the command below and by answering questions. 30 | 31 | ```bash 32 | webpack init 33 | ``` 34 | Example : 35 | 1. Will your application have multiple bundles? **No** 36 | 2. Which module will be the first to enter the application? [example: './src/index.js'] **./src/index.js** 37 | 3. Which folder will your generated bundles be in? [default: dist] **Enter** 38 | 4. Are you going to use this in production? **No** 39 | 5. Will you be using ES2015 (ES6)? **Yes** 40 | 6. Will you use one of the below CSS solutions? **No** 41 | 7. Name your `webpack.[name].js`? [default: 'config'] **Enter** 42 | 43 | This will install: 44 | - webpack-cli 45 | - uglifyjs-webpack-plugin 46 | - babel-core 47 | - babel-loder 48 | - babel-preset-env 49 | - webpack 50 | 51 | It will also generate the `webpack.config.js` file: 52 | ```javascript 53 | const webpack = require("webpack"); 54 | const path = require("path"); 55 | 56 | const UglifyjsJSPlugin = require("uglifyjs-webpack-plugin"); 57 | 58 | module.exports = { 59 | entry: './src/index.js', 60 | output: { 61 | filename: '[name].bundle.js', 62 | path: path.resolve(__dirname, dist) 63 | }, 64 | module: { 65 | rules: [ 66 | { 67 | test: /\.js$/, 68 | exclude: /node_modules/, 69 | loader: 'babel-loader', 70 | options: { 71 | presets: ['env'] 72 | } 73 | } 74 | ] 75 | }, 76 | plugins: [new UglifyJSPlugin()] 77 | }; 78 | ``` 79 | We can add this in `package.json` watch for changes and rebuild: 80 | ```json 81 | { 82 | "scripts": { 83 | "build": "webpack -w" 84 | } 85 | } 86 | ``` -------------------------------------------------------------------------------- /topics/users.md: -------------------------------------------------------------------------------- 1 | # Create 2 | 3 | ```bash 4 | # Guided user creation 5 | adduser 6 | 7 | # Scripted user creation 8 | useradd --uid --gid -m -s /usr/bin/zsh -d /var/www/ --password 9 | ``` 10 | 11 | # Login 12 | 13 | ```bash 14 | # Login as user 15 | su - 16 | 17 | # Login as root 18 | sudo -i 19 | 20 | # Logout 21 | CTRL + d 22 | ``` 23 | 24 | The root account is disabled by default in Ubuntu, so there is no root password, that's why `su` fails with an authentication error. 25 | 26 | # Permissions 27 | 28 | `ls -l` - Show file permissions. 29 | 30 | `chown USER:GROUP FILENAME` - Change file owner. 31 | 32 | `sudo usermod -a -G ` - Add user to a group. Needs a logout. 33 | 34 | `chmod` - Change file mode i.e. `rwx` permissions. 35 | 36 | `r` - Read. 37 | `w` - Write. 38 | `x` - Execute. 39 | 40 | | Permission | File Type | Owner | Group | Other | Meaning | 41 | | :--------: | :-------: | :---: | :---: | :---: | :-------------------------------------------------------------: | 42 | | -rwx------ | - | rwx | --- | --- | File that only the owner can read, write and execute. | 43 | | drw-rw---- | d | rw- | rw- | r-- | Directory that owner and group can read/write, others just read | 44 | 45 | Owner permissions trump group ones. 46 | 47 | `chmod +x FILE` - Add execute permission to owner, group and others. 48 | `chmod u+w FILE` - Add write permission to just the owner. 49 | `chmod o-r FILE` - Remove read permission to other users. 50 | 51 | This can get very tedious for each permission (9 commands), so instead, we can set the permissions by using octal numbers. 52 | 53 | First number is **owner**, second is **group**, and third is **others**. 54 | 55 | `chmod 644 FILE` - Owner read/write, group read, others read. 56 | 57 | | Dec | Permission | 58 | | :-: | -------------------- | 59 | | 7 | Read, write, execute | 60 | | 6 | Read, write | 61 | | 5 | Read, execute | 62 | | 4 | Read | 63 | | 3 | Write, execute | 64 | | 2 | Write | 65 | | 1 | Execute | 66 | | 0 | No permissions | 67 | 68 | `7, 6, 5, 4, 0` - Most used. 69 | 70 | A binary mask is used to determine the numbers. Add the column values for each 1 and the sum is the decimal number. 71 | 72 | | Type | Read (4) | Write (2) | Execute (1) | Decimal | 73 | | :-------: | :------: | :-------: | :---------: | :-----: | 74 | | **User** | 1 | 1 | 1 | 7 | 75 | | **Group** | 1 | 0 | 1 | 5 | 76 | | **Other** | 1 | 0 | 0 | 4 | 77 | 78 | The number `754` would give the owner full permissions, the group read/execute, and just read for the others. 79 | -------------------------------------------------------------------------------- /topics/vim.md: -------------------------------------------------------------------------------- 1 | # Vim 2 | 3 | If a file is read-only and can't be changed, use `sudo vim file` to open it as root. 4 | 5 | ## Modes 6 | 7 | `ESC` - Command (Default) 8 | `i` - Insert (Editing) 9 | `v` - Visual (Like Command, but with selection) 10 | 11 | ## General 12 | 13 | `:` - Commands. 14 | `.` - Repeat previous command. 15 | `u` - UNDO. 16 | `CTRL` + `r` - REDO. 17 | `c` + `movement` - Change up to movement. 18 | 19 | # Inside 20 | 21 | `command` + `i` + `character` - Do a command inside characters. 22 | 23 | `vi"` - Select everything inside "". 24 | `xi(` - Delete everything inside (). 25 | `ci{` - Change (Delete and enter insert mode) inside {}. 26 | 27 | ## Tabs 28 | 29 | `:tabe FILEPATH` - Open file in new tab 30 | `:tabn` - Next tab 31 | `:tabp` - Previous tab 32 | 33 | ## Copy & Paste 34 | 35 | Enter **visual mode** and select text. 36 | 37 | `y` - Copy (yank) selected. 38 | `d` - Cut selected. 39 | `p` - Paste after cursor. 40 | 41 | `x` - Delete selected. 42 | 43 | These can be combined with movements. Ex. `x2e` is delete next 2 words. 44 | 45 | `yy` - Copy (yank) line in **normal** mode. 46 | `dd` - Cut line in **normal** mode. 47 | 48 | ## Save & Exit 49 | 50 | `:w` - Save 51 | `:q` - Quit 52 | `:wq` - Save & Quit 53 | `:q!` - Cancel & Quit 54 | 55 | ## Moving 56 | 57 | All of these can be used in **visual** mode for selection. 58 | 59 | `j` - Down 60 | `k` - Up 61 | `h` - Left 62 | `l` - Right 63 | 64 | `w` - Forward one word. 65 | `b` - Back one word. 66 | `e` - End of word. 67 | 68 | Adding a number before a command, will repeat it n times. Ex. `3h` will go up 3 lines, `5dd` will detele 5 lines. 69 | 70 | `0` - Beginning of line. 71 | `$` - End of line. 72 | 73 | `%` - Jump to matching tag i.e. `)`, `}`, `]`. 74 | 75 | `f` + `character` - Jump **to** next character. 76 | `t` + `character` - Jump **before** next character. 77 | 78 | `*` - Next occurrence of word under cursor. 79 | `#` - Previous occurrence of word under cursor. 80 | 81 | `gg` - Beginning of file. 82 | `G` - End of file. 83 | `nG` - Jump to line n. 84 | 85 | ## Search 86 | 87 | `/` + `string` + `Enter` = Search for string **forwards**. 88 | `?` + `string` + `Enter` = Search for string **backwards**. 89 | `n` - Next occurrence. 90 | `N` - Previous occurrence. 91 | 92 | ## Replace 93 | 94 | `:%s/text/replacement/g` - Replace text on every line. 95 | `:s/text/replacement/g` - Replace text on current line. 96 | 97 | ## Insert 98 | 99 | `o` - Create new line **under** cursor and enter **INS** mode. 100 | `O` - Create new line **above** cursor and enter **INS** mode. 101 | 102 | `x` - Delete character. 103 | `X` - Backspace. 104 | 105 | `r` + `new character` - Change character under cursor without INS mode. 106 | 107 | ## Multiple Inserts 108 | 109 | `n times` + `i` + `string` + `ESC` = Multiple inserts. 110 | 111 | Ex. `5ifoo` + `ESC` will result in `foofoofoofoofoo`. 112 | 113 | ### Editor 114 | 115 | `:set number` - Show line numbers. 116 | -------------------------------------------------------------------------------- /topics/csharp.md: -------------------------------------------------------------------------------- 1 | # .NET Framework 2 | 3 | It's a computing framework for building applications on Windows, and it serves as an environment in which computer programs can run. 4 | 5 | It is composed of: 6 | - **Assemblies**, which are typically .EXE or .DLL files that contain compiled code which requires .NET to run. 7 | - **The Common Language Runtime (CLR)**. This is a set of Windows libraries whose job is to run assemblies. It's essentially a Virtual Machine. 8 | - **Class libraries**. A set of object-oriented APIs which can be used by assemblies. 9 | 10 | It's possible for anyone to create a compiler that compiles a language for .NET, but the most common languages that use .NET are C# and VB.NET. 11 | 12 | If you write your code to the framework, you can be sure it will work on anything that the framework says it can run on. In the case of Windows .NET, that means 'any' version of Windows. In the case of .NET Core, that's starting to mean 'any' modern device. 13 | 14 | ### CLR 15 | 16 | It's an application sitting in memory, whose job is to translate IL Code (Intermediate Language) into Machine Code i.e. JIT (Just-in-time-compilation). 17 | 18 | Java's "CLR" is called "JVM". 19 | 20 | C/C++ > Machine Code 21 | Java > ByteCode (JVM) > Machine Code 22 | C# > IL Code (CLR) > Machine Code 23 | 24 | ### Class Library 25 | 26 | Applications consist of the building block classes. 27 | 28 | Related classes are organized in containers called Namespaces. 29 | 30 | Namespaces are organized in an Assembly, either an EXE (Executable) or DLL (Dynamically Linked Library) 31 | 32 | When the application is compiled, one or more Assemblies are made. 33 | 34 | ### For Development: 35 | 36 | 1. .NET contains a large set of programs which you can call through your program. These are the programs which contain simple functions like join two arrays to complex functions like translate voice to text /or recognize red object in a image(image analyses) etc, Provide functionality to make a internet application, mobile application etc, alot of them are provided(you can call those functions from your program). The .NET libraries are soo vast that you can program Robots/Arduino etc to develop signal processing, image analysis, large set of web application frameworks, etc. 37 | 38 | 2. It maintains a common language underneath and allows you to program in different higher level languages like C#, VB, IronPython etc. When you compile it convert to a common language. It provides different set of build tools to develop applications, integrate, add other frameworks, allow others to easily write frameworks, etc. 39 | 40 | ### For End User: 41 | 42 | When you develop a program in .NET (or you can say using .NET) to run this program on many other computers you need to have a corresponding .NET framework available on that computer. So you have to install the .NET framework before you run your program. The .NET framework which you install on different computers have all the functionality your program needs but it wont have the tools for compile/build/develop .NET applications (because those are not needed on the end user machines. They also ported this framework to Linux so you can run .NET applications on Linux platform. -------------------------------------------------------------------------------- /topics/base.md: -------------------------------------------------------------------------------- 1 | base = how bytes are represented 2 | 3 | # base-2 - Binary 4 | 5 | Most basic representation. 1 byte is 8 binary characters or bits. 6 | 7 | | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | Number | 8 | | :------------ | :------------ | :------------ | :------------ | :------------ | :------------ | :------------ | :------------ | -----: | 9 | | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 231 | 10 | | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 11 | 12 | 231 = 128 + 64 + 32 + 4 + 2 + 1 13 | 14 | 231 in binary is 1110 0111 15 | 16 | # base-10 - Decimal 17 | 18 | | 102 | 101 | 100 | Number | 19 | | :------------- | :------------- | :------------- | -----: | 20 | | 2 | 3 | 1 | 231 | 21 | 22 | 231 = 200 + 30 + 1 23 | 24 | # base-16 - Hexadecimal 25 | 26 | Encodes 1 byte (8 bits) into 2 hex characters. 27 | 28 | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | 29 | | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | :-- | 30 | | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 31 | 32 | 231 in hexadecimal is `E7`. 33 | 34 | | 161 | 160 | Number | 35 | | :------------- | :------------- | -----: | 36 | | E | 7 | 231 | 37 | 38 | E7 = 14 x 161 + 7 x 160 39 | E7 = 14 x 16 + 7 x 1 40 | E7 = 224 + 7 = 231 41 | E7 = 1110 0111 42 | 43 | Hexadecimal numbers have either a `0x` prefix or an `h` suffix. So either `0xE7` or `E7h`. 44 | 45 | # base-64 46 | 47 | Encodes 3 source bytes (24 bits) into 4 base-64 characters. 48 | 49 | I was curious how on EARTH base64 can convert 3 input bytes into 4 output bytes for just 33% space growth (whereas hex converts 1 input byte into 2 output bytes for 100% space growth). Why specifically 3 input bytes? 50 | 51 | The answer is: 52 | 53 | 3 bytes = 3 x 8 bits = 24 bits. 54 | 55 | Why that magic "24 bits" number? Well, base 64 represents the numbers 0 to 63. How are those represented in binary? With 000000 (0) to 111111 (63). 56 | 57 | Bingo! Each base64 character represents 6 bits of input data using a single output byte (a single character such as "Z", etc). 58 | 59 | So 24 bits (3 full bytes of input) / 6 bits (base64 alphabet) = 4 bytes of base64. That's it! 60 | 61 | You may think "Why not base128 (7 bits of input = 8 bits of output), at just 14% size growth when encoding?". The answer for that is that base64 is the best we can find, since the lower 128 ASCII characters aren't all printable. Many are control characters such as NULL etc. 62 | 63 | There are obviously ways to create other systems such as perhaps "base81" etc, since you can do anything you want if you create a custom encoding algorithm. But the beauty of base64 is how it encodes data so cleanly in chunks of 6 bits. So that encoding scheme became popular. 64 | -------------------------------------------------------------------------------- /topics/architecture.md: -------------------------------------------------------------------------------- 1 | "Software Architecture" is just a fancy way of saying "how code is organised" and/or how "data flows" through a system. Whenever you see the word "pattern" it just means "a bunch of experienced people have concluded that this works well, so as beginners, we don't have to think too hard (up-front)." 2 | 3 | # C4 Model 4 | 5 | [Source](https://www.youtube.com/watch?v=1zYK615kepE) 6 | 7 | The model prevents unstandardized drawings of architectures due to the lack of common vocabulary. A common set of abstractions is more important than a common notation i.e. **"Abstraction first, notation second"**. 8 | 9 | Very often the code does not match the architecture diagrams. The diagrams are maps that help developers navigate a large and complex codebase. 10 | 11 | ![TEA](../pics/architecture/architecture_c4model_maps.jpg) 12 | 13 | ## Abstraction 14 | 15 | ![TEA](../pics/architecture/architecture_c4model_scope.jpg) 16 | 17 | A **software system** is made up of one or more **containers**, each of which contains one or more **components**, which in turn are implemented by one or more **code elements**. It's basically zooming in or out. 18 | 19 | - Context of the System 20 | - Containers 21 | - Components 22 | - Code 23 | 24 | #### Example 25 | 26 | - **[Context]** Customer uses CRM 27 | - **[Container]** Front End - Single Page App 28 | - **[Component]** Login component 29 | - **[Component]** Leads component 30 | - **[Code]** HTML 31 | - **[Code]** CSS 32 | - **[Code]** Javascript functions 33 | - **[Container]** Back End - RESTful API 34 | - **[Component]** Login endpoints 35 | - **[Component]** Leads endpoints 36 | - **[Code]** GET api/leads 37 | - **[Code]** GET api/lead/1 38 | - **[Code]** POST api/leads 39 | - **[Container]** Database 40 | - **[Component]** Login tables 41 | - **[Component]** Leads tables 42 | - **[Code]** lead table 43 | - **[Code]** lead_item table 44 | - **[Code]** lead_type table 45 | 46 | ## Notation 47 | 48 | Use shape, color and size to **complement** a diagram that already makes sense. 49 | 50 | ### Titles 51 | Short and meaningful. Include the diagram type. Ex. [System Context] Financial Risk System 52 | 53 | ### Acronyms 54 | 55 | Avoid using them as much as possible. At least provide the full meaning when using them. 56 | 57 | ### Elements 58 | 59 | Start with simple boxes containing the element's: 60 | - Name 61 | - Type 62 | - Technology 63 | - Description/Responsibility 64 | 65 | #### Example 66 | 67 | - [Person] **Anonymous User** - Anybody on the web. 68 | - [Software System] **acmeCRM** - Easy to use generic CRM. 69 | - [Container: Node + Express] **Back End API** - Returns JSON data to the Front End applications. 70 | - [Component: Node + Express] **Lead Routes** - Retrieved lead data from the database and returns it to the client. 71 | 72 | ### Lines 73 | 74 | Favor uni-directional lines showing the most important dependencies or data flow, with an annotation to be explicit about the purpose of the line and direction. Read the relationships out loud. 75 | 76 | Instead of: 77 | 78 | [Software System] Trade Data System ---> trade data ---> [Software System] Financial Risk System 79 | [Software System] Trade Data System ---> **sends** trade data **to** ---> [Software System] Financial Risk System 80 | 81 | ### Legend 82 | 83 | Explain the shapes, line styles, colors, borders, acronyms... Even if they are obvious. 84 | -------------------------------------------------------------------------------- /topics/testing.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | The idea is to automate the manual testing of code, with code. 4 | 5 | This requires an initial time investment, which is quickly paid back in the time saved by making sure the application is stable. 6 | 7 | # Test types 8 | 9 | - **Unit tests** 10 | Testing single functions with no dependencies (thousands). 11 | 12 | - **Integration test** 13 | Testing single functions with dependencies i.e. functions that call other functions (couple). Does the combination of single functions work? 14 | 15 | - **End-to-end (E2E) / UI test** 16 | Testing by simulating a literal manual UI interaction (few). 17 | 18 | # Setup 19 | 20 | The following is needed to test code. 21 | 22 | 1. **Test runner** 23 | Executes tests and summarizes results, with `Mocha`. 24 | 25 | 2. **Assertion library** 26 | Define testing logic and conditions, with `Chai`. 27 | 28 | 3. **Headless browser** - E2E testing 29 | Simulate browser interactions, with `Puppeteer`. 30 | 31 | - `Jest` is both a test runner and an assertion library. 32 | 33 | # Jest 34 | 35 | ```bash 36 | npm install --save-dev jest 37 | ``` 38 | 39 | ## Unit test 40 | 41 | **scripts.js** 42 | 43 | ```javascript 44 | exports.addNumbers = function(a, b) { 45 | return `The result is ${a + b}`; 46 | }; 47 | ``` 48 | 49 | **scripts.test.js** / **scripts.spec.js** 50 | 51 | We must name the test files like this, in order to be found. 52 | 53 | ```javascript 54 | const { addNumbers } = require("./scripts"); 55 | 56 | // Task runner 57 | test("should output a sum", () => { 58 | const sum = addNumbers(2, 3); 59 | // Assertion library 60 | expect(sum).toBe("The result is 5"); 61 | }); 62 | ``` 63 | 64 | **package.json** 65 | 66 | ```json 67 | "scripts": { 68 | "test": "jest" 69 | } 70 | ``` 71 | 72 | We can also run the tests automatically with every change we make. 73 | 74 | ```json 75 | "scripts": { 76 | "test": "jest --watch" 77 | } 78 | ``` 79 | 80 | We finally run the test... 81 | 82 | ```bash 83 | npm test 84 | 85 | -- 86 | PASS ./scripts.test.js 87 | ✓ should output a sum (3ms) 88 | 89 | Test Suites: 1 passed, 1 total 90 | Tests: 1 passed, 1 total 91 | Snapshots: 0 total 92 | Time: 1.605s 93 | Ran all test suites. 94 | ``` 95 | 96 | ## E2E UI test 97 | 98 | Puppeteer works with Jest. 99 | 100 | ```bash 101 | npm install --save-dev puppeteer 102 | ``` 103 | 104 | This literally creates a browser window in which the specified actions are simulated. 105 | 106 | **scripts.test.js** 107 | 108 | ```javascript 109 | test("Should insert a todo item", async () => { 110 | const browser = await puppeteer.launch({ 111 | headless: false, // Display the browser 112 | slowMo: 80, // slow down the actions in the browser 113 | args: ["--window-size=1920,1080"] 114 | }); 115 | const page = await browser.newPage(); 116 | 117 | await page.goto("http://domain.com/todo"); 118 | await page.type("input#todo", "Some arbitrary task"); 119 | await page.click("#btn-add-user"); 120 | 121 | const todoItem = await page.$eval(".todo-item", el => el.textContent); 122 | expect(todoItem).toBe("Some arbitrary task"); 123 | }); 124 | ``` 125 | 126 | The test will run much faster without rendering the browser. 127 | 128 | ```javascript 129 | const browser = await puppeteer.launch({ 130 | headless: true 131 | }); 132 | ``` 133 | -------------------------------------------------------------------------------- /topics/arduino.md: -------------------------------------------------------------------------------- 1 | # Arduino 2 | 3 | **Arduino** is a development board utilizing an **AVR ATMEGA328** MCU (microcontroller). An MCU can't do much unless it's in a circuit. 4 | 5 | The more professional option is to use a separate development board/launchpad for the MCUs. The idea is to plug in the MCU into it, program it, and take it out to be soldered in a circuit, rather than use the whole board like the Arduino. 6 | 7 | Other popular microcontrollers: 8051, PIC, AVR, ARM, MSP 8 | 9 | Microcontrollers have application specific small processing power while microprocessors have general purpose large processing power. 10 | 11 | Microcontrollers have built in RAM, ROM and other peripherals in a single chip. Microprocessors have only the CPU, and other peripherals, RAM, ROM should be connected externally. 12 | 13 | # Programming 14 | 15 | Unlike most previous programmable circuit boards, the Arduino does not need a separate piece of hardware (called a programmer) in order to load new code onto the board – you can simply use a USB cable. 16 | 17 | The Arduino IDE uses a simplified version of C++. 18 | 19 | Arduino basically works by setting something upfront once and then by trapping execution in an infinite loop. 20 | 21 | The code **will not** compile without `setup()` and `loop()`. 22 | 23 | ```c 24 | void setup() { 25 | // Setup code, run once 26 | } 27 | 28 | void loop() { 29 | // Main code, run repeatedly 30 | } 31 | ``` 32 | 33 | # Setup 34 | 35 | We can select the type of board we are working with at tools > board, or add ones with the boards manager. 36 | 37 | We define the way we are connecting to the board via a port at tools > port. It changes each time the board is disconnected. 38 | 39 | # Upload 40 | 41 | The code is compiled and uploaded into the chip via the USB cable. The built-in small LED light will blink in the frequency of the loop to indicate that it's working. 42 | 43 | # Serial Monitor 44 | 45 | We can see what Arduino outputs via tools > serial monitor. If we are getting weird characters, we need to set the **baud** value to the correct one. 46 | 47 | # Pull-up resistor 48 | 49 | Instead of adding resistors manually, we can use the built-in functionality. 50 | 51 | ```c 52 | pinMode(button, INPUT_PULLUP) 53 | ``` 54 | 55 | # digitalWrite vs analogWrite 56 | 57 | `digitalWrite` will set the specified pin to one of two states - HIGH/LOW, which equate to 5v (3.3v on some boards) and ground respectively. 58 | 59 | `analogWrite` can vary by the type of output used. It will set the pin to a periodic high/low signal, where the percentage of the signal spent high is proportional to the value written. Ex. `analogWrite(PIN, 255)`. 60 | 61 | pinMode(buzzerPin, OUTPUT); 62 | 63 | # Simple blinking LED example 64 | 65 | ```c 66 | int LED = 12; 67 | 68 | void setup() { 69 | pinMode(LED, OUTPUT); 70 | } 71 | 72 | void loop() { 73 | digitalWrite(LED, HIGH); 74 | delay(100); 75 | digitalWrite(LED, LOW); 76 | delay(100); 77 | } 78 | ``` 79 | 80 | ![Arduino LED](../pics/arduino_led.jpg) 81 | 82 | # Cop Car 83 | 84 | ```c 85 | int LED_RED = 12; 86 | int LED_BLUE = 13; 87 | int BUZZER = 10; 88 | 89 | void setup() { 90 | pinMode(LED_RED, OUTPUT); 91 | pinMode(LED_BLUE, OUTPUT); 92 | pinMode(BUZZER, OUTPUT); 93 | } 94 | 95 | void loop() { 96 | tone(BUZZER, 200, 250); 97 | digitalWrite(LED_RED, HIGH); 98 | delay(500); 99 | digitalWrite(LED_RED, LOW); 100 | 101 | tone(BUZZER, 400, 250); 102 | digitalWrite(LED_BLUE, HIGH); 103 | delay(500); 104 | digitalWrite(LED_BLUE, LOW); 105 | } 106 | ``` 107 | -------------------------------------------------------------------------------- /topics/ansible.md: -------------------------------------------------------------------------------- 1 | # Ansible 2 | 3 | What should the server look like vs How to make it that way. 4 | 5 | We configure the state of a server, rather than the installation process with scripts, or god forbid manual installation by typing each command. 6 | 7 | More importantly, it offers built-in monitoring and alerting after deployment, instead of configuring our own for each machine. Ex. Which servers are running which version? 8 | 9 | The configuration scripts serve as documentation compared to reading cryptic bash scripts. 10 | 11 | Ansible is a **declarative** system. Instead of saying **Install something**, we say **I want something to be installed** i.e. if it's already isntalled, do nothing... Otherwise install it. 12 | 13 | Ansible commands are idempotent, meaning they always result in the same, no matter how many times they run. 14 | 15 | Ansible does not require anything to run on the remote servers, aside from SSH access with private/public RSA keys. 16 | 17 | Ansible uses the `jinja2` templating engine to inject variables with `{{variable}}`. 18 | 19 | ## Things needed 20 | 21 | #### Inventory 22 | 23 | A list of machines to do things on. Can be a simple text file. 24 | 25 | ```ansible 26 | server1.company.com 27 | server2.company.com 28 | ``` 29 | 30 | Machines can be grouped by using `[group]`. Machines can belong to several groups. 31 | 32 | ```ansible 33 | [database] 34 | db1.company.com 35 | db2.company.com 36 | ``` 37 | ## Commands 38 | 39 | `ansible database -i invetory -m ping` - Run the ping module (-m) on all the machines in the database group, located in the inventory (-i) list. 40 | 41 | `ansible database -i inventory -m apt -a "name=mysql-server state=present"` - If mysql is not installed, install it on all machines missing it in the database group. 42 | 43 | ## Playbook 44 | 45 | Instead of running commands one by one, we can define a playbook(.yml) with all the commands in one place. 46 | 47 | Each task should have a name, so that it's printed in the output as it runs, as well as serve as documentation. 48 | 49 | ```yml 50 | -- 51 | - hosts: all 52 | tasks: 53 | - name: Update package list 54 | apt: update_cache=yes cache_valid_time=36000 # last 10 hours. 55 | 56 | - hosts: database 57 | tasks: 58 | - name: Install MySQL 59 | apt: name=mysql-server state=present 60 | - name: Copy fixtures 61 | template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf 62 | ``` 63 | 64 | `ansible-playbook -i inventory playbook.yml` - Run the playbook. 65 | 66 | #### Variables 67 | 68 | To prevent repetition, we can define variables and inject them where needed. 69 | 70 | ```yml 71 | -- 72 | - hosts: database 73 | vars: 74 | fixture_name: fixtures.sql # Variable 75 | tasks: 76 | - name: Install MySQL 77 | apt: name=mysql-server state=present 78 | - name: Copy fixtures 79 | copy: src={{fixture_name}} dest=/tmp/{{fixture_name}} 80 | ``` 81 | 82 | #### Loops 83 | 84 | ```yml 85 | -- 86 | - hosts: all 87 | tasks: 88 | - name: Install packages 89 | apt: name={{item}} state=present 90 | with_items: # Loop 91 | - python 92 | - python-pip 93 | - vim 94 | ``` 95 | 96 | #### Loops with Variables 97 | 98 | ```yml 99 | -- 100 | - hosts: all 101 | vars: 102 | packages: # Variable 103 | - python 104 | - python-pip 105 | - vim 106 | tasks: 107 | - name: Install packages 108 | apt: name={{item}} state=present 109 | with_items: packages # Variable 110 | ``` 111 | 112 | ## File Organization Convention 113 | -------------------------------------------------------------------------------- /topics/css.md: -------------------------------------------------------------------------------- 1 | # Grid 2 | 3 | Grid works pretty much like a table i.e. you define a grid with columns and rows, and then assign each child element a position in the grid. 4 | 5 | The positions are the lines at which the elements start or end. A grid with 5 columns and 5 rows is actually 6 lines across (5 columns) and 6 lines over (rows). 6 | 7 | ```html 8 |
9 |
Lorem ipsum dolor sit amet
10 |
11 |
Lorem
12 |
Lorem
13 |
Lorem
14 |
Lorem
15 |
Lorem
16 |
Lorem
17 |
Lorem
18 |
Lorem ipsum dolor sit amet
19 |
20 | ``` 21 | 22 | ```css 23 | #container { 24 | display: grid; 25 | grid-template-columns: 1fr 1fr 1fr 1fr 1fr; /* 5 columns, 6 lines */ 26 | grid-template-rows: repeat(5, 1fr); /* shorthand for 5 rows, 6 lines */ 27 | } 28 | #box1 { 29 | background: red; 30 | grid-column-start: 1; /* start at column line 1 */ 31 | grid-column-end: 2; /* end at column line 1 */ 32 | grid-row-start: 1; /* start at row line 1 */ 33 | grid-row-end: 2; /* end at rown line 1 */ 34 | } 35 | #box2 { 36 | grid-column: 3/-1; /* start at column line 3, end at -1 (last) */ 37 | grid-row: 2/-1; /* start at row line 2, end at -1 (last) */ 38 | display: grid; /* Nested grid */ 39 | grid-template-columns: repeat(3, 1fr); /* With separate columns */ 40 | grid-gap: 10px; /* Space between columns and rows */ 41 | padding: 10px; 42 | background: blue; 43 | } 44 | #box3 { 45 | background: rgba(0, 255, 0, 0.8); 46 | grid-column: 2/4; /* start at column line 2, end at 4 */ 47 | grid-row: 3/5; /* start at row line 3, end at 5 */ 48 | } 49 | .box { 50 | background: yellow; 51 | } 52 | ``` 53 | 54 | This CSS would result in: 55 | ![TEA](../pics/grid.jpg) 56 | 57 | # Flexbox 58 | 59 | This is for 1 dimension only, unlike the 2 dimensional grid. Flexbox can either make a row, or a column. 60 | 61 | It's not a choice of either flex or grid, but rather about combining them. Ex. A login form can be placed in the grid, but the inputs in it can flow with flex. 62 | 63 | ```css 64 | .class { 65 | display: flex; 66 | flex-direction: column; 67 | } 68 | ``` 69 | 70 | # Selectors 71 | 72 | ```CSS 73 | #menuItem:hover .menuSubItems { 74 | /* On the menu item hover, change all elements with the menuSubItems class. */ 75 | } 76 | 77 | #categories > ul > li { 78 | /* Change the lis only if they belong to the ul belonging to #categories. */ 79 | } 80 | 81 | .menuItem ul, li { 82 | /* Change all uls and lis belonging to the menuItem class. */ 83 | } 84 | ``` 85 | 86 | ### Fixed table header 87 | 88 | ```html 89 |
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |
Header 1Header 2
Data 1
Data 2
Data 3
101 |
102 | ``` 103 | 104 | #### CSS only 105 | 106 | ```css 107 | th { 108 | position: sticky; /* This makes a header fixed/sticky */ 109 | top: 0px; /* Won't work without this */ 110 | } 111 | ``` 112 | 113 | #### Javascript only 114 | 115 | ```javascript 116 | document.getElementById("table").addEventListener( 117 | "scroll", 118 | function() { 119 | var translate = "translate(0," + this.scrollTop + "px)"; 120 | this.querySelector("thead").style.transform = translate; 121 | }, 122 | false 123 | ); 124 | ``` 125 | -------------------------------------------------------------------------------- /topics/bash.md: -------------------------------------------------------------------------------- 1 | # Logical 2 | `&&` - AND 3 | `||` - OR 4 | 5 | # Redirection 6 | `>` - Redirect standard output and **overwrite**. 7 | `>>` - Redirect standard output and **append**. 8 | `<` - Redirect input to another command. Ex. `mail mike@somewhere.org < to_do.txt` 9 | 10 | # Piping 11 | `|` - Uses the **output** of one command as the **input** of another. 12 | 13 | # Command Substitution 14 | `$(PROGRAM_PATH)` - Use program output as variable. Ex. `echo "$(/bin/date) - Hi" >> logfile.log` 15 | 16 | # grep 17 | Only works for searching files or standard outputs. 18 | 19 | `grep ` - Returns all the lines containing the search criteria. 20 | 21 | # File movement 22 | 23 | ```bash 24 | # Navigate to D: 25 | cd /mnt/d 26 | 27 | # List all files WITH new line. Pasted in Excel gives one name per cell vertically. 28 | ls -1 > ../pics.txt 29 | 30 | # A && B – Run B only if A succeeded 31 | # One command from main folder 32 | cd 1 && ls -1 > ../pics.txt && cd ../2 && ls -1 >> ../pics.txt && cd .. 33 | 34 | # Wihtout .jpg extension. 35 | cd 1 && ls -1 | tr -d ".jpg" > ../pics.txt && cd ../2 && ls -1 | tr -d ".jpg" >> ../pics.txt && cd .. 36 | 37 | # Navigate to folder with files. List all files and replace new line with comma (,) and export one folder up into .csv file. 38 | ls -1 | tr "\\n" "," > ../pics.csv 39 | 40 | # Append (>>) files from other folder 41 | ls -1 | tr "\\n" "," >> ../pics.csv 42 | 43 | # List the different files from folder 1 vs folder 2 44 | diff <(ls -1a folder1) <(ls -1a folder2) 45 | 46 | # Check for different files not present in folder2 from folder1, and MOVE those in folder3 47 | rsync -rcC --compare-dest=folder2/ folder1/ folder3/ 48 | 49 | # Find all the files with a space in the name 50 | find ./ -name "* *" 51 | 52 | # Find all the files with a space in the name AND move them 53 | find ./ -name "* *" -exec mv -t ../folder {} + 54 | 55 | # Find all the files with a dash - in the name AND move them 56 | find ./ -name "*-*" -exec mv -t ../temp {} + 57 | 58 | # Find all files with 4 characters 59 | find ./ -name "????.jpg" 60 | 61 | # Find all files with 4 characters AND move them 62 | find ./ -name "????.jpg" -exec mv -t ../folder {} + 63 | 64 | # Count number of files in folder 65 | ls | wc -l 66 | 67 | # Count number of files in folder with 6 characters. 68 | find ./ -name "??????.jpg" | wc -l 69 | 70 | # List just the names of the images (without the extension). 71 | ls -1 | sed -e 's/\..*$//' > ../pics.txt 72 | ``` 73 | 74 | # Image manipulation 75 | Requires the `imagemagick` package 76 | ```bash 77 | sudo apt-get install imagemagick 78 | ``` 79 | ### Resizing 80 | ```bash 81 | # Resize image to specific dimensions, while trying to keep aspect ratio. 82 | convert image.jpg -resize 492x492! resized_image.jpg 83 | 84 | # Bulk resizing of images in a folder with conversion statuses, saved in a specified folder. 85 | for file in *.jpg; do convert $file -resize 492x492! ../resampled/$file && echo $file converted; done 86 | ``` 87 | 88 | ### Resampling 89 | ```bash 90 | # Reduce the image quality. Adjust the quality parameter 1-100. 91 | convert image.jpg -sampling-factor 4:2:0 -strip -quality 1 -interlace JPEG -colorspace RGB resampled_image.jpg 92 | 93 | # Bulk resampling of images in a folder with conversion statuses, saved in a specified folder. 94 | for file in *.jpg; do convert $file -sampling-factor 4:2:0 -strip -quality 1 -interlace JPEG -colorspace RGB ../resampled/$file && echo $file resampled; done 95 | ``` 96 | 97 | ### Watermarking 98 | ```bash 99 | # Watermarking 100 | composite -dissolve 30% -gravity center watermark2.jpg image.jpg watermarked_image.jpg 101 | 102 | # Bulk Watermarking (Save in a specific folder) 103 | for file in *.jpg; do composite -dissolve 30% -gravity center ../watermark.jpg $file ./watered/$file && echo $file watermarked; done 104 | ``` -------------------------------------------------------------------------------- /topics/mssql.md: -------------------------------------------------------------------------------- 1 | # Partition By 2 | 3 | We use this to make a "sub-query" i.e. select n-th item from a table for further use. 4 | 5 | ### Data 6 | 7 | ``` sql 8 | SELECT 9 | clientID, 10 | invoiceDate, 11 | revenue 12 | FROM sales 13 | ``` 14 | 15 | | clientID | invoiceDate | revenue | 16 | |---|---|---| 17 | 1017 | 2019-01-31 | 6574.65 18 | 116 | 2018-02-05 | 5593.22 19 | 1211 | 2018-01-15 | 3637.80 20 | 116 | 2018-02-16 | 1848.00 21 | 1211 | 2018-01-09 | 15615.65 22 | 1017 | 2019-02-14 | 1386.00 23 | 1211 | 2018-02-09 | 16145.72 24 | 116 | 2018-02-13 | 2784.51 25 | 1211 | 2018-03-28 | 8844.64 26 | 27 | 28 | ### Data with PARTITION BY 29 | 30 | In this case, we want to have the latest sale for each client. We can achieve this by partitioning the data i.e. ordering the sales for each client in descending order based on the date. We can then select only the desired row with `rowNumber`. 31 | 32 | ``` sql 33 | SELECT 34 | ROW_NUMBER() OVER (PARTITION BY clientID ORDER BY invoiceDate DESC) rowNumber, 35 | clientID, 36 | invoiceDate, 37 | revenue 38 | FROM sales 39 | ``` 40 | 41 | | rowNumber | clientID | invoiceDate | revenue | 42 | |---|---|---|---| 43 | 1 | 1017 | 2019-02-14 | 1386.00 44 | 2 | 1017 | 2019-01-31 | 6574.65 45 | 1 | 116 | 2018-02-16 | 1848.00 46 | 2 | 116 | 2018-02-13 | 2784.51 47 | 3 | 116 | 2018-02-05 | 5593.22 48 | 1 | 1211 | 2018-03-28 | 8844.64 49 | 2 | 1211 | 2018-02-09 | 16145.72 50 | 3 | 1211 | 2018-01-15 | 3637.80 51 | 4 | 1211 | 2018-01-09 | 15615.65 52 | 53 | ### Result 54 | 55 | ```sql 56 | SELECT 57 | lastSale.clientID, 58 | lastSale.invoiceDate, 59 | lastSale.revenue 60 | FROM ( 61 | SELECT 62 | ROW_NUMBER() OVER (PARTITION BY clientID ORDER BY invoiceDate DESC) rowNumber, 63 | clientID, 64 | invoiceDate, 65 | revenue 66 | FROM sales 67 | ) lastSale 68 | WHERE lastSale.rowNumber = 1 69 | ``` 70 | 71 | We only get the first row for each client i.e. the last sale (sorted by descending invoice date). 72 | 73 | |acReceiver | adDate | sales| 74 | |---|---|---| 75 | 1017 | 2019-02-14 | 1386.00 76 | 116 | 2018-02-16 | 1848.00 77 | 1211 | 2018-03-28 | 8844.64 78 | 79 | # Pivot 80 | 81 | In order for the pivoting to work, we must **only use the columns needed**, instead of all of them. This results in repeating rows. 82 | 83 | 84 | ### Data 85 | Here is some example data, obtained by the given query. 86 | 87 | | product | yearSold | revenue | 88 | |---|---|---| 89 | shoes | 2018 | 33924978.2497 90 | shirts | 2018 | 34362105.196 91 | hats | 2018 | 25119529.9395 92 | shoes | 2019 | 6947797.012 93 | shirts | 2019 | 8070039.2266 94 | hats | 2019 | 5780623.5762 95 | 96 | ```sql 97 | SELECT 98 | product, 99 | yearSold, 100 | revenue 101 | FROM sales 102 | GROUP BY 103 | yearSold, 104 | product 105 | ``` 106 | 107 | ### Approach 1 (FROM) 108 | 109 | ![TEA](../pics/sql/pivot_unpivot.png) 110 | 111 | ```sql 112 | SELECT 113 | product, -- grouping column 114 | [2019], -- spreading value 1 115 | [2018] -- spreading value 2 116 | FROM ( 117 | SELECT 118 | product, -- grouping column 119 | yearSold, -- spreading column 120 | revenue -- aggregation column 121 | FROM sales 122 | GROUP BY 123 | yearSold, 124 | product 125 | ) PivotData 126 | PIVOT ( 127 | SUM(revenue) -- aggregation function (aggregation column) 128 | FOR yearSold -- spreading column 129 | IN ( 130 | [2019], -- spreading value 1 131 | [2018]) -- spreading value 2 132 | ) piv 133 | ``` 134 | 135 | | product | 2019 | 2018| 136 | |---|---|---| 137 | shoes | 694 | 3392 138 | shirts | 807 | 3436 139 | hats | 578 | 2511 140 | 141 | ### Approach 2 (WITH) 142 | 143 | ```sql 144 | WITH PivotData AS ( 145 | SELECT 146 | product, 147 | yearSold, 148 | revenue 149 | FROM sales 150 | GROUP BY 151 | yearSold, 152 | product 153 | ) 154 | SELECT [group], [2019], [2018] 155 | FROM PivotData 156 | PIVOT ( SUM(revenue) FOR [year] IN ([2019], [2018]) ) piv 157 | ``` -------------------------------------------------------------------------------- /topics/nodemcu.md: -------------------------------------------------------------------------------- 1 | # NodeMCU/ ESP28266 2 | 3 | NodeMCU is a firmware that allows you to program the ESP8266 chip with a LUA script, or C/C++ via the Arduino IDE. 4 | 5 | The NodeMCU programming model is similar to that of Node.js, only in Lua. It is asynchronous and event-driven. Many functions, therefore, have parameters for callback functions. 6 | 7 | While the ESP8266 is often used as a ‘dumb’ Serial-to-WiFi bridge, it’s a very powerful microcontroller on its own, as it's basically an Arduino. 8 | 9 | # Power 10 | 11 | The chip itself uses 3.3v, but if the board has a usb port, then it knows that usb comes with a 5v supply, so it probably has a regulator built-in to convert the 5v to the 3.3v the chip needs. 12 | 13 | A phone charger or power bank should work just fine. 14 | 15 | https://tttapa.github.io/ESP8266/Chap04%20-%20Microcontroller.html 16 | 17 | # Setup 18 | 19 | 1. Start Arduino IDE and open Preferences window. 20 | 21 | 2. Enter http://arduino.esp8266.com/stable/package_esp8266com_index.json into Additional Board Manager URLs field. You can add multiple URLs, separating them with commas. 22 | 23 | 3. Open Boards Manager from Tools > Board menu and install esp8266 platform (and don't forget to select your ESP8266 board from Tools > Board menu after installation). 24 | 25 | # LED example 26 | 27 | ```c 28 | int LED = D7; 29 | 30 | void setup() { 31 | pinMode(LED, OUTPUT); 32 | } 33 | 34 | void loop() { 35 | digitalWrite(LED, LOW); 36 | delay(1000); 37 | digitalWrite(LED, HIGH); 38 | delay(2000); 39 | } 40 | ``` 41 | 42 | # Remote LED light 43 | 44 | Upload the code into NodeMCU, and go to the local address specified in the serial monitor in order to toggle the LED light, connected in a classic GPIO way. 45 | 46 | ```c 47 | #include 48 | 49 | const char* ssid = "WIFI_NAME"; 50 | const char* password = "WIFI_PASSWORD"; 51 | 52 | int ledPin = 13; // GPIO13---D7 of NodeMCU 53 | WiFiServer server(80); 54 | 55 | void setup() { 56 | Serial.begin(115200); 57 | delay(10); 58 | 59 | pinMode(ledPin, OUTPUT); 60 | digitalWrite(ledPin, LOW); 61 | 62 | // Connect to WiFi network 63 | Serial.println(); 64 | Serial.println(); 65 | Serial.print("Connecting to "); 66 | Serial.println(ssid); 67 | 68 | WiFi.begin(ssid, password); 69 | 70 | while (WiFi.status() != WL_CONNECTED) { 71 | delay(500); 72 | Serial.print("."); 73 | } 74 | Serial.println(""); 75 | Serial.println("WiFi connected"); 76 | 77 | // Start the server 78 | server.begin(); 79 | Serial.println("Server started"); 80 | 81 | // Print the IP address 82 | Serial.print("Use this URL to connect: "); 83 | Serial.print("http://"); 84 | Serial.print(WiFi.localIP()); 85 | Serial.println("/"); 86 | 87 | } 88 | 89 | void loop() { 90 | // Check if a client has connected 91 | WiFiClient client = server.available(); 92 | if (!client) { 93 | return; 94 | } 95 | 96 | // Wait until the client sends some data 97 | Serial.println("new client"); 98 | while(!client.available()){ 99 | delay(1); 100 | } 101 | 102 | // Read the first line of the request 103 | String request = client.readStringUntil('\r'); 104 | Serial.println(request); 105 | client.flush(); 106 | 107 | // Match the request 108 | 109 | int value = LOW; 110 | if (request.indexOf("/LED=ON") != -1) { 111 | digitalWrite(ledPin, HIGH); 112 | value = HIGH; 113 | } 114 | if (request.indexOf("/LED=OFF") != -1) { 115 | digitalWrite(ledPin, LOW); 116 | value = LOW; 117 | } 118 | 119 | // Set ledPin according to the request 120 | //digitalWrite(ledPin, value); 121 | 122 | // Return the response 123 | client.println("HTTP/1.1 200 OK"); 124 | client.println("Content-Type: text/html"); 125 | client.println(""); // do not forget this one 126 | client.println(""); 127 | client.println(""); 128 | 129 | client.print("Led is now: "); 130 | 131 | if(value == HIGH) { 132 | client.print("On"); 133 | } else { 134 | client.print("Off"); 135 | } 136 | client.println("

"); 137 | client.println(""); 138 | client.println("
"); 139 | client.println(""); 140 | 141 | delay(1); 142 | Serial.println("Client disonnected"); 143 | Serial.println(""); 144 | } 145 | ``` 146 | -------------------------------------------------------------------------------- /topics/linux.md: -------------------------------------------------------------------------------- 1 | # Linux 2 | 3 | # Basics 4 | 5 | `/` - Root directory 6 | `~` - Home directory 7 | 8 | `^` - Control key. 9 | `M` - Alt key. 10 | 11 | `CTRL` + `C` - Stop running command. 12 | `CTRL` + `D` - Close current shell session. 13 | `CTRL` + `L` - Clear screen. (Scrolls you down in reality) 14 | 15 | `CTRL` + `A` - Go to beginning of line. 16 | `CTRL` + `E` - Go to end of line. 17 | `CTRL` + `F` - Next word. 18 | `CTRL` + `B` - Previous word. 19 | 20 | `ALT` + `Backspace` - Delete last word. 21 | `ALT` + `Left` / `Right` - Go to previous / next word. 22 | `CTRL` + `U` - Delete whole line. 23 | 24 | `man COMMAND` - Command help. 25 | `history` - Lists all the commands used. 26 | `CTRL` + `R` - Search command history. Hit again for previous command. 27 | 28 | # Install 29 | 30 | `dpkg` is a backend for `apt-get`, which is a backend for `aptitude` (GUI). 31 | 32 | ## Packages 33 | 34 | ```bash 35 | apt-cache search PACKAGE # Search packages. 36 | apt-cache madison PACKAGE # List versions. 37 | 38 | apt-get update # Update the packages list. 39 | apt-get install PACKAGE # Install specified package. 40 | apt-get upgrade # Actually update the packages. 41 | 42 | apt list --installed # A list of installed packages. 43 | 44 | apt-get remove PACKAGE # Remove a specified package. 45 | add-apt-repository REPO # Add 3rd party repository or PPA (Personal Package Archive). 46 | 47 | curl URL # Output the URL content. 48 | wget "URL" # Download from URL. 49 | sudo dpkg –i FILE_NAME # Install downloaded file. 50 | ``` 51 | 52 | ## .deb 53 | 54 | Install `.deb` packages from the terminal. 55 | 56 | ```bash 57 | sudo dpkg -i 58 | sudo apt-get install -f 59 | ``` 60 | 61 | # Find 62 | 63 | ```bash 64 | find / # List root directory's content. 65 | find / | grep FILE # Search the output. 66 | 67 | sudo find / -iname FOLDER/FILE.ext # Find case insensitive. 68 | which PROGRAM # Find path to program. 69 | ``` 70 | 71 | # Utility 72 | 73 | ```bash 74 | # Navigation 75 | cd FOLDER # Change directory 76 | cd .. # Go back one up 77 | cd - # Go back to last working directory 78 | pwd # Current path 79 | 80 | # List 81 | ls -a # List all files, including hidden 82 | ls -l # List in a list format 83 | ll # Shorthand for ls -l 84 | 85 | # Read 86 | cat FILE # Show the file content in terminal 87 | less FILE # View file content in the less program 88 | head FILE # Show first 10 lines 89 | tail FILE # Show last 10 lines 90 | tail -f FILE # Log in real time 91 | 92 | # Create 93 | mkdir FOLDER # Create a folder 94 | touch FILE # Create a file 95 | 96 | # Copy/Paste 97 | cp PATH/FILE PATH/FILE # Create a copy 98 | mv PATH/FILE PATH/FILE # Rename or Cut & Paste a file 99 | 100 | # Delete 101 | rm FOLDER/FILE # Delete folder or file 102 | rm -r FOLDER # Delete a directory and its files 103 | 104 | # Printing 105 | echo TEXT # print text 106 | printf TEXT # print formatted text 107 | ``` 108 | 109 | ```bash 110 | \n # new line 111 | \r # carriage return, i.e. bring carret (cursor) to start of line 112 | ``` 113 | 114 | # Processes 115 | 116 | ```bash 117 | ps -ef # List all running processes. 118 | ps -ef | grep # Find a specific process. 119 | kill -9 # Kill a process by id. 120 | ``` 121 | 122 | # Environment Variables 123 | 124 | PATH is an enviroment variable. It tells your machine where to search for program executables, so when you run your **picc** program you can just do `picc` instead of `/usr/hitech/picc/9.82/bin/picc`. 125 | 126 | Add them to `~/.profile` to make them permanent. Paths require the `bin`, while variables don't. 127 | 128 | The variable is not in the environment until you export it. Otherwise it's just a shell variable. 129 | 130 | ```bash 131 | env # List all variables. 132 | echo "$HOME" # Specific variable, in this case **$PATH**. 133 | ``` 134 | 135 | Paths are delimited with `:`. 136 | 137 | ```bash 138 | # Method 1 139 | vim ~/.profile # Edit this file. 140 | PATH="$HOME/bin:$PATH" # Find this line. 141 | PATH="$HOME/bin:$PATH:/usr/hitech/picc/9.82/bin" # Change it into this. 142 | # It appends the new path to the existing system ones, just for this user. 143 | 144 | # Method 2 - Shorthand to avoid editing manually. 145 | export PATH="$PATH:/usr/hitech/picc/9.82/bin" # export ="" 146 | ``` 147 | 148 | # Password Generator 149 | 150 | Generate a random 14 character password by using the linux `/dev/urandom` file, a stream of mashed system data. 151 | 152 | `cat /dev/urandom | env LC_CTYPE=C tr -dc a-zA-Z0-9 | head -c 14` 153 | 154 | # Ubuntu on Windows 155 | 156 | `C:\Users\User\AppData\Local\lxss\home\user` - Filesystem location. 157 | 158 | `cd /mnt/` - Navigate to My Computer (C:, D:). 159 | -------------------------------------------------------------------------------- /topics/fp.md: -------------------------------------------------------------------------------- 1 | # Functional Programming 2 | 3 | Simple **is not** easy. Simple software is beautiful, and worth the effort. 4 | 5 | For `objects`, we add properties with the `...spread` operator, and remove them with `...spread destructuring`. 6 | 7 | For arrays, we add items also with the `...spread` operator, transform the array with `.map`, and remove items with `.filter`. 8 | 9 | In both objects and arrays, we summarize info with `.reduce`. 10 | 11 | # virtual-dom 12 | 13 | The view part won't work with HTML strings. The elements have to be proper DOM nodes. Using strings gives this error `Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.` 14 | 15 | ```javascript 16 | // Won't work 17 | var el = "

test satu dua tiga

"; // is a string 18 | document.body.appendChild(el); 19 | 20 | // Works 21 | var el = document.createElement("p"); // is a node 22 | el.innerHTML = "test satu dua tiga"; 23 | document.body.appendChild(el); 24 | ``` 25 | 26 | # hyperscript-helpers 27 | 28 | This small library helps make the code cleaner. 29 | 30 | ```javascript 31 | // instead of writing 32 | h("div"); 33 | 34 | // write 35 | div(); 36 | 37 | // instead of writing 38 | h("section#main", mainContents); 39 | 40 | // write 41 | section("#main", mainContents); 42 | ``` 43 | 44 | ### API 45 | 46 | ```javascript 47 | tagName(selector); 48 | tagName(attrs); 49 | tagName(children); 50 | tagName(attrs, children); 51 | tagName(selector, children); 52 | tagName(selector, attrs, children); 53 | Where; 54 | ``` 55 | 56 | - `selector` is string, starting with "." or "#". 57 | - `attrs` is an object of attributes. 58 | - `children` is a hyperscript node, an array of hyperscript nodes, a string or an array of strings. 59 | 60 | # Simple app 61 | 62 | 1. When we click the increment button, the `dispatch` function, defined in the `app` function is called, with the `MSGS.ADD` payload. 63 | 2. The `update` function, a switch statement, then uses the payload to match the behavior, in this case to add 1 to the current `model`. 64 | 3. The `view` function then uses the latest model to generate the DOM tree, but only with the changes parts, thanks to the `virtual-dom`. 65 | 66 | ```javascript 67 | const hh = require("hyperscript-helpers"); // Create HTML element functions 68 | const { h, diff, patch } = require("virtual-dom"); 69 | const createElement = require("virtual-dom/create-element"); 70 | 71 | // const { div, button } = require('hyperscript-helpers')(h); 72 | const { div, button } = hh(h); 73 | 74 | const initModel = 0; 75 | 76 | const MSGS = { 77 | ADD: "ADD", 78 | SUBTRACT: "SUBTRACT" 79 | }; 80 | 81 | // Updates the model after a view action. 82 | function update(msg, model) { 83 | switch (msg) { 84 | case MSGS.ADD: 85 | return model + 1; 86 | case MSGS.SUBTRACT: 87 | return model - 1; 88 | default: 89 | return model; 90 | } 91 | } 92 | 93 | // The dispatch reloads the view. Defined in app. 94 | function view(dispatch, model) { 95 | return div([ 96 | div({ className: "counter" }, `Count: ${model}`), 97 | button( 98 | { 99 | className: "button", 100 | onclick: () => dispatch(MSGS.ADD) 101 | }, 102 | "+" 103 | ), 104 | button( 105 | { 106 | className: "button", 107 | onclick: () => dispatch(MSGS.SUBTRACT) 108 | }, 109 | "-" 110 | ) 111 | ]); 112 | } 113 | 114 | // impure code contained inside app function 115 | function app(initModel, update, view, node) { 116 | // Initial view 117 | let model = initModel; 118 | let currentView = view(dispatch, model); 119 | let rootNode = createElement(currentView); 120 | node.appendChild(rootNode); 121 | 122 | function dispatch(msg) { 123 | model = update(msg, model); 124 | const updatedView = view(dispatch, model); 125 | const patches = diff(currentView, updatedView); 126 | rootNode = patch(rootNode, patches); 127 | currentView = updatedView; 128 | } 129 | } 130 | 131 | // Load app div 132 | const rootNode = document.getElementById("app"); 133 | 134 | app(initModel, update, view, rootNode); 135 | ``` 136 | 137 | # HTTP effects 138 | 139 | HTTP requests are triggered in a similar way to how the app performs state updates. 140 | 141 | Normal updates: 142 | 143 | - view generates a message. 144 | - update is called with the new message and current model. 145 | - update returns the new model. 146 | - view uses the new model to re-render the view. 147 | 148 | HTTP updates: 149 | 150 | - view generates a message. 151 | - update is called with the new message and current model. 152 | - update returns the new model, a url, and a message generating function. 153 | - the app function makes a server request with the url. 154 | - when the server responds, the message generating function returned from update, creates a new message that includes the server data. 155 | - update is called with the newly generated message. 156 | - update returns the new model. 157 | - view uses the new model to re-render the view. 158 | -------------------------------------------------------------------------------- /topics/node.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | Instead of writing all the code in one giant file, we can split the code into multiple files called `modules`. Only things that are highly related should go in a module. 4 | 5 | This increases maintainability, code reuse and abstraction (blackbox). 6 | 7 | **CommonJS** (old) - Synchronous 8 | ```javascript 9 | // foo.js module 10 | function foo() { 11 | return 'bar'; 12 | } 13 | module.exports.foo = foo; 14 | 15 | // index.js use 16 | const { foo } = require('foo'); 17 | ``` 18 | 19 | **ES6** - Must use Babel, can be asynchronous 20 | ```javascript 21 | // foo.js module 22 | export function foo() { 23 | return 'bar'; 24 | } 25 | 26 | // index.js use 27 | import { foo } from 'foo'; 28 | ``` 29 | 30 | Every file in Node is considered a module. Everything declared inside is scoped to the file i.e. they are private. 31 | 32 | Node does not give access to the global scope. In order to use the content of a module, we need to export it i.e. make it public. 33 | 34 | ```javascript 35 | var message = "hello"; 36 | console.log(global.message); // undefined 37 | ``` 38 | 39 | ## ES6 Modules 40 | 41 | A proper format, unlike the CommonJS convention. 42 | 43 | ```javascript 44 | // add.js 45 | export function add(a, b) { 46 | return a + b; 47 | } 48 | 49 | // index.js 50 | import { add } from "./add"; 51 | ``` 52 | 53 | Modules are exported with `export` and imported with `import`. We can export one or more objects from a module. 54 | 55 | There are `default` and `named` exports. We use a default export if there is a single object we want to export. 56 | 57 | **module** 58 | 59 | ```javascript 60 | import { Person } from "./person"; 61 | 62 | // Named export 63 | export function promote() {} 64 | 65 | // Default export 66 | export default class Teacher extends Person { 67 | constructor(name, degree) { 68 | super(name); 69 | this.degree = degree; 70 | } 71 | 72 | teach() { 73 | console.log("teach"); 74 | } 75 | } 76 | ``` 77 | 78 | **import** 79 | 80 | ```javascript 81 | import Teacher, { promote } from "./teacher"; 82 | 83 | // Default -> import ... from ""; 84 | // Named -> import { ... } from ""; 85 | 86 | const teacher = new Teacher("John", "MSc"); 87 | teacher.teach(); 88 | ``` 89 | 90 | ### Browsers 91 | 92 | Must include the `.js` file extension during import. 93 | 94 | **circle.js** 95 | 96 | ```javascript 97 | // Implementation detail, not exported 98 | const _radius = new WeakMap(); // private property 99 | 100 | // Public interface i.e. exported part 101 | export class Circle { 102 | constructor(radius) { 103 | _radius.set(this, radius); 104 | } 105 | 106 | draw() { 107 | console.log("Circle with radius" + _radius.get(this)); 108 | } 109 | } 110 | ``` 111 | 112 | **index.js** 113 | 114 | ```javascript 115 | import { Circle } from "./circle.js"; // Must include the .js file extension 116 | 117 | const c = new Circle(10); 118 | c.draw(); // Circle with radius 10 119 | ``` 120 | 121 | **index.html** 122 | 123 | We need to add the module type in order to avoid the `Uncaught SyntaxError: Unexpected token {` error, caused by the `import` curly brace. 124 | 125 | ```html 126 | 127 | ``` 128 | 129 | ## Old formats 130 | 131 | Conventions/syntax for defining modules. ES6 natively supports them. 132 | 133 | - **CommonJS** - Loads files synchronously. 134 | 135 | Since ES5 doesn't support modules, developers came up with different syntaxes to define them. These are only used in legacy applications. 136 | 137 | - **AMD** (Browser) - Asynchronous Module Definition. 138 | - **UMD** (Browser / Node)- Universal Module Definition. 139 | 140 | ### CommonJS (Node) 141 | 142 | Two problems: 143 | 144 | 1. Browsers cannot load files synchronously. This is solved via bundling a huge file including everything, even unused things. 145 | 2. JS engine cannot tell what a module exports until it runs it. 146 | 147 | ```javascript 148 | // add.js 149 | function add(a, b) { 150 | return a + b; 151 | } 152 | module.exports = add; 153 | 154 | // index.js 155 | const add = require("./add"); // Loads synchronously 156 | add(2, 3); // 5 157 | ``` 158 | 159 | CommonJS defines the: 160 | 161 | - `module.exports` for exporting modules. It represents the object that is exported from a module. 162 | - `module` refers to the current module (file). 163 | - `exports` is an object and property of `module`. 164 | - `require("./module")` for importing modules. 165 | 166 | #### Single class export 167 | 168 | When we import the `foo.js` module, we directly get the `Foo` class. 169 | 170 | ```javascript 171 | class Foo {} 172 | 173 | module.exports = Foo; 174 | ``` 175 | 176 | #### Multiple class exports 177 | 178 | We can import the `exports` objects and access its properties. 179 | 180 | ```javascript 181 | class Foo {} 182 | class Bar {} 183 | 184 | module.exports.Foo = Foo; 185 | module.exports.Bar = Bar; 186 | ``` 187 | 188 | #### Example 189 | 190 | **circle.js** 191 | 192 | ```javascript 193 | // Implementation detail, not exported 194 | const _radius = new WeakMap(); // private property 195 | 196 | // Public interface i.e. exported part 197 | class Circle { 198 | constructor(radius) { 199 | _radius.set(this, radius); 200 | } 201 | 202 | draw() { 203 | console.log("Circle with radius" + _radius.get(this)); 204 | } 205 | } 206 | 207 | module.exports = Circle; 208 | ``` 209 | 210 | **index.js** 211 | 212 | ```javascript 213 | const Circle = require("./circle"); 214 | 215 | const c = new Circle(10); 216 | c.draw(); // Circle with radius 10 217 | ``` 218 | -------------------------------------------------------------------------------- /topics/networking.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | Tools used for networking. 4 | 5 | ```bash 6 | sudo apt-get update && sudo apt-get upgrade 7 | sudo apt-get install netcat-openbsd tcpdump traceroute mtr 8 | ``` 9 | 10 | # Theory 11 | 12 | ## HTTP / TCP Model 13 | 14 | Each of these depends on the one below. Some of these don't belong on a specific layer. 15 | 16 | ![TEA](../pics/networking/TCPIP.jpg) 17 | 18 | HTTP = Hypertext Transfer Protocol 19 | TCP = Transmission Control Protocol 20 | 21 | All traffic is split up into messages called packets, sent between two computers in a stream, with the addresses of the sender and recipient in each one. 22 | 23 | HTTP is needed so that communicating systems can understand each other. TCP just provides "envelopes" that can transfer bytes around the network. 24 | 25 | An application protocol assigns structure and meaning to the contents of the envelopes. 26 | 27 | **If you speak English and I send you a letter written in French, you'll still get the letter, but you won't understand it.** 28 | 29 | HTTP is implemented in browsers and web servers, while TCP in the operating system. 30 | 31 | #### Simple HTTP Request 32 | 33 | ```bash 34 | # HTTP header 35 | GET /posts/1 HTTP/1.1 36 | Host: jsonplaceholder.typicode.com 37 | 38 | # Manual request - Returns header and body 39 | printf 'GET /posts/1 HTTP/1.1\r\nHost:jsonplaceholder.typicode.com\r\n\r\n' | nc jsonplaceholder.typicode.com 80 40 | 41 | # Just the body 42 | curl jsonplaceholder.typicode.com/posts/1 43 | ``` 44 | 45 | ## Ports 46 | 47 | Listening on a port is like waiting for a phone call on a specific phone number. 48 | 49 | Ports let servers distinguish one service from another on the same host and wait for someone to connect. 50 | 51 | Normally a server has well known ports for it's applications. ex. HTTP uses `port 80` and SSH uses `port 22`. The client initiates a connection, and it's associated with an arbitrary port on its end. 52 | 53 | Only one program can listen to a port in a given moment. Once started, the program can start child processe to listen for multiple connections on the same port i.e. a web server. 54 | 55 | The port range that a normal (non-root) user can listen on is `1024` through `65535`. Root access (including sudo)can listen on ports down to 1. 56 | 57 | If the other side doesn't pick up, an RST (Reset packet) error message is sent back. 58 | 59 | # DNS 60 | 61 | It's basically a phonebook for IP addresses. 62 | 63 | An `A Record` is matched with an IP address, so when someone looks for `www.google.com`, the A record is referenced and the IP address is sent back to the user. 64 | 65 | The DNS resolver i.e. client code is built into the OS. 66 | 67 | **CNAME** - Canonical Name i.e. alias for a domain. 68 | **AAAA** - IPv6 equivalent to an A record. 69 | **NS** - DNS Name server. The NS record for a particular domain specifies which DNS has the records. 70 | 71 | # Tools 72 | 73 | ## ping 74 | 75 | It sends individual packets to test if traffic can get from one address to another, and back. 76 | 77 | ```bash 78 | ping 8.8.8.8 79 | 80 | # send 5 packets 81 | ping -c 5 google.com 82 | ``` 83 | 84 | #### unknown host 85 | 86 | ```bash 87 | sudo vim /etc/resolv.conf 88 | # Add nameserver 8.8.8.8 89 | ``` 90 | 91 | ## lsof 92 | 93 | The `lsof` utility lists open files, including network sockets (listening or connected). 94 | 95 | ```bash 96 | # List only network sockets 97 | lsof -i 98 | ``` 99 | 100 | ## nc / netcat 101 | 102 | `netcat` is a tool for manually talking to servers, by connecting to a port and sending a string over it. It's a thing wrapper over TCP. 103 | 104 | ```bash 105 | nc en.wikipedia.org 80 106 | nc localhost 22 107 | nc gmail-smtp-in.l.google.com 80 108 | ``` 109 | 110 | To illustrate, we can use two terminals to talk to each other. Anything typed at the second console will be concatenated to the first, and vice-versa. This is a simple TCP server. The connection is ended with `CTRL` + `d`. 111 | 112 | ```bash 113 | # terminal 1 114 | nc -l 3456 # listen for an incoming connection on port 3456 115 | # typed text 116 | 117 | # terminal 2 118 | nc 127.0.0.1 3456 # connect to the machine and port being listened on 119 | # typed text 120 | ``` 121 | 122 | Commands can be sent via a `pipe`. 123 | 124 | ```bash 125 | echo 'message' | netcat server 80 126 | ``` 127 | 128 | `netcat` doesn't know anything about forming HTTP request, but in combination with `printf` and `piping`, it can be done. 129 | 130 | ```bash 131 | printf 'HEAD / HTTP/1.1\r\nHost: google.com\r\n\r\n' | nc google.com 80 132 | 133 | printf 'GET /posts/1 HTTP/1.1\r\nHost:jsonplaceholder.typicode.com\r\n\r\n' | nc jsonplaceholder.typicode.com 80 134 | ``` 135 | 136 | ## host 137 | 138 | Used for looking up records in the DNS. 139 | 140 | ```bash 141 | # Returns all the records 142 | host google.com 143 | 144 | # Returns just the A record 145 | host -t a google.com 146 | ``` 147 | 148 | ## dig 149 | 150 | Similar to `host` in showing DNS records, but in a way more readable for scripts and closer to the way they are stored in the DNS configuration files. 151 | 152 | ```bash 153 | dig google.com 154 | ``` 155 | 156 | # Static server 157 | 158 | This will start a static web server on port `8000`. The command has to be run in the directory with the `index.html` file. 159 | 160 | ```bash 161 | python -m SimpleHTTPServer 8080 162 | ``` 163 | 164 | # Networking 165 | 166 | **Gateway** is the router address we are talking to in order to connect to the rest of the network/internet. 167 | 168 | `127.x.x.x` - Your computer. 169 | `192.168.0.x` - Local address created by a router. 170 | 171 | `ifconfig` - Check IP address. 172 | `ping 8.8.8.8` - Ping IP address. 173 | `netstat -tupln` - Check open ports. 174 | 175 | `cat etc/network/interfaces` - Shows the interfaces brought up after booting. 176 | 177 | `/etc/hosts` is used to simulate a domain for an IP address. Add `127.0.0.1 domain.com` to avoid typing the IP address. 178 | -------------------------------------------------------------------------------- /topics/docker.md: -------------------------------------------------------------------------------- 1 | # Docker 2 | 3 | Docker is used to run apps/processes without actually installing them. This is useful because it ensures the same environment is running on all the machines using the images that make the containers. 4 | 5 | **Container** is a running instance of an **image**, which is a template for an environment, a snapshot of a system at a certain time. It has the OS, software and application code all bundled in one file. Images are built via a **Dockerfile**, a list of steps to perform to build the image. List of steps like configure the OS, install packages, copy project files into the right places... 6 | 7 | Dockerfile > (build) Image > (run) Container. 8 | 9 | There should be **only one** process per container. 10 | 11 | Localhost (127.0.0.1) for a container is itself. Containers can access each other by using their names as the domain. 12 | 13 | Docker uses a `unix socket` which means that it runs as `root` and asks for `sudo`. 14 | 15 | ## Installing Docker 16 | 17 | Add the GPG key. 18 | `curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -` 19 | 20 | Add the Docker repository to APT sources. 21 | `sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"` 22 | 23 | Update the package list to include Docker. 24 | `sudo apt-get update` 25 | 26 | Install Docker. 27 | `sudo apt-get install -y docker-ce` 28 | 29 | ## Basic Commands 30 | 31 | `docker run ` - Build a container from an image and run it. Each usage creates a new container. 32 | `docker start ` - Start an existing container by name or id. 33 | `docker stop ` - Stop a container by name or id. 34 | `docker ps` - List all running containers. `-a` for stopped ones. 35 | `docker rm ` - Delete a container by name or id. 36 | `docker exec -it bash` - Enter a container. 37 | 38 | ## Flags 39 | 40 | `--name ` - Name the container. 41 | `-p 8080:80` - Map the container's `80` port, to the webserver's `8080` port i.e. the container can be accessed via `8080`. 42 | `-d` - Run as daemon i.e. background process. 43 | `-v :` - Volume. Mount a local directory as a container directory. Used when not specified in Dockerfile. 44 | 45 | `sudo docker rm $(sudo docker ps -aq)` - Remove all containers. 46 | 47 | ## Build Container with Dockerfile 48 | 49 | #### Dockerfile 50 | `FROM ` - Always at top. Uses an image as a base. 51 | `RUN ` - Run commands on image **build**. Can be chained with &&. 52 | `CMD ["">]` - Run a command on container **start**. 53 | `COPY ` - Copy from local directory to container directory. 54 | `WORKDIR ` - Set work directory. Default is `/`. 55 | `EXPOSE ` - Expose a specific port. 56 | `#` - Comment. 57 | 58 | #### Build 59 | `docker build -t ` - Build an image by running all commands in the Dockerfile. 60 | 61 | ###### nginx Container Example 62 | ```Dockerfile 63 | FROM nginx 64 | COPY ./nginx.conf /etc/nginx/conf.d/default.conf 65 | COPY /src /www 66 | ``` 67 | 68 | ``` 69 | # ./nginx.conf - Bare minimum needed to run nginx. 70 | server { 71 | root /www; 72 | } 73 | ``` 74 | 75 | `sudo docker build -t nginx-static .` - Build the container. 76 | 77 | `sudo docker run -d -p 8080:80 --name nginx-static nginx-static` - For this to work, a port forwarding rule is needed on the VM with host `3000` and guest `8080`. Container `80` > VM `8080` > Host `3000`. 78 | 79 | Visit the website in the host via `127.0.0.1:3000`. 80 | 81 | ## Docker Compose 82 | 83 | `sudo apt-get install docker-compose` or get it from https://github.com/docker/compose/releases. 84 | 85 | After a while, running, starting and stopping containers gets very tedious. Instead of manually typing the docker commands one by one, we can define a `docker-compose.yml` configuration file to do it for us. 86 | 87 | We can either use pre-made Dockerfiles, or we can write their content directly in the compose file. 88 | 89 | All the locations are relative to the docker-compose file. 90 | 91 | ```yml 92 | version: '3' # Version of compose file format. 93 | 94 | services: 95 | products-service: # This can be named anyway. Used for connecting containers. 96 | build: ./products # Folder containing Dockerfile. 97 | volumes: # List of volumes to be mounted. 98 | - ./products:/usr/src/app # Source:Container 99 | ports: # List of ports. 100 | - 5001:80 # Host:Container port forwarding. 101 | ``` 102 | 103 | `sudo docker-compose build` - Recreate image. 104 | `--no-cache` - Recreate without cache. 105 | 106 | `sudo docker-compose up` - Run container. 107 | `sudo docker-compose dowm` - Stop and remove container. 108 | 109 | #### Container Networking 110 | 111 | ```yml 112 | version: "3" 113 | services: 114 | web: 115 | build: . 116 | ports: 117 | - "8000:8000" 118 | db: 119 | image: postgres 120 | ports: 121 | - "8001:5432" 122 | ``` 123 | 124 | When you run docker-compose up, the following happens: 125 | - A network called `myapp_default` is created. 126 | - A container is created using web’s configuration. It joins the network `myapp_default` under the name `web`. 127 | - A container is created using db’s configuration. It joins the network `myapp_default` under the name `db`. 128 | 129 | Each container can now look up the hostname web or db and get back the appropriate container’s IP address. For example, web’s application code could connect to the URL postgres://db:5432 and start using the Postgres database. 130 | 131 | It is important to note the distinction between HOST_PORT and CONTAINER_PORT. In the above example, for db, the HOST_PORT is 8001 and the container port is 5432 (postgres default). Networked service-to-service communication use the CONTAINER_PORT. When HOST_PORT is defined, the service is accessible outside the swarm as well. 132 | 133 | Within the web container, your connection string to db would look like postgres://db:5432, and from the host machine, the connection string would look like postgres://{DOCKER_IP}:8001. 134 | -------------------------------------------------------------------------------- /topics/react.md: -------------------------------------------------------------------------------- 1 | React is a library that only takes care of rendering the view while making sure it's in sync with the state. 2 | 3 | # React Create App 4 | 5 | Zero-configuration setup. 6 | 7 | ```bash 8 | sudo npm i -g create-react-app 9 | create-react-app app-name 10 | ``` 11 | 12 | It will install: 13 | 14 | - Lightweight development server 15 | - Webpack (bundler) 16 | - Babel (transpiler) 17 | 18 | It also enables hot module reloading, which means we don't have to re-build and refresh after each change. 19 | 20 | ### Errors 21 | 22 | You appear to be offline. Falling back to the local Yarn cache. 23 | 24 | ```bash 25 | sudo apt-get remove yarn && sudo apt-get purge yarn 26 | 27 | npm config set registry "https://registry.npmjs.org" 28 | ``` 29 | 30 | ### Eject 31 | 32 | This will permanently add all the abstracted dependencies in `package.json` and the config files will appear. This allows detailed configurations. 33 | 34 | ```bash 35 | npm run eject 36 | ``` 37 | 38 | # Hello World 39 | 40 | ```javascript 41 | // React object from module. 42 | import React from "react"; 43 | import ReactDOM from "react-dom"; 44 | 45 | const element =

Hello World

; // JSX expression 46 | 47 | ReactDOM.render(element, document.getElementById("app")); 48 | ``` 49 | 50 | # JSX 51 | 52 | It's syntactic sugar for creating HTML elements with javascript, instead of using templating engines. It's not a string, but an expression. 53 | 54 | ```jsx 55 | const element =

Hello World

; 56 | ``` 57 | 58 | Babel transpiles it into... 59 | 60 | ```javascript 61 | var element = React.createElement("h1", null, "Hello World"); 62 | ``` 63 | 64 | Since the compiled JSX makes a call to `React.createElement`, we need to import `React`, even if we don't use the object directly. 65 | 66 | This returns an `Object`, a React element, which is part of the virtual-DOM. 67 | 68 | The call to the function is the reason why we need one parent element, as Babel gets confused with multiple. 69 | 70 | # Virtual-DOM 71 | 72 | Lightweight in-memory representation of the UI. Instead of re-building the DOM on each change, the virtual DOM sees the changes and it just updates the changed parts in the real DOM. 73 | 74 | Whenever the state of the React element object changes... 75 | 76 | - React gets a new React element. 77 | - Compares it to the previous one to see the changes. 78 | - Update just the changed parts in the real DOM. 79 | 80 | The DOM updating is done by the `render()` method in the `react-dom` module. It takes the object returned from JSX and renders the HTML inside the referenced div. 81 | 82 | # Components 83 | 84 | A piece of UI. A javascript class that has some state to be displayed and a render method. 85 | 86 | **counter.jsx** 87 | 88 | ```javascript 89 | import React, { Component } from "react"; 90 | 91 | class Counter extends Component { 92 | render() { 93 | return ( 94 |
95 |
Counter
96 | 97 |
98 | ); 99 | } 100 | } 101 | 102 | export default Counter; 103 | ``` 104 | 105 | **index.js** 106 | 107 | ```javascript 108 | import React from "react"; 109 | import ReactDOM from "react-dom"; 110 | import Counter from "./components/counter"; 111 | 112 | ReactDOM.render(, document.getElementById("root")); 113 | ``` 114 | 115 | # State 116 | 117 | `setState` is used for updating the state AND re-rendering the view i.e. syncing the DOM with the virtual DOM. 118 | 119 | The method takes an object, and merges or overwrites the state object with it. 120 | 121 | If we update the state directly, React is unaware of the change, and nothing is rendered. 122 | 123 | # Events 124 | 125 | The event naming convention is to prefix the function with `handle`. 126 | 127 | ```javascript 128 | class Foo extends Component { 129 | handleSomething() { 130 | console.log("Something handled"); 131 | } 132 | 133 | render() { 134 | return ; 135 | } 136 | } 137 | ``` 138 | 139 | ## Binding this 140 | 141 | `onClick={this.handleSomething}` results in `undefined`, because `this` references the global object and React runs in `strict mode`. 142 | 143 | ### Arrow function 144 | 145 | ```javascript 146 | class Foo extends Component { 147 | state = { 148 | bar: "bar" 149 | }; 150 | 151 | handleSomething = () => { 152 | console.log(this.state.bar); 153 | }; 154 | 155 | render() { 156 | return ; 157 | } 158 | } 159 | ``` 160 | 161 | ### bind() 162 | 163 | Since we cannot use `onClick={this.handleSomething("value")}`, we need to use an arrow function. 164 | 165 | ```javascript 166 | class Foo extends Component { 167 | state = { 168 | bar: "bar" 169 | }; 170 | 171 | handleSomething() { 172 | console.log(this.state.bar); 173 | } 174 | 175 | render() { 176 | return ( 177 | 180 | ); 181 | } 182 | } 183 | ``` 184 | 185 | ## Event arguments 186 | 187 | ```javascript 188 | class Foo extends Component { 189 | state = { 190 | bar: "bar" 191 | }; 192 | 193 | handleSomething = argument => { 194 | console.log(argument); 195 | }; 196 | 197 | render() { 198 | return ( 199 | 202 | ); 203 | } 204 | } 205 | ``` 206 | 207 | # CSS 208 | 209 | ```javascript 210 | class Foo extends Component { 211 | styles = { 212 | fontSize: 10, 213 | fontWeight: "bold" 214 | }; 215 | 216 | render() { 217 | return
Some text
; 218 | } 219 | } 220 | ``` 221 | 222 | ```javascript 223 | class Foo extends Component { 224 | render() { 225 | return ( 226 |
Some text
227 | ); 228 | } 229 | } 230 | ``` 231 | -------------------------------------------------------------------------------- /topics/elm.md: -------------------------------------------------------------------------------- 1 | # Elm 2 | 3 | Elm code can be tested in the [sandbox app](http://elm-lang.org/examples/hello-html) without installation. 4 | 5 | # Install 6 | ```bash 7 | sudo npm install -g elm # Normal install 8 | sudo npm install --unsafe-perm -g elm # If npm gives you permission errors. 9 | ``` 10 | 11 | `elm-package install elm-lang/PACKAGE_NAME` - Install dependencies. 12 | 13 | #### Alternative 14 | Install yarn 15 | ```bash 16 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - 17 | echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list 18 | sudo apt-get update && sudo apt-get install yarn 19 | ``` 20 | 21 | Install Elm 22 | ```bash 23 | export PATH="$PATH:`yarn global bin`" # Add in order to use Elm commands. 24 | yarn global add elm 25 | ``` 26 | # Elm "Hello World!" 27 | Create the `Main.elm` file. This, along with all the dependecies will transpile into Javascript in step 3. 28 | 29 | ```elm 30 | import Html exposing (text) 31 | 32 | main = 33 | text "Hello, World!" 34 | ``` 35 | Create the `index.html` file, which will load the javascript file created in step 3. 36 | 37 | ```html 38 | 39 | 40 | 41 |
42 | 43 | 46 | 47 | 48 | ``` 49 | 50 | Compile/transpile the elm code into javascript. 51 | ```bash 52 | elm-make Main.elm --output=main.js # Locations are relative. 53 | ``` 54 | 55 | The result from this is the creation of: 56 | - `elm-stuff` - Holds the dependecies, like `node_modules`. 57 | - `elm-package.json` - Lists the dependecies, like `package.json`. 58 | - `main.js` - The transpiled elm code, to be used in `index.html`. 59 | 60 | # Build/Compile 61 | `elm-make Main.elm --output=../public/main.js` - Build 62 | 63 | # App Build Order 64 | 65 | 1. Connect modules / Navigation 66 | 2. Login 67 | 3. Saving Token 68 | 4. Logout 69 | 5. Lock/Control Access to Pages 70 | 6. Individual Pages (Modules) 71 | 72 | # The Elm Architecture 73 | 74 | ![TEA](../pics/elm/TEA.png) 75 | 76 | There are 3 main wiring parts between modules. They happen in the `Model`, `Update` and `View`. 77 | 78 | ![TEA](../pics/elm/elm_arch.png) 79 | 80 | # ChildModule.elm 81 | 82 | ```elm 83 | module ChildModule exposing(..) 84 | ``` 85 | 86 | **Note:** In order to import a module in `Main`, the source folder (where all the modules are) needs to be added in the `elm-package.json` file under `source-directories` like so: 87 | 88 | ```json 89 | "source-directories": [ 90 | ".", 91 | "src" 92 | ] 93 | ``` 94 | 95 | # Main.elm 96 | 97 | ## 1. Model 98 | 99 | The `Main` module doesn't need to know the details of `ChildModule`'s model. It just needs to know that the `ChildModule` has a model, which is exposed and can be referenced by using `ChildModule.Model`. The initial value can be referenced as well with `ChildModule.initModel`. 100 | 101 | So we just need to create a `childModule` field of type `ChildModule.Model`. 102 | 103 | ```elm 104 | import ChildModule 105 | 106 | type alias Model = 107 | { page : Page, 108 | , childModule : ChildModule.Model 109 | } 110 | 111 | initModel : Model 112 | initModel = 113 | { page = ChildModulePage 114 | , childModule = ChildModule.initModel 115 | } 116 | ``` 117 | 118 | ## 2. Update 119 | 120 | When the message is of type `ChildModuleMsg` i.e. originating from an outside module, we pull out the included message and put it into the identifier `cmMsg`. 121 | 122 | The `Main` module doesn't know how to handle this message directly, but the `ChildModule`'s **update function** does (for any message in that module), so we just call it to deal with the `ChildModule`'s **model**. 123 | 124 | To do this, we update the model by setting the `childModule` field to the value returned by calling the `ChildModule`'s **update function** and passing it the two parameters, the **message** `cmMsg` and the **current model** for the child module `model.childModule` 125 | 126 | ```elm 127 | type Msg 128 | = ChangePage Page 129 | | ChildModuleMsg ChildModule.messages 130 | 131 | update : Msg -> Model -> Model 132 | update msg model = 133 | case msg of 134 | ChangePage page -> 135 | { model | page = page } 136 | 137 | ChildModuleMsg cmMsg -> 138 | { model | childModule = ChildModule.update cmMsg model.childModule } 139 | ``` 140 | ## 3. View 141 | 142 | This is a **GOTCHA** part due to the different `Html Msg` types. We need to transform the html capable of generating `ChildModule` messages into `Html` capable of generating `Main` messages by using `map`. 143 | 144 | The first parameter for the `map` function is a transformation function, which is the `ChildModuleMsg`'s type constructor that acts as a function. 145 | 146 | The second parameter is the `ChildModule`'s view function with the **current model** as an argument, hence the tuple. 147 | 148 | **In other words, we are transforming any message coming from the child view, into main messages by using map.** 149 | 150 | ```elm 151 | view : Model -> Html Msg 152 | view model = 153 | let 154 | page = 155 | case model.page of 156 | ChildModulePage -> 157 | Html.map ChildModuleMsg (ChildModule.view model.childModule) 158 | in 159 | div [] [ page ] 160 | 161 | ``` 162 | 163 | # Coonection and Navigation 164 | 165 | After creating a `ChildModule`, exposing it and adding it to `elm-package.json`'s `source-directories`, we need to connect the module and navigate between them. 166 | 167 | The connection is explained in **The Elm Architecture** above. 168 | 169 | To use the navigation, we need to install the package with `elm-package install elm-lang/navigation` along with th dependencies and import the package with `include Navigation`. 170 | 171 | After that, in the `main` function, we change the `Html.program` function call into `Navigation.program location`. 172 | 173 | ```elm 174 | main : Program Never Model Msg 175 | main = 176 | -- Html.program 177 | Navigation.program locationToMsg 178 | { init = init 179 | , update = update 180 | , view = view 181 | , subscriptions = subscriptions 182 | } 183 | ``` 184 | 185 | `Navigation.program` takes a function as a parameter, which takes a location as a parameter. 186 | 187 | The `locationToMsg` is called every time the URL changes. The function takes a `Navigation.Location` and returns a `Msg`. 188 | 189 | This function needs to: 190 | 1. Transform the URL hash into a `Page`. 191 | 2. Return the page as part of a `Msg`. 192 | 3. The message is fed back into the `update` function. 193 | -------------------------------------------------------------------------------- /topics/dom.md: -------------------------------------------------------------------------------- 1 | Instead of using JQuery for simple DOM manipulation, we can use Vanilla JS to achieve the same. JQuery is simply an abstraction library. 2 | 3 | # Select 4 | ```javascript 5 | // By ID 6 | document.getElementById('id'); 7 | 8 | // By class 9 | document.getElementsByClassName('class-name'); // Returns an array 10 | 11 | // By tag 12 | document.getElementsByTagName('li'); // Returns an array 13 | ``` 14 | 15 | ### Query Selector 16 | Can select any element with the same command, but it grabs **only the first one**. This is pretty much JQuery if we replace `document.querySelector` with `$`. 17 | 18 | ```javascript 19 | document.querySelector('#id'); // ID 20 | document.querySelector('.class-name'); // Class 21 | document.querySelector('li'); // Tag 22 | 23 | // Select specific element by Class 24 | document.querySelector('.class-name:nth-child(2)'); // Just the 2nd one. 25 | 26 | // Select all elements 27 | document.querySelectorAll('.class-name'); 28 | 29 | // Select all elements by Class 30 | document.querySelectorAll('.class-name:nth-child(odd)'); // Every other one. Returns array. 31 | 32 | // Examples 33 | document.querySelector("header .container"); 34 | document.querySelector("header h1"); 35 | ``` 36 | ### Display 37 | ```javascript 38 | // Show the class. 39 | element.className; 40 | 41 | // Return an array of classes. The array can be modified with .add or .remove 42 | element.classList; 43 | ``` 44 | 45 | ### Parent/Child 46 | ```javascript 47 | var element = document.getElementById('id'); 48 | 49 | // Parent 50 | element.parentNode // Selects the parent element. 51 | element.parentNode.parentNode // Ad infinitum 52 | 53 | // Child 54 | element.children // Returns an array. 55 | element.firstElementChild 56 | element.lastElementChild 57 | 58 | // Bad child. These include blank elements in the returned array. 59 | element.childNode 60 | element.firstChild 61 | element.lastChild 62 | 63 | // Sibling 64 | element.nextElementSibling // Not nextSibling. 65 | element.previousElementSibling // Not previousSibling. 66 | ``` 67 | 68 | # Change 69 | ```javascript 70 | var element = document.getElementById('id'); 71 | 72 | // Text 73 | element.textContent = "New text"; 74 | element.innerText = "New text"; 75 | 76 | // HTML 77 | element.innerHtml = "
Text
"; 78 | 79 | // CSS 80 | element.style.borderBottom = "solid 1px red"; 81 | ``` 82 | 83 | ### Common Elements 84 | `document` - Whole DOM. 85 | `document.domain` - The domain name. 86 | `document.URL` - The URL. 87 | `document.title` - The title. 88 | `document.doctype` - The document type. 89 | `document.head` - The head object. 90 | `document.body` - The body object. 91 | `document.forms` - Array of all forms. 92 | `document.links` - Array of all links. 93 | `document.images` - Array of all images. 94 | 95 | # Create / Remove 96 | ```javascript 97 | // Element 98 | var element = document.createElement("div"); 99 | 100 | // Class 101 | element.className = "class-name"; 102 | 103 | // classList 104 | element.classList.add("class-name"); 105 | element.classList.remove("class-name"); 106 | 107 | // ID 108 | element.id = "id"; 109 | 110 | // Attribute 111 | element.setAttribute("title", "Hello World!"); 112 | 113 | // Text Node 114 | var text = document.createTextNode("Hello World!"); 115 | 116 | // Add text to div 117 | element.appendChild(text); 118 | 119 | // Remove the child element 120 | element.removeChild(text); 121 | ``` 122 | 123 | # Events 124 | 125 | ### Old way 126 | 127 | ```html 128 | 129 | ``` 130 | ```javascript 131 | function buttonClick(){ 132 | console.log("Button clicked."); 133 | } 134 | ``` 135 | 136 | ### Event Listener 137 | ```html 138 | 139 | ``` 140 | ```javascript 141 | var button = document.getElementById("button"); 142 | 143 | button.addEventListener("click", buttonClick); 144 | 145 | function buttonClick(){ 146 | console.log("Button clicked."); 147 | } 148 | ``` 149 | We can pass in the event and do all kinds of things with it, as it contains information such as the event type, mouse coordinates etc. 150 | ```javascript 151 | function buttonClick(e){ 152 | console.log(e); // Logs the event. 153 | console.log(e.target); // The clicked element. 154 | console.log(e.target.id); // Clicked element id. 155 | console.log(e.target.className); // Clicked element class. 156 | 157 | console.log(e.ctrlkey); // Is control pressed boolean. altkey, shiftkey... 158 | } 159 | ``` 160 | 161 | ### Bulk Event Listeners 162 | ```javascript 163 | document.querySelectorAll('#myTable td') 164 | .forEach(e => e.addEventListener("click", function() { 165 | // Here, `this` refers to the element the event was hooked on 166 | console.log("clicked") 167 | })); 168 | ``` 169 | Thit creates a separate function for each cell; **instead, you could share one function without losing any functionality.** 170 | 171 | ```javascript 172 | function clickHandler() { 173 | // Here, `this` refers to the element the event was hooked on 174 | console.log("clicked") 175 | } 176 | 177 | document.querySelectorAll('#myTable td') 178 | .forEach(e => e.addEventListener("click", clickHandler)); 179 | ``` 180 | 181 | **Example** 182 | ```javascript 183 | var hover = document.querySelectorAll('.hover'); 184 | 185 | // The functions are cointained inside another one to prevent execution on load. 186 | hover.forEach(e => e.addEventListener("mouseover", () => mouseOver(e))); 187 | hover.forEach(e => e.addEventListener("mouseout", () => mouseOut(e))); 188 | 189 | function mouseOver(e) { 190 | e.classList.remove("w3-black"); 191 | e.classList.add("w3-teal"); 192 | } 193 | 194 | function mouseOut(e) { 195 | e.classList.remove("w3-teal"); 196 | e.classList.add("w3-black"); 197 | } 198 | ``` 199 | 200 | ### Mouse 201 | ```javascript 202 | element.addEventListener("click", runEvent); 203 | ``` 204 | 205 | `click`- On click. 206 | `dblclick`- On double click. 207 | `mousedown` - On mouse button press. 208 | `mouseup` - On mouse button release. 209 | `mouseenter` - On hover over the element (parent) itself. 210 | `mouseover` - On hover over the child elements. 211 | `mouseleave` - On blur out of the element (parent) itself. 212 | `mouseout` - On blur out of child elements. 213 | `mousemove` - Any mouse movement. 214 | 215 | ### Input 216 | ```javascript 217 | var itemInput = document.querySelector('input[type="text"]'); 218 | var form = document.querySelector('form'); 219 | var select = document.querySelector('select'); // A selector with options. 220 | 221 | itemInput.addEventListener("keydown", runEvent); // Input events. 222 | select.addEventListener("change", runEvent); // Selector events. "input" works the same. 223 | 224 | function runEvent(e){ 225 | console.log(e.target.value); // Logs out the input value. Or selector value. 226 | } 227 | ``` 228 | `focus` - On input click event. 229 | `blur` - Click outside of input event. 230 | `copy, cut, paste` - Input action events. 231 | `input` - Any interaction with the input. 232 | 233 | ### Submit 234 | Submitting a form registers an event for a split second and it vanishes. In order to prevent that and make it persistent, we need to use the event method `preventDefault()` i.e. it stops the normal form submission to a file. 235 | 236 | ```javascript 237 | form.addEventListener("submit", runEvent); 238 | 239 | function runEvent(e){ 240 | e.preventDefault(); 241 | console.log(e.target.value); // Logs out the input value. Or selector value. 242 | } 243 | ``` 244 | 245 | ### Keyboard 246 | `keydown` - Any keyboard button press and release. 247 | `keyup` - Button release. 248 | `keypress` - Button press. -------------------------------------------------------------------------------- /topics/javascript.md: -------------------------------------------------------------------------------- 1 | # Language 2 | 3 | The complete JavaScript implementation is made up of three distinct parts: 4 | 5 | - The Core (based on ECMAScript spec) 6 | - The Document Object Model (DOM) 7 | - The Browser Object Model (BOM) 8 | 9 | ## ECMAScript 10 | 11 | ECMA-262 describes it like this: 12 | 13 | ``` 14 | ECMAScript can provide core scripting capabilities for a variety of host environments, and therefore the core scripting language is specified... apart from any particular host environment. 15 | ``` 16 | 17 | A Web browser is considered a host environment for ECMAScript, but it is not the only host environment. A list of other host environments listed here. 18 | 19 | Apart from DOM and BOM, each browser has its own implementation of the ECMAScript interface. 20 | 21 | ## Document Object Model (DOM) 22 | 23 | The Document Object Model (DOM) is an application programming interface (API) for HTML as well as XML. 24 | 25 | The DOM maps out an entire page as a document composed of a hierarchy of nodes like a tree structure and using the DOMAPI nodes can be removed, added, and replaced. 26 | 27 | ### DOM level 1 28 | 29 | Consisted of two modules: the DOM Core, which provided a way to map the structure of an XML-based document to allow for easy access to and manipulation of any part of a document, and the DOM HTML, which extended the DOM Core by adding HTML-specific objects and methods. 30 | 31 | ### DOM Level 2 32 | 33 | Introduced several new modules of the DOM to deal with new types of interfaces: 34 | 35 | - DOM Views — describes interfaces to keep track of the various views of a document (that is, the document before CSS styling and the document after CSS styling) 36 | - DOM Events — describes interfaces for events 37 | - DOM Style — describes interfaces to deal with CSS-based styles 38 | - DOM Traversal and Range — describes interfaces to traverse and manipulate a document tree 39 | 40 | ### DOM Level 3 41 | 42 | Further extends the DOM with the introduction of methods to load and save documents in a uniform way (contained in a new module called DOM Load and Save) as well as methods to validate a document (DOM Validation). In Level 3, the DOM Core is extended to support all of XML 1.0, including XML Infoset, XPath, and XML Base. 43 | 44 | Note that the DOM is not JavaScript-specific, and indeed has been implemented in numerous other languages. For Web browsers, however, the DOM has been implemented using ECMAScript and now makes up a large part of the JavaScript language. 45 | 46 | Other DOMs 47 | 48 | - Scalable Vector Graphics (SVG) 49 | - Mathematical Markup Language (MathML) 50 | - Synchronized Multimedia Integration Language (SMIL) 51 | 52 | ## Browser Object Model (BOM) 53 | 54 | Browsers feature a Browser Object Model (BOM) that allows access and manipulation of the browser window. Using the BOM, developers can move the window, change text in the status bar, and perform other actions that do not directly relate to the page content. 55 | 56 | Because no standards exist for the BOM, each browser has its own implementation. 57 | 58 | # Event Loop 59 | 60 | ![TEA](../pics/js_event_loop.png) 61 | 62 | Based on [Philip Roberts' talk](https://www.youtube.com/watch?v=8aGhZQkoFbQ). 63 | 64 | The Javascript runtime only knows of the `heap` and `call stack`. 65 | 66 | The rest of the functionality, like async stuff, is provided in the form of `WebAPIs` by the browser/Node. 67 | 68 | For async operations, the `callback` is offloaded into a separate `queue`, which is emptied by the `event loop` one by one as soon as the `stack` becomes empty. 69 | 70 | Without the `event loop` the stack would be blocked during the whole duration of the async operaiton, basically freezing the app. 71 | 72 | # Hoisting 73 | 74 | Both variable and function declarations are hoisted to the top on code execution, meaning that their order is irrelevant i.e functions can be called before they are declared. 75 | 76 | # Variables 77 | 78 | ```javascript 79 | var a; // Regular. 80 | let c; // Block scoped. 81 | const b; // Immutable. 82 | ``` 83 | 84 | # Functions 85 | 86 | Functions are first class objects - a function is a regular object of type `function`. The function object type has a constructor: `Function`. 87 | 88 | There are several ways to declare a function. 89 | 90 | The difference is how the function interacts with the external components (the outer scope, the enclosing context, object that owns the method, etc) and the invocation type (regular function invocation, method invocation, constructor call, etc). 91 | 92 | ## Function declaration 93 | 94 | **Hoisted**. Available immediately after parsing, before any code is executed. 95 | 96 | The function declaration creates a variable in the current scope with the identifier equal to function name. This variable holds the function object. 97 | 98 | ```javascript 99 | function foo() {} 100 | foo(); 101 | ``` 102 | 103 | Use them when a function expression is not appropriate or when it is important that that a function is hoisted. 104 | 105 | ## Function expression 106 | 107 | **Not hoisted.** Available only after the variable assignment is executed. 108 | 109 | ```javascript 110 | // Named 111 | let bar = function foo() {}; 112 | bar(); 113 | foo(); // undefined 114 | ``` 115 | 116 | Use them when you are doing recursion or want to see the function name in the debugger. 117 | 118 | ```javascript 119 | // Anonymous 120 | let foo = function() {}; 121 | foo(); 122 | 123 | let bar = foo(); 124 | bar(); // Error: not a function. 125 | ``` 126 | 127 | Use them when you want to pass a function as an argument to another function or you want to form a closure. 128 | 129 | ## IIFE - immediately Invoked Function Expression 130 | 131 | ```javascript 132 | (function() { 133 | // ... 134 | })(); 135 | ``` 136 | 137 | Use them for the module pattern. 138 | 139 | ## ES6 140 | 141 | Binds `this` automatically. 142 | 143 | ```javascript 144 | let foo = () => {}; 145 | ``` 146 | 147 | Use them when you want to lexically bind the `this` value. 148 | 149 | ## Function constructor (Avoid this) 150 | 151 | ```javascript 152 | let foo = new Function(); 153 | ``` 154 | 155 | ## Other 156 | 157 | - Use function declaration generators `function* foo(){}` when you want to exit and then re-enter a function. 158 | - Use function expression generators `let foo = function* [name](){}` when you want to exit and then re-enter a nested function. 159 | 160 | ## Function parameters vs arguments 161 | 162 | An argument is the value supplied to the parameter. 163 | 164 | ```javascript 165 | function foo(bar) { 166 | // bar is a parameter 167 | console.log(bar); 168 | } 169 | 170 | foo("baz"); // baz is an argument. 171 | ``` 172 | 173 | # Useful 174 | 175 | ## Truthy / Falsy 176 | 177 | Strings with at least one letter and numbers larger than zero are `truthy`. 178 | 179 | ```javascript 180 | console.log(true && "foo"); // foo 181 | console.log(true && "foo" && 1); // 1 182 | ``` 183 | 184 | # Debugging 185 | 186 | ```javascript 187 | // Write to console 188 | console.log(); 189 | 190 | // Show DOM element 191 | console.dir(); 192 | 193 | // Display the call stack of a function 194 | console.trace(); 195 | 196 | // Track execution time 197 | console.time("point"); // undefined 198 | console.timeEnd("point"); // point: 1337.42 ms 199 | 200 | // Count the number of executions 201 | console.count("foo"); // foo: 1 202 | console.count("foo"); // foo: 2 203 | console.countReset("foo"); // undefined 204 | console.count("foo"); // foo: 1 205 | 206 | // Avoid if-else statements 207 | function greaterThan(a, b) { 208 | console.assert(a > b, { message: "a is not greater than b", a: a, b: b }); 209 | } 210 | greaterThan(2, 1); // a is not greater than b, a: 2, b: 1 211 | 212 | // Heap size 213 | console.memory; 214 | 215 | // Display a table. Takes an array of objects. 216 | console.table(array); 217 | ``` 218 | -------------------------------------------------------------------------------- /topics/mobile.md: -------------------------------------------------------------------------------- 1 | # Mobile development 2 | 3 | ## Native 4 | 5 | No compilation needed, as the app is written in the native language. 6 | 7 | - Java (Android) 77% share 8 | - Swift (iPhone) 19% share 9 | 10 | ## Hybrid 11 | 12 | Like Electron, but for mobile devices. 13 | 14 | - PhoneGap - Same as Cordova, vanilla JS, paid version. 15 | - Cordova - Same as PhoneGap, vanilla JS, open source. 16 | - Ionic - Angular UI library on top of Cordova that gives a native look. 17 | 18 | ## Compiled 19 | 20 | **Only** the UI components are compiled to their native equivalents. The rest runs in the language runtime. 21 | 22 | - React Native (Javascript) Have to build your own components. 23 | - Native Script (Javascript) Less popular 24 | - Flutter (Dart) 25 | 26 | # Android 27 | 28 | ## Setup Overview 29 | 30 | - JDK 31 | - SDK 32 | - Packages 33 | - Environment Variables 34 | - NodeJS 35 | - Cordova 36 | 37 | ## API Level 38 | 39 | The Android platform provides a framework API that applications can use to interact with the underlying Android system. Updates to the framework API are designed so that the new API remains compatible with earlier versions of the API. 40 | 41 | | Codename | Version | API | Distribution | 42 | | ----------- | ------- | --- | ------------ | 43 | | Oreo | 8.0.0 | 26 | 11% | 44 | | Nougat | 7.0.0 | 24 | 20% | 45 | | Marshmallow | 6.0.0 | 23 | 22% | 46 | 47 | ### Java Development Kit (JDK) 48 | 49 | The JDK (Java Development Kit) contains the JRE (Java Runtime Environment). 50 | 51 | Open JDK = open-source variant of the JRE and JDK. 52 | 53 | Java version 1.8.0_5 = JDK 8 update 5 54 | 55 | ```bash 56 | sudo apt update 57 | sudo apt install openjdk-8-jdk 58 | 59 | java -version # java version "1.8.0_181" 60 | 61 | # Add this line to ~/.profile 62 | export JAVA_HOME="/usr/lib/jvm/java-1.8.0-openjdk-amd64" 63 | 64 | export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 65 | export PATH=$PATH:/usr/lib/jvm/java-8-openjdk-amd64/bin 66 | 67 | # Reload configuration 68 | source ~/.profile 69 | ``` 70 | 71 | ## Gradle 72 | 73 | As of Cordova-Android 6.4.0, Gradle is now required to be installed to build Android. Gradle requires Java Development Kit (JDK) 7 or higher in order to work. 74 | 75 | ```bash 76 | wget https://services.gradle.org/distributions/gradle-4.9-bin.zip 77 | sudo unzip -d /opt/gradle gradle-4.9-bin.zip 78 | ``` 79 | 80 | ## Android SDK 81 | 82 | By default, the Android SDK does not include everything you need to start developing. 83 | 84 | The Android SDK can be broken down into several components. These include: 85 | 86 | - SDK-tools 87 | - Platform-tools 88 | - Build-tools 89 | - The Android Debug Bridge (ADB) 90 | - Android Emulator 91 | 92 | Arguably the most important parts of this package are in the SDK-tools. You will need these tools regardless of which version of Android you are targeting. 93 | 94 | These are what will actually compile your code along with any data and resource files into an APK, an Android package, which is an archive file with an `.apk` suffix. 95 | 96 | One APK file contains all the contents of an Android app and is the file that Android-powered devices use to install the app. 97 | 98 | **From the SDK you really only need sdk-tools, platform-tools, build-tools and the latest API.** 99 | 100 | ```bash 101 | sudo apt-get install android-sdk 102 | ``` 103 | 104 | ```bash 105 | wget https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip 106 | sudo unzip -d /home sdk-tools-linux-4333796.zip 107 | 108 | # Add this line to ~/.profile 109 | export PATH=/opt/pradip/tools:/opt/pradip/tools/bin:$PATH 110 | 111 | # Reload configuration 112 | source ~/.profile 113 | ``` 114 | 115 | After installing the Android SDK, you must also install the packages for whatever API level you wish to target. It is recommended that you install the highest SDK version that your version of cordova-android supports. 116 | 117 | ```bash 118 | sdkmanager --list 119 | ``` 120 | 121 | Android Platform SDK for your targeted version of Android 122 | Android SDK build-tools version 19.1.0 or higher 123 | Android Support Repository (found under "Extras") 124 | 125 | ## Environment Variables 126 | 127 | We need to configure and export the environment variables so that the executables can be run directly from anywhere. Add them to `~/.bashrc` to make them permanent. 128 | 129 | ```bash 130 | sudo vim ~/.profile 131 | ``` 132 | 133 | add following code to the end of the file... 134 | 135 | ```bash 136 | # Gradle 137 | PATH=$PATH:/opt/gradle/gradle-4.9/bin 138 | 139 | # Android SDK 140 | ANDROID_HOME="/usr/lib/android-sdk/" 141 | PATH="${PATH}:${ANDROID_HOME}tools/:${ANDROID_HOME}platform-tools/" 142 | ``` 143 | 144 | save, exit and run source to relad the configuration. 145 | 146 | ```bash 147 | source ~/.profile 148 | ``` 149 | 150 | ## SDK Manager 151 | 152 | https://www.androidauthority.com/android-sdk-tutorial-beginners-634376/ 153 | https://www.androidauthority.com/how-to-install-android-sdk-software-development-kit-21137/ 154 | 155 | ## Android Virtual Device Manager (AVD) 156 | 157 | Create a virtual device where you set the desired device with the system image downloaded via the SDK manager, as well as the target API. 158 | 159 | ## Build Process 160 | 161 | https://developer.android.com/studio/build 162 | 163 | # Apache Cordova 164 | 165 | Mobile apps can be created with HTML, CSS and Javascript. 166 | 167 | The mobile app is a website running in a webview, like Electron for desktop. A webview is a wrapper i.e. a shell browser, without the menus, tabs etc. 168 | 169 | The native device features can be accessed through the wrapper, not directly. Also, The UI components automatically adjust to the platform. 170 | 171 | ## History 172 | 173 | - PhoneGap was previously a product of Adobe. 174 | - To keep it open-source always and follow standards, PhoneGap codebase was handed over to Apache. 175 | - At Apache, it got a name change as Cordova. 176 | - And now it’s better known as Apache Cordova. 177 | - Ionic sits on top of Cordova as a UI library with Angular, to give the web app a native feel. 178 | 179 | PhoneGap is paid. 180 | Cordova is open source. 181 | The codebase is the same. 182 | 183 | If you use phonegap/Cordova you are using plain JavaScript (and can therefore choose to add any framework, including Angular, to that) whereas if you're using ionic then you're an AngularJs developer. 184 | 185 | ## Install 186 | 187 | To run Cordova, node is required. NPM is used for intalling Cordova, along with the plarforms and plugins. 188 | 189 | ```bash 190 | sudo npm i cordova -g 191 | ``` 192 | 193 | When the app is compiled, the target platform SDK is required. 194 | 195 | - Adroid Stuido for Android SDK. 196 | - Xcode for iPhone SDK. 197 | 198 | ## Create app 199 | 200 | ```bash 201 | #cordova folder_name package_name app_name 202 | cordova create myApp com.domain.app AppName 203 | ``` 204 | 205 | This will create the following: 206 | 207 | - `config.xml` - Old configuration (Don't use) 208 | - `hooks` - Special build tools go here. 209 | - `package.json` - Configuration 210 | - `platforms` - SKDs are stored here. 211 | - `plugins` - Like node_modules 212 | - `res` - Additional resources, like icons. 213 | - `www` - The web app lives here. 214 | - css 215 | - img 216 | - js 217 | - index.html 218 | 219 | The phone doesn't call the apps by name. It uses a special internal name to reference them. 220 | 221 | Reverse domain name notation is used as the naming convention for the packages. They are based on registered domain names, and are only reversed for sorting purposes. 222 | 223 | For example, if a company making a product called `MyProduct` has the registered domain name `example.com`, they could use the reverse-DNS string `com.example.MyProduct` to describe it. 224 | 225 | Reverse-DNS names are a simple way of reducing name-space collisions, since any domain name is registered by only one party at a time. 226 | 227 | ## Add platform 228 | 229 | ```bash 230 | cordova platform add android 231 | ``` 232 | 233 | ## Emulate app 234 | 235 | This will load the app inside the emulator. You first need to create it with a system image for the target platform with AVD. 236 | 237 | ```bash 238 | cordova emulate android 239 | ``` 240 | 241 | ## Build app 242 | 243 | This will build the app i.e. `.apk` file, which can be installed on an android device. 244 | 245 | ```bash 246 | cordova build android 247 | ``` 248 | -------------------------------------------------------------------------------- /topics/mysql.md: -------------------------------------------------------------------------------- 1 | # Best practices 2 | 3 | ### Naming Convention 4 | 5 | - **Singular form**. Both tables and columns. 6 | - Be consistent! Doesn't matter if you use camelCase or snake_case. Use whatever the front-end uses. 7 | - Avoid abbreviations or prefixes. 8 | 9 | ### Performance 10 | 11 | - Try to stick to `where` clauses on indexed columns, instead of `like`. 12 | - Don't go crazy with `joins`. 13 | - Don't use varchar(255). Try to use the lowest number possible. 14 | 15 | # Install MySQL 16 | 17 | ```bash 18 | sudo apt-get install mysql-server 19 | 20 | sudo mysql_secure_installation 21 | # Change root password to more secure. 22 | # Remove anonymous users. 23 | # Disable remote root login. Root should only connect via `localhost`. 24 | # Remove test database and access to it. 25 | # Reload privilege tables. 26 | 27 | systemctl restart mysql 28 | # sudo service mysql start 29 | ``` 30 | 31 | # Command line 32 | 33 | [Digital Ocean tutorial](https://www.digitalocean.com/community/tutorials/a-basic-mysql-tutorial) 34 | Commands are **not** case sensitive, but table names are. **All commands must end with** `;`. 35 | 36 | `sudo mysql -u root -p` - Log into MySQL as root, with password. 37 | `;` - Execute/End current command. 38 | `ENTER` - Starts a new line. `;` is expected. 39 | 40 | # Users 41 | 42 | ```bash 43 | # Log in as new user, with password. 44 | sudo mysql -u user -p 45 | ``` 46 | 47 | ```sql 48 | -- Create user 49 | CREATE USER 'user'@'localhost' IDENTIFIED BY 'password'; 50 | 51 | -- Give access to certain areas. In this case, it's for everything as *.* stands for dbName.tableName i.e. all of them. 52 | GRANT ALL PRIVILEGES ON * . * TO 'user'@'localhost'; 53 | 54 | -- Reload the privileges. 55 | FLUSH PRIVILEGES; 56 | 57 | -- List all users. 58 | SELECT USER(); 59 | 60 | -- Show current user. 61 | SELECT CURRENT_USER(); 62 | 63 | -- Delete user. 64 | DROP USER 'user'@'localhost'; 65 | ``` 66 | 67 | ## Permissions 68 | 69 | **Options:** ALL PRIVILEGES, CREATE, DROP, DELETE, INSERT, SELECT, UPDATE, GRANT OPTION (User can give permissions). 70 | 71 | ```sql 72 | -- Give a specific permission, for a specific table. 73 | GRANT permission ON dbName.tableName TO ''@'localhost'; 74 | 75 | -- Remove a permission. 76 | REVOKE permission ON dbName.tableName FROM ''@'localhost'; 77 | ``` 78 | 79 | ## Change password 80 | 81 | ```sql 82 | ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass'; 83 | FLUSH PRIVILEGES; 84 | ``` 85 | 86 | # Database 87 | 88 | ```sql 89 | SHOW DATABASES; -- List databases. 90 | SELECT database(); -- Show current database. 91 | USE dbName; -- Select a database. 92 | 93 | CREATE DATABASE dbName; -- Create a database. 94 | DROP DATABASE dbName; -- Delete a database. 95 | ``` 96 | 97 | ## Tables 98 | 99 | ### Create 100 | 101 | ```sql 102 | SHOW TABLES; -- List all tables. 103 | DESCRIBE tableName; -- Display columns and types. 104 | 105 | -- Shows the query that creates the table. 106 | SHOW CREATE TABLE tableName; 107 | 108 | -- Create a table. 109 | CREATE TABLE tableName (column1 DATATYPE, column2 DATATYPE); 110 | 111 | -- Example 112 | CREATE TABLE user ( 113 | id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Important 114 | name VARCHAR(255), 115 | pass VARCHAR(255) 116 | ); 117 | ``` 118 | 119 | ### Modify 120 | 121 | ```sql 122 | -- Rename a table. 123 | RENAME TABLE tableName1 TO tableName2; 124 | 125 | -- Add a column at end. 126 | ALTER TABLE tableName ADD columnName DATATYPE; 127 | 128 | -- Add a column at certain location. 129 | ALTER TABLE tableName ADD columnName DATATYPE AFTER columnName; 130 | 131 | -- Delete a column. 132 | ALTER TABLE tableName DROP columnName; 133 | 134 | -- Change a column name. Has to be backticks. 135 | ALTER TABLE tableName CHANGE `oldcolname` `newcolname` datatype(length); 136 | 137 | -- Reset AUTO_INCREMENT id. For this to work, the table must be empty. 138 | ALTER TABLE table AUTO_INCREMENT = 1; 139 | ``` 140 | 141 | ### Delete 142 | 143 | Be **VERY** careful with this one. **ALWAYS** select first, delete second. 144 | 145 | ```sql 146 | DROP TABLE tableName; 147 | ``` 148 | 149 | ## Foreign Keys 150 | 151 | They are used for **data integrity** i.e. they prevent entering values that don't exist in the linked table (gives an error). 152 | 153 | A FOREIGN KEY is a field in one table that refers to the PRIMARY KEY in another table. 154 | 155 | The table containing the foreign key is called the child table, and the table containing the candidate key is called the referenced or parent table. 156 | 157 | ```sql 158 | -- Add foreign key. 159 | ALTER TABLE table1 ADD FOREIGN KEY (idColumn) REFERENCES table2(idColumn); 160 | 161 | -- Remove foreign key. 162 | ALTER TABLE tableName DROP FOREIGN KEY FK_columnName; 163 | 164 | -- Foreign key definition during table creation. 165 | SHOW CREATE TABLE tableName; 166 | 167 | -- List foreign keys. 168 | SELECT 169 | tableName, 170 | COLUMNNAME, 171 | CONSTRAINT_NAME, 172 | REFERENCED_tableName, 173 | REFERENCED_COLUMNNAME 174 | FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 175 | WHERE 176 | REFERENCED_tableName = 'my_table'; 177 | 178 | -- One-liner. 179 | SELECT tableName, COLUMNNAME, CONSTRAINT_NAME, REFERENCED_tableName, REFERENCED_COLUMNNAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_tableName = 'my_table'; 180 | ``` 181 | 182 | ## Records 183 | 184 | ```sql 185 | -- Get records. 186 | SELECT * FROM tableName; 187 | 188 | -- Add record. 189 | INSERT INTO tableName (column1, column2) VALUES (value1, value2); 190 | 191 | -- Example 192 | INSERT INTO user ('id', 'name', 'pass') 193 | VALUES (NULL, 'john', 'abc123'); 194 | 195 | -- Modify record. 196 | UPDATE tableName SET columnName = 'value' WHERE criteria; 197 | 198 | -- Example 199 | UPDATE user SET name = 'Mike' WHERE id = 1; 200 | 201 | -- Delete record. 202 | DELETE FROM tableName WHERE columnName = ; 203 | ``` 204 | 205 | ### INSERT ON DUPLICATE KEY UPDATE 206 | 207 | Insert if `id` doesn't exit. Else, update the data at said `id`. 208 | 209 | ```sql 210 | +----+--------------+ 211 | | id | columnName | 212 | +----+--------------+ 213 | | 1 | foo | 214 | | 2 | bar | 215 | | 3 | baz | 216 | +----+--------------+ 217 | 218 | INSERT INTO table (id, columnName) 219 | VALUES 220 | (1, 'qux'), 221 | (null, 'hex') 222 | ON DUPLICATE KEY UPDATE 223 | columnName = values(columnName); 224 | 225 | +----+--------------+ 226 | | id | columnName | 227 | +----+--------------+ 228 | | 1 | qux | -- Value updated 229 | | 2 | bar | 230 | | 3 | baz | 231 | | 4 | hex | -- Inserted row 232 | +----+--------------+ 233 | ``` 234 | 235 | # Size 236 | 237 | ```sql 238 | -- Check the size of all the databases 239 | SELECT table_schema AS "Database", 240 | ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS "Size (MB)" 241 | FROM information_schema.TABLES 242 | GROUP BY table_schema; 243 | 244 | -- Check the size of all the tables in a database 245 | SELECT tableName AS "Table", 246 | ROUND(((data_length + index_length) / 1024 / 1024), 2) AS "Size (MB)" 247 | FROM information_schema.TABLES 248 | WHERE table_schema = "database_name" -- Change this one 249 | ORDER BY (data_length + index_length) DESC; 250 | ``` 251 | 252 | # Backup 253 | 254 | To do this, we use the `mysqldump` command which creates a file with the SQL statements necessary to re -create the database. Use `--databases` in order to have `CREATE TABLE IF NOT EXIST` included in the dump. 255 | 256 | ```bash 257 | mysqldump --add-drop-table --databases dbName > backup.sql 258 | 259 | # Simplest command. 260 | mysqldump --databases dbName > backup.sql 261 | 262 | # Multiple databases. 263 | mysqldump --databases db1 db2 > backup.sql 264 | 265 | # Everything. 266 | mysqldump --all-databases > backup.sql 267 | 268 | # Prompt for password. 269 | mysqldump -p --databases dbName > backup.sql 270 | 271 | # Options 272 | 273 | # add a DROP TABLE statement before each CREATE TABLE. 274 | --add-drop-table 275 | 276 | # Only database structure, without contents. 277 | --no-data 278 | ``` 279 | 280 | ## Restore 281 | 282 | If the dump was created without using `--databases`, then the database must be manually created before restoring. Also, the database must be specified with `mysql dbName < backup.sql`. Otherwise, just use: 283 | 284 | ```bash 285 | # Restore a database. 286 | mysql < backup.sql 287 | 288 | # Prompt for password. 289 | mysql -p < backup.sql 290 | 291 | # From a compressed file. 292 | gzip -d < backup.sql.gz | mysql 293 | 294 | # If the database already exists and we want to restore it. 295 | mysql dbName < backup.sql 296 | ``` 297 | 298 | # MySQL Workbench 299 | 300 | ## Creating a Database 301 | 302 | 1. Create a localhost connection as root on port 3306. 303 | 2. Create a model **AND** name it. 304 | 3. Forward Engineer the model in the localhost connection. 305 | 4. Find the created database and populate it. 306 | 307 | ## Terminology 308 | 309 | `Model` holds all the schemas. There can be many modes, and each can have many schemas. 310 | 311 | `Schema` is the overall design of the database which defines the tables, number of columns, foreign keys... This rarely changed, if at all... 312 | 313 | `EER Diagram` is a visual representation of a schema with boxes for tables and lines for table relations. 314 | 315 | `Database` is an instance of a schema. It's also where the data lives. 316 | 317 | A database is created by forward engineering a schema. An existing database is expanded with the new schema objects, but it does not alter the existing ones. 318 | 319 | To overwrite them, the tables need to be dropped first, which is an option during the forward engineering. 320 | 321 | `Meta-data` is data about the database i.e. where the schema is stored. 322 | 323 | # Tuning 324 | 325 | ```bash 326 | sudo apt-get install mysqltuner 327 | ``` 328 | 329 | It's a utility used to find out what could be done in order to optimize MySQL for the hardware and workload. 330 | 331 | It needs a bit of data to work properly, so a period should pass before running it, as it looks for usage patterns. 332 | 333 | To run it, just use `mysqltuner`. 334 | -------------------------------------------------------------------------------- /topics/electronics.md: -------------------------------------------------------------------------------- 1 | # Terminology 2 | 3 | #### Circuit 4 | 5 | Your circuit is the collection of all the connections you’ve made, using wires, resistors, LEDs, buttons, GPIO and other pins, etc. 6 | 7 | It can be closed (like when you press a button, and a signal is able to traverse from one end to the other), or it can be open (a button is not pressed, or there’s some other break in the circuit). 8 | 9 | An open circuit is like a long train of dominos, where you've removed 4 or 5 from the middle. You can try sending a signal from one end, but it's never going to bridge the gap. 10 | 11 | #### Firmware 12 | 13 | A set of programs and routines that are built into the device running them. They are typically essential for the basic operation of the device and are not usually accessible by the user. 14 | 15 | #### Serial 16 | 17 | Data sent over time, most often one single bit after another. All the protocols are serial protocols. 18 | 19 | #### Bus 20 | 21 | A set of wires which transfer data. One wire can carry one bit: a 0 (low voltage) or 1 (high voltage). A bus is just a collection of wires, so a 4-bit bus has four wires and can carry four bits. 22 | 23 | #### Relay 24 | 25 | It's an electronic switch. Instead of manually flipping it, it's done via a 5V signal. It can be open (NO) or closed (NC) by default, so the signal would od the opposite. Ex. Arduino sends a signal to the relay to close the circuit for turning on a lamp. 26 | 27 | #### Abbreviations 28 | 29 | **Baud** - Measure for communication speed over a data channel. Equivalent to bits per second. 30 | 31 | **VIN** - Voltage that is currently supplied to the board. 32 | 33 | **VCC** - Input pin on the board if you want to power it from a pin instead of a port. 34 | 35 | **COM** - Common connection for relay or transistor outputs. When the output is activated, the PLC will energize the relay or transistor, effectively connecting the NO (normally open) pin to the COM (common) pin.. 36 | **NO** - Normally open relay. 37 | **NC** - Normally closed relay. 38 | 39 | #### PWM 40 | 41 | Pulse Width Modulation, or PWM, is a technique for getting analog results with digital means. Digital control is used to create a square wave, a signal switched between on and off. This on-off pattern can simulate voltages in between full on (5 Volts) and off (0 Volts) by changing the portion of the time the signal spends on versus the time that the signal spends off. 42 | 43 | # GPIO - General Purpose Input Output 44 | 45 | Used to interact with the real world. 46 | 47 | Each GPIO pin has two states. You can call them on or off, high or low, 1 or 0, etc. A pin is set "high" when it's outputting 3.3v or reading in 3.3v, and "low" when it's off. 48 | 49 | Output pins are like switches that the Raspberry Pi can turn on or off (like turning on/off a LED light). But it can also send a signal to another device. 50 | 51 | Input pins are like switches that you can turn on or off from the outside world (like a on/off light switch). But it can also be a data from a sensor, or a signal from another device. 52 | 53 | ## Floating 54 | 55 | The pins receive surrounding noise from other electronic devices, which interferes with the regular signals. This is called a **floating pin**. 56 | 57 | This also happens with with other modules such as a switch on a breadboard. 58 | 59 | To prevent this, we need to use a **pull-up resistor** i.e. pull the pin up to a voltage when nothing happens (switch is off) 60 | 61 | Micro-controllers have built-in pull-up resistors. 62 | 63 | ### Pull Down 64 | 65 | When you have a circuit that connects 3.3v to a GPIO pin, it'll read HIGH when the circuit is closed. When it's open, it could read anything. You need a "pull down" resistor connecting your circuit to ground, so that it reads LOW when the circuit is open. (I'll show this in effect later.) 66 | 67 | ### Pull Up 68 | 69 | Similarly, if you have a circuit connecting your GPIO pin to ground when it's closed, it'll read LOW. You need a "pull up" resistor so that, when it's open, it defaults to the HIGH state. 70 | 71 | # Communication Protocols 72 | 73 | **I2C** - Easiest and most expandable bus. Raspberry has two I2C buses, bus 0 and bus 1. Capable of expanding the Rpi to thousands of output ports. Programming is very easy. 74 | 75 | **SPI** - Only 2 chip select lines so max number of devices is very limited. Bus is faster and can be driven over longer cable runs than I2C. Programming more difficult. Device selection very limited unless you are willing to solder SMD. 76 | 77 | **UART (RS-232)** - Welcome to the 1970s. Lever shifters are a must. No intelligence at all. Pretty boring stuff actually. 78 | 79 | ## I2C - Inter-Integrated Circuit 80 | 81 | It's a bus that allows easy communication between components which reside on the same circuit board. 82 | 83 | It's a synchronous protocol, and it's the first we see which has some "intelligence" in it; the other ones dumbly shifted bits in and out, and that was that. 84 | 85 | I2C uses only 2 wires, one for the clock (SCL) and one for the data (SDA). That means that master and slave send data over the same wire, again controlled by the master who creates the clock signal. 86 | 87 | I2C doesn't use separate Slave Selects to select a particular device, but has addressing. The first byte sent by the master holds a 7 bit address (so that you can use 127 devices on the bus) and a read/write bit, indicating whether the next byte(s) will also come from the master or should come from the slave. 88 | 89 | After each byte, the receiver must send a "0" to acknowledge the reception of the byte, which the master latches with a 9th clock pulse. 90 | 91 | If the master wants to write a byte, the same process repeats: the master puts bit after bit on the bus and each time gives a clock pulse to signal that the data is ready to be read. 92 | 93 | If the master wants to receive data it only generates the clock pulses. The slave has to take care that the next bit is ready when the clock pulse is given. 94 | 95 | This protocol is patented by NXP (formerly Phillips), to save licensing cost, Atmel using the word TWI (2-wire interface) which exactly same as I2C, so any AVR device will not have I2C but it will have TWI. 96 | 97 | Two or more signals on the same wire may cause conflicts, and you would have a problem if one device sends a "1" while the other sends a "0". Therefore the bus is wired-OR'd: two resistors pull the bus to a high level, and the devices only send low levels. If they want to send a high level they simply release the bus. 98 | 99 | - SDA - Serial data 100 | - SCL - Serial clock 101 | 102 | ## SPI - Serial Peripheral Interface 103 | 104 | The SPI bus is a serial communication protocol for controlling and communicating with almost any digital electronic device that accepts a clocked serial stream of bits. SPI is typically used for short distance communication and most commonly found in embedded devices. 105 | 106 | A master sends a clock signal, and upon each clock pulse it shifts one bit out to the slave, and one bit in, coming from the slave. Signal names are therefore SCK for clock, MOSI for Master Out Slave In, and MISO for Master In Slave Out. 107 | 108 | By using SS (Slave Select) signals the master can control more than one slave on the bus. There are two ways to connect multiple slave devices to one master, one is mentioned above i.e. using slave select, and other is daisy chaining, it uses fewer hardware pins (select lines), but software gets complicated. 109 | 110 | - MISO - Master Input, Slave Output 111 | - MOSI - Master Output, Slave Input 112 | - SCLK - Serial Clock 113 | - SS - Slave Select 114 | 115 | ## UART - Universal asynchronous receiver-transmitter (Serial) 116 | 117 | A computer microchip used for translation between parallel and serial data. 118 | 119 | The UART functions to convert parallel data from PC bus lines to serial data for transmission via line drivers to RS-232, RS-422, and RS-485 devices. 120 | 121 | UART is responsible for sending and receiving a sequence of bits. At the output of a UART these bits are usually represented by logic level voltages. These bits can become RS-232, RS-422, RS-485, or perhaps some proprietary spec. 122 | 123 | This is, essentially, a serial communications interface. The "universal" part means that it can be configured to support many different specific serial protocols. The term is generic, and does not represent a specific standard. At minimum it means that it has a TX and an RX line, which sends a serial data stream and receives a serial data stream. 124 | 125 | It's one of the most used serial protocols. Most controllers have a hardware UART on board. It uses a single data line for transmitting and one for receiving data. 126 | 127 | Most often 8-bit data is transferred, as follows: 1 start bit (low level), 8 data bits and 1 stop bit (high level). The low level start bit and high level stop bit mean that there's always a high to low transition to start the communication. That's what describes UART. No voltage level, so you can have it at 3.3 V or 5 V, whichever your microcontroller uses. 128 | 129 | Note that the microcontrollers which want to communicate via UART have to agree on the transmission speed, the bit-rate, as they only have the start bits falling edge to synchronize. That's called asynchronous communication. 130 | 131 | - TxD - Transmitter, carries data from DTE to DCE. 132 | - RxD - Receiver, carries data from DCE to DTE. 133 | 134 | **TTL** (Transistor Transistor Logic) is not a protocol. It's an older technology for digital logic, but the name is often used to refer to the 5 V supply voltage, often incorrectly referring to what should be called UART. 135 | 136 | ### RS-232 137 | 138 | A standard defining the signals (serial communication transmission of data) between two devices, defining the signal names, their purpose, voltage levels, connectors and pinouts. 139 | 140 | - DTE (data terminal equipment) ex. computer terminal. 141 | - DCE (data communication equipment) ex. modem. 142 | 143 | # Breadboard 144 | 145 | Red - Power 146 | Blue - Ground 147 | Green - Tie-points (Do not cross the trench) 148 | Trench - Middle 149 | 150 | ![TEA](../pics/breadboard.png) 151 | 152 | # Components 153 | 154 | #### Resistor 155 | 156 | #### Capacitor 157 | 158 | #### Diode 159 | 160 | #### Transistor 161 | -------------------------------------------------------------------------------- /topics/es6.md: -------------------------------------------------------------------------------- 1 | # Let / Const 2 | 3 | These are a replacement for `var`. 4 | `let` has block scoping and `const` is immutable. 5 | 6 | ### var 7 | 8 | ```javascript 9 | function testVar() { 10 | var a = 30; 11 | if (true) { 12 | var a = 50; 13 | console.log(a); 14 | } 15 | console.log(a); 16 | } 17 | testVar(); // 50 50 18 | 19 | for (var i = 0; i < 5; i++) { 20 | console.log(i); // 1, 2, 3, 4 21 | } 22 | console.log(i); // 5 23 | ``` 24 | 25 | ### let 26 | 27 | ```javascript 28 | function testLet() { 29 | let a = 30; 30 | if (true) { 31 | let a = 50; 32 | console.log(a); 33 | } 34 | console.log(a); 35 | } 36 | testLet(); // 50 30 37 | 38 | for (let i = 0; i < 5; i++) { 39 | console.log(i); // 1, 2, 3, 4 40 | } 41 | console.log(i); // undefined 42 | ``` 43 | 44 | ### const 45 | 46 | It is not completely immutable. It only prevents the reassignment of a value to a constant, but it doesn't care about modifying the object. 47 | 48 | ```javascript 49 | const pi = 3.14; 50 | pi = 42; // TypeError: Assignment to constant variable. 51 | 52 | const person = { 53 | name: "John" 54 | }; 55 | person.name = "Mike"; 56 | console.log(person.name); // Mike. Doesn't prevent mutation. 57 | ``` 58 | 59 | # Classes 60 | 61 | ```javascript 62 | class User { 63 | // Called during instantiation. 64 | constructor(username, email, password) { 65 | (this.username = username), 66 | (this.email = email), 67 | (this.password = passwrod); 68 | } 69 | 70 | // Callable without instantiation. 71 | static countUser() { 72 | console.log("There are 50 users"); 73 | } 74 | 75 | // Regular method. 76 | register() { 77 | console.log(this.username + " is registered."); 78 | } 79 | } 80 | 81 | // Instantiation. 82 | let bob = new User("Bob", "bob@email.com", "1234"); 83 | bob.register(); // Bob is registered. 84 | 85 | User.countUser(); // There are 50 users. 86 | ``` 87 | 88 | # Inheritance 89 | 90 | ```javascript 91 | class Member extends User { 92 | constructor(username, email, password, memberPackage) { 93 | super(username, email, password); // Avoids doing this.username = username... 94 | this.package = memberPackage; // Needs to be assigned since not in parent class. 95 | } 96 | 97 | getPackage() { 98 | console.log(this.username + " uses the " + this.package + " package."); 99 | } 100 | } 101 | 102 | let mike = new Member("Mike", "mike@email.com", "1234", "standard"); 103 | mike.getPackage(); // Mike uses the standard package. 104 | mike.register(); // Mike is registered. 105 | ``` 106 | 107 | # Template Literals 108 | 109 | Backticks allow multiline strings. Also, we can inject variables and functions with `${ var }`. 110 | 111 | ### Before 112 | 113 | ```javascript 114 | var name = "John"; 115 | var template = 116 | "

Hello, " + name + "

" + "

This is a simple template.

"; 117 | ``` 118 | 119 | ### After 120 | 121 | ```javascript 122 | let name = "John"; 123 | let template = `

Hello, ${name}

124 |

This is a simple template.

`; 125 | ``` 126 | 127 | # Strings 128 | 129 | ```javascript 130 | let string = "Hello, I love Javascript."; 131 | 132 | string.startsWith("Hello"); // true 133 | string.endsWith("Javascript"); // false, since there is no dot. 134 | string.includes("love"); // true 135 | ``` 136 | 137 | # Numbers 138 | 139 | ```javascript 140 | Number.isNaN("cat"); // true 141 | Number.isInteger(1); // true 142 | ``` 143 | 144 | # Set 145 | 146 | This is a collection of unique values. If we pass in an array with duplicates, we will get a collection (**object**) with unique values back. A `weakSet` is a collection of **unique objects** only. 147 | 148 | ```javascript 149 | var array = [1, 2, 3, 3]; 150 | 151 | var set = new Set(array); // {1, 2, 3} 152 | 153 | // Set methods 154 | set.size; // 3 155 | set.add("cat"); // [1, 2, 3, "cat"] 156 | set.delete(2); // [1, 3, "cat"] 157 | 158 | // Convert to array 159 | var array = Array.from(set); // [1, 2, 3] 160 | var array2 = [...set]; // [1, 2, 3] 161 | ``` 162 | 163 | # Arrow Functions 164 | 165 | ```javascript 166 | function hello(name) { 167 | return "Hello" + name; 168 | } 169 | console.log(hello("Jack")); // Hello Jack 170 | 171 | // As long as no curly braces are used after the fat arrow, the return is implicit. 172 | var hello = name => "Hello " + name; 173 | console.log(hello("Jack")); // Hello Jack 174 | ``` 175 | 176 | **They don't rebind this, they inherit it.** 177 | 178 | It provides a shorter syntax, and more importantly, it binds `this` lexically, avoiding the usage of `that` or `self`. `Arguments` and `this` inside arrow functions reference their outer function. 179 | 180 | Until arrow functions, every new function defined its own `this` value. An arrow function **does not** have its own `this`; the `this` value of the enclosing execution context is used. 181 | 182 | ```javascript 183 | const obj = { 184 | data: "John", 185 | getData() { 186 | console.log(this.data); 187 | }, 188 | getData2: () => { 189 | console.log(this.data); 190 | } 191 | }; 192 | 193 | obj.getData(); // John 194 | obj.getData2(); // undefined 195 | ``` 196 | 197 | By not having a `this`, they are best suited for non-method functions. Using them as methods results in `undefined`. 198 | 199 | ```javascript 200 | // Old 201 | function Person() { 202 | var that = this; 203 | that.age = 0; 204 | 205 | setInterval(function growUp() { 206 | that.age++; // this.age would refer to growUp, instead of Person. 207 | }, 1000); 208 | } 209 | 210 | // New 211 | function Person() { 212 | this.age = 0; 213 | 214 | setInterval(() => { 215 | this.age++; // this refers to the Person object. 216 | }, 1000); 217 | } 218 | ``` 219 | 220 | # For loop 221 | 222 | ```javascript 223 | let items = [1, 2, 3]; 224 | // Old 225 | for (var i = 0; i < items.length; i++) { 226 | console.log(array[i]); 227 | } 228 | 229 | // New 230 | for (let item of items) { 231 | console.log(item); 232 | } 233 | ``` 234 | 235 | # Generators 236 | 237 | These are functions that can be paused and resumed. It can return i.e. yield values on each pause. 238 | 239 | ```javascript 240 | function* generateThreeNumbers() { 241 | yield 1; 242 | yield 2; 243 | yield 3; 244 | } 245 | 246 | var numberIterator = generateThreeNumbers(); 247 | 248 | numberIterator.next(); // { value: 1, done: false } 249 | numberIterator.next(); // { value: 2, done: false } 250 | numberIterator.next(); // { value: 3, done: false } 251 | numberIterator.next(); // { value: undefined, done: true } 252 | ``` 253 | 254 | another example... 255 | 256 | ```javascript 257 | function* generator() { 258 | console.log("Hello"); 259 | yield "Yield 1 ran..."; 260 | console.log("World"); 261 | yield "Yield 2 ran..."; 262 | return "Done"; 263 | } 264 | 265 | let gen = generator(); // Set the generator to a variable to extract data. 266 | 267 | console.log(gen.next().value); // Hello, Yield 1 ran... 268 | console.log(gen.next().value); // World, Yield 2 ran... 269 | console.log(gen.next().value); // Done... 270 | 271 | for (let g of gen) { 272 | console.log(g); // Hello, Yield 1 ran, World, Yield 2 ran. Ignores last. 273 | } 274 | ``` 275 | 276 | # Destructuring 277 | 278 | ```javascript 279 | const address = { 280 | street: "", 281 | city: "", 282 | country: "" 283 | }; 284 | 285 | // old 286 | const street = address.street; 287 | const city = address.city; 288 | const country = address.country; 289 | 290 | // new 291 | const { street, city, country: ctry } = address; // We can also rename the variables 292 | 293 | // array 294 | var foo = [1, 2, 3, 4]; 295 | 296 | var [one, two, three] = foo; 297 | console.log(one); // 1 298 | console.log(two); // 2 299 | console.log(three); // 3 300 | 301 | // Default values. They work only if a property is undefined. null, false and 0 are all still values! 302 | var obj = { a: 1 }; 303 | 304 | var { a, b = "something" } = obj; 305 | console.log(a); // 1 306 | console.log(b); // something 307 | ``` 308 | 309 | Electron example 310 | 311 | ```javascript 312 | // Old 313 | const electron = require("electron"); 314 | const app = electron.app; 315 | const BrowserWindow = electron.BrowserWindow; 316 | 317 | // New 318 | const electron = require("electron"); 319 | const { app, BrowserWindow } = electron; 320 | ``` 321 | 322 | # Spread 323 | 324 | Used for copying or deleting properties from one object to another. 325 | 326 | ### Copy 327 | 328 | ```javascript 329 | // Without spread 330 | const meal = { 331 | id: 1, 332 | description: "Breakfast" 333 | }; 334 | 335 | const updatedMeal = { 336 | id: meal.id, 337 | description: meal.description, 338 | calories: 600 339 | }; 340 | 341 | // With spread 342 | const meal = { 343 | id: 1, 344 | description: "Breakfast" 345 | }; 346 | 347 | const updatedMeal = { 348 | ...meal, // Injects the id and description properties from meal. 349 | description: "Brunch", // This has precedence over the spread operator. 350 | calories: 600 351 | }; 352 | ``` 353 | 354 | ### Delete 355 | 356 | ```javascript 357 | const meal = { 358 | id: 1, 359 | description: "Breakfast", 360 | calories: 600 361 | } 362 | 363 | const = { id, ...mealWithoutId} = meal; // Destructuring. 364 | console.log(mealWithoutId); // Object without the id property. 365 | ``` 366 | 367 | ### Array 368 | 369 | ```javascript 370 | const first = [1, 2, 3]; 371 | const second = [4, 5, 6]; 372 | 373 | // old 374 | const combined = first.concat(second); 375 | 376 | // new 377 | const combined = [...first, "a", ...second, "b"]; // Easy to add other items. 378 | 379 | // Another example 380 | const meals = [ 381 | { id: 1, description: "Breakfast", calories: 420 }, 382 | { id: 2, description: "Lunch", calories: 520 } 383 | ]; 384 | 385 | const meal = { 386 | id: 3, 387 | description: "Snack", 388 | calories: 180 389 | }; 390 | 391 | const updatedMeals = [...meals, meal]; // Returns a new array with the addition. 392 | ``` 393 | -------------------------------------------------------------------------------- /topics/restful.md: -------------------------------------------------------------------------------- 1 | The key principles of REST involve separating your API into logical resources. These resources are manipulated using HTTP requests where each method has a specific meaning. 2 | 3 | The most used ones are (CRUD): 4 | - **POST** - Create 5 | - **GET** - Read 6 | - **PUT** - Update 7 | - **DELETE** - Delete 8 | 9 | Use 2 base URLs per resource. In your URLs - **nouns are good; verbs are bad**. 10 | 11 | The endpoints should **always** be plural. 12 | 13 | Resource | POST | GET | PUT | DELETE 14 | --- | --- | --- | --- | --- 15 | /dogs | create new dog | list **all** dogs | update **all** dogs | delete **all** dogs 16 | /dogs/123 | **ERROR** | show **one** dog | update **one** dog | delete **one** dog 17 | 18 | ### Example 19 | 20 | Method | Resource | Result 21 | --- | --- | --- 22 | GET | /tickets | Retrieves a list of tickets 23 | GET | /tickets/12 | Retrieves a specific ticket 24 | POST | /tickets | Creates a new ticket 25 | PUT | /tickets/12 | Updates ticket #12 26 | PATCH | /tickets/12 | Partially updates ticket #12 27 | DELETE | /tickets/12 | Deletes ticket #12 28 | 29 | ### Nested resources 30 | 31 | Method | Resource | Result 32 | --- | --- | --- 33 | GET | /tickets/12/messages | Retrieves list of messages for ticket #12 34 | GET | /tickets/12/messages/5 | Retrieves message #5 for ticket #12 35 | POST | /tickets/12/messages | Creates a new message in ticket #12 36 | PUT | /tickets/12/messages/5 | Updates message #5 for ticket #12 37 | PATCH | /tickets/12/messages/5 | Partially updates message #5 for ticket #12 38 | DELETE | /tickets/12/messages/5 | Deletes message #5 for ticket #12 39 | 40 | ### Actions that don't fit into CRUD 41 | 42 | Restructure the action to appear like a field of a resource. This works if the action doesn't take parameters. For example an activate action could be mapped to a boolean activated field and updated via a PATCH to the resource. 43 | 44 | Treat it like a sub-resource with RESTful principles. For example, GitHub's API lets you star a gist with PUT /gists/:id/star and unstar with DELETE /gists/:id/star. 45 | 46 | Sometimes you really have no way to map the action to a sensible RESTful structure. For example, a multi-resource search doesn't really make sense to be applied to a specific resource's endpoint. In this case, /search would make the most sense even though it isn't a resource. This is OK - just do what's right from the perspective of the API consumer and make sure it's documented clearly to avoid confusion. 47 | 48 | # SSL everywhere - all the time 49 | 50 | Always use SSL. No exceptions. Today, your web APIs can get accessed from anywhere there is internet (like libraries, coffee shops, airports among others). Not all of these are secure. Many don't encrypt communications at all, allowing for easy eavesdropping or impersonation if authentication credentials are hijacked. 51 | 52 | Another advantage of always using SSL is that guaranteed encrypted communications simplifies authentication efforts - you can get away with simple access tokens instead of having to sign each API request. 53 | 54 | One thing to watch out for is non-SSL access to API URLs. Do not redirect these to their SSL counterparts. Throw a hard error instead! The last thing you want is for poorly configured clients to send requests to an unencrypted endpoint, just to be silently redirected to the actual encrypted endpoint. 55 | 56 | # Result filtering, sorting & searching 57 | 58 | It's best to keep the base resource URLs as lean as possible. Complex result filters, sorting requirements and advanced searching (when restricted to a single type of resource) can all be easily implemented as query parameters on top of the base URL. Let's look at these in more detail: 59 | 60 | ### Filtering 61 | 62 | Use a unique query parameter for each field that implements filtering. For example, when requesting a list of tickets from the /tickets endpoint, you may want to limit these to only those in the open state. This could be accomplished with a request like GET /tickets?state=open. Here, state is a query parameter that implements a filter. 63 | 64 | ### Sorting 65 | 66 | Similar to filtering, a generic parameter sort can be used to describe sorting rules. Accommodate complex sorting requirements by letting the sort parameter take in list of comma separated fields, each with a possible unary negative to imply descending sort order. Let's look at some examples: 67 | 68 | `GET /tickets?sort=-priority` - Retrieves a list of tickets in descending order of priority 69 | 70 | `GET /tickets?sort=-priority,created_at` - Retrieves a list of tickets in descending order of priority. Within a specific priority, older tickets are ordered first 71 | 72 | ### Searching 73 | 74 | Sometimes basic filters aren't enough and you need the power of full text search. Perhaps you're already using ElasticSearch or another Lucene based search technology. When full text search is used as a mechanism of retrieving resource instances for a specific type of resource, it can be exposed on the API as a query parameter on the resource's endpoint. Let's say q. Search queries should be passed straight to the search engine and API output should be in the same format as a normal list result. 75 | 76 | Combining these together, we can build queries like: 77 | 78 | `GET /tickets?sort=-updated_at` - Retrieve recently updated tickets. 79 | `GET /tickets?state=closed&sort=-updated_at` - Retrieve recently closed tickets. 80 | `GET /tickets?q=return&state=open&sort=-priority,created_at` - Retrieve the highest priority open tickets mentioning the word 'return' 81 | 82 | # JSON only responses 83 | 84 | It's time to leave XML behind in APIs. It's verbose, it's hard to parse, it's hard to read, its data model isn't compatible with how most programming languages model data and its extendibility advantages are irrelevant when your output representation's primary needs are serialization from an internal representation. 85 | 86 | # snake_case vs camelCase for field names 87 | 88 | If you're using JSON (JavaScript Object Notation) as your primary representation format, the "right" thing to do is to follow JavaScript naming conventions - and that means camelCase for field names! 89 | 90 | If you then go the route of building client libraries in various languages, it's best to use idiomatic naming conventions in them - camelCase for C# & Java, snake_case for python & ruby. 91 | 92 | Food for thought: I've always felt that snake_case is easier to read than JavaScript's convention of camelCase. I just didn't have any evidence to back up my gut feelings, until now. Based on an eye tracking study on camelCase and snake_case (PDF) from 2010, **snake_case is 20% easier to read than camelCase**! That impact on readability would affect API explorability and examples in documentation. 93 | 94 | Many popular JSON APIs use snake_case. I suspect this is due to serialization libraries following naming conventions of the underlying language they are using. Perhaps we need to have JSON serialization libraries handle naming convention transformations. 95 | 96 | # Pretty print by default & ensure gzip is supported 97 | An API that provides white-space compressed output isn't very fun to look at from a browser. Although some sort of query parameter (like ?pretty=true) could be provided to enable pretty printing, an API that pretty prints by default is much more approachable. The cost of the extra data transfer is negligible, especially when you compare to the cost of not implementing gzip. 98 | 99 | Consider some use cases: What if an API consumer is debugging and has their code print out data it received from the API - It will be readable by default. Or if the consumer grabbed the URL their code was generating and hit it directly from the browser - it will be readable by default. These are small things. Small things that make an API pleasant to use! 100 | 101 | ### But what about all the extra data transfer? 102 | 103 | Let's look at this with a real world example. I've pulled some data from GitHub's API, which uses pretty print by default. I'll also be doing some gzip comparisons: 104 | ```bash 105 | $ curl https://api.github.com/users/veesahni > with-whitespace.txt 106 | $ ruby -r json -e 'puts JSON JSON.parse(STDIN.read)' < with-whitespace.txt > without-whitespace.txt 107 | $ gzip -c with-whitespace.txt > with-whitespace.txt.gz 108 | $ gzip -c without-whitespace.txt > without-whitespace.txt.gz 109 | ``` 110 | The output files have the following sizes: 111 | ```bash 112 | without-whitespace.txt - 1252 bytes 113 | with-whitespace.txt - 1369 bytes 114 | without-whitespace.txt.gz - 496 bytes 115 | with-whitespace.txt.gz - 509 bytes 116 | ``` 117 | 118 | In this example, the whitespace increased the output size by 8.5% when gzip is not in play and 2.6% when gzip is in play. On the other hand, the act of gzipping in itself provided over 60% in bandwidth savings. Since the cost of pretty printing is relatively small, it's best to pretty print by default and ensure gzip compression is supported! 119 | 120 | To further hammer in this point, Twitter found that there was an 80% savings (in some cases) when enabling gzip compression on their Streaming API. Stack Exchange went as far as to never return a response that's not compressed! 121 | 122 | # Authentication 123 | 124 | A RESTful API should be stateless. This means that request authentication should not depend on cookies or sessions. Instead, each request should come with some sort authentication credentials. 125 | 126 | By always using SSL, the authentication credentials can be simplified to a randomly generated access token that is delivered in the user name field of HTTP Basic Auth. The great thing about this is that it's completely browser explorable - the browser will just popup a prompt asking for credentials if it receives a 401 Unauthorized status code from the server. 127 | 128 | However, this token-over-basic-auth method of authentication is only acceptable in cases where it's practical to have the user copy a token from an administration interface to the API consumer environment. In cases where this isn't possible, OAuth 2 should be used to provide secure token transfer to a third party. OAuth 2 uses Bearer tokens & also depends on SSL for its underlying transport encryption. 129 | 130 | An API that needs to support JSONP will need a third method of authentication, as JSONP requests cannot send HTTP Basic Auth credentials or Bearer tokens. In this case, a special query parameter access_token can be used. Note: there is an inherent security issue in using a query parameter for the token as most web servers store query parameters in server logs. 131 | 132 | For what it's worth, all three methods above are just ways to transport the token across the API boundary. The actual underlying token itself could be identical. 133 | 134 | # HTTP status codes 135 | 136 | HTTP defines a bunch of meaningful status codes that can be returned from your API. These can be leveraged to help the API consumers route their responses accordingly. I've curated a short list of the ones that you definitely should be using: 137 | 138 | Code | Message | Meaning 139 | --- | --- | --- 140 | 200 | OK | Response to a successful GET, PUT, PATCH or DELETE. Can also be used for a POST that doesn't result in a creation. 141 | 201 | Created | Response to a POST that results in a creation. Should be combined with a Location header pointing to the location of the new resource 142 | 204 | No Content | Response to a successful request that won't be returning a body (like a DELETE request) 143 | 304 | Not Modified | Used when HTTP caching headers are in play 144 | 400 | Bad Request | The request is malformed, such as if the body does not parse 145 | 401 | Unauthorized | When no or invalid authentication details are provided. Also useful to trigger an auth popup if the API is used from a browser 146 | 403 | Forbidden | When authentication succeeded but authenticated user doesn't have access to the resource 147 | 404 | Not Found | When a non-existent resource is requested 148 | 405 | Method Not Allowed | When an HTTP method is being requested that isn't allowed for the authenticated user 149 | 410 | Gone | Indicates that the resource at this end point is no longer available. Useful as a blanket response for old API versions 150 | 415 | Unsupported Media Type | If incorrect content type was provided as part of the request 151 | 422 | Unprocessable Entity | Used for validation errors 152 | 429 |Too Many Requests | When a request is rejected due to rate limiting -------------------------------------------------------------------------------- /topics/async.md: -------------------------------------------------------------------------------- 1 | # Basics 2 | 3 | Asynchronous Javascript is based on events. Every promise and observable library is based on them. 4 | 5 | Synchronous code uses a `call stack`, a data structure keeping track of the program execution. 6 | 7 | Asynchronous code uses an `event queue`, a list of functions handled in a FIFO manner, which is checked repeatedly by the `event loop`. 8 | 9 | The event loop is a programming construct that waits for and dispatches functions in the `event queue` to the `call stack`. 10 | 11 | ```javascript 12 | setTimeout(() => { 13 | console.log("I will happen later..."); 14 | }, 5000); 15 | ``` 16 | 17 | This doesn't execute after 5 seconds... It gets added to the `event queue` after 5 seconds. 18 | 19 | In reality, **Javascript is not asynchronous at all**. It comes from the environment i.e. browsers and nodejs, specifically the Behavior Object Model (BOM). 20 | 21 | window 22 | 23 | - Document Object Model (DOM) 24 | - getElementById 25 | - Behavior Object Model (BOM) 26 | - setTimeout 27 | - XMLHttpRequest 28 | - fetch 29 | - history 30 | - ECMAScript 31 | - Object 32 | - Array 33 | - Function 34 | 35 | # AJAX 36 | 37 | This is all done via vanilla Javascript, but it can be done via libraries such as JQuery, Axios, Superagent, Fetch API, Node HTTP... 38 | 39 | ```javascript 40 | var xhr = new XMLHttpRequest(); 41 | 42 | xhr.open("GET", "http://www.api.com/data", true); 43 | 44 | xhr.onload = function() { 45 | if (this.status == 200) { 46 | return JSON.parse(this.responseText); 47 | } 48 | }; 49 | 50 | xhr.onerror = function() { 51 | console.log("error"); 52 | }; 53 | 54 | xhr.send(); 55 | ``` 56 | 57 | Can also be done like this. 58 | 59 | ```javascript 60 | var request = new XMLHttpRequest(); 61 | 62 | request.addEventListener("load", event => { 63 | console.log(event.target.responseText); 64 | }); 65 | 66 | request.addEventListener("error", event => { 67 | console.error(event.target.responseText); 68 | }); 69 | 70 | request.open("GET", "http://www.api.com/data"); 71 | request.send(); 72 | ``` 73 | 74 | **Regular HTTP request** 75 | `Client` --- Request ---> `Server` 76 | `Client` <--- Response --- `Server` 77 | 78 | **Ajax** 79 | `Client` --- JS Call ---> `Ajax Engine` --- XMLHttpRequest (XHR) ---> `Server` 80 | `Client` <--- HTML --- `Ajax Engine` <--- JSON --- `Server` 81 | 82 | ## XMLHttpRequest (XHR) Object 83 | 84 | This API in the form of an object is provided by the browser's Javascript environment, and it has its own properties and methods which transfer data between the browser and a server. 85 | 86 | ```html 87 | 88 | ``` 89 | 90 | ```javascript 91 | document.getElementById("button").addEventListener("click", loadData); 92 | ``` 93 | 94 | ### Old way 95 | 96 | We have to make sure we are on the `readyState 4`. 97 | 98 | ```javascript 99 | // Create XHR Object 100 | var xhr = new XMLHttpRequest(); // Can be named req 101 | 102 | // Establish server connection - type, url/file, async 103 | xhr.open("GET", "http://www.api.com/data", true); // readyState 1 104 | 105 | xhr.onreadystatechange = function() { 106 | // readyState 1, 2, 3, 4 107 | if (this.readyState == 4 && this.status == 200) { 108 | return JSON.parse(this.responseText); 109 | } 110 | }; 111 | 112 | // If it fails 113 | xhr.onerror = function() { 114 | console.log("error"); 115 | }; 116 | 117 | // Send request 118 | xhr.send(); 119 | ``` 120 | 121 | **readyState values** 122 | 123 | ``` 124 | 0. Request not initialized. 125 | 1. Server connection established. 126 | 2. Request received. 127 | 3. Processing request. 128 | 4. Request finished and response ready. 129 | ``` 130 | 131 | ### New way 132 | 133 | The difference from the old way is that `onload` will not run unless we are on `readyState 4` 134 | 135 | ```javascript 136 | // Create XHR Object 137 | var xhr = new XMLHttpRequest(); // Can be named req 138 | 139 | // Establish server connection - type, url/file, async 140 | xhr.open("GET", "http://www.api.com/data", true); // readyState 1 141 | 142 | xhr.onload = function() { 143 | // readyState 1, 4 144 | if (this.status == 200) { 145 | return JSON.parse(this.responseText); 146 | } 147 | }; 148 | 149 | // If it fails 150 | xhr.onerror = function() { 151 | console.log("error"); 152 | }; 153 | 154 | // Send request 155 | xhr.send(); 156 | ``` 157 | 158 | ### Loading 159 | 160 | ```javascript 161 | xhr.onprogress = function() { 162 | // readyState 3 163 | // Show loading... 164 | }; 165 | ``` 166 | 167 | ### POST 168 | 169 | ```html 170 |
171 | 172 | 173 |
174 | ``` 175 | 176 | ```javascript 177 | document.getElementById("form").addEventListener("submit", submitForm); 178 | 179 | function submitForm(e) { 180 | e.preventDefault(); 181 | 182 | var input = document.getElementById("input").value; 183 | var params = "input=" + input; 184 | 185 | var xhr = new XMLHttpRequest(); 186 | 187 | xhr.open("POST", "http://www.api.com/data", true); 188 | 189 | xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 190 | 191 | xhr.onload = function() { 192 | // readyState 1, 4 193 | if (this.status == 200) { 194 | return JSON.parse(this.responseText); 195 | } 196 | }; 197 | 198 | xhr.onerror = function() { 199 | console.log("error"); 200 | }; 201 | 202 | xhr.send(params); 203 | } 204 | ``` 205 | 206 | # Fetch API 207 | 208 | An AJAX library using promises, available by default in all modern browsers. A promise is like a placeholder for a response we are going to get in the future. 209 | 210 | Fetch always returns a promise. Promise resolves to the response object. This response object has different helper methods like response.json(), response.text(), response.blob() etc. 211 | 212 | Fetch also takes a second parameter, which is a configuration object. 213 | 214 | ## GET 215 | 216 | ```javascript 217 | // ES5 218 | function getData() { 219 | fetch("http://www.api.com/data") // Return response promise. 220 | .then(function(res) { 221 | return res.json(); // Return data. 222 | }) 223 | .then(function(data) { 224 | return data; // Do something with data. 225 | }) 226 | .catch(function(err) { 227 | return err; // Catch error. 228 | }); 229 | } 230 | 231 | // ES6 232 | function getText() { 233 | fetch("http://www.api.com/data") // Return response promise. 234 | .then(res => res.json()) // Return data. 235 | .then(data => data) // Do something with data. 236 | .catch(err => err); // Catch error. 237 | } 238 | ``` 239 | 240 | ## POST 241 | 242 | ```javascript 243 | function postData() { 244 | fetch("http://www.api.com/data", { 245 | method: "POST", 246 | headers: { 247 | Accept: "application/json", 248 | "Content-type": "application/json" 249 | }, 250 | body: JSON.stringify({ title: title, body: body }) // Payload 251 | }) // Return response promise. 252 | .then(res => res.json()) // Return data. 253 | .then(data => data) // Do something with data. 254 | .catch(err => err); // Catch error. 255 | } 256 | ``` 257 | 258 | # Callbacks 259 | 260 | A callback is a function that is to be executed after another function has finished executing — hence the name ‘call back’. 261 | 262 | In JavaScript, functions are objects. Because of this, functions can take functions as arguments, and can be returned by other functions. Functions that do this are called **higher-order functions**. Any function that is passed as an argument is called a **callback function**. 263 | 264 | ```javascript 265 | function foo(input, callback) { 266 | console.log(input); 267 | callback(); 268 | } 269 | 270 | // Anonymous callback. Logs Foo Bar. 271 | foo("Foo", function() { 272 | console.log("Bar"); 273 | }); 274 | ``` 275 | 276 | Passing named functions. 277 | 278 | ```javascript 279 | function baz(input) { 280 | console.log(input); 281 | } 282 | 283 | // This executes the baz function immediately. 284 | // Logs Baz Foo and "TypeError: callback is not a function 285 | foo("Foo", baz("Baz")); 286 | 287 | // Named callback. Logs Foo Baz. 288 | foo("Foo", function() { 289 | baz("Baz"); 290 | }); 291 | 292 | // Works fine because it doesn't execute immediately. 293 | // Must have no arguments. Logs Foo Qux. 294 | foo("Foo", logQux); 295 | 296 | function logQux() { 297 | console.log("Qux"); 298 | } 299 | ``` 300 | 301 | Another example... 302 | 303 | ```javascript 304 | function callbackSandwich(callbackFunction) { 305 | console.log("Top piece of bread."); 306 | callbackFunction(); 307 | console.log("Bottom piece of bread."); 308 | } 309 | 310 | // We pass in an anonymous function, to be called inside. 311 | callbackSandwich(function() { 312 | console.log("Slice of cheese."); 313 | }); 314 | ``` 315 | 316 | ## AJAX with callback 317 | 318 | ```javascript 319 | var request = new XMLHttpRequest(); 320 | 321 | request.addEventListener("load", event => { 322 | console.log(event.target.responseText); 323 | }); 324 | 325 | request.open("GET", "http://www.api.com/data"); 326 | request.send(); 327 | ``` 328 | 329 | Can be refactored into... 330 | 331 | ```javascript 332 | function ajax(method, url, callback) { 333 | var request = new XMLHttpRequest(); 334 | request.addEventListener("load", callback); 335 | request.open(method, url); 336 | request.send(); 337 | } 338 | 339 | ajax("GET", "http://www.api.com/data", event => { 340 | console.log("SUCCESS", event.target.responseText); 341 | }); 342 | ``` 343 | 344 | Which is pretty much what the ajax libraries do. 345 | 346 | # Promises 347 | 348 | The `Promise()` constructor takes a function, which takes the `resolve` and `reject` functions. 349 | 350 | ```javascript 351 | new Promise((resolve, reject) => { 352 | if (goodThingsHappen) { 353 | resolve(goodThings); // passed to .then() 354 | } else { 355 | reject(reasonsForFailing); 356 | } 357 | }); 358 | ``` 359 | 360 | The promise object is used for deferred and asynchronous computations and it represents and operation that hasn't completed yet, but is expected in the future. 361 | 362 | Promises are obtained with `.then()`. 363 | 364 | ```javascript 365 | // Immediately resolved. 366 | let myPromise = Promise.resolve("Foo"); 367 | myPromise.then((res) => console.log(res);) // Foo 368 | 369 | // Delayed 370 | var myPromise = new Promise(function(resolve, reject){ 371 | setTimeout(() => resolve(4), 2000); // Return 4 after 2 seconds. 372 | }); 373 | 374 | myPromise.then((res) => { 375 | res += 3; // Wait for the 4 and add 3 to it. 376 | console.log(res); // 7 after 2 seconds. 377 | }); 378 | ``` 379 | 380 | ## Fetch under the hood with Promises 381 | 382 | ```javascript 383 | function fetch(method, url) { 384 | return new Promise(function(resolve, reject) { 385 | let xhr = new XMLHttpRequest(); 386 | xhr.open(method, url); 387 | xhr.onload = function() { 388 | if (this.status >= 200 && this.staus <= 300) { 389 | resolve(xhr.response); 390 | } else { 391 | reject({ 392 | status: this.status, 393 | statusText: xhr.statusText 394 | }); 395 | } 396 | }; 397 | xhr.onerror = function() { 398 | reject({ 399 | status: this.status, 400 | statusText: xhr.statusText 401 | }); 402 | }; 403 | xhr.send(); 404 | }); 405 | } 406 | 407 | fetch("GET", "http://jsonplaceholder.typicode.com/todos") 408 | .then(function(data) { 409 | let todos = JSON.parse(data); 410 | let output = ""; 411 | for (let todo of todos) { 412 | output += ` 413 |
  • 414 |

    ${todo.title}

    415 |

    ${todo.item}

    416 | `; 417 | } 418 | document.getElementById("list").innerHTML = output; 419 | }) 420 | .catch(function(err) { 421 | console.log(err); 422 | }); 423 | ``` 424 | 425 | ## Promise All 426 | 427 | Takes an array of promises and executes if they are all successful. 428 | 429 | ```javascript 430 | Promise.all([ 431 | fetch("/api/endpoint"), 432 | fetch("/api/another-endpoint"), 433 | fetch("/api/yet-another-endpoint") 434 | ]) 435 | .then(responses => { 436 | // array of responses 437 | console.log(responses[0]); // users 438 | console.log(responses[1]); // products 439 | console.log(responses[2]); // clients 440 | }) 441 | .catch(err => { 442 | console.log(err); 443 | }); 444 | ``` 445 | 446 | ## Chaining 447 | 448 | ```javascript 449 | let futureNumber = Promise.resolve(2); // 2 450 | 451 | futureNumber 452 | .then(n => n + 1) // 3 453 | .then(n => n * 2) // 6 454 | .then(n => Math.pow(n, 2)) // 36 455 | .then(n => console.log(n)); // 36 456 | 457 | futureNumber.then(n => console.log(n)); //2 458 | ``` 459 | 460 | # Async/Await 461 | 462 | This is basically promises mixed in with generators. 463 | 464 | ```javascript 465 | const getUsers = async () => { 466 | const user1 = await ajax("http://api.com/users/1"); 467 | const user2 = await ajax("http://api.com/users/2"); 468 | console.log(user1, user2); 469 | }; 470 | 471 | getUsers(); 472 | ``` 473 | 474 | Under the hood it looks like... 475 | 476 | ```javascript 477 | const request = url => { 478 | ajax("GET", url).then(response => it.next(JSON.parse(response))); 479 | }; 480 | 481 | function* main() { 482 | const user1 = yield ajax("http://api.com/users/1"); 483 | const user2 = yield ajax("http://api.com/users/2"); 484 | console.log(user1, user2); 485 | } 486 | 487 | const it = main(); 488 | it.next(); 489 | ``` 490 | -------------------------------------------------------------------------------- /topics/electron.md: -------------------------------------------------------------------------------- 1 | # General 2 | 3 | Electron is a framework which allows to create desktop apps with HTML, CSS and Javascript. It's basically a Chrome browser with less features. It can also access the file system, whilst web apps cannot. 4 | 5 | The HTML, CSS and Javascript can compile to executables for Windows, Mac or Linux. 6 | 7 | Some notable apps that are built with it are Atom, VS Code and Slack. 8 | 9 | **Try and keep in mind that Electron is simply a "manager" for a browser instance. It's the glue between the OS and the BrowserWindow.** 10 | 11 | **As soon as you're working in a renderer process, you're writing standard javascript and Electron really doesn't matter any longer.** 12 | 13 | # Install 14 | 15 | Don't install Electron as a global because then other people have to set stuff up to run your app (i.e. they now have to micromanage which version of Electron they have installed globally). 16 | 17 | ```bash 18 | npm install electron --save-dev 19 | ``` 20 | 21 | **All tools should be installed as dev dependencies.** 22 | 23 | ### Errors 24 | 25 | When running `npm install electron`, some users occasionally encounter installation errors. 26 | 27 | In almost all cases, these errors are the result of network problems and not actual issues with the electron npm package. Errors like `ELIFECYCLE`, `EAI_AGAIN`, `ECONNRESET`, and `ETIMEDOUT` are all indications of such network problems. 28 | 29 | **The best resolution is to try reconnecting, switching networks, or just waiting for a bit before trying to install again.** 30 | 31 | # Run 32 | 33 | **Before anything, make sure that `package.json` is updated with the relevant entry file. Default is `index.js`.** 34 | 35 | ```json 36 | "main": "main.js" 37 | ``` 38 | 39 | **The electron library is not used in the final app build.** 40 | 41 | If electron was installed locally in `node_modules`. 42 | 43 | ```bash 44 | ./node_modules/.bin/electron . 45 | npm start # We use the above command inside package.json. 46 | ``` 47 | 48 | If electron was installed globally. 49 | 50 | ```bash 51 | electron main.js 52 | electron . # Same as above. Looks for main.js inside current directory. 53 | npm start # We use the above command inside package.json. 54 | ``` 55 | 56 | Using the wrong one will result in an `ELIFECYCLE` error. 57 | 58 | ### ENOSPC error 59 | 60 | Listen uses inotify by default on Linux to monitor directories for changes. It's not uncommon to encounter a system limit on the number of files you can monitor. For example, Ubuntu Lucid's (64bit) inotify limit is set to 8192. 61 | 62 | When this limit is not enough to monitor all files inside a directory, the limit must be increased for Listen to work properly. Set a permanent limit with: 63 | 64 | ```bash 65 | echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p 66 | ``` 67 | 68 | # Simple app 69 | 70 | **main.js** 71 | 72 | ```javascript 73 | const electron = require("electron"); 74 | const { app, BrowserWindow } = electron; 75 | 76 | let mainWindow; 77 | 78 | function createWindow() { 79 | mainWindow = new BrowserWindow({ width: 800, height: 600 }); 80 | mainWindow.loadURL(`file://${__dirname}/index.html`); 81 | mainWindow.on("closed", function() { 82 | mainWindow = null; 83 | }); 84 | } 85 | 86 | app.on("ready", createWindow); 87 | ``` 88 | 89 | We keep the `mainWindow` variable in the global scope in order to prevent it from being garbage collected, thus losing the window. 90 | 91 | **index.html** 92 | 93 | ```html 94 | 95 | 96 | 97 | Window 98 | 99 | 100 |

    Some content

    101 | 102 | 105 | 106 | ``` 107 | 108 | # Main vs Renderer Process 109 | 110 | Electron operates in two runtime contexts i.e. processes. 111 | 112 | - **Main** (one) / Node.js / Server / main.js 113 | - File system access. 114 | - Compiled module support. 115 | - CommonJS modules. 116 | 117 | * **Renderer** (many) / Chromium browser / Client side 118 | - HTML and CSS renderer. 119 | - DOM access. 120 | - Web API. 121 | 122 | The main process can create many renderer processes (browser windows), but there is only one main process handling this. 123 | 124 | # IPC (Inter Process Communication) 125 | 126 | It allows us to send messages (with a payload) between the Main and Renderer processes. To use this, we need: 127 | 128 | - The `ipcMain` module in the `Main` process. 129 | - The `ipcRenderer` module in the `Renderer` processes. 130 | 131 | By default, these modules send messages asynchronously, which is recommended. 132 | 133 | ## ipcMain 134 | 135 | `ipcMain` can only listen for `Renderer` messages and reply to them by using `webContents.send()`. 136 | 137 | ```javascript 138 | // Main 139 | var ipcMain = require("electron").ipcMain; 140 | 141 | win = new BrowserWindow(); 142 | 143 | ipcMain.on("asynchronous-message", (e, args) => { 144 | console.log(args); // prints "ping" 145 | event.sender.send("asynchronous-reply", "pong"); 146 | }); 147 | 148 | win.webContents.send("channel", "foo!"); 149 | ``` 150 | 151 | ## ipcRenderer 152 | 153 | `ipcRenderer` can send messages to the `Main` process. It also listens to messages sent from it. 154 | 155 | You can have 2 windows communicate via the HTML5 messaging API. Again, **when ipc is not required for sending something to The main process which is OS related, there's no need.** 156 | 157 | ```javascript 158 | // Renderer 159 | var ipcRenderer = require("electron").ipcRenderer; 160 | 161 | ipcRenderer.send("asynchronous-message", "ping"); 162 | 163 | ipcRenderer.on("asynchronous-reply", (e, args) => { 164 | console.log(args); // prints "pong" 165 | }); 166 | 167 | ipcRenderer.on("channel", (e, args) => { 168 | console.log(args); // Prints 'foo!' 169 | }); 170 | ``` 171 | 172 | ## Remote 173 | 174 | Basically the `remote` module makes it easy to do stuff normally restricted to the main process in a render process without lots of manual ipc messages back and forth. 175 | 176 | In Electron, GUI-related modules (such as dialog, menu etc.) are only available in the main process, not in the renderer process. In order to use them from the renderer process, the ipc module is necessary to send inter-process messages to the main process. 177 | 178 | **With the remote module, you can invoke methods of the main process object without explicitly sending inter-process messages**, similar to Java's RMI. An example of creating a browser window from a renderer process: 179 | 180 | ```javascript 181 | const remote = require("electron").remote; 182 | const BrowserWindow = remote.BrowserWindow; 183 | 184 | var win = new BrowserWindow(); 185 | win.loadURL("https://github.com"); 186 | ``` 187 | 188 | # Examples 189 | 190 | ## Developer Tools 191 | 192 | ```javascript 193 | // Add this line in the createWindow main process. 194 | mainWindow.webContents.openDevTools(); 195 | ``` 196 | 197 | ## Menu 198 | 199 | If there's no custm menu specified, Electron shows a default one. Using a custom one overrides it. 200 | 201 | ```javascript 202 | const electron = require("electron"); 203 | // We need to pull menu. 204 | const { app, BrowserWindow, Menu } = electron; 205 | 206 | let mainWindow; 207 | 208 | function createWindow() { 209 | mainWindow = new BrowserWindow({ width: 800, height: 600 }); 210 | mainWindow.loadURL(`file://${__dirname}/index.html`); 211 | 212 | // Build menu 213 | const mainMenu = Menu.buildFromTemplate(mainMenuTemplate); 214 | // Set Menu 215 | Menu.setApplicationMenu(mainMenu); 216 | } 217 | 218 | app.on("ready", createWindow); 219 | 220 | // Array of menu objects 221 | const mainMenuTemplate = [ 222 | { 223 | label: "Menu item", 224 | submenu: [{ label: "Submenu item 1" }, { label: "Submenu item 2" }] 225 | } 226 | ]; 227 | ``` 228 | 229 | ## New Window 230 | 231 | ```javascript 232 | const electron = require("electron"); 233 | // We need to pull menu. 234 | const { app, BrowserWindow, Menu } = electron; 235 | 236 | let mainWindow; 237 | 238 | // Main window. 239 | function createWindow() { 240 | mainWindow = new BrowserWindow({ width: 800, height: 600 }); 241 | mainWindow.loadURL(`file://${__dirname}/index.html`); 242 | 243 | // Build menu 244 | const mainMenu = Menu.buildFromTemplate(mainMenuTemplate); 245 | // Set Menu 246 | Menu.setApplicationMenu(mainMenu); 247 | } 248 | 249 | // Create new window. 250 | function createNewWindow() { 251 | newWindow = new BrowserWindow({ 252 | width: 600, 253 | height: 400, 254 | title: "New Window" 255 | }); 256 | newWindow.loadURL(`file://${__dirname}/newWindow.html`); 257 | } 258 | 259 | app.on("ready", createWindow); 260 | 261 | // Array of menu objects 262 | const mainMenuTemplate = [ 263 | { 264 | label: "New window", 265 | click() { 266 | // Make the menu item clickable. 267 | createNewWindow(); // Call this in the main process. 268 | } 269 | } 270 | ]; 271 | ``` 272 | 273 | ## Shortcuts (Accelerators) 274 | 275 | # Electron Reload 276 | 277 | An npm library used for tracking changes in `.html` and `.js` rederer files, to avoid closing/starting electron to refresh. 278 | 279 | ```bash 280 | npm install electron-reload --save-dev 281 | ``` 282 | 283 | ```javascript 284 | // main.js 285 | require("electron-reload")(__dirname); 286 | ``` 287 | 288 | # Packaging 289 | 290 | The app's general information is contained in `package.json`. We should always package the app from a copy, instead of the working file. 291 | 292 | The dev-dependencies should also be removed before packaging, along with the code requiring them. 293 | 294 | ## Electron Packager 295 | 296 | ```bash 297 | sudo npm install -g electron-packager 298 | ``` 299 | 300 | There are two ways of packaging the app. 301 | 302 | ```bash 303 | # Electron as a dev-dependency, to avoid packaging the module as well. 304 | electron-packager . 305 | 306 | # Electron version as a flag. The version will be downloaded. 307 | electron-packager . --electron-version="1.8.2" 308 | ``` 309 | 310 | ### Platform 311 | 312 | If we don't specify a platform, the app will be packaged in the host OS. 313 | 314 | ```bash 315 | # Linux 316 | electron-packager . --platform=linux --arch=x64 317 | 318 | # Windows 319 | electron-packager . --platform=win32 --arch=ia32 320 | ``` 321 | 322 | ### asar 323 | 324 | We can see the source files via `Contents/Resources/app`. We can hide these by packaging them in an `.asar` archive. This is similar to a `.tar` file, but without compression. This archive can be easily unpacked, but it does provide an extra layer of security. 325 | 326 | ```bash 327 | # Use asar to hide the source code. 328 | electron-packager . --asar=true 329 | ``` 330 | 331 | The source code would now be in `Contents/Resources/app.asar`. 332 | 333 | ### icon 334 | 335 | The icon should be a square picture in several formats. `.png` for Linux, `.ico` for Windows, and `.icns` for Mac. A simple tool for these conversions is http://iconverticons.com. The icons need to be located in the source folder. 336 | 337 | ```bash 338 | electron-packager . --icon=icon 339 | ``` 340 | 341 | ### Flags 342 | 343 | ```bash 344 | # Overwrites the previous packaging with the new one. 345 | --overwrite 346 | ``` 347 | 348 | ### Full commands 349 | 350 | [Source](https://www.christianengvall.se/electron-packager-tutorial) 351 | 352 | ```bash 353 | # Linux 354 | electron-packager . electron-tutorial-app --overwrite --asar=true --platform=linux --arch=x64 --icon=assets/icons/png/1024x1024.png --prune=true --out=release-builds 355 | 356 | # Windows 357 | electron-packager . electron-tutorial-app --overwrite --asar=true --platform=win32 --arch=ia32 --icon=assets/icons/win/icon.ico --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName="Electron Tutorial App" 358 | ``` 359 | 360 | ## Electron Builder 361 | 362 | Compared to electron-packager, this has many more features and allows us to package, sign and release the app as a part of a highly configurable workflow. The main use is the ability to publish versions automatically. 363 | 364 | ```bash 365 | sudo npm install -g electron-builder 366 | ``` 367 | 368 | In order to use this module for efficiently, we can add it as a dev-dependency and run the commands as npm scripts in package.json. 369 | 370 | # Updating 371 | 372 | ## Electron Updater 373 | 374 | Use `autoUpdater` from `electron-updater` instead of electon. It allows to listen for various update events after checking a URL. 375 | 376 | ```bash 377 | npm install electron-updater 378 | ``` 379 | 380 | ```javascript 381 | import { autoUpdater } from "electron-updater"; 382 | 383 | autoUpdater.on("update-available", () => {}); 384 | ``` 385 | 386 | # Native Node Modules 387 | 388 | **This mostly applies to C based libraries such as bcrypt and ffi.** 389 | 390 | Electron is a pre-built library, and it is often built against a different version of the V8 node binary than your system. Installing native npm packages normally would result in an error like this... 391 | 392 | ```bash 393 | App threw an error during load. 394 | Error: Module version mismatch. Expected 50, got 46. 395 | ``` 396 | 397 | In order to use native modules, we need to manually specify the location of the electron headers. To simplify this, we can use a custom script `electron-npm`, which we can call instead of `npm install` for native modules. 398 | 399 | ```bash 400 | # electron-npm script 401 | export npm_config_target=1.7.10 # Electron's version. Find with ./node_modules/.bin/electron -v 402 | export npm_config_arch=x64 # The architecture. 403 | export npm_config_disturl=https://atom.io/download/atom-shell # Download headers. 404 | export npm_config_runtime=electron # Tell node-pre-gyp we are building for Electron. 405 | export npm_config_build_from_source=true # Tell node-pre-gyp to build module from source code. 406 | npm install $1 # Replace with the first argument passed. 407 | ``` 408 | 409 | Now, we can install the npm packages with... 410 | 411 | ```bash 412 | ./electron-npm package # Instead of "npm install package" 413 | ``` 414 | -------------------------------------------------------------------------------- /topics/git.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | A commit in a git repository records a snapshot of all the files in your directory. It's like a giant copy and paste, but even better! 4 | 5 | Git wants to keep commits as lightweight as possible though, so it doesn't just blindly copy the entire directory every time you commit. It can (when possible) compress a commit as a set of changes, or a "delta", from one version of the repository to the next. 6 | 7 | # Quick Edit 8 | 9 | Download from repository and set user. 10 | 11 | ```git 12 | git clone URL 13 | git config user.name "NAME" 14 | git config user.email "EMAIL" 15 | ``` 16 | 17 | Make changes and upload back. 18 | 19 | ```git 20 | git status 21 | git add . 22 | git commit -m "MESSAGE" 23 | git push origin master 24 | ``` 25 | 26 | A previously cloned repo on a server can now pull just the changes (clone is used only the first time to create the local repo). 27 | 28 | `git pull` - (`git fetch` + `git merge`) 29 | 30 | Github repo > Clone to local > Push to Github > Pull changes to server 31 | 32 | # Tips 33 | 34 | Master branch = Timeline 35 | 36 | `HEAD` = Last commit on current branch. 37 | 38 | HEAD is the symbolic name for the currently checked out commit -- it's essentially what commit you're working on top of. 39 | 40 | Commit messages should be in the present tense instead of past. They should tell what a commit does instead of what happened. Ex. Add new module vs Added new module. 41 | 42 | Git uses vi as the default editor. 43 | 44 | # Setup 45 | 46 | ```bash 47 | # Initialize an empty repo inside a .git hidden directory. 48 | git init 49 | ``` 50 | 51 | ## Git Ignore 52 | 53 | This is a list of files/folders to be ignored in commits. To use it, create a `.gitignore` file in the working directory, **NOT** inside `.git`. 54 | 55 | Each line in the file is a new ignore rule. Ex. To ignore `node_modules/`, just add that as one line. 56 | 57 | If the ignoring is added after committing the files to be ignored, they need to be untracked. Use `git rm -r --cached .` to untrack everything, and the `git add/git commit`. **Careful as this can lose progress to files.** 58 | 59 | Also, pattern matching can be used to ignore specific files in specific places. Ex. `*.txt` ignores all text files, while `routes/*.js` ignores all javascript files in that folder. To ingore a folder, use `FOLDER/`. 60 | 61 | Finally, use `#` to comment. 62 | 63 | # Workflow 64 | 65 | it's generally considered good practice to avoid merges where possible. 66 | 67 | A good workflow is to leave the `master` for production and do all the coding in a separate `develop` branch. The `develop` branch can expand into `feature` branches which would later be merged back. When a certain stable version is reached in `develop`, it can be merged with `master` along with a version tag. 68 | 69 | Additonal brances such as `release` and `hotfix` can be introduced between the `master` and `develop` ones. 70 | 71 | If a branch is not shown, it's due to fast-forwarding i.e. no changes were made in the branch being merged into, hence the simpler merge log. 72 | 73 | # Example Project 74 | 75 | ``` 76 | * e67ccc4 (HEAD -> master) Merge branch 'header' 77 | |\ 78 | | * ce37b16 (header) Fix original header 79 | * | 707692c Merge branch 'footer' 80 | |\ \ 81 | | * | 2dc6e90 (footer) Expand footer 82 | | * | fd61a63 Create footer.html 83 | * | | 8083e87 Add fifth bla in CAPS 84 | * | | 8d56117 Add fourth bla in index.html 85 | * | | 86c50f0 Added third bla in index.html 86 | |/ / 87 | | | * 26326bb (header2) Fix header2 version 88 | | | * d83bebc Modify header into version 2 89 | | |/ 90 | | * c2d4091 Create header.html 91 | |/ 92 | * 9524ae9 Create index.html 93 | ``` 94 | 95 | # Help 96 | 97 | ```bash 98 | # List all the commands. 99 | git help 100 | 101 | # Explain a specific command. 102 | git help COMMAND 103 | ``` 104 | 105 | # Configuration 106 | 107 | ```bash 108 | # Setting up owner of changes for all repos. Github contributions count only with the github email. 109 | git config --global user.name "NAME" 110 | git config --global user.email "EMAIL" 111 | ``` 112 | 113 | # Staging 114 | 115 | ```bash 116 | # What changed since last commit? 117 | git status 118 | 119 | # Stage an untracked file for committing. 120 | git add FILENAME 121 | 122 | # Multiple files. 123 | git add FILENAME FILENAME 124 | 125 | # A folder. 126 | git add FOLDER/ 127 | 128 | # All specific file types. 129 | git add *.js 130 | 131 | # ... in a folder. 132 | git add FOLDER/*.js 133 | 134 | # ... in whole project. 135 | git add "*.js" 136 | 137 | # Track everything. 138 | git add . 139 | 140 | # Unstage files. 141 | git reset HEAD FILENAME 142 | ``` 143 | 144 | # Committing 145 | 146 | Each commit moves the HEAD further up the timeline. 147 | 148 | ```bash 149 | # Commit changes with inline message. 150 | git commit -m "MESSAGE" 151 | ``` 152 | 153 | If the `-m` is ommited, the screen will move to the `vi` text editor, which can be exited with `:q`. 154 | 155 | # Tagging 156 | 157 | A reference to a specific commit, used mostly for release versioning. 158 | 159 | ```bash 160 | # Create tag. 161 | git tag -a v0.0.1 -m "Version 0.0.1" 162 | 163 | # List tags. 164 | git tag 165 | 166 | # Open a specific version. 167 | git checkout v0.0.1 168 | 169 | # Push tags to remote repo. 170 | git push --tags 171 | ``` 172 | 173 | # See Changes / Diff 174 | 175 | ```bash 176 | # Commit history. 177 | git log 178 | 179 | # Show unstaged differences since last commit. 180 | git diff 181 | 182 | # Show differences after staging. 183 | git diff --staged 184 | 185 | # Show differences between current and specific commit. 186 | git diff HASH 187 | ``` 188 | 189 | ## Tree 190 | 191 | ```bash 192 | # A visual tree with branch names included. 193 | git log --oneline --decorate --all --graph 194 | 195 | # Add the "tree" alias as a shortcut. 196 | git config --global alias.tree "log --oneline --decorate --all --graph" 197 | ``` 198 | 199 | # Undo 200 | 201 | DON'T DO THESE AFTER PUSHING! 202 | 203 | ```bash 204 | # Revert a file to the last commit version. 205 | git checkout -- FILENAME 206 | 207 | # UNDO commit and move everything back to staging. The carrot on the HEAD means move to the previous commit. 208 | git reset --soft HEAD^ 209 | 210 | # DELETE the last 2 commits. 211 | git reset --HARD HEAD^^ 212 | 213 | # DELETE everything after the specified commit. 214 | git reset --HARD HASH 215 | 216 | # Change last commit with overriding message. 217 | git commit --amend -m "MESSAGE" 218 | 219 | # Force change on GitHub. Git interprets the "^" after the hash as the parent of this very commmit, and the "+" as a force push. 220 | git push origin +hash^:master 221 | ``` 222 | 223 | # Remote 224 | 225 | A project can have multiple remotes ex. origin, test, production... 226 | 227 | ```bash 228 | # Add a remote i.e. bookmark a repo i.e. This NAME = this URL. The name is usually "origin", but it can be anything. 229 | git remote add NAME URL 230 | 231 | # List all remotes. 232 | git remote -v 233 | 234 | # Check a remote. 235 | git remote show origin 236 | 237 | # Remove a remote. 238 | git remote rm NAME 239 | ``` 240 | 241 | # Push 242 | 243 | Define which local branch (usually master) to push to which repository (usually origin). It asks for user and pass. 244 | 245 | ```bash 246 | # git push -u REPO_NAME BRANCH_NAME 247 | git push -u origin master 248 | ``` 249 | 250 | `-u` remember the repo and the branch, so that only `git push` can be used. 251 | 252 | # Pull 253 | 254 | Used to update the local repo with the latest changes. Should be done often. 255 | 256 | ```bash 257 | git pull 258 | ``` 259 | 260 | Behind the scenes, this creates an origin/master branch which is automatically merged into the master one, unless there is a merge conflict. 261 | 262 | ## Pull Requests 263 | 264 | Once someone completes a feature, they don’t immediately merge it into master. Instead, they push the feature branch to the central server and file a pull request asking to merge their additions into master. 265 | 266 | This gives other developers an opportunity to review the changes before they become a part of the main codebase. 267 | 268 | You can think of pull requests as a discussion dedicated to a particular branch. 269 | 270 | For example, if a developer needs help with a particular feature, all they have to do is file a pull request. Interested parties will be notified automatically, and they’ll be able to see the question right next to the relevant commits. 271 | 272 | Once a pull request is accepted, the actual act of publishing a feature is much the same as in the Centralized Workflow. First, you need to make sure your local master is synchronized with the upstream master. Then, you merge the feature branch into master and push the updated master back to the central repository. 273 | 274 | # Clone 275 | 276 | ```bash 277 | # Create a local repository from a remote one. 278 | git clone URL 279 | 280 | # ... with a different name. 281 | git clone URL NEW_NAME 282 | ``` 283 | 284 | Cloning does: 285 | 286 | - Download entire repo into a new local one. 287 | - Add "origin" remote, pointing to the clone URL. 288 | - Check out initial branch. (Set head to master) 289 | 290 | # Branch 291 | 292 | **Do not mess with the master**. The master branch is deployable production code, meant to be stable. Instead, work on new features in separate branches, which would then be `merged` or `rebased` into master. 293 | 294 | **Branches are local**, meaning they cannot be worked on at the same time. 295 | 296 | Branches in Git are incredibly lightweight as well. They are simply pointers to a specific commit -- nothing more. This is why many Git enthusiasts chant the mantra: **branch early, and branch often**. 297 | 298 | Because there is no storage / memory overhead with making many branches, it's easier to logically divide up your work than have big beefy branches. 299 | 300 | A branch essentially says "I want to include the work of this commit and all parent commits." 301 | 302 | Switching branches will only show the files in that branch. 303 | 304 | #### Create 305 | 306 | ```bash 307 | # Create new branch. HEAD still on master (Use checkout to switch). 308 | git branch 309 | 310 | # Create AND move to a branch. 311 | git checkout -b 312 | 313 | # Create a remote branch. Usually origin. 314 | git push 315 | ``` 316 | 317 | #### Navigate 318 | 319 | ```bash 320 | # Check which branch we are on. 321 | git branch 322 | 323 | # Check remote branches. 324 | git branch -r 325 | 326 | # Move to a specific branch (Set HEAD from master to ). This is like switching timelines. 327 | git checkout 328 | ``` 329 | 330 | #### Delete 331 | 332 | ```bash 333 | # Delete a branch. 334 | git branch -d 335 | 336 | # Delete a remote branch 337 | git push --delete 338 | ``` 339 | 340 | ## Merge 341 | 342 | **The merging is done from the perspective of where we merge `INTO`.** 343 | 344 | Merging in Git creates a special commit that has two unique parents. A commit with two parents essentially means "I want to include all the work from this parent over here and this one over here, and the set of all their parents." 345 | 346 | Move (checkout) to the branch (master) you want to merge into, and use: 347 | 348 | ```bash 349 | git merge BRANCH_NAME 350 | ``` 351 | 352 | `master` now points to a commit that has two parents. If you follow the arrows up the commit tree from master, you will hit every commit along the way to the root. This means that master contains all the work in the repository now. 353 | 354 | Merging is very easy if the master branch is not modified. This is fast-forwarding. 355 | 356 | If both branches were modified, a commit is created to do the merge. (Vi editor opens for the message) 357 | 358 | ``` 359 | 0 360 | |\ 361 | 2 1 - 2 master, 1 branch 362 | |/ 363 | 3 - master assimilates branch 364 | ``` 365 | 366 | ## Rebase 367 | 368 | **The "merging" is done from the perspective of where we merge `FROM`.** 369 | 370 | The second way of combining work between branches is rebasing. Rebasing essentially takes a set of commits, "copies" them, and plops them down somewhere else i.e. it serializes the history if you do not want a lot of branches in the final history. 371 | 372 | While this sounds confusing, the advantage of rebasing is that it can be used to make a nice linear sequence of commits. The commit log / history of the repository will be a lot cleaner if only rebasing is allowed. 373 | 374 | Move (checkout) to the branch (BRANCH_NAME) you want to merge from, and use: 375 | 376 | ```bash 377 | git rebase master 378 | ``` 379 | 380 | **This makes it look like two features were developed sequentially, when in reality they were developed in parallel.** 381 | 382 | ``` 383 | 0 384 | |\ 385 | 1 1 - 1 branch 386 | | 387 | 2 - 2 master 388 | | 389 | 3 - branch (1) was added to the original timeline. 390 | ``` 391 | 392 | # Example Workflows 393 | 394 | ## Work on a new admin feature, fix a bug in master, and merge the new admin feature. 395 | 396 | Create a new branch and add features. Each commit moves the HEAD. 397 | 398 | ``` 399 | git checkout -b admin 400 | 401 | git add admin/dashboard.html 402 | git commit -m "Add dashboard" 403 | 404 | git add admin/users.html 405 | git commit -m "Add user admin" 406 | ``` 407 | 408 | Fix bugs on master. Move to the master branch, check that we are on it and pull the latest changes from the remote. Push changes to remote. 409 | 410 | ``` 411 | git checkout master 412 | 413 | git branch 414 | 415 | git pull 416 | 417 | git add store.rb 418 | git commit -m "Fix store bug" 419 | 420 | git add product.rb 421 | git commit -m "Fix product" 422 | 423 | git push 424 | ``` 425 | 426 | Move back to the admin feature to finish changes. When done, move to master branch and merge with admin. 427 | 428 | ``` 429 | git checkout admin 430 | 431 | git checkout master 432 | 433 | git merge admin 434 | ``` 435 | 436 | What the timeline (master) looks like. \* = commit. 437 | 438 | ``` 439 | * - Merge 440 | |\ 441 | | * - Admin feature 442 | * | - Bug fix 443 | * | - Bug fix 444 | | * - Admin feature 445 | |/ 446 | * - Last commit before branch 447 | ``` 448 | 449 | # Useful 450 | 451 | While we all used git (and Github) in college to collaborate and save code, we mainly stuck to the the basic "add, commit, push" flow and didn't really go outside of that much, mainly because we didn't know it all that well at the time. But looking back after 2+ years of using [git] in a professional environment, here was out shortlist of things we wish we knew git could do (in order of importance) 452 | 453 | 1. **git reset HEAD** 454 | If you could learn one thing about git besides how to commit and push, this would be it. When you commit to git, those commits generate a log that is identified by a commit hash. By using the command `git reset HEAD ` (there are other variants, this is the most straightforward), you can essentially go back in time in your code. What this is great for is if you are in a point in your project where you are pretty certain _you're going to fuck something up_, committing is like doing a quick save in a video game right before a boss fight. Something goes wrong, reset to the last commit. 455 | 456 | 2. **Branching and Pull Request Workflow** 457 | In college we all worked off a single branch pushing our code up to save it. While this worked, the occasional push by a teammate who didn't properly test their code caused our project to crash and one of us having to fix it (this usually happened <12 hours before deadlines). Branching and pull requests would have eliminated that. Not only are they working on a different branch so pushing up won't mess with the original copy. When they want to merge their code, going through a PR (pull request) process will involve the code getting reviewed by another person to make sure it all works. 458 | 459 | 3. **git init** 460 | When I first started with git I always thought that you had to have a remote somewhere to use it (ie on github or gitlab). As I have learned that is not the case, you can initialize a git repository in any directory and commit any files, you are only restricted from pushing until you add a remote (duh). This is great to pair with the 1st tip, even if you are working by yourself. Having the ability to go back if you mess something up is essential. 461 | 462 | TBH that's really it. Git is a _very_ complex application that even I haven't fully learned yet. However, it has a fairly easy learning curve letting you take advantages of the most important bits quickly. If you have any questions feel free to post below and I'll be happy to answer best I can. 463 | --------------------------------------------------------------------------------