# Node.js
## NPM
Whenever creating a new node project, use to set it up
```
npm init
```
[NPM](https://www.npmjs.com/) is a package manager for node.js and js libraries and frameworks. You can look up packages there, and install them for your project with:
```
npm install package-name --save
```
## module.exports/require
Traditionally, importing JS files into other JS files has not been supported... until now! There are several ways to do this, but node allows you to add things the to module.exports object.
```javascript
module.exports = 'foo';
```
Whatever is on there, will be the return value of
```javascript
require('yourJSFile.js');
```
You can assign this to a variable to use later
## Instantation
First install express with `npm install express --save` and require it
```javascript
var express = require('express'); //include express package
```
`express` has lots of abilities, but we just want to start up a server app:
```javascript
var app = express(); // create an express app
```
Then make it listen on a port
```javascript
app.listen(3000, function(){ //start the server
console.log('listening on port ' + PORT);
});
```
## CRUD and HTTP Verbs
In comp sci, there are different kinds of action you can take on data
- create
- read
- update
- destroy
There are different kinds of 'methods' you can use to make a request to a server that map to these actions:
- post (create)
- get (read)
- put/patch (update)
- delete (delete)
PUT is for updating an entire model, PATCH is for changing just a few attributes
## Routing
Basic routing can be done at the app level
```javascript
app.get('/', function(req, res){ // route for /
res.send('hi'); //respond with 'hi'
});
```
This sets up an event listener for any GET request that comes into the server with the path of `/`. Give it a callback function which takes a request variable and a respond variable. Each of these have different methods/properties which we'll learn about
## Middleware
We can define a callback function that is called or all requests and then continues on to other request handlers
```javascript
app.use(function(req, res, next){
console.log('middleware');
next();
})
```
`next();` tells express to continue processing the request. `app.get(),app.post()`, etc have this ability too, but it's rarely used.
Just like with `app.get(),app.post()`, etc we can add the ability to handle just those requests that match a url pattern
```javascript
app.use('/foo', function(req, res, next){
console.log('middleware');
next();
})
```
## MVC
One of the main goals of express is to cleanly separate data from the view layer. To do this, it follows the Model View Controller pattern, which creates a middleman (Controller) which passes data (Models) off to the presentation/html (View) layer
In addition, putting all your routes inside server.js can become difficult to maintain with a lot of variables. We can group similar urls together into separate "controller" files.
```javascript
var runsController = require('./controllers/runs.js'); //require our own runsController
app.use('/runs/', runsController); //use it for anything starting with /runs
```
Now, create a controllers directory, create an appropriately named file, and use:
```javascript
var controller = require('express').Router(); //require express and create a router (controller)
controller.get('/', function(req, res){ //route for finding all routes by a the session user
res.send('runs index');
});
module.exports = controller;
```
## Views
Let's separate the views from the controller. Install express with `npm install ejs --save`
Create a directory called 'views' and create an appropriately named file with the extension .ejs. Now we can reference it. Express will assume the file path starts with the 'views' directory you created.
```javascript
var controller = require('express').Router(); //require express and create a router (controller)
controller.get('/', function(req, res){ //route for finding all routes by a the session user
res.render('viewFile.ejs');
});
module.exports = controller;
```
EJS files are just html, but you can use javascript to dynamically create HTML:
```html
<% for(var i = 0; i < 4; i++) { %>
-
<%= i %>
<% } %>
```
You can pass data into the view file by adding a second parameter that's an object. The properties of the object will become the variable name that's accessible in the view file.
```javascript
var controller = require('express').Router(); //require express and create a router (controller)
controller.get('/', function(req, res){ //route for finding all routes by a the session user
res.render('viewFile.ejs', {
variable1Name: 'variable 1 value'
});
});
module.exports = controller;
```
Now inside the .ejs file, we can access `variable1Name` like so:
```html
Value: <%= variable1Name; %>
```
## URL Params/Query Strings
Data can be passed to the server through query strings (a.ka. GET parameters) which look like ?param1=value1¶m2=value2
They can be accessed like so:
```javascript
app.get('/', function(req, res){
var param1 = req.query.param1;
var param2 = req.query.param2;
});
```
Your route can also have parameters in the path section
```javascript
app.get('/:id', function(req, res){
var id = req.params.id;
});
```
## Body Parser
We can also pass data to server in the body of the request.
### Form data
```html
```
`npm install body-parser --save` and require it
```javascript
var bodyParser = require('body-parser');
```
Next, tell express to expect form data
```javascript
app.use(bodyParser.urlencoded({ extended: false })) //tell body parser that we'll be passing in form data
```
Then, inside any request handler, we can access the form data, formatted as a JS object:
```javascript
app.post('/run', function(req, res){
var param1 = req.body.param1;
});
```
### JSON
Install and require `body-parser` as before, but the middleware changes:
```javascript
controller.use(bodyParser.json()); //anything handled by this controller is expecting JSON data, not form data
```
Now instead of using form data, we can use Postman. Create a new tab, choose method, select "body", choose "raw", click on Text dropdown and choose JSON(application/json). Make sure Headers have a line for "Content-Type" set to "application/json"
We can capture the `req.body` params the same way as with form data.
## Method Override
Unfortunately, forms can only use methods that are GET or POST. To fake DELETE, or PUT/PATCH we use the package `method-override`. Install it using `npm install method-override --save` and require it
```javascript
var methodOverride = require('method-override');
```
Use it:
```javascript
controller.use(methodOverride('_method')); //tell method override to expect ?method=PUT/DELETE attached to POST requests
```
Then in our form we add an extra get param (the param name must match what's passed to the methodOverride function):
```html
```
Now the appropriate route handler will handle the request
```javascript
app.delete('/runs', function(req, res){
});
```
## REST
There are seven routes which control basic HTTP operations for data:
https://gist.github.com/alexpchin/09939db6f81d654af06b
| **URL** |**HTTP Verb**|**Action**|
|-----------------|-------------|----------|
| /photos/ | GET | index |
| /photos/new | GET | new |
| /photos | POST | create |
| /photos/:id | GET | show |
| /photos/:id/edit| GET | edit |
| /photos/:id | PATCH/PUT | update |
| /photos/:id | DELETE | destroy |
## Session
Cookies are used in browsers to store data on a user's computer. This way, when the user returns, the site can use that data to customize the app. Cookies are stored in plain-text though, so typically we use sessions, which are encrypted cookies that only last as long as the user's browser is open.
`npm install express-session --save` and require it:
```javascript
var session = require('express-session'); //include express sessions for session work
```
Now we "use" it:
```javascript
app.use(session({ //setting up session encryption info
secret: "seakrett", //unique keyword for encrypting session data
resave: false, // don't resave session if nothing changed
saveUninitialized: false //even if no data, set a cookie
}));
```
To set data, simply run:
```javascript
req.session.userData = 'some value';
```
To get data, simply run:
```javascript
var userData = req.session.userData;
```
## Bcrypt
To encrypt information, we `npm install bcrypt --save` and require it:
```javascript
var bcrypt = require('bcrypt');
```
To encrypt a value:
```javascript
var encryptedValue = bcrypt.hashSync('value to encrypt', bcrypt.genSaltSync(10));
```
genSaltSync determines how difficult it is to crack the encryption. The higher the number, the harder it is, but the longer it takes. 10 is usually good.
Using this technique, the same starting value will not be encrypted the same way twice. This prevents from a hacker from guessing other users' passwords based on matching encrypted values. This means that we can never decrypt a salted value. Instead, we can only compare it with another salted value to see if they so close that they can't be anything but the same.
```javascript
var valuesMatch = bcrypt.compareSync('does salted value match this?', saltedValue);
```
## Static
## Database