├── .gitignore ├── Chapter02 ├── communicating-with-sockets │ ├── client.js │ └── server.js ├── fetching-metadata │ ├── .DS_Store │ ├── chmod-octal.js │ ├── chmod.js │ ├── file.txt │ └── metadata.js ├── file-watching │ ├── file.txt │ ├── package-lock.json │ ├── package.json │ └── watch.js ├── interfacing-with-io │ ├── greeting.js │ └── greeting2.js └── working-with-files │ ├── .DS_Store │ ├── hello.txt │ ├── readWriteAsync.js │ ├── readWriteAsync2.js │ ├── readWriteAsyncNamed.js │ ├── readWriteAsyncTimeout.js │ ├── readWritePromise.js │ └── readWriteSync.js ├── Chapter03 ├── learning-streams │ ├── async-generator.js │ ├── for-await-read-stream.js │ ├── infinite-read.js │ ├── paused-stream.js │ ├── read-stream.js │ └── write-stream.js ├── object-streams │ ├── object-stream.js │ ├── package-lock.json │ └── package.json ├── piping-streams │ ├── file.txt │ └── pipe-stream.js ├── stream-pipelines │ ├── file.txt │ ├── newFile.txt │ ├── pipeline.js │ └── promise-pipeline.js └── transform-stream │ ├── file.txt │ ├── newFile.txt │ ├── transform-stream-es6.js │ └── transform-stream.js ├── Chapter04 ├── file-upload │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── form.html │ └── server.js ├── http-server │ └── server.js ├── making-requests │ └── requests.js ├── post-server │ ├── json-server.js │ ├── public │ │ └── form.html │ └── server.js ├── server-smtp │ ├── package-lock.json │ ├── package.json │ ├── send-email.js │ └── server.js └── websocket-server │ ├── client.js │ ├── node-client.js │ ├── package-lock.json │ ├── package.json │ ├── public │ └── index.html │ └── server.js ├── Chapter05 ├── consuming-modules │ ├── package-lock.json │ ├── package.json │ └── require-express.js ├── ecmascript-modules │ ├── .gitignore │ ├── get-name │ │ └── index.mjs │ ├── package-lock.json │ ├── package.json │ └── server.mjs └── reverse-sentence │ ├── .gitignore │ ├── .npmignore │ ├── README.md │ ├── index.js │ ├── package-lock.json │ └── package.json ├── Chapter06 ├── express-app-ejs │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── styles.css │ ├── routes │ │ └── index.js │ └── views │ │ └── index.ejs ├── express-app-generated │ ├── app.js │ ├── bin │ │ └── www │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── views │ │ ├── error.ejs │ │ └── index.ejs ├── express-app │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── styles.css │ └── routes │ │ └── index.js ├── express-custom-middleware │ ├── app.js │ ├── middleware │ │ └── logger.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── styles.css │ └── routes │ │ └── index.js ├── express-post-app │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── styles.css │ └── routes │ │ └── index.js ├── fastify-app │ ├── package-lock.json │ ├── package.json │ ├── server.js │ └── test.js ├── fastify-generated-app │ ├── .gitignore │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── plugins │ │ ├── README.md │ │ └── support.js │ ├── services │ │ ├── README.md │ │ ├── example │ │ │ └── index.js │ │ └── root.js │ └── test │ │ ├── helper.js │ │ ├── plugins │ │ └── support.test.js │ │ └── services │ │ ├── example.test.js │ │ └── root.test.js ├── fastify-plugin-app │ ├── .vscode │ │ └── settings.json │ ├── package-lock.json │ ├── package.json │ ├── plugins │ │ └── hello-route.js │ ├── server.js │ └── test.js ├── hapi-app │ ├── .vscode │ │ └── settings.json │ ├── package-lock.json │ ├── package.json │ └── server.js ├── hapi-static-app │ ├── .vscode │ │ └── settings.json │ ├── files │ │ └── file.txt │ ├── package-lock.json │ ├── package.json │ └── server.js ├── hapi-static │ ├── .vscode │ │ └── settings.json │ ├── files │ │ └── file.txt │ ├── package-lock.json │ ├── package.json │ └── server.js ├── hapi-views-app │ ├── .vscode │ │ └── settings.json │ ├── package-lock.json │ ├── package.json │ ├── server.js │ └── views │ │ └── index.ejs ├── koa-app │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── styles.css │ └── routes │ │ └── index.js ├── koa-cascade │ ├── app.js │ ├── package-lock.json │ └── package.json ├── koa-custom-middleware │ ├── app.js │ ├── middleware │ │ └── logger.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── styles.css │ └── routes │ │ └── index.js └── koa-views-app │ ├── app.js │ ├── package-lock.json │ ├── package.json │ ├── public │ └── styles.css │ ├── routes │ └── index.js │ └── views │ └── index.ejs ├── Chapter07 ├── leveldb-app │ ├── package-lock.json │ ├── package.json │ └── tasks.js ├── leveldb-filter │ ├── filter.js │ ├── package-lock.json │ └── package.json ├── leveldb-memdown-app │ ├── package-lock.json │ ├── package.json │ └── tasks.js ├── mongodb-app │ ├── package-lock.json │ ├── package.json │ └── tasks.js ├── mongoose-app │ ├── customers.js │ └── package-lock.json ├── mysql-app │ ├── .env │ ├── insert.js │ ├── package-lock.json │ ├── package.json │ └── tasks.js ├── postgres-app │ ├── .env │ ├── package.json │ └── tasks.js ├── postgres-object-app │ ├── .env │ ├── package-lock.json │ └── tasks.js └── redis-app │ ├── package-lock.json │ ├── package.json │ ├── tasks-auth.js │ └── tasks.js ├── Chapter08 ├── enabling-travis │ ├── .gitignore │ ├── .travis.yml │ ├── package-lock.json │ ├── package.json │ └── test.js ├── stubbing-http-requests │ ├── github.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── octokitUserData.js │ │ └── test.js ├── testing-with-jest │ ├── coverage │ │ ├── clover.xml │ │ ├── coverage-final.json │ │ ├── lcov-report │ │ │ ├── base.css │ │ │ ├── block-navigation.js │ │ │ ├── favicon.png │ │ │ ├── index.html │ │ │ ├── prettify.css │ │ │ ├── prettify.js │ │ │ ├── sort-arrow-sprite.png │ │ │ ├── sorter.js │ │ │ └── uppercase.js.html │ │ └── lcov.info │ ├── package-lock.json │ ├── package.json │ ├── test │ │ └── test.js │ └── uppercase.js ├── testing-with-mocha │ ├── calculator.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ └── test.js ├── testing-with-tape │ ├── calculator.js │ ├── package-lock.json │ ├── package.json │ └── test │ │ └── test.js └── using-puppeteer │ ├── package-lock.json │ ├── package.json │ └── test │ └── test.js ├── Chapter09 ├── audit-deps │ ├── package-lock.json │ └── package.json ├── express-auth │ ├── package-lock.json │ ├── package.json │ ├── routes │ │ ├── auth.js │ │ └── index.js │ ├── server.js │ └── views │ │ ├── index.ejs │ │ └── login.ejs ├── express-csrf │ ├── csrf-server.js │ ├── csurf-server.js │ ├── fixed-server.js │ ├── package-lock.json │ ├── package.json │ └── server.js ├── express-helmet │ ├── package-lock.json │ ├── package.json │ └── server.js ├── express-input │ ├── fixed-server.js │ ├── package-lock.json │ ├── package.json │ └── server.js ├── express-xss │ ├── collection-server.js │ ├── constraints-server.js │ ├── fixed-server.js │ ├── package-lock.json │ ├── package.json │ ├── protocol-safe-server.js │ └── server.js ├── hashing-with-bcrypt │ ├── hash.js │ ├── package-lock.json │ ├── package.json │ └── validate-password.js ├── http-app │ └── server.js └── json-pollution │ ├── fixed-server.js │ ├── package-lock.json │ └── server.js ├── Chapter10 ├── benchmarking-http │ ├── app.js │ ├── bin │ │ └── www │ ├── package-lock.json │ ├── package.json │ ├── post-server.js │ ├── public │ │ ├── index.html │ │ └── stylesheets │ │ │ └── style.css │ └── routes │ │ ├── index.js │ │ └── users.js ├── benchmarking-views │ ├── app.js │ ├── bin │ │ └── www │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── views │ │ ├── error.jade │ │ ├── index.jade │ │ └── layout.jade ├── flamegraph-app │ ├── app.js │ ├── bin │ │ └── www │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── views │ │ ├── error.jade │ │ ├── index.jade │ │ └── layout.jade ├── optimize-async │ ├── calculate-average.js │ ├── package-lock.json │ ├── package.json │ ├── server-no-processing.js │ ├── server.js │ └── values.js ├── optimize-sync │ ├── benchmark.js │ ├── loop.js │ ├── package-lock.json │ ├── package.json │ └── slow.js ├── profiling-memory │ ├── leaky-server.js │ ├── max-listeners.js │ └── server.js └── worker-app │ ├── fibonacci-worker.js │ ├── fibonacci.js │ └── hello-worker.js ├── Chapter11 ├── bookstore-error-handling │ ├── app.js │ ├── bin │ │ └── www │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ ├── inventory.js │ │ └── users.js │ └── views │ │ ├── error.ejs │ │ ├── index.ejs │ │ └── inventory.ejs ├── bookstore-web-app │ ├── .vscode │ │ └── settings.json │ ├── app.js │ ├── bin │ │ └── www │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ ├── inventory.js │ │ └── users.js │ └── views │ │ ├── error.ejs │ │ ├── index.ejs │ │ └── inventory.ejs ├── fastify-microservice │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Dockerfile-run │ ├── app.js │ ├── deployment │ │ ├── fastify-app-svc.yml │ │ └── fastify-app.yml │ ├── package.json │ ├── plugins │ │ ├── README.md │ │ └── support.js │ ├── routes │ │ ├── README.md │ │ ├── example │ │ │ └── index.js │ │ └── root.js │ └── test │ │ ├── helper.js │ │ ├── plugins │ │ └── support.test.js │ │ └── routes │ │ ├── example.test.js │ │ └── root.test.js └── loopback-bookstore │ ├── .dockerignore │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .mocharc.json │ ├── .npmrc │ ├── .prettierignore │ ├── .prettierrc │ ├── .vscode │ ├── settings.json │ └── tasks.json │ ├── .yo-rc.json │ ├── DEVELOPING.md │ ├── Dockerfile │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ └── index.html │ ├── src │ ├── __tests__ │ │ ├── README.md │ │ └── acceptance │ │ │ ├── home-page.acceptance.ts │ │ │ ├── ping.controller.acceptance.ts │ │ │ └── test-helper.ts │ ├── application.ts │ ├── controllers │ │ ├── README.md │ │ ├── books.controller.ts │ │ ├── index.ts │ │ └── ping.controller.ts │ ├── datasources │ │ ├── README.md │ │ ├── index.ts │ │ └── local.datasource.ts │ ├── index.ts │ ├── migrate.ts │ ├── models │ │ ├── README.md │ │ ├── book.model.ts │ │ └── index.ts │ ├── openapi-spec.ts │ ├── repositories │ │ ├── README.md │ │ ├── book.repository.ts │ │ └── index.ts │ └── sequence.ts │ └── tsconfig.json ├── Chapter12 ├── core-debug-logs │ ├── package-lock.json │ ├── package.json │ └── server.js ├── debugging-with-chrome │ ├── package-lock.json │ ├── package.json │ ├── random.js │ └── server.js ├── diagnostic-report │ └── server.js ├── express-debug-app │ ├── package-lock.json │ ├── package.json │ └── server.js ├── express-debug-custom │ ├── package-lock.json │ ├── package.json │ └── server.js ├── express-morgan-app │ ├── app.js │ ├── bin │ │ └── www │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── views │ │ ├── error.ejs │ │ └── index.ejs ├── express-pino-app │ ├── package-lock.json │ ├── package.json │ └── server.js ├── express-winston-app │ ├── app.js │ ├── bin │ │ └── www │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── views │ │ ├── error.ejs │ │ └── index.ejs └── stack-trace-app │ ├── async-stack-trace.js │ ├── package-lock.json │ ├── package.json │ ├── routes.js │ └── server.js ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | -------------------------------------------------------------------------------- /Chapter02/communicating-with-sockets/client.js: -------------------------------------------------------------------------------- 1 | const net = require("net"); 2 | 3 | const HOSTNAME = "localhost"; 4 | const PORT = 3000; 5 | 6 | const socket = net.connect(PORT, HOSTNAME); 7 | 8 | socket.write("World"); 9 | 10 | socket.on("data", (data) => { 11 | console.log(data.toString()); 12 | }); 13 | -------------------------------------------------------------------------------- /Chapter02/communicating-with-sockets/server.js: -------------------------------------------------------------------------------- 1 | const net = require("net"); 2 | 3 | const HOSTNAME = "localhost"; 4 | const PORT = 3000; 5 | 6 | net 7 | .createServer((socket) => { 8 | console.log("Client connected."); 9 | 10 | socket.on("data", (name) => { 11 | socket.write(`Hello ${name}!`); 12 | }); 13 | }) 14 | .listen(PORT, HOSTNAME); 15 | -------------------------------------------------------------------------------- /Chapter02/fetching-metadata/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js-14-Cookbook/b697d5f5cbd36282ee4dc21024d3bd842dc363fc/Chapter02/fetching-metadata/.DS_Store -------------------------------------------------------------------------------- /Chapter02/fetching-metadata/chmod-octal.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const file = "./file.txt"; 3 | 4 | fs.chmodSync(file, 0o664); 5 | -------------------------------------------------------------------------------- /Chapter02/fetching-metadata/chmod.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const file = "./file.txt"; 3 | 4 | fs.chmodSync( 5 | file, 6 | fs.constants.S_IRUSR | 7 | fs.constants.S_IWUSR | 8 | fs.constants.S_IRGRP | 9 | fs.constants.S_IWGRP | 10 | fs.constants.S_IROTH 11 | ); 12 | -------------------------------------------------------------------------------- /Chapter02/fetching-metadata/file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js-14-Cookbook/b697d5f5cbd36282ee4dc21024d3bd842dc363fc/Chapter02/fetching-metadata/file.txt -------------------------------------------------------------------------------- /Chapter02/fetching-metadata/metadata.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const file = process.argv[2]; 3 | 4 | function printMetadata(file) { 5 | try { 6 | const fileStats = fs.statSync(file); 7 | console.log(fileStats); 8 | } catch (err) { 9 | console.error("Error reading file path:", file); 10 | } 11 | } 12 | 13 | printMetadata(file); 14 | -------------------------------------------------------------------------------- /Chapter02/file-watching/file.txt: -------------------------------------------------------------------------------- 1 | dfadfHELLO! 2 | ls 3 | Hello again; 4 | gs 5 | gsgds 6 | gsdsdf 7 | sddsf 8 | sdfsd 9 | sdda 10 | dfsdf 11 | dsad 12 | sdasd 13 | -------------------------------------------------------------------------------- /Chapter02/file-watching/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "file-watching", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "moment": { 8 | "version": "2.24.0", 9 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", 10 | "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter02/file-watching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "file-watching", 3 | "version": "1.0.0", 4 | "main": "watch.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "moment": "^2.24.0" 13 | }, 14 | "devDependencies": {}, 15 | "description": "" 16 | } 17 | -------------------------------------------------------------------------------- /Chapter02/file-watching/watch.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const file = "./file.txt"; 3 | const moment = require("moment"); 4 | 5 | fs.watch(file, (eventType, filename) => { 6 | const time = moment().format("MMMM Do YYYY, h:mm:ss a"); 7 | return console.log(`${filename} updated ${time}`); 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter02/interfacing-with-io/greeting.js: -------------------------------------------------------------------------------- 1 | process.stdin.on("data", (data) => { 2 | const name = data.toString().trim().toUpperCase(); 3 | process.stdout.write(`Hello ${name}!`); 4 | }); 5 | -------------------------------------------------------------------------------- /Chapter02/interfacing-with-io/greeting2.js: -------------------------------------------------------------------------------- 1 | process.stdin.on("data", (data) => { 2 | const name = data.toString().trim().toUpperCase(); 3 | if (name !== "") { 4 | process.stdout.write(`Hello ${name}!`); 5 | } else { 6 | process.stderr.write("Input was empty."); 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter02/working-with-files/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js-14-Cookbook/b697d5f5cbd36282ee4dc21024d3bd842dc363fc/Chapter02/working-with-files/.DS_Store -------------------------------------------------------------------------------- /Chapter02/working-with-files/hello.txt: -------------------------------------------------------------------------------- 1 | HELLO WORLD! 2 | -------------------------------------------------------------------------------- /Chapter02/working-with-files/readWriteAsync.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const filepath = path.join(process.cwd(), "hello.txt"); 5 | 6 | fs.readFile(filepath, "utf8", (err, contents) => { 7 | if (err) { 8 | return console.log(err); 9 | } 10 | console.log("File Contents:", contents); 11 | const upperContents = contents.toUpperCase(); 12 | 13 | fs.writeFileSync(filepath, upperContents); 14 | console.log("File updated."); 15 | }); 16 | -------------------------------------------------------------------------------- /Chapter02/working-with-files/readWriteAsync2.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const filepath = path.join(process.cwd(), "hello.txt"); 5 | 6 | fs.readFile(filepath, "utf8", (err, contents) => { 7 | if (err) { 8 | return console.log(err); 9 | } 10 | console.log("File Contents:", contents); 11 | const upperContents = contents.toUpperCase(); 12 | 13 | fs.writeFile(filepath, upperContents, (err) => { 14 | if (err) throw err; 15 | console.log("File updated."); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /Chapter02/working-with-files/readWriteAsyncNamed.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const filepath = path.join(process.cwd(), "hello.txt"); 5 | 6 | fs.readFile(filepath, "utf8", (err, contents) => { 7 | if (err) { 8 | return console.log(err); 9 | } 10 | console.log("File Contents:", contents); 11 | 12 | const upperContents = contents.toUpperCase(); 13 | updateFile(filepath, upperContents); 14 | }); 15 | 16 | function updateFile(filepath, contents) { 17 | fs.writeFile(filepath, contents, function (err) { 18 | if (err) throw err; 19 | console.log("File updated."); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /Chapter02/working-with-files/readWriteAsyncTimeout.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const filepath = path.join(process.cwd(), "hello.txt"); 5 | 6 | fs.readFile(filepath, "utf8", (err, contents) => { 7 | if (err) { 8 | return console.log(err); 9 | } 10 | console.log("File Contents:", contents); 11 | const upperContents = contents.toUpperCase(); 12 | 13 | setTimeout(() => updateFile(filepath, upperContents), 10); 14 | }); 15 | 16 | function updateFile(filepath, contents) { 17 | fs.writeFile(filepath, contents, function (err) { 18 | if (err) throw err; 19 | console.log("File updated."); 20 | }); 21 | } 22 | 23 | setInterval(() => process.stdout.write("**** \n"), 1).unref(); 24 | -------------------------------------------------------------------------------- /Chapter02/working-with-files/readWritePromise.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs").promises; 2 | const path = require("path"); 3 | 4 | const filepath = path.join(process.cwd(), "hello.txt"); 5 | 6 | async function run() { 7 | try { 8 | const contents = await fs.readFile(filepath, "utf8"); 9 | console.log("File Contents:", contents); 10 | } catch (error) { 11 | console.error(error); 12 | } 13 | } 14 | 15 | run(); 16 | -------------------------------------------------------------------------------- /Chapter02/working-with-files/readWriteSync.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const filepath = path.join(process.cwd(), "hello.txt"); 5 | 6 | const contents = fs.readFileSync(filepath, "utf8"); 7 | console.log("File Contents:", contents); 8 | 9 | const upperContents = contents.toUpperCase(); 10 | 11 | fs.writeFileSync(filepath, upperContents); 12 | console.log("File updated."); 13 | -------------------------------------------------------------------------------- /Chapter03/learning-streams/async-generator.js: -------------------------------------------------------------------------------- 1 | const { Readable } = require("stream"); 2 | 3 | async function* generate() { 4 | yield "Node.js"; 5 | yield "is"; 6 | yield "a"; 7 | yield "JavaScript"; 8 | yield "Runtime"; 9 | } 10 | 11 | const readable = Readable.from(generate()); 12 | 13 | readable.on("data", (chunk) => { 14 | console.log(chunk); 15 | }); 16 | -------------------------------------------------------------------------------- /Chapter03/learning-streams/for-await-read-stream.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const rs = fs.createReadStream("./file.txt"); 4 | 5 | async function run() { 6 | for await (const chunk of rs) { 7 | console.log("Read chunk:", chunk); 8 | } 9 | console.log("No more data."); 10 | } 11 | 12 | run(); 13 | -------------------------------------------------------------------------------- /Chapter03/learning-streams/infinite-read.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const rs = fs.createReadStream("/dev/urandom"); 4 | 5 | let size = 0; 6 | rs.on("data", (data) => { 7 | size += data.length; 8 | console.log("File size:", size); 9 | }); 10 | -------------------------------------------------------------------------------- /Chapter03/learning-streams/paused-stream.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const rs = fs.createReadStream("./file.txt"); 4 | 5 | rs.on("readable", () => { 6 | // Read data 7 | let data = rs.read(); 8 | while (data !== null) { 9 | console.log("Read chunk:", data); 10 | data = rs.read(); 11 | } 12 | }); 13 | 14 | rs.on("end", () => { 15 | console.log("No more data."); 16 | }); 17 | -------------------------------------------------------------------------------- /Chapter03/learning-streams/read-stream.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const rs = fs.createReadStream("./file.txt"); 4 | 5 | rs.on("data", (data) => { 6 | console.log("Read chunk:", data.toString()); 7 | }); 8 | 9 | rs.on("end", () => { 10 | console.log("No more data."); 11 | }); 12 | -------------------------------------------------------------------------------- /Chapter03/learning-streams/write-stream.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const file = fs.createWriteStream("./file.txt"); 4 | 5 | for (let i = 0; i <= 1000000; i++) { 6 | file.write( 7 | "Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine.\n" 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /Chapter03/object-streams/object-stream.js: -------------------------------------------------------------------------------- 1 | const { Transform } = require("stream"); 2 | const { stringify } = require("ndjson"); 3 | 4 | const Name = Transform({ 5 | objectMode: true, 6 | transform: ({ forename, surname }, encoding, callback) => { 7 | callback(null, { name: forename + " " + surname }); 8 | }, 9 | }); 10 | 11 | Name.pipe(stringify()).pipe(process.stdout); 12 | 13 | Name.write({ forename: "John", surname: "Doe" }); 14 | Name.write({ forename: "Jane", surname: "Doe" }); 15 | -------------------------------------------------------------------------------- /Chapter03/object-streams/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "object-streams", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "object-stream.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "ndjson": "^2.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter03/piping-streams/file.txt: -------------------------------------------------------------------------------- 1 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 2 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 3 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 4 | 5 | -------------------------------------------------------------------------------- /Chapter03/piping-streams/pipe-stream.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const rs = fs.createReadStream("file.txt"); 4 | 5 | rs.pipe(process.stdout); 6 | -------------------------------------------------------------------------------- /Chapter03/stream-pipelines/file.txt: -------------------------------------------------------------------------------- 1 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 2 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 3 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 4 | -------------------------------------------------------------------------------- /Chapter03/stream-pipelines/newFile.txt: -------------------------------------------------------------------------------- 1 | NODE.JS IS A JAVASCRIPT RUNTIME BUILT ON GOOGLE CHROME'S V8 JAVASCRIPT ENGINE. 2 | NODE.JS IS A JAVASCRIPT RUNTIME BUILT ON GOOGLE CHROME'S V8 JAVASCRIPT ENGINE. 3 | NODE.JS IS A JAVASCRIPT RUNTIME BUILT ON GOOGLE CHROME'S V8 JAVASCRIPT ENGINE. 4 | -------------------------------------------------------------------------------- /Chapter03/stream-pipelines/pipeline.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const { pipeline, Transform } = require("stream"); 3 | 4 | const uppercase = new Transform({ 5 | transform(chunk, encoding, callback) { 6 | // Data processing 7 | callback(null, chunk.toString().toUpperCase()); 8 | }, 9 | }); 10 | 11 | pipeline( 12 | fs.createReadStream("./file.txt"), 13 | uppercase, 14 | fs.createWriteStream("./newFile.txt"), 15 | (err) => { 16 | if (err) { 17 | console.error("Pipeline failed.", err); 18 | } else { 19 | console.log("Pipeline succeeded."); 20 | } 21 | } 22 | ); 23 | -------------------------------------------------------------------------------- /Chapter03/stream-pipelines/promise-pipeline.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const stream = require("stream"); 3 | const util = require("util"); 4 | 5 | const pipeline = util.promisify(stream.pipeline); 6 | 7 | const uppercase = new stream.Transform({ 8 | transform(chunk, encoding, callback) { 9 | // Data processing 10 | callback(null, chunk.toString().toUpperCase()); 11 | }, 12 | }); 13 | 14 | async function run() { 15 | await pipeline( 16 | fs.createReadStream("./file.txt"), 17 | uppercase, 18 | fs.createWriteStream("./newFile.txt") 19 | ); 20 | console.log("Pipeline succeeded."); 21 | } 22 | 23 | run().catch((err) => { 24 | console.error("Pipeline failed.", err); 25 | }); 26 | -------------------------------------------------------------------------------- /Chapter03/transform-stream/file.txt: -------------------------------------------------------------------------------- 1 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 2 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 3 | Node.js is a JavaScript runtime built on Google Chrome's V8 JavaScript engine. 4 | -------------------------------------------------------------------------------- /Chapter03/transform-stream/newFile.txt: -------------------------------------------------------------------------------- 1 | NODE.JS IS A JAVASCRIPT RUNTIME BUILT ON GOOGLE CHROME'S V8 JAVASCRIPT ENGINE. 2 | NODE.JS IS A JAVASCRIPT RUNTIME BUILT ON GOOGLE CHROME'S V8 JAVASCRIPT ENGINE. 3 | NODE.JS IS A JAVASCRIPT RUNTIME BUILT ON GOOGLE CHROME'S V8 JAVASCRIPT ENGINE. 4 | -------------------------------------------------------------------------------- /Chapter03/transform-stream/transform-stream-es6.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const { Transform } = require("stream"); 3 | 4 | const rs = fs.createReadStream("./file.txt"); 5 | const newFile = fs.createWriteStream("./newFile.txt"); 6 | 7 | class Uppercase extends Transform { 8 | constructor() { 9 | super(); 10 | } 11 | 12 | _transform(chunk, encoding, callback) { 13 | this.push(chunk.toString().toUpperCase()); 14 | callback(); 15 | } 16 | } 17 | 18 | rs.pipe(new Uppercase()).pipe(newFile); 19 | -------------------------------------------------------------------------------- /Chapter03/transform-stream/transform-stream.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const { Transform } = require("stream"); 3 | 4 | const rs = fs.createReadStream("./file.txt"); 5 | 6 | const newFile = fs.createWriteStream("./newFile.txt"); 7 | 8 | const uppercase = new Transform({ 9 | transform(chunk, encoding, callback) { 10 | // Data processing 11 | callback(null, chunk.toString().toUpperCase()); 12 | }, 13 | }); 14 | 15 | rs.pipe(uppercase).pipe(newFile); 16 | -------------------------------------------------------------------------------- /Chapter04/file-upload/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "file-upload", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "formidable": { 8 | "version": "1.2.2", 9 | "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", 10 | "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter04/file-upload/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "file-upload", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "formidable": "^1.2.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter04/file-upload/public/form.html: -------------------------------------------------------------------------------- 1 |
6 | -------------------------------------------------------------------------------- /Chapter04/file-upload/server.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const http = require("http"); 3 | const path = require("path"); 4 | 5 | const form = fs.readFileSync(path.join(__dirname, "public", "form.html")); 6 | 7 | const formidable = require("formidable"); 8 | 9 | http 10 | .createServer((req, res) => { 11 | if (req.method === "GET") { 12 | get(res); 13 | return; 14 | } 15 | if (req.method === "POST") { 16 | post(req, res); 17 | return; 18 | } 19 | error(405, res); 20 | }) 21 | .listen(3000); 22 | 23 | function get(res) { 24 | res.writeHead(200, { 25 | "Content-Type": "text/html", 26 | }); 27 | res.end(form); 28 | } 29 | 30 | function error(code, res) { 31 | res.statusCode = code; 32 | res.end(http.STATUS_CODES[code]); 33 | } 34 | 35 | function post(req, res) { 36 | if (!/multipart\/form-data/.test(req.headers["content-type"])) { 37 | error(415, res); 38 | return; 39 | } 40 | 41 | const form = formidable({ 42 | multiples: true, 43 | uploadDir: "./uploads", 44 | }); 45 | 46 | form.parse(req, (err, fields, files) => { 47 | if (err) return err; 48 | res.writeHead(200, { 49 | "Content-Type": "application/json", 50 | }); 51 | res.end(JSON.stringify({fields,files,})); 52 | }); 53 | } -------------------------------------------------------------------------------- /Chapter04/http-server/server.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | 3 | const HOSTNAME = process.env.HOSTNAME || "0.0.0.0"; 4 | const PORT = process.env.PORT || 3000; 5 | 6 | const server = http.createServer((req, res) => { 7 | if (req.method !== "GET") return error(res, 405); 8 | if (req.url === "/todo") return todo(res); 9 | if (req.url === "/") return index(res); 10 | error(res, 404); 11 | }); 12 | 13 | function error(res, code) { 14 | res.statusCode = code; 15 | res.end(`{"error": "${http.STATUS_CODES[code]}"}`); 16 | } 17 | 18 | function todo(res) { 19 | res.end('[{"task_id": 1, "description": "walk dog"}]}'); 20 | } 21 | 22 | function index(res) { 23 | res.end('{"name": "todo-server"}'); 24 | } 25 | 26 | server.listen(PORT, HOSTNAME, () => { 27 | console.log(`Server listening on port ${server.address().port}`); 28 | }); 29 | -------------------------------------------------------------------------------- /Chapter04/making-requests/requests.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | const https = require("https"); 3 | 4 | // http.get("http://example.com", (res) => res.pipe(process.stdout)); 5 | 6 | const payload = `{ 7 | "name": "Beth", 8 | "job": "Software Engineer" 9 | }`; 10 | 11 | const opts = { 12 | method: "POST", 13 | hostname: "postman-echo.com", 14 | path: "/post", 15 | headers: { 16 | "Content-Type": "application/json", 17 | "Content-Length": Buffer.byteLength(payload), 18 | }, 19 | }; 20 | 21 | const req = https.request(opts, (res) => { 22 | process.stdout.write("Status Code: " + res.statusCode + "\n"); 23 | process.stdout.write("Body: "); 24 | res.pipe(process.stdout); 25 | }); 26 | 27 | req.on("error", (err) => console.error("Error: ", err)); 28 | 29 | req.end(payload); 30 | -------------------------------------------------------------------------------- /Chapter04/post-server/json-server.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | const fs = require("fs"); 3 | const path = require("path"); 4 | 5 | const form = fs.readFileSync(path.join(__dirname, "public", "form.html")); 6 | 7 | http 8 | .createServer((req, res) => { 9 | if (req.method === "GET") { 10 | get(res); 11 | return; 12 | } 13 | 14 | if (req.method === "POST") { 15 | post(req, res); 16 | return; 17 | } 18 | error(405, res); 19 | }) 20 | .listen(3000); 21 | 22 | function get(res) { 23 | res.writeHead(200, { 24 | "Content-Type": "text/html", 25 | }); 26 | res.end(form); 27 | } 28 | 29 | function post(req, res) { 30 | if (req.headers["content-type"] !== "application/json") { 31 | error(415, res); 32 | return; 33 | } 34 | 35 | let input = ""; 36 | 37 | req.on("data", (chunk) => { 38 | input += chunk.toString(); 39 | }); 40 | 41 | req.on("end", () => { 42 | const parsed = JSON.parse(input); 43 | 44 | if (parsed.err) { 45 | error(400, "Bad Request", res); 46 | return; 47 | } 48 | 49 | console.log("Received data: ", parsed); 50 | res.end('{"data": ' + input + "}"); 51 | }); 52 | } 53 | 54 | function error(code, res) { 55 | res.statusCode = code; 56 | res.end(http.STATUS_CODES[code]); 57 | } 58 | -------------------------------------------------------------------------------- /Chapter04/post-server/public/form.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 31 | -------------------------------------------------------------------------------- /Chapter04/post-server/server.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | const fs = require("fs"); 3 | const path = require("path"); 4 | 5 | const form = fs.readFileSync(path.join(__dirname, "public", "form.html")); 6 | 7 | http 8 | .createServer((req, res) => { 9 | if (req.method === "GET") { 10 | get(res); 11 | return; 12 | } 13 | if (req.method === "POST") { 14 | post(req, res); 15 | return; 16 | } 17 | error(405, res); 18 | }) 19 | .listen(3000); 20 | 21 | function get(res) { 22 | res.writeHead(200, { 23 | "Content-Type": "text/html", 24 | }); 25 | res.end(form); 26 | } 27 | 28 | function post(req, res) { 29 | if (req.headers["content-type"] !== "application/x-www-form-urlencoded") { 30 | error(415, res); 31 | return; 32 | } 33 | 34 | let input = ""; 35 | 36 | req.on("data", (chunk) => { 37 | input += chunk.toString(); 38 | }); 39 | 40 | req.on("end", () => { 41 | console.log(input); 42 | res.end(http.STATUS_CODES[200]); 43 | }); 44 | } 45 | 46 | function error(code, res) { 47 | res.statusCode = code; 48 | res.end(http.STATUS_CODES[code]); 49 | } 50 | -------------------------------------------------------------------------------- /Chapter04/server-smtp/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server-smtp", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "base32.js": { 8 | "version": "0.1.0", 9 | "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", 10 | "integrity": "sha1-tYLexpPC8R6JPPBk7mrFthMaIgI=" 11 | }, 12 | "ipv6-normalize": { 13 | "version": "1.0.1", 14 | "resolved": "https://registry.npmjs.org/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz", 15 | "integrity": "sha1-GzJYKQ02X6gyOeiZB93kWS52IKg=" 16 | }, 17 | "nodemailer": { 18 | "version": "6.4.6", 19 | "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.6.tgz", 20 | "integrity": "sha512-/kJ+FYVEm2HuUlw87hjSqTss+GU35D4giOpdSfGp7DO+5h6RlJj7R94YaYHOkoxu1CSaM0d3WRBtCzwXrY6MKA==" 21 | }, 22 | "smtp-server": { 23 | "version": "3.6.0", 24 | "resolved": "https://registry.npmjs.org/smtp-server/-/smtp-server-3.6.0.tgz", 25 | "integrity": "sha512-DVEVWzL4s1GWzAs4+6rbhNZpAn61+V8l4b7R8zHLAW2jmlwKz9IKQmdgm5sNruCRnS01BYyitI98vJo7LDnXfg==", 26 | "requires": { 27 | "base32.js": "0.1.0", 28 | "ipv6-normalize": "1.0.1", 29 | "nodemailer": "6.4.5" 30 | }, 31 | "dependencies": { 32 | "nodemailer": { 33 | "version": "6.4.5", 34 | "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.4.5.tgz", 35 | "integrity": "sha512-NH7aNVQyZLAvGr2+EOto7znvz+qJ02Cb/xpou98ApUt5tEAUSVUxhvHvgV/8I5dhjKTYqUw0nasoKzLNBJKrDQ==" 36 | } 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Chapter04/server-smtp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server-smtp", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "nodemailer": "^6.4.6", 15 | "smtp-server": "^3.6.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter04/server-smtp/send-email.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require("nodemailer"); 2 | 3 | const transporter = nodemailer.createTransport({ 4 | host: "localhost", 5 | port: 4321, 6 | }); 7 | 8 | transporter.sendMail( 9 | { 10 | from: "beth@example.com", 11 | to: "laddie@example.com", 12 | subject: "Hello", 13 | text: "Hello world!", 14 | }, 15 | (err, info) => { 16 | if (err) { 17 | console.log(err); 18 | } 19 | console.log("Message Sent:", info); 20 | } 21 | ); 22 | -------------------------------------------------------------------------------- /Chapter04/server-smtp/server.js: -------------------------------------------------------------------------------- 1 | const SMTPServer = require("smtp-server").SMTPServer; 2 | 3 | const PORT = 4321; 4 | 5 | const server = new SMTPServer({ 6 | disabledCommands: ["STARTTLS", "AUTH"], 7 | logger: true, 8 | }); 9 | 10 | server.on("error", (err) => { 11 | console.error(err); 12 | }); 13 | 14 | server.listen(PORT); 15 | -------------------------------------------------------------------------------- /Chapter04/websocket-server/client.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const http = require("http"); 3 | 4 | const index = fs.readFileSync("public/index.html"); 5 | 6 | const server = http.createServer((req, res) => { 7 | res.setHeader("Content-Type", "text/html"); 8 | res.end(index); 9 | }); 10 | 11 | server.listen(8080); 12 | -------------------------------------------------------------------------------- /Chapter04/websocket-server/node-client.js: -------------------------------------------------------------------------------- 1 | const WebSocket = require("ws"); 2 | const ws = new WebSocket("ws://localhost:3000"); 3 | 4 | ws.on("open", () => { 5 | console.log("Connected"); 6 | }); 7 | 8 | ws.on("close", () => { 9 | console.log("Disconnected"); 10 | }); 11 | 12 | ws.on("message", (message) => { 13 | console.log("Received:", message); 14 | }); 15 | 16 | setInterval(() => { 17 | ws.send("Hello"); 18 | }, 3000); 19 | -------------------------------------------------------------------------------- /Chapter04/websocket-server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ws-server", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ws": { 8 | "version": "7.2.5", 9 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", 10 | "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter04/websocket-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ws-server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "ws": "^7.2.5" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter04/websocket-server/public/index.html: -------------------------------------------------------------------------------- 1 |Welcome to <%= title %>
11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter06/express-app-generated/app.js: -------------------------------------------------------------------------------- 1 | var createError = require("http-errors"); 2 | var express = require("express"); 3 | var path = require("path"); 4 | var cookieParser = require("cookie-parser"); 5 | var logger = require("morgan"); 6 | 7 | var indexRouter = require("./routes/index"); 8 | var usersRouter = require("./routes/users"); 9 | 10 | var app = express(); 11 | 12 | // view engine setup 13 | app.set("views", path.join(__dirname, "views")); 14 | app.set("view engine", "ejs"); 15 | 16 | app.use(logger("dev")); 17 | app.use(express.json()); 18 | app.use(express.urlencoded({ extended: false })); 19 | app.use(cookieParser()); 20 | app.use(express.static(path.join(__dirname, "public"))); 21 | 22 | app.use("/", indexRouter); 23 | app.use("/users", usersRouter); 24 | 25 | // catch 404 and forward to error handler 26 | app.use(function (req, res, next) { 27 | next(createError(404)); 28 | }); 29 | 30 | // error handler 31 | app.use(function (err, req, res, next) { 32 | // set locals, only providing error in development 33 | res.locals.message = err.message; 34 | res.locals.error = req.app.get("env") === "development" ? err : {}; 35 | 36 | // render the error page 37 | res.status(err.status || 500); 38 | res.render("error"); 39 | }); 40 | 41 | module.exports = app; 42 | -------------------------------------------------------------------------------- /Chapter06/express-app-generated/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-app-generated", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "cookie-parser": "~1.4.4", 10 | "debug": "~2.6.9", 11 | "ejs": "~2.6.1", 12 | "express": "~4.16.1", 13 | "http-errors": "~1.6.3", 14 | "morgan": "~1.9.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter06/express-app-generated/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00b7ff; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter06/express-app-generated/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get("/", function (req, res, next) { 6 | res.render("index", { title: "Express" }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter06/express-app-generated/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get("/", function (req, res, next) { 6 | res.send("respond with a resource"); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter06/express-app-generated/views/error.ejs: -------------------------------------------------------------------------------- 1 |<%= error.stack %>4 | -------------------------------------------------------------------------------- /Chapter06/express-app-generated/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
Welcome to <%= title %>
10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter06/express-app/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const path = require("path"); 3 | const index = require("./routes/index"); 4 | 5 | const PORT = process.env.PORT || 3000; 6 | 7 | const app = express(); 8 | 9 | app.use(express.static(path.join(__dirname, "public"))); 10 | app.use("/", index); 11 | 12 | app.listen(PORT, () => { 13 | console.log(`Server listening on port ${PORT}`); 14 | }); 15 | -------------------------------------------------------------------------------- /Chapter06/express-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/express-app/public/styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js-14-Cookbook/b697d5f5cbd36282ee4dc21024d3bd842dc363fc/Chapter06/express-app/public/styles.css -------------------------------------------------------------------------------- /Chapter06/express-app/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | 4 | router.get("/", (req, res) => { 5 | const title = "Express"; 6 | res.send(` 7 | 8 | 9 |Welcome to ${title}
14 | 15 | 16 | `); 17 | }); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /Chapter06/express-custom-middleware/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const path = require("path"); 3 | const index = require("./routes/index"); 4 | const logger = require("./middleware/logger"); 5 | 6 | const PORT = process.env.PORT || 3000; 7 | 8 | const app = express(); 9 | 10 | app.use(logger()); 11 | app.use(express.static(path.join(__dirname, "public"))); 12 | app.use("/", index); 13 | 14 | app.listen(PORT, () => { 15 | console.log(`Server listening on port ${PORT}`); 16 | }); 17 | -------------------------------------------------------------------------------- /Chapter06/express-custom-middleware/middleware/logger.js: -------------------------------------------------------------------------------- 1 | module.exports = logger; 2 | 3 | function logger() { 4 | return (req, res, next) => { 5 | console.log("Request received:", req.method, req.url); 6 | next(); 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter06/express-custom-middleware/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/express-custom-middleware/public/styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js-14-Cookbook/b697d5f5cbd36282ee4dc21024d3bd842dc363fc/Chapter06/express-custom-middleware/public/styles.css -------------------------------------------------------------------------------- /Chapter06/express-custom-middleware/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | 4 | router.get("/", (req, res) => { 5 | const title = "Express"; 6 | res.send(` 7 | 8 | 9 |Welcome to ${title}
14 | 15 | 16 | `); 17 | }); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /Chapter06/express-post-app/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const path = require("path"); 3 | const index = require("./routes/index"); 4 | const bodyParser = require("body-parser"); 5 | 6 | const PORT = process.env.PORT || 3000; 7 | 8 | const app = express(); 9 | 10 | app.use( 11 | bodyParser.urlencoded({ 12 | extended: false, 13 | }) 14 | ); 15 | app.use(express.static(path.join(__dirname, "public"))); 16 | app.use("/", index); 17 | 18 | app.listen(PORT, () => { 19 | console.log(`Server listening on port ${PORT}`); 20 | }); 21 | -------------------------------------------------------------------------------- /Chapter06/express-post-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.19.0", 14 | "express": "^4.17.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter06/express-post-app/public/styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js-14-Cookbook/b697d5f5cbd36282ee4dc21024d3bd842dc363fc/Chapter06/express-post-app/public/styles.css -------------------------------------------------------------------------------- /Chapter06/express-post-app/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = express.Router(); 3 | 4 | router.get("/:name?", function (req, res) { 5 | const title = "Express"; 6 | const name = req.params.name; 7 | res.send(` 8 | 9 | 10 |Welcome to ${title}${name ? `, ${name}.` : ""}
16 | 19 | 20 | 21 | `); 22 | }); 23 | 24 | router.post("/data", function (req, res) { 25 | res.redirect(`/${req.body.name}`); 26 | }); 27 | 28 | module.exports = router; 29 | -------------------------------------------------------------------------------- /Chapter06/fastify-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fastify-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "fastify": "^2.14.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/fastify-app/server.js: -------------------------------------------------------------------------------- 1 | const fastify = require("fastify")(); 2 | 3 | const PORT = process.env.PORT || 3000; 4 | 5 | // fastify.get("/", async (request, reply) => { 6 | // return { message: "Hello world!" }; 7 | // }); 8 | 9 | fastify.route({ 10 | method: "GET", 11 | url: "/", 12 | handler: async (request, reply) => { 13 | reply.send({ message: "Hello world!" }); 14 | }, 15 | }); 16 | 17 | const startServer = async () => { 18 | try { 19 | await fastify.listen(PORT); 20 | console.log(`server listening on ${fastify.server.address().port}`); 21 | } catch (err) { 22 | console.error(err); 23 | process.exit(1); 24 | } 25 | }; 26 | 27 | startServer(); 28 | -------------------------------------------------------------------------------- /Chapter06/fastify-app/test.js: -------------------------------------------------------------------------------- 1 | fastify.route({ 2 | method: "GET", 3 | url: "/", 4 | handler: function (request, reply) { 5 | reply.send({ message: "Hello world!" }); 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # 0x 40 | profile-* 41 | 42 | # mac files 43 | .DS_Store 44 | 45 | # vim swap files 46 | *.swp 47 | 48 | # webstorm 49 | .idea 50 | 51 | # vscode 52 | .vscode 53 | *code-workspace 54 | 55 | # clinic 56 | profile* 57 | *clinic* 58 | *flamegraph* 59 | 60 | # generated code 61 | examples/typescript-server.js 62 | test/types/index.js 63 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/app.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | const AutoLoad = require('fastify-autoload') 5 | 6 | module.exports = function (fastify, opts, next) { 7 | // Place here your custom code! 8 | 9 | // Do not touch the following lines 10 | 11 | // This loads all plugins defined in plugins 12 | // those should be support plugins that are reused 13 | // through your application 14 | fastify.register(AutoLoad, { 15 | dir: path.join(__dirname, 'plugins'), 16 | options: Object.assign({}, opts) 17 | }) 18 | 19 | // This loads all plugins defined in services 20 | // define your routes in one of these 21 | fastify.register(AutoLoad, { 22 | dir: path.join(__dirname, 'services'), 23 | options: Object.assign({}, opts) 24 | }) 25 | 26 | // Make sure to call next when done 27 | next() 28 | } 29 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fastify-generated", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "tap test/**/*.test.js", 11 | "start": "fastify start -l info app.js", 12 | "dev": "fastify start -w -l info -P app.js" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "fastify": "^2.0.0", 19 | "fastify-plugin": "^1.5.0", 20 | "fastify-autoload": "^1.0.0", 21 | "fastify-cli": "^1.5.0" 22 | }, 23 | "devDependencies": { 24 | "tap": "^12.5.3" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/plugins/README.md: -------------------------------------------------------------------------------- 1 | # Plugins Folder 2 | 3 | Plugins define behavior that is common to all the routes in your 4 | application. Authentication, caching, templates, and all the other cross 5 | cutting concerns should be handled by plugins placed in this folder. 6 | 7 | Files in this folder are typically defined through the 8 | [`fastify-plugin`](https://github.com/fastify/fastify-plugin) module, 9 | making them non-encapsulated. They can define decorators and set hooks 10 | that will then be used in the rest of your application. 11 | 12 | Check out: 13 | 14 | * [The hitchhiker's guide to plugins](https://github.com/fastify/fastify/blob/master/docs/Plugins-Guide.md) 15 | * [Fastify decorators](https://www.fastify.io/docs/latest/Decorators/). 16 | * [Fastify lifecycle](https://www.fastify.io/docs/latest/Lifecycle/). 17 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/plugins/support.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fp = require('fastify-plugin') 4 | 5 | // the use of fastify-plugin is required to be able 6 | // to export the decorators to the outer scope 7 | 8 | module.exports = fp(function (fastify, opts, next) { 9 | fastify.decorate('someSupport', function () { 10 | return 'hugs' 11 | }) 12 | next() 13 | }) 14 | 15 | // If you prefer async/await, use the following 16 | // 17 | // module.exports = fp(async function (fastify, opts) { 18 | // fastify.decorate('someSupport', function () { 19 | // return 'hugs' 20 | // }) 21 | // }) 22 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/services/README.md: -------------------------------------------------------------------------------- 1 | # Services Folder 2 | 3 | Services define routes within your application. Fastify provides an 4 | easy path to a microservice architecture, in the future you might want 5 | to independently deploy some of those. 6 | 7 | In this folder you should define all the services that define the routes 8 | of your web application. 9 | Each service is a [Fastify 10 | plugin](https://www.fastify.io/docs/latest/Plugins/), it is 11 | encapsulated (it can have its own independent plugins) and it is 12 | typically stored in a file; be careful to group your routes logically, 13 | e.g. all `/users` routes in a `users.js` file. We have added 14 | a `root.js` file for you with a '/' root added. 15 | 16 | If a single file become too large, create a folder and add a `index.js` file there: 17 | this file must be a Fastify plugin, and it will be loaded automatically 18 | by the application. You can now add as many files as you want inside that folder. 19 | In this way you can create complex services within a single monolith, 20 | and eventually extract them. 21 | 22 | If you need to share functionality between services, place that 23 | functionality into the `plugins` folder, and share it via 24 | [decorators](https://www.fastify.io/docs/latest/Decorators/). 25 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/services/example/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = function (fastify, opts, next) { 4 | fastify.get('/example', function (request, reply) { 5 | reply.send('this is an example') 6 | }) 7 | 8 | next() 9 | } 10 | 11 | // If you prefer async/await, use the following 12 | // 13 | // module.exports = async function (fastify, opts) { 14 | // fastify.get('/example', async function (request, reply) { 15 | // return 'this is an example' 16 | // }) 17 | // } 18 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/services/root.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = function (fastify, opts, next) { 4 | fastify.get('/', function (request, reply) { 5 | reply.send({ root: true }) 6 | }) 7 | 8 | next() 9 | } 10 | 11 | // If you prefer async/await, use the following 12 | // 13 | // module.exports = async function (fastify, opts) { 14 | // fastify.get('/', async function (request, reply) { 15 | // return { root: true } 16 | // }) 17 | // } 18 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/test/helper.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // This file contains code that we reuse 4 | // between our tests. 5 | 6 | const Fastify = require('fastify') 7 | const fp = require('fastify-plugin') 8 | const App = require('../app') 9 | 10 | // Fill in this config with all the configurations 11 | // needed for testing the application 12 | function config () { 13 | return {} 14 | } 15 | 16 | // automatically build and tear down our instance 17 | function build (t) { 18 | const app = Fastify() 19 | 20 | // fastify-plugin ensures that all decorators 21 | // are exposed for testing purposes, this is 22 | // different from the production setup 23 | app.register(fp(App), config()) 24 | 25 | // tear down our app after we are done 26 | t.tearDown(app.close.bind(app)) 27 | 28 | return app 29 | } 30 | 31 | module.exports = { 32 | config, 33 | build 34 | } 35 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/test/plugins/support.test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const { test } = require('tap') 4 | const Fastify = require('fastify') 5 | const Support = require('../../plugins/support') 6 | 7 | test('support works standalone', (t) => { 8 | t.plan(2) 9 | const fastify = Fastify() 10 | fastify.register(Support) 11 | 12 | fastify.ready((err) => { 13 | t.error(err) 14 | t.equal(fastify.someSupport(), 'hugs') 15 | }) 16 | }) 17 | 18 | // If you prefer async/await, use the following 19 | // 20 | // test('support works standalone', async (t) => { 21 | // const fastify = Fastify() 22 | // fastify.register(Support) 23 | // 24 | // await fastify.ready() 25 | // t.equal(fastify.someSupport(), 'hugs') 26 | // }) 27 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/test/services/example.test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const { test } = require('tap') 4 | const { build } = require('../helper') 5 | 6 | test('example is loaded', (t) => { 7 | t.plan(2) 8 | const app = build(t) 9 | 10 | app.inject({ 11 | url: '/example' 12 | }, (err, res) => { 13 | t.error(err) 14 | t.equal(res.payload, 'this is an example') 15 | }) 16 | }) 17 | 18 | // If you prefer async/await, use the following 19 | // 20 | // test('example is loaded', async (t) => { 21 | // const app = build(t) 22 | // 23 | // const res = await app.inject({ 24 | // url: '/example' 25 | // }) 26 | // t.equal(res.payload, 'this is an example') 27 | // }) 28 | -------------------------------------------------------------------------------- /Chapter06/fastify-generated-app/test/services/root.test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const { test } = require('tap') 4 | const { build } = require('../helper') 5 | 6 | test('default root route', (t) => { 7 | t.plan(2) 8 | const app = build(t) 9 | 10 | app.inject({ 11 | url: '/' 12 | }, (err, res) => { 13 | t.error(err) 14 | t.deepEqual(JSON.parse(res.payload), { root: true }) 15 | }) 16 | }) 17 | 18 | // If you prefer async/await, use the following 19 | // 20 | // test('default root route', async (t) => { 21 | // const app = build(t) 22 | // 23 | // const res = await app.inject({ 24 | // url: '/' 25 | // }) 26 | // t.deepEqual(JSON.parse(res.payload), { root: true }) 27 | // }) 28 | -------------------------------------------------------------------------------- /Chapter06/fastify-plugin-app/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } -------------------------------------------------------------------------------- /Chapter06/fastify-plugin-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fastify-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "fastify": "^2.14.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/fastify-plugin-app/plugins/hello-route.js: -------------------------------------------------------------------------------- 1 | async function routes(fastify) { 2 | fastify.get("/", async (request, reply) => { 3 | return { message: "Hello world!" }; 4 | }); 5 | } 6 | 7 | module.exports = routes; 8 | -------------------------------------------------------------------------------- /Chapter06/fastify-plugin-app/server.js: -------------------------------------------------------------------------------- 1 | const fastify = require("fastify")(); 2 | 3 | const PORT = process.env.PORT || 3000; 4 | 5 | fastify.register(require("./plugins/hello-route")); 6 | 7 | const startServer = async () => { 8 | try { 9 | await fastify.listen(PORT); 10 | console.log(`server listening on ${fastify.server.address().port}`); 11 | } catch (err) { 12 | console.error(err); 13 | process.exit(1); 14 | } 15 | }; 16 | 17 | startServer(); 18 | -------------------------------------------------------------------------------- /Chapter06/fastify-plugin-app/test.js: -------------------------------------------------------------------------------- 1 | fastify.route({ 2 | method: "GET", 3 | url: "/", 4 | handler: function (request, reply) { 5 | reply.send({ message: "Hello world!" }); 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /Chapter06/hapi-app/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } 4 | -------------------------------------------------------------------------------- /Chapter06/hapi-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hapi-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@hapi/hapi": "^19.1.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/hapi-app/server.js: -------------------------------------------------------------------------------- 1 | const Hapi = require("@hapi/hapi"); 2 | 3 | const PORT = process.env.PORT || 3000; 4 | const HOSTNAME = process.env.HOSTNAME || "localhost"; 5 | 6 | const initialize = async () => { 7 | const server = Hapi.server({ 8 | port: PORT, 9 | host: HOSTNAME, 10 | }); 11 | 12 | server.route({ 13 | method: "GET", 14 | path: "/", 15 | handler: (request, h) => { 16 | return "Welcome to Hapi.js"; 17 | }, 18 | }); 19 | 20 | await server.start(); 21 | console.log("Server listening on", server.info.uri); 22 | }; 23 | 24 | initialize(); 25 | -------------------------------------------------------------------------------- /Chapter06/hapi-static-app/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } 4 | -------------------------------------------------------------------------------- /Chapter06/hapi-static-app/files/file.txt: -------------------------------------------------------------------------------- 1 | This is a static file. -------------------------------------------------------------------------------- /Chapter06/hapi-static-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hapi-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@hapi/hapi": "^19.1.1", 14 | "@hapi/inert": "^6.0.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter06/hapi-static-app/server.js: -------------------------------------------------------------------------------- 1 | const Hapi = require("@hapi/hapi"); 2 | const path = require("path"); 3 | 4 | const PORT = process.env.PORT || 3000; 5 | const HOSTNAME = process.env.HOSTNAME || "localhost"; 6 | 7 | const initialize = async () => { 8 | const server = Hapi.server({ 9 | port: PORT, 10 | host: HOSTNAME, 11 | }); 12 | 13 | await server.register(require("@hapi/inert")); 14 | 15 | server.route({ 16 | method: "GET", 17 | path: "/", 18 | handler: { 19 | file: path.join(__dirname, "files/file.txt"), 20 | }, 21 | }); 22 | 23 | await server.start(); 24 | console.log("Server listening on", server.info.uri); 25 | }; 26 | 27 | initialize(); 28 | -------------------------------------------------------------------------------- /Chapter06/hapi-static/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } 4 | -------------------------------------------------------------------------------- /Chapter06/hapi-static/files/file.txt: -------------------------------------------------------------------------------- 1 | This is a static file. -------------------------------------------------------------------------------- /Chapter06/hapi-static/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hapi-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@hapi/hapi": "^19.1.1", 14 | "@hapi/inert": "^6.0.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter06/hapi-static/server.js: -------------------------------------------------------------------------------- 1 | const Hapi = require("@hapi/hapi"); 2 | const path = require("path"); 3 | 4 | const PORT = process.env.PORT || 3000; 5 | const HOSTNAME = process.env.HOSTNAME || "localhost"; 6 | 7 | const initialize = async () => { 8 | const server = Hapi.server({ 9 | port: PORT, 10 | host: HOSTNAME, 11 | }); 12 | 13 | await server.register(require("@hapi/inert")); 14 | 15 | server.route({ 16 | method: "GET", 17 | path: "/", 18 | handler: { 19 | file: path.join(__dirname, "files/file.txt"), 20 | }, 21 | }); 22 | 23 | await server.start(); 24 | console.log("Server listening on", server.info.uri); 25 | }; 26 | 27 | initialize(); 28 | -------------------------------------------------------------------------------- /Chapter06/hapi-views-app/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } 4 | -------------------------------------------------------------------------------- /Chapter06/hapi-views-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hapi-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@hapi/hapi": "^19.1.1", 14 | "@hapi/vision": "^6.0.0", 15 | "ejs": "^3.1.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter06/hapi-views-app/server.js: -------------------------------------------------------------------------------- 1 | const Hapi = require("@hapi/hapi"); 2 | 3 | const PORT = process.env.PORT || 3000; 4 | const HOSTNAME = process.env.HOSTNAME || "localhost"; 5 | 6 | const initialize = async () => { 7 | const server = Hapi.server({ 8 | port: PORT, 9 | host: HOSTNAME, 10 | }); 11 | 12 | await server.register(require("@hapi/vision")); 13 | 14 | server.views({ 15 | engines: { 16 | ejs: require("ejs"), 17 | }, 18 | relativeTo: __dirname, 19 | path: "views", 20 | }); 21 | 22 | server.route({ 23 | method: "GET", 24 | path: "/", 25 | handler: function (request, h) { 26 | return h.view("index", { 27 | title: "Hapi.js", 28 | }); 29 | }, 30 | }); 31 | 32 | await server.start(); 33 | console.log("Server listening on", server.info.uri); 34 | }; 35 | 36 | initialize(); 37 | -------------------------------------------------------------------------------- /Chapter06/hapi-views-app/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |Welcome to <%= title %>
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Chapter06/koa-app/app.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const Koa = require("koa"); 4 | const serve = require("koa-static"); 5 | const router = require("@koa/router")(); 6 | const index = require("./routes/index"); 7 | 8 | const PORT = process.env.PORT || 3000; 9 | 10 | const app = new Koa(); 11 | 12 | app.use(serve(path.join(__dirname, "public"))); 13 | 14 | router.use("/", index.routes()); 15 | app.use(router.routes()); 16 | 17 | app.listen(PORT, () => { 18 | console.log(`Server listening on port ${PORT}`); 19 | }); 20 | -------------------------------------------------------------------------------- /Chapter06/koa-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@koa/router": "^8.0.8", 14 | "koa": "^2.12.0", 15 | "koa-static": "^5.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter06/koa-app/public/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } -------------------------------------------------------------------------------- /Chapter06/koa-app/routes/index.js: -------------------------------------------------------------------------------- 1 | const router = require("@koa/router")(); 2 | 3 | router.get("/", async function (ctx) { 4 | const title = "Koa.js"; 5 | ctx.body = ` 6 | 7 | 8 |Welcome to ${title}
13 | 14 | 15 | `; 16 | }); 17 | 18 | module.exports = router; -------------------------------------------------------------------------------- /Chapter06/koa-cascade/app.js: -------------------------------------------------------------------------------- 1 | const Koa = require('koa'); 2 | const app = new Koa(); 3 | 4 | app.use(async (ctx, next) => { 5 | console.log("First middleware start") 6 | await next(); 7 | console.log("First middleware return") 8 | }); 9 | 10 | app.use(async (ctx, next) => { 11 | console.log("Second middleware start") 12 | await next(); 13 | console.log("Second middleware return") 14 | 15 | }); 16 | 17 | app.use(async ctx => { 18 | console.log("Third middleware start"); 19 | console.log("Third middleware return"); 20 | }); 21 | 22 | app.listen(3000); -------------------------------------------------------------------------------- /Chapter06/koa-cascade/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa-cascade", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "koa": "^2.12.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/koa-custom-middleware/app.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const Koa = require("koa"); 4 | const serve = require("koa-static"); 5 | const router = require("@koa/router")(); 6 | const index = require("./routes/index"); 7 | 8 | const logger = require("./middleware/logger"); 9 | 10 | const PORT = process.env.PORT || 3000; 11 | 12 | const app = new Koa(); 13 | 14 | app.use(logger()); 15 | app.use(serve(path.join(__dirname, "public"))); 16 | 17 | router.use("/", index.routes()); 18 | app.use(router.routes()); 19 | 20 | app.listen(PORT, () => { 21 | console.log(`Server listening on port ${PORT}`); 22 | }); 23 | -------------------------------------------------------------------------------- /Chapter06/koa-custom-middleware/middleware/logger.js: -------------------------------------------------------------------------------- 1 | module.exports = logger; 2 | 3 | function logger() { 4 | return async (ctx, next) => { 5 | console.log("Request received:", ctx.req.method, ctx.req.url); 6 | await next(); 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter06/koa-custom-middleware/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@koa/router": "^8.0.8", 14 | "koa": "^2.12.0", 15 | "koa-static": "^5.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter06/koa-custom-middleware/public/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | -------------------------------------------------------------------------------- /Chapter06/koa-custom-middleware/routes/index.js: -------------------------------------------------------------------------------- 1 | const router = require("@koa/router")(); 2 | 3 | router.get("/", async function (ctx) { 4 | const title = "Koa.js"; 5 | ctx.body = ` 6 | 7 | 8 |Welcome to ${title}
13 | 14 | 15 | `; 16 | }); 17 | 18 | module.exports = router; 19 | -------------------------------------------------------------------------------- /Chapter06/koa-views-app/app.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const Koa = require("koa"); 4 | const serve = require("koa-static"); 5 | const router = require("@koa/router")(); 6 | const views = require('koa-views') 7 | const index = require("./routes/index"); 8 | 9 | const PORT = process.env.PORT || 3000; 10 | 11 | const app = new Koa(); 12 | 13 | 14 | app.use(views(path.join(__dirname, 'views'), { 15 | extension: 'ejs' 16 | })) 17 | 18 | app.use(serve(path.join(__dirname, "public"))); 19 | 20 | router.use("/", index.routes()); 21 | app.use(router.routes()); 22 | 23 | app.listen(PORT, () => { 24 | console.log(`Server listening on port ${PORT}`); 25 | }); -------------------------------------------------------------------------------- /Chapter06/koa-views-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@koa/router": "^8.0.8", 14 | "ejs": "^3.1.3", 15 | "koa": "^2.12.0", 16 | "koa-ejs": "^4.3.0", 17 | "koa-static": "^5.0.0", 18 | "koa-views": "^6.2.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter06/koa-views-app/public/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | -------------------------------------------------------------------------------- /Chapter06/koa-views-app/routes/index.js: -------------------------------------------------------------------------------- 1 | const router = require("@koa/router")(); 2 | 3 | router.get("/", async function (ctx, next) { 4 | ctx.state = { 5 | title: "Koa.js", 6 | }; 7 | await ctx.render("index"); 8 | }); 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /Chapter06/koa-views-app/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |Welcome to <%= title %>
11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter07/leveldb-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leveldb-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "tasks.js", 6 | "dependencies": { 7 | "level": "^6.0.1", 8 | "leveldown": "^5.6.0", 9 | "levelup": "^4.4.0" 10 | }, 11 | "devDependencies": {}, 12 | "scripts": { 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /Chapter07/leveldb-app/tasks.js: -------------------------------------------------------------------------------- 1 | const levelup = require("levelup"); 2 | const leveldown = require("leveldown"); 3 | 4 | const db = levelup(leveldown("./data")); 5 | 6 | const task = process.argv[2]; 7 | 8 | if (!task) { 9 | listTasks(); 10 | } else { 11 | addTask(); 12 | } 13 | 14 | function addTask() { 15 | const key = `Task: ${Math.random().toString(32).replace(".", "")}`; 16 | db.put(key, task, (err) => { 17 | if (err) throw err; 18 | listTasks(); 19 | }); 20 | } 21 | 22 | function listTasks() { 23 | db.createReadStream().on("data", (data) => { 24 | console.log(data.key.toString(), "=", data.value.toString()); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/leveldb-filter/filter.js: -------------------------------------------------------------------------------- 1 | const levelup = require("levelup"); 2 | const leveldown = require("leveldown"); 3 | const db = levelup(leveldown("./data")); 4 | 5 | db.put("Task:1", ""); 6 | db.put("Task:2", ""); 7 | db.put("Task:3", ""); 8 | db.put("Task:4", ""); 9 | 10 | db.createReadStream({ 11 | gte: "Task:1", 12 | lte: "Task:3", 13 | }).on("data", function (data) { 14 | console.log(data.key.toString()); 15 | }); 16 | 17 | db.batch() 18 | .put("forename", "Beth") 19 | .put("surname", "Griggs") 20 | .del("forename") 21 | .write(() => console.log("Batch operations complete.")); 22 | -------------------------------------------------------------------------------- /Chapter07/leveldb-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leveldb-filter", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "filter.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "leveldown": "^5.6.0", 14 | "levelup": "^4.4.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter07/leveldb-memdown-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leveldb-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "tasks.js", 6 | "dependencies": { 7 | "level": "^6.0.1", 8 | "levelup": "^4.4.0", 9 | "memdown": "^5.1.0" 10 | }, 11 | "devDependencies": {}, 12 | "scripts": { 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /Chapter07/leveldb-memdown-app/tasks.js: -------------------------------------------------------------------------------- 1 | const levelup = require("levelup"); 2 | const memdown = require("memdown"); 3 | 4 | const db = levelup(memdown("./data")); 5 | 6 | const task = process.argv[2]; 7 | 8 | if (!task) { 9 | listTasks(); 10 | } else { 11 | addTask(); 12 | } 13 | 14 | function addTask() { 15 | const key = `Task: ${Math.random().toString(32).replace(".", "")}`; 16 | db.put(key, task, (err) => { 17 | if (err) throw err; 18 | listTasks(); 19 | }); 20 | } 21 | 22 | function listTasks() { 23 | db.createReadStream().on("data", (data) => { 24 | console.log(data.key.toString(), "=", data.value.toString()); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/mongodb-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongodb-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "tasks.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "mongodb": "^3.5.7" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter07/mongodb-app/tasks.js: -------------------------------------------------------------------------------- 1 | const { MongoClient } = require("mongodb"); 2 | const task = process.argv[2]; 3 | 4 | const URI = "mongodb://localhost:27017/"; 5 | 6 | MongoClient.connect( 7 | URI, 8 | { 9 | useUnifiedTopology: true, 10 | }, 11 | connected 12 | ); 13 | 14 | function connected(err, client) { 15 | if (err) throw err; 16 | const tasks = client.db("tasklist").collection("tasks"); 17 | 18 | if (task) { 19 | addTask(client, tasks); 20 | } else { 21 | listTasks(client, tasks); 22 | } 23 | } 24 | 25 | function addTask(client, tasks) { 26 | tasks.insertOne( 27 | { 28 | task: task, 29 | }, 30 | (err) => { 31 | if (err) throw err; 32 | console.log("New Task: ", task); 33 | listTasks(client, tasks); 34 | } 35 | ); 36 | } 37 | 38 | function listTasks(client, tasks) { 39 | tasks.find().each((err, doc) => { 40 | if (err) throw err; 41 | if (!doc) { 42 | client.close(); 43 | return; 44 | } 45 | console.log(doc); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /Chapter07/mongoose-app/customers.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const URI = "mongodb://localhost:27017/customers"; 3 | 4 | mongoose.connect(URI, { 5 | useNewUrlParser: true, 6 | useUnifiedTopology: true, 7 | }); 8 | 9 | const Customer = mongoose.model("Customer", { 10 | forename: String, 11 | surname: String, 12 | }); 13 | 14 | const customer1 = new Customer({ 15 | forename: "Beth", 16 | surname: "Griggs", 17 | }); 18 | 19 | customer1.save().then((doc) => { 20 | console.log("Added new customer:", doc.forename, doc.surname); 21 | listCustomers(); 22 | }); 23 | 24 | function listCustomers() { 25 | console.log("Customers:"); 26 | Customer.find().then((doc) => { 27 | doc.forEach((customer) => { 28 | console.log(`- ${customer.surname}, ${customer.forename}`); 29 | mongoose.connection.close(); 30 | }); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /Chapter07/mysql-app/.env: -------------------------------------------------------------------------------- 1 | DB_MYSQL_USER=root 2 | DB_MYSQL_PASSWORD=PASSWORD -------------------------------------------------------------------------------- /Chapter07/mysql-app/insert.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const mysql = require("mysql"); 3 | 4 | const db = mysql.createConnection({ 5 | user: process.env.DB_MYSQL_USER, 6 | password: process.env.DB_MYSQL_PASSWORD, 7 | }); 8 | 9 | db.query("CREATE DATABASE tasks"); 10 | db.query("USE tasks"); 11 | 12 | db.query( 13 | "CREATE TABLE tasks.tasks (" + 14 | "id INT NOT NULL AUTO_INCREMENT, " + 15 | "task TEXT NOT NULL, PRIMARY KEY ( id )" + 16 | ")" 17 | ); 18 | 19 | const ignore = new Set(["ER_DB_CREATE_EXISTS", "ER_TABLE_EXISTS_ERROR"]); 20 | 21 | db.on("error", (err) => { 22 | if (ignore.has(err.code)) return; 23 | throw err; 24 | }); 25 | 26 | if (process.argv[2]) { 27 | db.query( 28 | ` 29 | INSERT INTO tasks.tasks (task) 30 | VALUES (?); 31 | `, 32 | [process.argv[2]] 33 | ); 34 | } 35 | 36 | db.query( 37 | ` 38 | SELECT * FROM tasks.tasks; 39 | `, 40 | (err, results, fields) => { 41 | console.log(results); 42 | } 43 | ); 44 | 45 | db.end(); 46 | -------------------------------------------------------------------------------- /Chapter07/mysql-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mysql-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "dotenv": "^8.2.0", 14 | "mysql": "^2.18.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter07/mysql-app/tasks.js: -------------------------------------------------------------------------------- 1 | const mysql = require("mysql"); 2 | require("dotenv").config(); 3 | 4 | const db = mysql.createConnection({ 5 | user: process.env.DB_MYSQL_USER, 6 | password: process.env.DB_MYSQL_PASSWORD, 7 | }); 8 | 9 | db.query("CREATE DATABASE tasks"); 10 | db.query("USE tasks"); 11 | 12 | db.query(` 13 | CREATE TABLE tasks.tasks ( 14 | id INT NOT NULL AUTO_INCREMENT, 15 | task TEXT NOT NULL, PRIMARY KEY ( id )) 16 | `); 17 | 18 | const ignore = new Set(["ER_DB_CREATE_EXISTS", "ER_TABLE_EXISTS_ERROR"]); 19 | 20 | db.on("error", (err) => { 21 | if (ignore.has(err.code)) return; 22 | throw err; 23 | }); 24 | 25 | db.query(` 26 | INSERT INTO tasks.tasks (task) 27 | VALUES ("Walk the dog."); 28 | `); 29 | 30 | db.query( 31 | ` 32 | SELECT * FROM tasks.tasks; 33 | `, 34 | (err, results, fields) => { 35 | console.log(results); 36 | db.end(); 37 | } 38 | ); 39 | -------------------------------------------------------------------------------- /Chapter07/postgres-app/.env: -------------------------------------------------------------------------------- 1 | PGUSER=postgres 2 | PGPASSWORD=PASSWORD 3 | PGPORT=5432 -------------------------------------------------------------------------------- /Chapter07/postgres-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postgres-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "tasks.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "dotenv": "^8.2.0", 14 | "pg": "^8.2.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter07/postgres-app/tasks.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const pg = require("pg"); 3 | const db = new pg.Client(); 4 | const task = process.argv[2]; 5 | 6 | const CREATE_TABLE_SQL = `CREATE TABLE IF NOT EXISTS tasks 7 | (id SERIAL, task TEXT NOT NULL, PRIMARY KEY ( id ))`; 8 | const INSERT_TASK_SQL = `INSERT INTO tasks (task) VALUES ($1);`; 9 | const GET_TASKS_SQL = `SELECT * FROM tasks;`; 10 | 11 | db.connect((err) => { 12 | if (err) throw err; 13 | db.query(CREATE_TABLE_SQL, (err) => { 14 | if (err) throw err; 15 | if (task) { 16 | db.query(INSERT_TASK_SQL, [task], (err) => { 17 | if (err) throw err; 18 | listTasks(); 19 | }); 20 | } else { 21 | listTasks(); 22 | } 23 | }); 24 | }); 25 | 26 | function listTasks() { 27 | db.query(GET_TASKS_SQL, (err, results) => { 28 | if (err) throw err; 29 | console.log(results.rows); 30 | db.end(); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /Chapter07/postgres-object-app/.env: -------------------------------------------------------------------------------- 1 | PGUSER=postgres 2 | PGPASSWORD=PASSWORD 3 | PGPORT=5432 -------------------------------------------------------------------------------- /Chapter07/postgres-object-app/tasks.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const pg = require("pg"); 3 | const db = new pg.Client(); 4 | const task = process.argv[2]; 5 | 6 | const CREATE_TABLE_SQL = `CREATE TABLE IF NOT EXISTS task_docs 7 | (id SERIAL, doc jsonb);`; 8 | const INSERT_TASK_SQL = `INSERT INTO task_docs (doc) VALUES ($1);`; 9 | const GET_TASKS_SQL = `SELECT * FROM task_docs;`; 10 | 11 | db.connect((err) => { 12 | if (err) throw err; 13 | db.query(CREATE_TABLE_SQL, (err) => { 14 | if (err) throw err; 15 | if (task) { 16 | db.query(INSERT_TASK_SQL, [task], (err) => { 17 | if (err) throw err; 18 | listTasks(); 19 | }); 20 | } else { 21 | listTasks(); 22 | } 23 | }); 24 | }); 25 | 26 | function listTasks() { 27 | db.query(GET_TASKS_SQL, (err, results) => { 28 | if (err) throw err; 29 | console.log(results.rows); 30 | db.end(); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /Chapter07/redis-app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redis-app", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "denque": { 8 | "version": "1.4.1", 9 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", 10 | "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" 11 | }, 12 | "redis": { 13 | "version": "3.0.2", 14 | "resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz", 15 | "integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==", 16 | "requires": { 17 | "denque": "^1.4.1", 18 | "redis-commands": "^1.5.0", 19 | "redis-errors": "^1.2.0", 20 | "redis-parser": "^3.0.0" 21 | } 22 | }, 23 | "redis-commands": { 24 | "version": "1.5.0", 25 | "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", 26 | "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" 27 | }, 28 | "redis-errors": { 29 | "version": "1.2.0", 30 | "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", 31 | "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" 32 | }, 33 | "redis-parser": { 34 | "version": "3.0.0", 35 | "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", 36 | "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", 37 | "requires": { 38 | "redis-errors": "^1.0.0" 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Chapter07/redis-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redis-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "redis": "^3.0.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter07/redis-app/tasks-auth.js: -------------------------------------------------------------------------------- 1 | const redis = require("redis"); 2 | const client = redis.createClient({ 3 | port: 6380, 4 | password: "PASSWORD", 5 | }); 6 | const task = process.argv[2]; 7 | 8 | client.on("error", (err) => { 9 | console.log("Error:", err); 10 | }); 11 | 12 | if (!task) { 13 | listTasks(); 14 | } else { 15 | addTask(task); 16 | } 17 | 18 | function addTask(task) { 19 | const key = `Task: ${Math.random().toString(32).replace(".", "")}`; 20 | client.hmset(key, { 21 | task, 22 | }); 23 | listTasks(); 24 | } 25 | 26 | function listTasks() { 27 | client.keys("Task:*", (err, keys) => { 28 | if (err) throw err; 29 | keys.forEach((key) => { 30 | client.hgetall(key, (err, task) => { 31 | if (err) throw err; 32 | console.log(task); 33 | }); 34 | }); 35 | client.quit(); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /Chapter07/redis-app/tasks.js: -------------------------------------------------------------------------------- 1 | const redis = require("redis"); 2 | const client = redis.createClient(); 3 | const task = process.argv[2]; 4 | 5 | client.on("error", (err) => { 6 | console.log("Error:", err); 7 | }); 8 | 9 | if (!task) { 10 | listTasks(); 11 | } else { 12 | addTask(task); 13 | } 14 | 15 | function addTask(task) { 16 | const key = `Task: ${Math.random().toString(32).replace(".", "")}`; 17 | client.hmset(key, { 18 | task, 19 | }); 20 | listTasks(); 21 | } 22 | 23 | function listTasks() { 24 | client.keys("Task:*", (err, keys) => { 25 | if (err) throw err; 26 | keys.forEach((key) => { 27 | client.hgetall(key, (err, task) => { 28 | if (err) throw err; 29 | console.log(task); 30 | }); 31 | }); 32 | client.quit(); 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /Chapter08/enabling-travis/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 14 -------------------------------------------------------------------------------- /Chapter08/enabling-travis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "enabling-travis", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/bethgriggs/enabling-travis.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/bethgriggs/enabling-travis/issues" 18 | }, 19 | "homepage": "https://github.com/bethgriggs/enabling-travis#readme", 20 | "devDependencies": { 21 | "tape": "^5.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter08/enabling-travis/test.js: -------------------------------------------------------------------------------- 1 | const test = require("tape"); 2 | test("test integer addition", function (t) { 3 | t.plan(1); 4 | t.equal(1 + 1, 2); 5 | }); 6 | 7 | test("test string addition", function (t) { 8 | t.plan(1); 9 | // Expected to fail 10 | t.equal("1" + "1", 2); 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /Chapter08/stubbing-http-requests/github.js: -------------------------------------------------------------------------------- 1 | const fetch = require("node-fetch"); 2 | 3 | module.exports.getGitHubUser = (username) => { 4 | return fetch("https://api.github.com/users/" + username) 5 | .then((res) => res.json()) 6 | .then((json) => { 7 | return json; 8 | }); 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /Chapter08/stubbing-http-requests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stubbing-http-requests", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "node-fetch": "^2.6.0", 14 | "tape": "^5.0.1" 15 | }, 16 | "devDependencies": { 17 | "sinon": "^9.0.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter08/stubbing-http-requests/test/octokitUserData.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | login: "octokit", 3 | id: 3430433, 4 | node_id: "MDEyOk9yZ2FuaXphdGlvbjM0MzA0MzM=", 5 | avatar_url: "https://avatars0.githubusercontent.com/u/3430433?v=4", 6 | gravatar_id: "", 7 | url: "https://api.github.com/users/octokit", 8 | html_url: "https://github.com/octokit", 9 | followers_url: "https://api.github.com/users/octokit/followers", 10 | following_url: "https://api.github.com/users/octokit/following{/other_user}", 11 | gists_url: "https://api.github.com/users/octokit/gists{/gist_id}", 12 | starred_url: "https://api.github.com/users/octokit/starred{/owner}{/repo}", 13 | subscriptions_url: "https://api.github.com/users/octokit/subscriptions", 14 | organizations_url: "https://api.github.com/users/octokit/orgs", 15 | repos_url: "https://api.github.com/users/octokit/repos", 16 | events_url: "https://api.github.com/users/octokit/events{/privacy}", 17 | received_events_url: "https://api.github.com/users/octokit/received_events", 18 | type: "Organization", 19 | site_admin: false, 20 | name: "Octokit", 21 | company: null, 22 | blog: "http://octokit.github.io", 23 | location: null, 24 | email: null, 25 | hireable: null, 26 | bio: "Official clients for the GitHub API", 27 | twitter_username: "octokit", 28 | public_repos: 44, 29 | public_gists: 0, 30 | followers: 0, 31 | following: 0, 32 | created_at: "2013-01-30T18:13:42Z", 33 | updated_at: "2020-06-09T20:53:23Z", 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /Chapter08/stubbing-http-requests/test/test.js: -------------------------------------------------------------------------------- 1 | const test = require("tape"); 2 | const sinon = require("sinon"); 3 | 4 | const github = require("../github.js"); 5 | const octokitUserData = require("./octokitUserData.js"); 6 | 7 | test("Get GitHub user by username", async function (t) { 8 | t.plan(3); 9 | 10 | sinon.stub(github, "getGitHubUser").returns(octokitUserData); 11 | 12 | const githubUser = await github.getGitHubUser("octokit"); 13 | 14 | t.equal(githubUser.id, 3430433); 15 | t.equal(githubUser.login, "octokit"); 16 | t.equal(githubUser.name, "Octokit"); 17 | }); 18 | -------------------------------------------------------------------------------- /Chapter08/testing-with-jest/coverage/clover.xml: -------------------------------------------------------------------------------- 1 | 2 |Welcome to Express
8 | <% if (user) { %> 9 |Hello <%= user.name %>!
10 | 11 | <% } else { %> 12 | 13 | <% } %> 14 | 15 | 16 | -------------------------------------------------------------------------------- /Chapter09/express-auth/views/login.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 |Email: ${mockUser.email}
52 | 56 | `); 57 | }); 58 | 59 | app.post("/update", (req, res) => { 60 | if (!req.session.user) return res.sendStatus(403); 61 | mockUser.email = req.body.email; 62 | res.redirect("/"); 63 | }); 64 | 65 | app.listen(3000, () => { 66 | console.log("Server listening on port 3000"); 67 | }); 68 | -------------------------------------------------------------------------------- /Chapter09/express-csrf/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-csrf", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.19.0", 14 | "csurf": "^1.11.0", 15 | "express": "^4.17.1", 16 | "express-session": "^1.17.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter09/express-csrf/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const bodyParser = require("body-parser"); 3 | const session = require("express-session"); 4 | const app = express(); 5 | 6 | const mockUser = { 7 | username: "beth", 8 | password: "badpassword", 9 | email: "beth@example.com", 10 | }; 11 | 12 | app.use( 13 | session({ 14 | secret: "Node Cookbook", 15 | name: "SESSIONID", 16 | resave: false, 17 | saveUninitialized: false, 18 | }) 19 | ); 20 | 21 | app.use(bodyParser.urlencoded({ extended: false })); 22 | 23 | app.get("/", (req, res) => { 24 | if (req.session.user) return res.redirect("/account"); 25 | res.send(` 26 |Email: ${mockUser.email}
51 | 55 | `); 56 | }); 57 | 58 | app.post("/update", (req, res) => { 59 | if (!req.session.user) return res.sendStatus(403); 60 | mockUser.email = req.body.email; 61 | res.redirect("/"); 62 | }); 63 | 64 | app.listen(3000, () => { 65 | console.log("Server listening on port 3000"); 66 | }); 67 | -------------------------------------------------------------------------------- /Chapter09/express-helmet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-helmet", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1", 14 | "helmet": "^4.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter09/express-helmet/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | const helmet = require("helmet"); 4 | 5 | app.use(helmet()); 6 | 7 | app.get("/", (req, res) => res.send("Hello World!")); 8 | 9 | app.listen(3000, () => { 10 | console.log("Server listening on port 3000"); 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /Chapter09/express-input/fixed-server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | 4 | app.get("/", (req, res) => { 5 | asyncWork(() => { 6 | let msg = req.query.msg; 7 | if (Array.isArray(msg)) msg = msg.pop(); 8 | const upper = (msg || "").toUpperCase(); 9 | res.send(upper); 10 | }); 11 | }); 12 | 13 | asyncWork = (callback) => { 14 | setTimeout(callback, 0); 15 | }; 16 | 17 | app.listen(3000, () => { 18 | console.log("Server listening on port 3000"); 19 | }); 20 | -------------------------------------------------------------------------------- /Chapter09/express-input/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-input", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter09/express-input/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | 4 | app.get("/", (req, res) => { 5 | asyncWork(() => { 6 | const upper = (req.query.msg || "").toUpperCase(); 7 | res.send(upper); 8 | }); 9 | }); 10 | 11 | asyncWork = (callback) => { 12 | setTimeout(callback, 0); 13 | }; 14 | 15 | app.listen(3000, () => { 16 | console.log("Server listening on port 3000"); 17 | }); 18 | -------------------------------------------------------------------------------- /Chapter09/express-xss/collection-server.js: -------------------------------------------------------------------------------- 1 | require("http") 2 | .createServer((req, res) => { 3 | console.log( 4 | req.connection.remoteAddress, 5 | Buffer.from(req.url.split("/attack/")[1], "base64").toString().trim() 6 | ); 7 | }) 8 | .listen(3001, () => { 9 | console.log("Collection Server listening on port 3001"); 10 | }); 11 | -------------------------------------------------------------------------------- /Chapter09/express-xss/constraints-server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | 4 | app.get("/", (req, res) => { 5 | const { previous, lang, token } = req.query; 6 | 7 | if (!validateParameters({ previous, token, lang }, req.query)) { 8 | res.sendStatus(422); 9 | return; 10 | } 11 | 12 | getServiceStatus((status) => { 13 | res.send(` 14 |Welcome to Express
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-http/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-http/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-http/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-views/app.js: -------------------------------------------------------------------------------- 1 | var createError = require('http-errors'); 2 | var express = require('express'); 3 | var path = require('path'); 4 | var cookieParser = require('cookie-parser'); 5 | var logger = require('morgan'); 6 | 7 | var indexRouter = require('./routes/index'); 8 | var usersRouter = require('./routes/users'); 9 | 10 | var app = express(); 11 | 12 | // view engine setup 13 | app.set('views', path.join(__dirname, 'views')); 14 | app.set('view engine', 'jade'); 15 | 16 | app.use(logger('dev')); 17 | app.use(express.json()); 18 | app.use(express.urlencoded({ extended: false })); 19 | app.use(cookieParser()); 20 | app.use(express.static(path.join(__dirname, 'public'))); 21 | 22 | app.use('/', indexRouter); 23 | app.use('/users', usersRouter); 24 | 25 | // catch 404 and forward to error handler 26 | app.use(function(req, res, next) { 27 | next(createError(404)); 28 | }); 29 | 30 | // error handler 31 | app.use(function(err, req, res, next) { 32 | // set locals, only providing error in development 33 | res.locals.message = err.message; 34 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 35 | 36 | // render the error page 37 | res.status(err.status || 500); 38 | res.render('error'); 39 | }); 40 | 41 | module.exports = app; 42 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-views/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmarking-views", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "cookie-parser": "~1.4.4", 10 | "debug": "~2.6.9", 11 | "express": "~4.16.1", 12 | "http-errors": "~1.6.3", 13 | "jade": "~1.11.0", 14 | "morgan": "~1.9.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-views/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-views/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-views/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-views/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-views/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /Chapter10/benchmarking-views/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /Chapter10/flamegraph-app/app.js: -------------------------------------------------------------------------------- 1 | var createError = require('http-errors'); 2 | var express = require('express'); 3 | var path = require('path'); 4 | var cookieParser = require('cookie-parser'); 5 | var logger = require('morgan'); 6 | 7 | var indexRouter = require('./routes/index'); 8 | var usersRouter = require('./routes/users'); 9 | 10 | var app = express(); 11 | 12 | // view engine setup 13 | app.set('views', path.join(__dirname, 'views')); 14 | app.set('view engine', 'jade'); 15 | 16 | app.use(logger('dev')); 17 | app.use(express.json()); 18 | app.use(express.urlencoded({ extended: false })); 19 | app.use(cookieParser()); 20 | app.use(express.static(path.join(__dirname, 'public'))); 21 | 22 | app.use('/', indexRouter); 23 | app.use('/users', usersRouter); 24 | 25 | // catch 404 and forward to error handler 26 | app.use(function(req, res, next) { 27 | next(createError(404)); 28 | }); 29 | 30 | // error handler 31 | app.use(function(err, req, res, next) { 32 | // set locals, only providing error in development 33 | res.locals.message = err.message; 34 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 35 | 36 | // render the error page 37 | res.status(err.status || 500); 38 | res.render('error'); 39 | }); 40 | 41 | module.exports = app; 42 | -------------------------------------------------------------------------------- /Chapter10/flamegraph-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flamegraph-app", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "cookie-parser": "~1.4.4", 10 | "debug": "~2.6.9", 11 | "express": "~4.16.1", 12 | "http-errors": "~1.6.3", 13 | "jade": "~1.11.0", 14 | "morgan": "~1.9.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter10/flamegraph-app/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter10/flamegraph-app/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter10/flamegraph-app/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter10/flamegraph-app/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /Chapter10/flamegraph-app/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /Chapter10/flamegraph-app/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /Chapter10/optimize-async/calculate-average.js: -------------------------------------------------------------------------------- 1 | const MongoClient = require("mongodb").MongoClient; 2 | const URL = "mongodb://localhost:27017/"; 3 | 4 | MongoClient.connect(URL, { useUnifiedTopology: true }, (err, client) => { 5 | if (err) throw err; 6 | 7 | const db = client.db("data"); 8 | const values = db.collection("values"); 9 | const averages = db.collection("averages"); 10 | 11 | values.find({}).toArray((err, data) => { 12 | if (err) throw err; 13 | 14 | // Calculate average 15 | const average = 16 | data.reduce((accumulator, value) => accumulator + value.value, 0) / 17 | data.length; 18 | 19 | averages.find({}).toArray((err) => { 20 | if (err) throw err; 21 | 22 | averages.insertOne({ value: average }, (err) => { 23 | if (err) throw err; 24 | console.log("Stored average in database."); 25 | client.close(); 26 | }); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /Chapter10/optimize-async/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "optimize-async", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1", 14 | "mongodb": "^3.6.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter10/optimize-async/server-no-processing.js: -------------------------------------------------------------------------------- 1 | const MongoClient = require("mongodb").MongoClient; 2 | const URL = "mongodb://localhost:27017/"; 3 | 4 | const express = require("express"); 5 | const app = express(); 6 | 7 | MongoClient.connect(URL, { useUnifiedTopology: true }, (err, client) => { 8 | if (err) throw err; 9 | 10 | const db = client.db("data"); 11 | const average = db.collection("averages"); 12 | 13 | app.get("/", (req, res) => { 14 | average.findOne({}, (err, data) => { 15 | if (err) throw err; 16 | res.send(`Average of all values is ${data.value}.`); 17 | }); 18 | }); 19 | app.listen(3000); 20 | }); 21 | -------------------------------------------------------------------------------- /Chapter10/optimize-async/server.js: -------------------------------------------------------------------------------- 1 | const MongoClient = require("mongodb").MongoClient; 2 | const URL = "mongodb://localhost:27017/"; 3 | 4 | const express = require("express"); 5 | const app = express(); 6 | 7 | MongoClient.connect(URL, { useUnifiedTopology: true }, (err, client) => { 8 | if (err) throw err; 9 | const db = client.db("data"); 10 | const values = db.collection("values"); 11 | 12 | app.get("/", (req, res) => { 13 | values.find({}).toArray(function sum(err, data) { 14 | if (err) { 15 | res.send(err); 16 | return; 17 | } 18 | 19 | // Calculate average 20 | const average = 21 | data.reduce((accumulator, value) => accumulator + value.value, 0) / 22 | data.length; 23 | res.send(`Average of all values is ${average}.`); 24 | }); 25 | }); 26 | app.listen(3000); 27 | }); 28 | -------------------------------------------------------------------------------- /Chapter10/optimize-async/values.js: -------------------------------------------------------------------------------- 1 | const MongoClient = require("mongodb").MongoClient; 2 | const URL = "mongodb://localhost:27017/"; 3 | 4 | let values = []; 5 | const numberOfValues = 1000; 6 | 7 | let count = 0; 8 | for (count; count < numberOfValues; count++) { 9 | values.push({ value: Math.round(Math.random() * 100000) }); 10 | } 11 | 12 | MongoClient.connect(URL, { useUnifiedTopology: true }, (err, client) => { 13 | if (err) throw err; 14 | 15 | const db = client.db("data"); 16 | 17 | db.collection("values").insertMany(values, (err) => { 18 | if (err) throw err; 19 | console.log(`Added ${numberOfValues} random values.`); 20 | client.close(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /Chapter10/optimize-sync/benchmark.js: -------------------------------------------------------------------------------- 1 | const benchmark = require("benchmark"); 2 | const slow = require("./slow"); 3 | const loop = require("./loop"); 4 | const suite = new benchmark.Suite(); 5 | const maxNumber = 100; // number to pass through to sumOfSquares() 6 | 7 | suite.add("slow", function () { 8 | slow(maxNumber); 9 | }); 10 | 11 | suite.add("loop", function () { 12 | loop(maxNumber); 13 | }); 14 | 15 | suite.on("complete", printResults); 16 | suite.run(); 17 | 18 | function printResults() { 19 | this.forEach((benchmark) => { 20 | console.log(benchmark.toString()); 21 | }); 22 | console.log("Fastest implementation is", this.filter("fastest")[0].name); 23 | } 24 | -------------------------------------------------------------------------------- /Chapter10/optimize-sync/loop.js: -------------------------------------------------------------------------------- 1 | function sumOfSquares(maxNumber) { 2 | let i = 0; 3 | let sum = 0; 4 | for (i; i <= maxNumber; i++) { 5 | sum += i ** 2; 6 | } 7 | return sum; 8 | } 9 | 10 | module.exports = sumOfSquares; 11 | -------------------------------------------------------------------------------- /Chapter10/optimize-sync/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "optimize-sync", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "benchmark": { 8 | "version": "2.1.4", 9 | "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", 10 | "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", 11 | "requires": { 12 | "lodash": "^4.17.4", 13 | "platform": "^1.3.3" 14 | } 15 | }, 16 | "lodash": { 17 | "version": "4.17.20", 18 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 19 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" 20 | }, 21 | "platform": { 22 | "version": "1.3.6", 23 | "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", 24 | "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter10/optimize-sync/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "optimize-sync", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "benchmark": "^2.1.4" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter10/optimize-sync/slow.js: -------------------------------------------------------------------------------- 1 | function sumOfSquares(maxNumber) { 2 | const array = Array.from(Array(maxNumber + 1).keys()); 3 | 4 | return array 5 | .map((number) => { 6 | return number ** 2; 7 | }) 8 | .reduce((accumulator, item) => { 9 | return accumulator + item; 10 | }); 11 | } 12 | 13 | module.exports = sumOfSquares; 14 | -------------------------------------------------------------------------------- /Chapter10/profiling-memory/leaky-server.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | 3 | const server = http.createServer((req, res) => { 4 | server.on("connection", () => { 5 | console.log("connected"); 6 | }); 7 | res.end("Hello World!"); 8 | }); 9 | 10 | server.listen(3000, () => { 11 | console.log("Server listening on port 3000"); 12 | }); 13 | -------------------------------------------------------------------------------- /Chapter10/profiling-memory/max-listeners.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | 3 | const server = http.createServer((req, res) => { 4 | server.setMaxListeners(1); 5 | 6 | server.on("connection", () => { 7 | console.log("connected"); 8 | }); 9 | res.end("Hello World!"); 10 | }); 11 | 12 | server.listen(3000, () => { 13 | console.log("Server listening on port 3000"); 14 | }); 15 | -------------------------------------------------------------------------------- /Chapter10/profiling-memory/server.js: -------------------------------------------------------------------------------- 1 | const http = require("http"); 2 | 3 | const server = http.createServer((req, res) => { 4 | res.end("Hello World!"); 5 | }); 6 | 7 | server.on("connection", () => { 8 | console.log("connected"); 9 | }); 10 | 11 | server.listen(3000, () => { 12 | console.log("Server listening on port 3000"); 13 | }); 14 | -------------------------------------------------------------------------------- /Chapter10/worker-app/fibonacci-worker.js: -------------------------------------------------------------------------------- 1 | const { 2 | Worker, 3 | isMainThread, 4 | parentPort, 5 | workerData, 6 | } = require("worker_threads"); 7 | 8 | const n = 10; 9 | // Fibonacci calculator 10 | const fibonacci = (n) => { 11 | let a = 0, b = 1, next = 1, i = 2; 12 | for (i; i <= n; i++) { 13 | next = a + b; 14 | a = b; 15 | b = next; 16 | } 17 | return next; 18 | }; 19 | 20 | if (isMainThread) { 21 | // Main thread code 22 | const worker = new Worker(__filename, { 23 | workerData: n, 24 | }); 25 | worker.on("message", (msg) => { 26 | console.log(`The Fibonacci number at position ${n} is ${msg}`); 27 | }); 28 | console.log("..."); 29 | } else { 30 | // Worker code 31 | parentPort.postMessage(fibonacci(workerData)); 32 | } 33 | -------------------------------------------------------------------------------- /Chapter10/worker-app/fibonacci.js: -------------------------------------------------------------------------------- 1 | const n = 10; 2 | // Fibonacci calculator 3 | const fibonacci = (n) => { 4 | let a = 0, b = 1, next = 1, i = 2; 5 | for (i; i <= n; i++) { 6 | next = a + b; 7 | a = b; 8 | b = next; 9 | } 10 | console.log(`The Fibonacci number at position ${n} is ${next}`); 11 | }; 12 | 13 | fibonacci(n); 14 | console.log("..."); 15 | -------------------------------------------------------------------------------- /Chapter10/worker-app/hello-worker.js: -------------------------------------------------------------------------------- 1 | const { 2 | Worker, 3 | isMainThread, 4 | parentPort, 5 | workerData, 6 | } = require("worker_threads"); 7 | 8 | if (isMainThread) { 9 | // Main thread code 10 | const worker = new Worker(__filename, { 11 | workerData: "Beth", 12 | }); 13 | worker.on("message", (msg) => { 14 | console.log(msg); 15 | }); 16 | } else { 17 | // Worker code 18 | const greeting = `Hello ${workerData}!`; 19 | parentPort.postMessage(greeting); 20 | } 21 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/app.js: -------------------------------------------------------------------------------- 1 | var createError = require("http-errors"); 2 | var express = require("express"); 3 | var path = require("path"); 4 | var cookieParser = require("cookie-parser"); 5 | var logger = require("morgan"); 6 | 7 | var indexRouter = require("./routes/index"); 8 | var usersRouter = require("./routes/users"); 9 | var inventoryRouter = require("./routes/inventory"); 10 | 11 | var app = express(); 12 | 13 | // view engine setup 14 | app.set("views", path.join(__dirname, "views")); 15 | app.set("view engine", "ejs"); 16 | 17 | app.use(logger("dev")); 18 | app.use(express.json()); 19 | app.use(express.urlencoded({ extended: false })); 20 | app.use(cookieParser()); 21 | app.use(express.static(path.join(__dirname, "public"))); 22 | 23 | app.use("/", indexRouter); 24 | app.use("/users", usersRouter); 25 | app.use("/inventory", inventoryRouter); 26 | 27 | // catch 404 and forward to error handler 28 | app.use(function (req, res, next) { 29 | next(createError(404)); 30 | }); 31 | 32 | // error handler 33 | app.use(function (err, req, res, next) { 34 | // set locals, only providing error in development 35 | res.locals.message = err.message; 36 | res.locals.error = req.app.get("env") === "development" ? err : {}; 37 | 38 | // render the error page 39 | res.status(err.status || 500); 40 | res.render("error"); 41 | }); 42 | 43 | module.exports = app; 44 | 45 | process.on("unhandledRejection", (reason, promise) => { 46 | console.log("Unhandled Rejection at:", promise, "reason:", reason); 47 | process.exit(1); 48 | }); 49 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bookstore-web-app", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "cookie-parser": "~1.4.4", 10 | "debug": "~2.6.9", 11 | "ejs": "~2.6.1", 12 | "express": "~4.16.1", 13 | "http-errors": "~1.6.3", 14 | "morgan": "~1.9.1", 15 | "node-fetch": "^2.6.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/routes/inventory.js: -------------------------------------------------------------------------------- 1 | const { Router } = require("express"); 2 | const fetch = require("node-fetch"); 3 | 4 | const router = Router(); 5 | 6 | router.get("/", function (req, res) { 7 | fetch("http://localhost:3000/books") 8 | .then((res) => res.json()) 9 | .then((json) => 10 | res.render("inventory", { 11 | books: json, 12 | }) 13 | ) 14 | .catch((error) => { 15 | res.render("error", { 16 | error: error, 17 | message: error.message, 18 | }); 19 | }); 20 | }); 21 | 22 | router.post("/add", function (req, res) { 23 | console.log(req.body); 24 | 25 | fetch("http://localhost:3000/books", { 26 | method: "POST", 27 | body: JSON.stringify(req.body), 28 | headers: { "Content-Type": "application/json" }, 29 | }) 30 | .then(res.redirect("/inventory")) 31 | .catch((err) => { 32 | throw err; 33 | }); 34 | }); 35 | 36 | module.exports = router; 37 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/views/error.ejs: -------------------------------------------------------------------------------- 1 |<%= error.stack %>4 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
Welcome to <%= title %>
10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter11/bookstore-error-handling/views/inventory.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |<%= error.stack %>4 | -------------------------------------------------------------------------------- /Chapter11/bookstore-web-app/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
Welcome to <%= title %>
10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter11/bookstore-web-app/views/inventory.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |<%= error.stack %>4 | -------------------------------------------------------------------------------- /Chapter12/express-morgan-app/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
Welcome to <%= title %>
10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter12/express-pino-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-pino-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "express": "^4.17.1", 15 | "express-pino-logger": "^5.0.0", 16 | "pino": "^6.3.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter12/express-pino-app/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | const PORT = 3000; 4 | 5 | const pino = require("pino")(); 6 | const logger = require("express-pino-logger")({ 7 | instance: pino, 8 | }); 9 | 10 | app.use(logger); 11 | 12 | app.get("/", (req, res) => { 13 | req.log.info("Generating random number"); 14 | const randomNumber = getRandomNumber(); 15 | res.send(`${randomNumber}`); 16 | }); 17 | 18 | app.listen(PORT, () => pino.info(`Server listening on port ${PORT}`)); 19 | 20 | function getRandomNumber() { 21 | return Math.floor(Math.random() * 100) + 1; 22 | } 23 | -------------------------------------------------------------------------------- /Chapter12/express-winston-app/app.js: -------------------------------------------------------------------------------- 1 | var createError = require('http-errors'); 2 | var express = require('express'); 3 | var path = require('path'); 4 | var cookieParser = require('cookie-parser'); 5 | 6 | var winston = require('winston'); 7 | var expressWinston = require('express-winston'); 8 | 9 | var indexRouter = require('./routes/index'); 10 | var usersRouter = require('./routes/users'); 11 | 12 | var app = express(); 13 | 14 | // view engine setup 15 | app.set('views', path.join(__dirname, 'views')); 16 | app.set('view engine', 'ejs'); 17 | 18 | app.use(expressWinston.logger({ 19 | transports: [ 20 | new winston.transports.Console({ 21 | json: true 22 | }) 23 | ] 24 | })); 25 | 26 | app.use(express.json()); 27 | app.use(express.urlencoded({ extended: false })); 28 | app.use(cookieParser()); 29 | app.use(express.static(path.join(__dirname, 'public'))); 30 | 31 | app.use('/', indexRouter); 32 | app.use('/users', usersRouter); 33 | 34 | // catch 404 and forward to error handler 35 | app.use(function(req, res, next) { 36 | next(createError(404)); 37 | }); 38 | 39 | // error handler 40 | app.use(function(err, req, res, next) { 41 | // set locals, only providing error in development 42 | res.locals.message = err.message; 43 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 44 | 45 | // render the error page 46 | res.status(err.status || 500); 47 | res.render('error'); 48 | }); 49 | 50 | module.exports = app; 51 | -------------------------------------------------------------------------------- /Chapter12/express-winston-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-winston-app", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "cookie-parser": "~1.4.4", 10 | "debug": "~2.6.9", 11 | "ejs": "~2.6.1", 12 | "express": "~4.16.1", 13 | "express-winston": "^4.0.3", 14 | "http-errors": "~1.6.3", 15 | "winston": "^3.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter12/express-winston-app/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter12/express-winston-app/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter12/express-winston-app/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /Chapter12/express-winston-app/views/error.ejs: -------------------------------------------------------------------------------- 1 |<%= error.stack %>4 | -------------------------------------------------------------------------------- /Chapter12/express-winston-app/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
Welcome to <%= title %>
10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter12/stack-trace-app/async-stack-trace.js: -------------------------------------------------------------------------------- 1 | foo().then( 2 | () => console.log("success"), 3 | (error) => console.error(error.stack) 4 | ); 5 | 6 | async function foo() { 7 | await bar(); 8 | } 9 | 10 | async function bar() { 11 | await Promise.resolve(); 12 | throw new Error("Fail"); 13 | } 14 | -------------------------------------------------------------------------------- /Chapter12/stack-trace-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stack-trace-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter12/stack-trace-app/routes.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const router = new express.Router(); 3 | 4 | router.get("/", (req, res) => { 5 | res.send(recursiveContent()); 6 | }); 7 | 8 | function recursiveContent(content, i = 15) { 9 | --i; 10 | if (i !== 0) { 11 | return recursiveContent(content, i); 12 | } else { 13 | return content.undefined_property; 14 | } 15 | } 16 | 17 | module.exports = router; 18 | -------------------------------------------------------------------------------- /Chapter12/stack-trace-app/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const routes = require("./routes"); 3 | const app = express(); 4 | 5 | app.use(routes); 6 | app.listen(3000, () => { 7 | console.log("Server listening on port 3000"); 8 | }); 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------