NodeJS
REQUIRED TOOLS Browser: Chrome https://www.google.com/chrome/browser/desktop/index.html NodeJS (current) 8.6 https://nodejs.org API tester: Postman (as plugin for Chrome) IDE: Jetbrains Webstorm / Jetbrains IntelliJ IDEA MongoDB Community Server https://www.mongodb.com/download-center#community Robo3T – MongoDB GUI Client https://robomongo.org/download
NodeJS Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
Where to host NodeJS app ? Amazon Web Services – Free Tier https://aws.amazon.com/free/ Google cloud platform – free trial https://cloud.google.com/nodejs/ Microsoft Azure – free trial https://docs.microsoft.com/en-us/nodejs/azure/?view=azure-node-2.0.0 Private VPS / Hosting
CREATING NODEJS PROJECT Manually npm init Webstorm: File->New->Project
ADDING PACKAGES New node_modules directory created Package.json: TIP: npm i –S <package_name>@<version> npm i –S express@4.14.0 { "name": "my-first-app", "version": "1.0.0", "description": "Some description", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Krzysztof Bzowski", "license": "ISC", "dependencies": { "express": "^4.16.0" } TIP: npm install Will install all mising dependencies
ADDING PACKAGES VIA WEBSTORM File -> Settings -> Languages & Frameworks -> Node.js and NPM
PREPARATIONS – SIMPLE VERSION! Directory structure Project root node_modules src public Api Files: server.js api/index.js Starting script: package.json { […] "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node dist\server.js" }, […] }
PREPARATIONS – CODING ASSISTANCE File -> Settings -> Languages & Frameworks | Node.js and npm
BABEL The compiler for writing next generation JavaScript npm i -D babel-cli npm i -D babel-preset-env Webstorm: Files -> Settings -> Tools -> File Watchers
RUNNING - WEBSTORM Run -> Edit configuration Start Debug
Server Config Create file config.js EDITOR TRANSPILED BY BABEL const env = process.env; export const nodeEnv = env.Node_ENV || 'development' export default { port: env.PORT || 8080 }; 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var env = process.env; var nodeEnv = exports.nodeEnv = env.Node_ENV || 'development'; exports.default = { port: env.PORT || 8080 }; //# sourceMappingURL=config.js.map
Server – server.js Local module Core module Event emiter object import config, {nodeEnv} from "./config"; import http from 'http' Core module Event emiter object const server = http.createServer(); server.listen(8080); server.on('request', (req, res) => { // Handle request }); Event callback with parameters: Request Response
Server – server.js import config, {nodeEnv} from "./config"; import http from 'http' const server = http.createServer(); server.listen(8080); server.on('request', (req, res) => { // Handle request res.write('Hello HTTP!\n'); res.end(); });
Testing - Postman Request type Bookmark Send request RESPONSE
Express.js Core HTTP module is powerfull but with growing application it will be very hard to handle all requests. This is why Express framework (and many more) were created import config, {nodeEnv} from "./config"; import express from 'express' const server= express(); // Routing server.get('/', (req, res) => { res.send('Hello express'); }); server.listen(config.port, () => { console.log('Express listening on port ', config.port); });
Express.js - routing import config, {nodeEnv} from "./config"; import express from 'express' const server= express(); // Routing server.get('/', (req, res) => { res.send('Hello express'); }); server.get('/about', (req, res) => { res.send('This is Express App on ' + config.port); }); server.listen(config.port, () => { console.log('Express listening on port ', config.port); });
Express.js – return file import fs from "fs"; […] server.get('/about.html', (req, res) => { fs.readFile('./public/about.html', (err, data) => { res.send(data.toString()); }) }); ./public/about.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>About</title> </head> <body> <h1>About</h1> <p>This is Express App!</p> </body> </html>
Express.js – menage static files No fs module No routing ./server.js: […] server.use(express.static('public’));
Express.js - Routing ./api/index.js: ./server.js: import express from 'express' const router = express.Router(); router.get('/', (req, res) => { res.send({data: []}) }); export default router; ./server.js: import config, {nodeEnv} from "./config"; import apiRouter from './api' import express from 'express' const server= express(); server.use('/api', apiRouter); server.use(express.static('public')); server.listen(config.port, () => { console.log('Express listening on port ', config.port); });
REST Representational state transfer (REST) or RESTful web services GET == Read POST == Create PUT == Update PATCH == Modify (partially) DELETE = Remove
REST HTTP Methods POST Create GET Read PUT Update/Replace PATCH HTTP Verb CRUD Entire Collection (e.g. /collection) Specific Item (e.g. /collection/{id}) POST Create 201 (Created), 'Location' header with link to /collection/{id} containing new ID. 404 (Not Found), 409 (Conflict) if resource already exists.. GET Read 200 (OK), list of customers. Use pagination, sorting and filtering to navigate big lists. 200 (OK), single customer. 404 (Not Found), if ID not found or invalid. PUT Update/Replace 405 (Method Not Allowed), unless you want to update/replace every resource in the entire collection. 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. PATCH Update/Modify 405 (Method Not Allowed), unless you want to modify the collection itself. DELETE Delete 405 (Method Not Allowed), unless you want to delete the whole collection—not often desirable. 200 (OK). 404 (Not Found), if ID not found or invalid.
Handling errors ./api/index.js: […] router.get('/user/:id', (req, res) => { if(req.params.id == 1){ res.send({ id: 1, name: 'Krzysztof' }) } else { res.status(404).send({ error: 'user not found' }) } });
POST ./server.js: ./api/index.js: import bodyParser from 'body-parser’ […] const server = express(); server.use(bodyParser.json()); ./api/index.js: router.post('/user', (req, res) => { console.log(req.body); res.send(req.body); console.log(`Trying to create ${req.body.name} user.`); });
POST REQUEST BODY RESPONSE BODY
MongoDB Running server "c:\Program Files\MongoDB\Server\3.4\bin\mongod.exe" --dbpath=e:\MongoDB\ TIP: Make an desktop shortcut with this command! Database storage Some convenient path with write access (i.e. home directory)
MongoDB
MongoDB Create database
MongoDB Create collection with example data { "name" : "Krzysztof", "role" : "teacher" }
MongoDB Browse data
MongoDB – Access from NodeJS npm i -S mongodb ./config.js: const env = process.env; export const nodeEnv = env.Node_ENV || 'development'; export default { mongoUri: 'mongodb://localhost:27017/ie2017NS', port: env.PORT || 8080 };
MongoDB – Access from NodeJS import {MongoClient, ObjectID} from 'mongodb' import assert from 'assert' import config from '../config' let mdb; MongoClient.connect(config.mongoUri, (err, db) => { assert.equal(null, err); mdb = db; }); const router = express.Router(); router.get('/user', (req, res) => { let users = {}; mdb.collection('User').find({}).toArray(function(err, docs) { docs.forEach((doc) => { users[doc._id] = doc; }); res.send(users); }); });
MongoDB – filter data router.get('/user/:userId', (req, res) => { let users = {}; mdb.collection('User') .findOne({_id : ObjectID(req.params.userId)}) .then(user => res.send(user)) .catch(console.error) });
MongoDB – Inserting documents router.post('/user', (req, res) => { const name = req.body.name; const role = req.body.role; mdb.collection('User').insertOne({ name, role }).then(result => { res.send(result.insertedId) }) });
MongoDB – Update document router.put('/user/:userId', (req, res) => { let uid = req.params.userId; const role = req.body.role; mdb.collection('User').findOneAndUpdate( {_id: ObjectID(uid)}, { $set: { role } }, {new: true} ).then(result => { if (result.ok === 1) { res.send(''); } else { res.status(404).send({'Error': 'User not found'}) } }).catch(err => { let g = 3; }) });
MongoDB – Delete document router.delete('/user/:userId', (req, res) => { let uid = req.params.userId; mdb.collection('User').deleteOne( {_id: ObjectID(uid)} ).then(result => { if(result.deletedCount === 0){ res.status(404).send({'Error': 'User not found'}) } else { res.send(''); } }) });