├── appendix-a ├── listing_a12 │ ├── favicon.ico │ ├── package.json │ └── index.js ├── listing_a7 │ ├── readme.md │ ├── index.js │ └── package.json ├── listing_a6 │ ├── readme.md │ ├── index.js │ └── package.json ├── listing_a1 │ ├── index.js │ └── package.json ├── listing_a8 │ ├── index.js │ └── package.json ├── listing_a4 │ ├── index.js │ └── package.json ├── listing_a5 │ ├── package.json │ ├── readme.md │ └── index.js ├── listing_a13 │ ├── package.json │ └── index.js ├── listing_a3 │ ├── package.json │ └── index.js ├── listing_a2 │ ├── index.js │ └── package.json ├── listing_a11 │ ├── package.json │ └── index.js ├── listing_a14 │ └── package.json ├── listing_a10 │ └── package.json └── listing_a9 │ └── package.json ├── ch08-databases ├── listing8_17 │ ├── app.db │ │ ├── LOCK │ │ ├── 000003.log │ │ ├── CURRENT │ │ ├── LOG │ │ └── MANIFEST-000002 │ ├── index.js │ └── package.json ├── listing8_18 │ ├── app.db │ │ ├── LOCK │ │ ├── CURRENT │ │ ├── LOG.old │ │ ├── 000005.log │ │ ├── MANIFEST-000004 │ │ └── LOG │ ├── package.json │ └── index.js ├── listing8_19 │ ├── app.db │ │ ├── LOCK │ │ ├── 000008.log │ │ ├── CURRENT │ │ ├── 000007.ldb │ │ ├── MANIFEST-000006 │ │ ├── LOG.old │ │ └── LOG │ ├── package.json │ └── index.js ├── listing8_20 │ ├── app.db │ │ ├── LOCK │ │ ├── CURRENT │ │ ├── 000007.ldb │ │ ├── 000010.log │ │ ├── MANIFEST-000009 │ │ ├── LOG │ │ └── LOG.old │ ├── package.json │ └── index.js ├── listing8_7 │ ├── tldr.sqlite │ ├── package.json │ └── index.js ├── listing8_21 │ ├── index.js │ └── package.json ├── listing8_8 │ ├── index.js │ └── package.json ├── listing8_1 │ ├── index.js │ └── package.json ├── listing8_10 │ ├── index.js │ └── package.json ├── listing8_23.js ├── listing8_2 │ ├── package.json │ └── index.js ├── listing8_3 │ ├── package.json │ └── create-tables.js ├── listing8_4 │ ├── package.json │ └── create-tables.js ├── listing8_5 │ ├── package.json │ ├── index.js │ └── create-tables.js ├── listing8_14 │ ├── package.json │ └── index.js ├── listing8_15 │ └── package.json ├── listing8_16 │ ├── package.json │ └── index.js ├── listing8_9 │ ├── package.json │ └── index.js ├── listing8_13 │ ├── package.json │ └── index.js ├── listing8_22 │ ├── package.json │ └── index.js ├── listing8_6 │ └── package.json └── listing8_24.js ├── ch02-intro-to-node ├── listing_213 │ ├── done │ │ └── .keep │ ├── watch │ │ └── .keep │ └── index.js ├── listing_217 │ ├── rss_feeds.txt │ └── package.json ├── listing_207 │ ├── template.html │ └── titles.json ├── listing_208 │ ├── template.html │ └── titles.json ├── listing_204-205-206 │ ├── template.html │ └── titles.json ├── listing_210 │ └── index.js ├── listing_209 │ └── echo_server.js ├── listing_214 │ └── index.js ├── listing_201 │ └── currency.js ├── listing_202 │ ├── currency.js │ └── test_currency.js ├── listing_215 │ └── index.js ├── listing_216 │ ├── package.json │ └── index.js └── listing_219 │ └── package.json ├── ch11-command-line ├── listing11-1 │ ├── test.json │ ├── package.json │ └── index.js ├── listing11-2 │ ├── test.json │ └── package.json └── snippets │ ├── uglify-example │ ├── main.js │ └── package.json │ ├── exit-message.js │ └── time.js ├── ch06-connect-and-express ├── listing6_11 │ ├── views │ │ ├── menu.ejs │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ └── entries.ejs │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ ├── users.js │ │ └── entries.js │ └── package.json ├── listing6_12 │ ├── views │ │ ├── menu.ejs │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ └── entries.ejs │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── package.json ├── listing6_14 │ ├── views │ │ ├── menu.ejs │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ └── entries.ejs │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── package.json ├── listing6_9-10 │ ├── views │ │ ├── menu.ejs │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ └── entries.ejs │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ ├── users.js │ │ └── entries.js │ └── package.json ├── listing6_15-21 │ ├── views │ │ ├── menu.ejs │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ └── entries.ejs │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── user-test.js │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── package.json ├── listing6_22-24 │ ├── views │ │ ├── menu.ejs │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ ├── messages.ejs │ │ └── entries.ejs │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ ├── package.json │ └── middleware │ │ └── messages.js ├── listing6_6 │ ├── views │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── error.jade │ │ └── layout.jade │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── package.json ├── listing6_7 │ ├── views │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── error.jade │ │ └── layout.jade │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ ├── package.json │ └── models │ │ └── entry.js ├── listing6_8 │ ├── views │ │ ├── index.jade │ │ ├── error.ejs │ │ └── layout.jade │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ └── users.js │ └── package.json ├── listing6_25-27 │ ├── views │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ ├── messages.ejs │ │ ├── menu.ejs │ │ └── entries.ejs │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.js │ │ ├── users.js │ │ └── login.js │ ├── package.json │ └── middleware │ │ └── messages.js ├── listing6_28-30 │ ├── views │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ ├── messages.ejs │ │ ├── menu.ejs │ │ └── entries.ejs │ ├── routes │ │ ├── index.js │ │ └── users.js │ ├── middleware │ │ ├── user.js │ │ └── messages.js │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ └── package.json ├── listing6_31-32 │ ├── views │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ ├── messages.ejs │ │ ├── menu.ejs │ │ └── entries.ejs │ ├── routes │ │ ├── index.js │ │ └── users.js │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── package.json │ └── middleware │ │ ├── page.js │ │ └── messages.js ├── listing6_33 │ ├── views │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ ├── messages.ejs │ │ ├── entries │ │ │ └── xml.ejs │ │ ├── menu.ejs │ │ └── entries.ejs │ ├── routes │ │ ├── index.js │ │ └── users.js │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── package.json │ └── middleware │ │ └── page.js ├── listing6_34 │ ├── views │ │ ├── index.jade │ │ ├── error.ejs │ │ ├── layout.jade │ │ ├── messages.ejs │ │ ├── entries │ │ │ └── xml.ejs │ │ ├── menu.ejs │ │ └── entries.ejs │ ├── routes │ │ ├── index.js │ │ └── users.js │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── package.json │ └── middleware │ │ └── page.js ├── full-app │ ├── views │ │ ├── error.ejs │ │ ├── messages.ejs │ │ ├── entries │ │ │ └── xml.ejs │ │ ├── index.ejs │ │ ├── 404.ejs │ │ ├── menu.ejs │ │ ├── pager.ejs │ │ ├── 5xx.ejs │ │ └── entries.ejs │ ├── routes │ │ └── users.js │ ├── middleware │ │ ├── user.js │ │ ├── page.js │ │ └── messages.js │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ └── package.json ├── hello-world │ ├── server.js │ └── package.json ├── listing6_5 │ ├── server.js │ └── package.json ├── listing6_3 │ ├── server.js │ ├── logger.js │ └── package.json ├── listing6_1 │ ├── package.json │ └── server.js ├── listing6_2 │ ├── package.json │ └── server.js └── listing6_4 │ ├── logger.js │ ├── package.json │ ├── server.js │ └── errors.js ├── ch03-what-is-a-node-web-app ├── .gitignore ├── later │ ├── views │ │ ├── foot.ejs │ │ ├── article.ejs │ │ ├── head.ejs │ │ └── articles.ejs │ └── package.json ├── listing3_6 │ ├── views │ │ ├── foot.ejs │ │ ├── head.ejs │ │ ├── article.ejs │ │ └── articles.ejs │ └── package.json ├── listing3_1 │ └── package.json ├── listing3_2 │ └── package.json ├── listing3_3 │ └── package.json ├── listing3_4 │ └── package.json └── listing3_5 │ └── package.json ├── .gitignore ├── ch05-server-side-frameworks ├── kraken-example │ ├── public │ │ ├── css │ │ │ └── app.less │ │ ├── components │ │ │ └── requirejs │ │ │ │ ├── README.md │ │ │ │ └── bower.json │ │ ├── templates │ │ │ ├── index.dust │ │ │ ├── errors │ │ │ │ ├── 404.dust │ │ │ │ ├── 500.dust │ │ │ │ └── 503.dust │ │ │ └── layouts │ │ │ │ └── master.dust │ │ └── js │ │ │ └── app.js │ ├── locales │ │ └── US │ │ │ └── en │ │ │ ├── index.properties │ │ │ ├── layouts │ │ │ └── master.properties │ │ │ └── errors │ │ │ ├── 404.properties │ │ │ ├── 503.properties │ │ │ └── 500.properties │ ├── .npmignore │ ├── README.md │ ├── .bowerrc │ ├── models │ │ └── index.js │ ├── .nodemonignore │ ├── .editorconfig │ ├── tasks │ │ ├── clean.js │ │ ├── copy-browser-modules.js │ │ ├── mochacli.js │ │ ├── requirejs.js │ │ ├── eslint.js │ │ ├── less.js │ │ └── copyto.js │ ├── controllers │ │ └── index.js │ ├── .yo-rc.json │ ├── server.js │ ├── bower.json │ ├── .eslintrc │ └── Gruntfile.js ├── loopback-example │ ├── .eslintignore │ ├── .eslintrc │ ├── .yo-rc.json │ ├── README.md │ ├── client │ │ └── README.md │ ├── server │ │ ├── datasources.json │ │ ├── component-config.json │ │ ├── boot │ │ │ ├── authentication.js │ │ │ └── root.js │ │ ├── middleware.development.json │ │ └── config.json │ ├── .gitignore │ └── .editorconfig ├── example-derby-app │ ├── app │ │ ├── server.js │ │ ├── index.html │ │ └── index.js │ ├── .gitignore │ └── package.json ├── listing5_2 │ ├── server.js │ └── package.json ├── listing5_1 │ ├── package.json │ └── server.js ├── listing5_3 │ ├── package.json │ └── server.js ├── koa-router-example │ ├── package.json │ └── server.js ├── listing5_4 │ └── package.json └── flatiron-example │ ├── package.json │ └── server.js ├── ch12-desktop ├── electron-quick-start │ ├── .gitignore │ ├── app │ │ ├── events.jsx │ │ ├── index.jsx │ │ └── headers.jsx │ ├── readfile.js │ ├── .babelrc │ ├── notes.md │ ├── webpack.config.js │ └── index.html ├── electron-quick-start-print │ ├── .gitignore │ ├── app │ │ ├── events.jsx │ │ ├── index.jsx │ │ └── headers.jsx │ ├── readfile.js │ ├── .babelrc │ ├── notes.md │ ├── webpack.config.js │ └── index.html ├── listing12_1 │ └── readfile.js └── listing12_2 │ └── index.html ├── ch04-front-end ├── es2015-example │ ├── .babelrc │ ├── browser.js │ └── package.json ├── webpack-commonjs │ ├── app │ │ ├── hello.js │ │ └── index.js │ ├── webpack.config.js │ └── package.json ├── gulp-example │ ├── app │ │ └── index.jsx │ ├── dist │ │ ├── all.js.map │ │ └── all.js │ ├── gulpfile.js │ └── package.json ├── webpack-example │ ├── app │ │ └── index.jsx │ ├── webpack.config.js │ └── package.json └── webpack-hotload-example │ ├── app │ └── index.jsx │ ├── dist │ └── index.html │ └── webpack.config.js ├── ch09-testing ├── sinon-js-examples │ ├── sample.json │ ├── package.json │ ├── db.js │ ├── spies.js │ └── stub.js ├── debug-stacktraces │ ├── index.js │ ├── async.js │ └── package.json ├── debug-example │ ├── index.js │ └── package.json ├── vows-todo │ ├── package.json │ ├── test │ │ └── todo-test.js │ └── todo.js ├── chai-examples │ ├── package.json │ └── index.js ├── memdb │ └── package.json ├── tips │ ├── package.json │ ├── index.js │ └── test │ │ └── tips.js ├── selenium │ ├── package.json │ ├── index.js │ └── test │ │ └── specs │ │ └── todo.spec.js └── listing_9_1-7 │ └── todo.js ├── appendix-b-scraping ├── NODE_4_NOTICE ├── listing_b1 │ ├── test.js │ ├── package.json │ └── index.js ├── listing_b2 │ ├── test.js │ ├── messy_html_example.html │ ├── package.json │ └── index.js ├── listing_b5 │ ├── books.csv │ ├── input.html │ └── package.json ├── snippets │ └── messy_html_example.html ├── listing_b4 │ └── package.json └── listing_b3 │ ├── package.json │ └── index.js ├── ch07-templates ├── pug-snippets │ ├── template.pug │ ├── link-example.js │ ├── data-example.js │ ├── iteration-example.js │ └── package.json ├── listing7_10 │ ├── templates │ │ ├── layout.pug │ │ └── page.pug │ ├── package.json │ └── index.js ├── ejs-snippets │ ├── context.js │ ├── escape.js │ ├── delimiter.js │ └── package.json ├── listing7_5 │ ├── templates │ │ └── students.ejs │ └── package.json ├── listing7_11 │ ├── templates │ │ ├── layout.pug │ │ └── page.pug │ ├── package.json │ └── index.js ├── hogan-snippet │ ├── index.js │ └── package.json ├── listing7_1-2 │ ├── entries.txt │ └── package.json ├── listing7_4 │ ├── package.json │ └── templates │ │ └── blog_page.ejs ├── listing7_8 │ ├── index.js │ └── package.json ├── listing7_9 │ ├── package.json │ └── index.js └── listing7_7 │ └── index.html ├── ch10-deployment ├── listing10_1 │ └── hellonode.conf └── listing10_2 │ └── index.js ├── readme.md └── rename.js /appendix-a/listing_a12/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch08-databases/listing8_17/app.db/LOCK: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch08-databases/listing8_18/app.db/LOCK: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch08-databases/listing8_19/app.db/LOCK: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch08-databases/listing8_20/app.db/LOCK: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_213/done/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_213/watch/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch08-databases/listing8_17/app.db/000003.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch08-databases/listing8_19/app.db/000008.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch11-command-line/listing11-1/test.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /ch11-command-line/listing11-2/test.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/views/menu.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/views/menu.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/views/menu.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/views/menu.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/views/menu.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/views/menu.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/css/app.less: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ch08-databases/listing8_17/app.db/CURRENT: -------------------------------------------------------------------------------- 1 | MANIFEST-000002 2 | -------------------------------------------------------------------------------- /ch08-databases/listing8_18/app.db/CURRENT: -------------------------------------------------------------------------------- 1 | MANIFEST-000004 2 | -------------------------------------------------------------------------------- /ch08-databases/listing8_19/app.db/CURRENT: -------------------------------------------------------------------------------- 1 | MANIFEST-000006 2 | -------------------------------------------------------------------------------- /ch08-databases/listing8_20/app.db/CURRENT: -------------------------------------------------------------------------------- 1 | MANIFEST-000009 2 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /ch04-front-end/es2015-example/.babelrc: -------------------------------------------------------------------------------- 1 | { "presets": ["es2015"] } 2 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/.eslintignore: -------------------------------------------------------------------------------- 1 | /client/ -------------------------------------------------------------------------------- /ch09-testing/sinon-js-examples/sample.json: -------------------------------------------------------------------------------- 1 | {"name":"Charles Dickens"} -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /ch09-testing/debug-stacktraces/index.js: -------------------------------------------------------------------------------- 1 | require('./async.js')(); 2 | -------------------------------------------------------------------------------- /ch11-command-line/snippets/uglify-example/main.js: -------------------------------------------------------------------------------- 1 | console.log('Hello from main.js'); -------------------------------------------------------------------------------- /appendix-b-scraping/NODE_4_NOTICE: -------------------------------------------------------------------------------- 1 | The samples in this chapter use Node 4.0 (or above) 2 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/later/views/foot.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "loopback" 3 | } -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_6/views/foot.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-loopback": {} 3 | } -------------------------------------------------------------------------------- /ch07-templates/pug-snippets/template.pug: -------------------------------------------------------------------------------- 1 | - messages.forEach(message => { 2 | p= message 3 | - }) -------------------------------------------------------------------------------- /ch08-databases/listing8_17/app.db/LOG: -------------------------------------------------------------------------------- 1 | 2016/12/16-12:23:02.222320 7000076ba000 Delete type=3 #1 2 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b1/test.js: -------------------------------------------------------------------------------- 1 | var scraper = require('./index'); 2 | 3 | scraper.run(); 4 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b2/test.js: -------------------------------------------------------------------------------- 1 | var scraper = require('./index'); 2 | 3 | scraper.run(); 4 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/locales/US/en/index.properties: -------------------------------------------------------------------------------- 1 | greeting=Hello, {name}! 2 | -------------------------------------------------------------------------------- /ch08-databases/listing8_18/app.db/LOG.old: -------------------------------------------------------------------------------- 1 | 2016/12/16-12:23:02.222320 7000076ba000 Delete type=3 #1 2 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_217/rss_feeds.txt: -------------------------------------------------------------------------------- 1 | http://blog.nodejs.org/feed/ 2 | http://blog.npmjs.org/rss 3 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-commonjs/app/hello.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | return 'hello'; 3 | }; 4 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/locales/US/en/layouts/master.properties: -------------------------------------------------------------------------------- 1 | greeting=Hello, {name}! 2 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | .build/ 4 | node_modules/ 5 | *.iml 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/README.md: -------------------------------------------------------------------------------- 1 | kraken-example 2 | =========== 3 | 4 | An example Kraken app 5 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/example-derby-app/app/server.js: -------------------------------------------------------------------------------- 1 | require('derby-starter').run(__dirname, { port: 8005 }); 2 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/example-derby-app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | *.swp 4 | .idea* 5 | /public/derby 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "public/components", 3 | "json": "bower.json" 4 | } -------------------------------------------------------------------------------- /ch07-templates/listing7_10/templates/layout.pug: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | block title 4 | body 5 | block content 6 | 7 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-commonjs/app/index.js: -------------------------------------------------------------------------------- 1 | const hello = require('./hello'); 2 | const jquery = require('jquery'); 3 | 4 | hello(); 5 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_6/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_8/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch08-databases/listing8_7/tldr.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_7/tldr.sqlite -------------------------------------------------------------------------------- /ch09-testing/debug-stacktraces/async.js: -------------------------------------------------------------------------------- 1 | module.exports = () => { 2 | setTimeout(() => { 3 | throw new Error(); 4 | }) 5 | }; 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/README.md: -------------------------------------------------------------------------------- 1 | # My Application 2 | 3 | The project is generated by [LoopBack](http://loopback.io). -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/client/README.md: -------------------------------------------------------------------------------- 1 | ## Client 2 | 3 | This is the place for your application front-end files. 4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_6/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_8/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch08-databases/listing8_17/index.js: -------------------------------------------------------------------------------- 1 | const level = require('level'); 2 | 3 | const db = level('./app.db', { 4 | valueEncoding: 'json' 5 | }); 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /ch08-databases/listing8_18/app.db/000005.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_18/app.db/000005.log -------------------------------------------------------------------------------- /ch08-databases/listing8_19/app.db/000007.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_19/app.db/000007.ldb -------------------------------------------------------------------------------- /ch08-databases/listing8_20/app.db/000007.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_20/app.db/000007.ldb -------------------------------------------------------------------------------- /ch08-databases/listing8_20/app.db/000010.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_20/app.db/000010.log -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/server/datasources.json: -------------------------------------------------------------------------------- 1 | { 2 | "db": { 3 | "name": "db", 4 | "connector": "memory" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/app/events.jsx: -------------------------------------------------------------------------------- 1 | import {EventEmitter} from 'events'; 2 | const Events = new EventEmitter(); 3 | export default Events; 4 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_6/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /ch08-databases/listing8_17/app.db/MANIFEST-000002: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_17/app.db/MANIFEST-000002 -------------------------------------------------------------------------------- /ch08-databases/listing8_18/app.db/MANIFEST-000004: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_18/app.db/MANIFEST-000004 -------------------------------------------------------------------------------- /ch08-databases/listing8_19/app.db/MANIFEST-000006: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_19/app.db/MANIFEST-000006 -------------------------------------------------------------------------------- /ch08-databases/listing8_20/app.db/MANIFEST-000009: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexyoung/nodejsinaction/master/ch08-databases/listing8_20/app.db/MANIFEST-000009 -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/app/events.jsx: -------------------------------------------------------------------------------- 1 | import {EventEmitter} from 'events'; 2 | const Events = new EventEmitter(); 3 | export default Events; 4 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_6/views/head.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | Later 4 | 5 | 6 |
7 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/server/component-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "loopback-component-explorer": { 3 | "mountPath": "/explorer" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ch12-desktop/listing12_1/readfile.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | module.exports = (cb) => { 4 | fs.readFile('./main.js', { encoding: 'utf8' }, cb); 5 | }; 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/locales/US/en/errors/404.properties: -------------------------------------------------------------------------------- 1 | header=File not found 2 | description=The URL {url} did not resolve to a route. -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/components/requirejs/README.md: -------------------------------------------------------------------------------- 1 | # requirejs-bower 2 | 3 | Bower packaging for [RequireJS](http://requirejs.org). 4 | 5 | -------------------------------------------------------------------------------- /ch07-templates/listing7_10/templates/page.pug: -------------------------------------------------------------------------------- 1 | extends layout 2 | block title 3 | title Messages 4 | block content 5 | each message in messages 6 | p= message 7 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/locales/US/en/errors/503.properties: -------------------------------------------------------------------------------- 1 | header=Service unavailable 2 | description=The service is unavailable. Please try back shortly. 3 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/readfile.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | module.exports = (cb) => { 4 | fs.readFile('./main.js', { encoding: 'utf8' }, cb); 5 | }; 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/templates/index.dust: -------------------------------------------------------------------------------- 1 | {>"layouts/master" /} 2 | 3 | {{@pre type="content" key="greeting"/} 5 | {/body} 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/hello-world/server.js: -------------------------------------------------------------------------------- 1 | const app = require('connect')(); 2 | app.use((req, res, next) => { 3 | res.end('Hello, world!'); 4 | }); 5 | app.listen(3000); 6 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/readfile.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | module.exports = (cb) => { 4 | fs.readFile('./main.js', { encoding: 'utf8' }, cb); 5 | }; 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/models/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function IndexModel() { 4 | return { 5 | name: 'index' 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b5/books.csv: -------------------------------------------------------------------------------- 1 | title, author, sourceDate, dbDate 2 | Catch-22, Joseph Heller, 11 November 1961, 1961-11-11 3 | A Handful of Dust, Evelyn Waugh, 1934, 1934-01-01 4 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_207/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Latest Posts

6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_208/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Latest Posts

6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/later/views/article.ejs: -------------------------------------------------------------------------------- 1 | <% include head %> 2 |
3 |

<%= article.title %>

4 | <%- article.content %> 5 |
6 | <% include foot %> 7 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/locales/US/en/errors/500.properties: -------------------------------------------------------------------------------- 1 | header=Internal server error 2 | description=The URL {url} had the following error {err}. -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "babel-plugin-transform-class-properties", 4 | "transform-react-jsx" 5 | ], 6 | "presets": ["es2015"] 7 | } 8 | -------------------------------------------------------------------------------- /appendix-a/listing_a7/readme.md: -------------------------------------------------------------------------------- 1 | ### Multipart example 2 | 3 | This example accepts file uploads. 4 | 5 | Usage: 6 | 7 | ``` 8 | curl -F file=@index.js http://localhost:3000 9 | ``` 10 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_6/views/article.ejs: -------------------------------------------------------------------------------- 1 | <% include head %> 2 |
3 |

<%= article.title %>

4 | <%- article.content %> 5 |
6 | <% include foot %> 7 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "babel-plugin-transform-class-properties", 4 | "transform-react-jsx" 5 | ], 6 | "presets": ["es2015"] 7 | } 8 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_204-205-206/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Latest Posts

6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_207/titles.json: -------------------------------------------------------------------------------- 1 | [ 2 | "Kazakhstan is a huge country... what goes on there?", 3 | "This weather is making me craaazy", 4 | "My neighbor sort of howls at night" 5 | ] 6 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_208/titles.json: -------------------------------------------------------------------------------- 1 | [ 2 | "Kazakhstan is a huge country... what goes on there?", 3 | "This weather is making me craaazy", 4 | "My neighbor sort of howls at night" 5 | ] 6 | -------------------------------------------------------------------------------- /ch04-front-end/es2015-example/browser.js: -------------------------------------------------------------------------------- 1 | class Example { 2 | render() { 3 | return '

Example

'; 4 | } 5 | } 6 | 7 | const example = new Example(); 8 | console.log(example.render()); 9 | -------------------------------------------------------------------------------- /ch11-command-line/snippets/exit-message.js: -------------------------------------------------------------------------------- 1 | process.stdin.pipe(process.stdout); 2 | process.on('exit', () => { 3 | const args = process.argv.slice(2); 4 | console.error(args.join(' ')); 5 | }); 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_6/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_6/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_8/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_8/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 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_204-205-206/titles.json: -------------------------------------------------------------------------------- 1 | [ 2 | "Kazakhstan is a huge country... what goes on there?", 3 | "This weather is making me craaazy", 4 | "My neighbor sort of howls at night" 5 | ] 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_5/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | 4 | app.get('/', (req, res) => { 5 | res.send('Hello'); 6 | }); 7 | 8 | app.listen(3000); 9 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/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 | -------------------------------------------------------------------------------- /ch07-templates/ejs-snippets/context.js: -------------------------------------------------------------------------------- 1 | const ejs = require('ejs'); 2 | const template = '<%= message %>'; 3 | const context = { message: 'Hello template!' }; 4 | console.log(ejs.render(template, context)); 5 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/later/views/head.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | Later 4 | 5 | 6 | 7 |
8 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/example-derby-app/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Holler: 4 |

{{hello.message}}

5 | -------------------------------------------------------------------------------- /ch04-front-end/gulp-example/app/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | ReactDOM.render( 5 |

Hello, world!

, 6 | document.getElementById('example') 7 | ); 8 | 9 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-example/app/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | ReactDOM.render( 5 |

Hello, world!

, 6 | document.getElementById('example') 7 | ); 8 | 9 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/.nodemonignore: -------------------------------------------------------------------------------- 1 | /.build/* # Build folder 2 | /public/* # ignore all public resources 3 | /.* # any hidden (dot) files 4 | *.md # Markdown files 5 | *.css # CSS files 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/server/boot/authentication.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function enableAuthentication(server) { 4 | // enable authentication 5 | server.enableAuth(); 6 | }; 7 | -------------------------------------------------------------------------------- /ch08-databases/listing8_18/app.db/LOG: -------------------------------------------------------------------------------- 1 | 2016/12/16-12:23:42.818774 700003c19000 Recovering log #3 2 | 2016/12/16-12:23:42.820278 700003c19000 Delete type=0 #3 3 | 2016/12/16-12:23:42.820374 700003c19000 Delete type=3 #2 4 | -------------------------------------------------------------------------------- /ch08-databases/listing8_20/app.db/LOG: -------------------------------------------------------------------------------- 1 | 2016/12/16-12:26:12.496126 70000eefa000 Recovering log #8 2 | 2016/12/16-12:26:12.497558 70000eefa000 Delete type=0 #8 3 | 2016/12/16-12:26:12.497636 70000eefa000 Delete type=3 #6 4 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_210/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const net = require('net'); 3 | const server = net.createServer(socket => { 4 | socket.once('data', data => socket.write(data)); 5 | }); 6 | server.listen(8888); 7 | -------------------------------------------------------------------------------- /ch07-templates/pug-snippets/link-example.js: -------------------------------------------------------------------------------- 1 | const pug = require('pug'); 2 | const template = 'a(href = url)'; 3 | const context = { url: 'http://google.com' }; 4 | const fn = pug.compile(template); 5 | console.log(fn(context)); -------------------------------------------------------------------------------- /ch08-databases/listing8_19/app.db/LOG.old: -------------------------------------------------------------------------------- 1 | 2016/12/16-12:23:42.818774 700003c19000 Recovering log #3 2 | 2016/12/16-12:23:42.820278 700003c19000 Delete type=0 #3 3 | 2016/12/16-12:23:42.820374 700003c19000 Delete type=3 #2 4 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-hotload-example/app/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | ReactDOM.render( 5 |

Hello, World!

, 6 | document.getElementById('example') 7 | ); 8 | 9 | -------------------------------------------------------------------------------- /ch07-templates/ejs-snippets/escape.js: -------------------------------------------------------------------------------- 1 | const ejs = require('ejs'); 2 | const template = '<%= message %>'; 3 | const context = {message: ""}; 4 | console.log(ejs.render(template, context)); 5 | -------------------------------------------------------------------------------- /ch07-templates/ejs-snippets/delimiter.js: -------------------------------------------------------------------------------- 1 | const ejs = require('ejs'); 2 | ejs.delimiter = '$' 3 | const template = '<$= message $>'; 4 | const context = { message: 'Hello template!' }; 5 | console.log(ejs.render(template, context)); 6 | -------------------------------------------------------------------------------- /ch07-templates/pug-snippets/data-example.js: -------------------------------------------------------------------------------- 1 | const pug = require('pug'); 2 | const template = 'strong #{message}'; 3 | const context = { message: 'Hello template!' }; 4 | const fn = pug.compile(template); 5 | console.log(fn(context)); 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/templates/errors/404.dust: -------------------------------------------------------------------------------- 1 | {>"layouts/master" /} 2 | 3 | {{@pre type="content" key="header"/} 5 |

{@pre type="content" key="description"/}

6 | {/body} 7 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/templates/errors/500.dust: -------------------------------------------------------------------------------- 1 | {>"layouts/master" /} 2 | 3 | {{@pre type="content" key="header"/} 5 |

{@pre type="content" key="description"/}

6 | {/body} 7 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/templates/errors/503.dust: -------------------------------------------------------------------------------- 1 | {>"layouts/master" /} 2 | 3 | {{@pre type="content" key="header"/} 5 |

{@pre type="content" key="description"/}

6 | {/body} 7 | -------------------------------------------------------------------------------- /ch07-templates/listing7_5/templates/students.ejs: -------------------------------------------------------------------------------- 1 | <% if (students.length) { %> 2 |
    3 | <% students.forEach((student) => { %> 4 |
  • <%= student.name %> (<%= student.age %>)
  • 5 | <% }) %> 6 |
7 | <% } %> 8 | -------------------------------------------------------------------------------- /ch11-command-line/snippets/time.js: -------------------------------------------------------------------------------- 1 | process.stdin.pipe(process.stdout); 2 | const start = Date.now(); 3 | process.on('exit', () => { 4 | const timeTaken = Date.now() - start; 5 | console.error(`Time (s): ${timeTaken / 1000}`); 6 | }); 7 | -------------------------------------------------------------------------------- /ch08-databases/listing8_21/index.js: -------------------------------------------------------------------------------- 1 | const level = require('levelup') 2 | const memdown = require('memdown') 3 | 4 | const db = level('./level-articles.db', { 5 | keyEncoding: 'json', 6 | valueEncoding: 'json', 7 | db: memdown 8 | }); 9 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_209/echo_server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const net = require('net'); 3 | const server = net.createServer((socket) => { 4 | socket.on('data', (data) => { 5 | socket.write(data); 6 | }); 7 | }); 8 | server.listen(8888); 9 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-commonjs/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: './app/index.js', 6 | output: { path: __dirname, filename: 'dist/bundle.js' }, 7 | }; 8 | -------------------------------------------------------------------------------- /ch08-databases/listing8_8/index.js: -------------------------------------------------------------------------------- 1 | const { MongoClient } = require('mongodb'); 2 | 3 | MongoClient.connect('mongodb://localhost:27017/articles') 4 | .then(db => { 5 | console.log('Client ready'); 6 | db.close(); 7 | }, console.error); 8 | -------------------------------------------------------------------------------- /ch09-testing/debug-example/index.js: -------------------------------------------------------------------------------- 1 | const debugViews = require('debug')('debug-example:views'); 2 | const debugModels = require('debug')('debug-example:models'); 3 | 4 | debugViews('Example view message'); 5 | debugModels('Example model message'); 6 | -------------------------------------------------------------------------------- /appendix-a/listing_a6/readme.md: -------------------------------------------------------------------------------- 1 | ### JSON parser example 2 | 3 | This example parsers request bodies that contain JSON. 4 | 5 | Usage: 6 | 7 | ``` 8 | curl -d '{"name":"tobi"}' -H "Content-Type: application/json" http://localhost:3000 9 | ``` 10 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/messages.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.messages) { %> 2 | <% messages.forEach(function(message) { %> 3 |

<%= message.string %>

4 | <% }) %> 5 | <% removeMessages() %> 6 | <% } %> 7 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/views/messages.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.messages) { %> 2 | <% messages.forEach((message) => { %> 3 |

<%= message.string %>

4 | <% }) %> 5 | <% removeMessages() %> 6 | <% } %> 7 | 8 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/views/messages.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.messages) { %> 2 | <% messages.forEach((message) => { %> 3 |

<%= message.string %>

4 | <% }) %> 5 | <% removeMessages() %> 6 | <% } %> 7 | 8 | -------------------------------------------------------------------------------- /ch07-templates/listing7_11/templates/layout.pug: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | - const baseUrl = "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/" 4 | block title 5 | block style 6 | block scripts 7 | body 8 | block content 9 | 10 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/server/middleware.development.json: -------------------------------------------------------------------------------- 1 | { 2 | "final:after": { 3 | "strong-error-handler": { 4 | "params": { 5 | "debug": true, 6 | "log": true 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/views/messages.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.messages) { %> 2 | <% messages.forEach((message) => { %> 3 |

<%= message.string %>

4 | <% }) %> 5 | <% removeMessages() %> 6 | <% } %> 7 | 8 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/views/messages.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.messages) { %> 2 | <% messages.forEach((message) => { %> 3 |

<%= message.string %>

4 | <% }) %> 5 | <% removeMessages() %> 6 | <% } %> 7 | 8 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/views/messages.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.messages) { %> 2 | <% messages.forEach((message) => { %> 3 |

<%= message.string %>

4 | <% }) %> 5 | <% removeMessages() %> 6 | <% } %> 7 | 8 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/views/messages.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.messages) { %> 2 | <% messages.forEach((message) => { %> 3 |

<%= message.string %>

4 | <% }) %> 5 | <% removeMessages() %> 6 | <% } %> 7 | 8 | -------------------------------------------------------------------------------- /ch08-databases/listing8_1/index.js: -------------------------------------------------------------------------------- 1 | const pg = require('pg'); 2 | const db = new pg.Client({ database: 'articles' }); 3 | 4 | db.connect((err, client) => { 5 | if (err) throw err; 6 | console.log('Connected to database', db.database); 7 | db.end(); 8 | }); -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_214/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | function asyncFunction(callback) { 3 | setTimeout(callback, 200); 4 | } 5 | let color = 'blue'; 6 | asyncFunction(() => { 7 | console.log('The color is', color); 8 | }); 9 | color = 'green'; 10 | -------------------------------------------------------------------------------- /ch07-templates/hogan-snippet/index.js: -------------------------------------------------------------------------------- 1 | const hogan = require('hogan.js'); 2 | const templateSource = '{{message}}'; 3 | const context = { message: 'Hello template!' }; 4 | const template = hogan.compile(templateSource); 5 | 6 | console.log(template.render(context)); -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/user-test.js: -------------------------------------------------------------------------------- 1 | const User = require('./models/user'); 2 | const user = new User({ name: 'Example', pass: 'test' }); 3 | 4 | user.save((err) => { 5 | if (err) console.error(err); 6 | console.log('user id %d', user.id); 7 | }); 8 | -------------------------------------------------------------------------------- /ch11-command-line/snippets/uglify-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "browserify": "13.3.0", 4 | "uglify-js": "2.7.5" 5 | }, 6 | "scripts": { 7 | "build": "browserify -e main.js > bundle.js && uglifyjs bundle.js > bundle.min.js" 8 | } 9 | } -------------------------------------------------------------------------------- /appendix-a/listing_a1/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const cookieParser = require('cookie-parser'); 3 | 4 | connect() 5 | .use(cookieParser()) 6 | .use((req, res, next) => { 7 | res.end(JSON.stringify(req.cookies)); 8 | }) 9 | .listen(3000); 10 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/notes.md: -------------------------------------------------------------------------------- 1 | install 'request': 2 | 3 | npm install --save request 4 | 5 | 6 | Tips: 7 | 8 | 9 | 1. Don't make requests in the renderer process, use ipc main instead (https://github.com/atom/electron/blob/master/docs/api/ipc-main.md) 10 | 11 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_8/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', (req, res) => { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', (req, res) => { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/notes.md: -------------------------------------------------------------------------------- 1 | install 'request': 2 | 3 | npm install --save request 4 | 5 | 6 | Tips: 7 | 8 | 9 | 1. Don't make requests in the renderer process, use ipc main instead (https://github.com/atom/electron/blob/master/docs/api/ipc-main.md) 10 | 11 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/.gitignore: -------------------------------------------------------------------------------- 1 | *.csv 2 | *.dat 3 | *.iml 4 | *.log 5 | *.out 6 | *.pid 7 | *.seed 8 | *.sublime-* 9 | *.swo 10 | *.swp 11 | *.tgz 12 | *.xml 13 | .DS_Store 14 | .idea 15 | .project 16 | .strong-pm 17 | coverage 18 | node_modules 19 | npm-debug.log 20 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_6/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_6/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_8/routes/users.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', (req, res, next) => { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/routes/users.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', (req, res, next) => { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /ch08-databases/listing8_10/index.js: -------------------------------------------------------------------------------- 1 | const db = require('./db'); 2 | 3 | db().then(() => { 4 | db.Article.create({ title: 'An article!' }).then(() => { 5 | db.Article.all().then(articles => { 6 | console.log(articles); 7 | process.exit(); 8 | }); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /appendix-b-scraping/snippets/messy_html_example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Alex's Dated Book Website

4 | 5 | 6 | 7 | 8 | 9 |
Catch-22Joseph Heller
10 | 11 | 12 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', (req, res, next) => { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/routes/users.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const 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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/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 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/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 | -------------------------------------------------------------------------------- /appendix-a/listing_a7/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const multipart = require('connect-multiparty'); 3 | 4 | connect() 5 | .use(multipart()) 6 | .use((req, res, next) => { 7 | console.log(req.files); 8 | res.end('Upload received\n'); 9 | }) 10 | .listen(3000); 11 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b2/messy_html_example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Alex's Dated Book Website

4 | 5 | 6 | 7 | 8 | 9 |
Catch-22Joseph Heller
10 | 11 | 12 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/later/views/articles.ejs: -------------------------------------------------------------------------------- 1 | <% include head %> 2 | 11 | <% include foot %> 12 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/server/boot/root.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(server) { 4 | // Install a `/` route that returns server status 5 | var router = server.loopback.Router(); 6 | router.get('/', server.loopback.status()); 7 | server.use(router); 8 | }; 9 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/entries/xml.ejs: -------------------------------------------------------------------------------- 1 | 2 | <% entries.forEach(function(entry){ %> 3 | 4 | <%= entry.title %> 5 | <%= entry.body %> 6 | <%= entry.username %> 7 | 8 | <% }) %> 9 | 10 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/views/entries/xml.ejs: -------------------------------------------------------------------------------- 1 | 2 | <% entries.forEach((entry) => { %> 3 | 4 | <%= entry.title %> 5 | <%= entry.body %> 6 | <%= entry.username %> 7 | 8 | <% }) %> 9 | 10 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/views/entries/xml.ejs: -------------------------------------------------------------------------------- 1 | 2 | <% entries.forEach(entry => { %> 3 | 4 | <%= entry.title %> 5 | <%= entry.body %> 6 | <%= entry.username %> 7 | 8 | <% }) %> 9 | 10 | -------------------------------------------------------------------------------- /appendix-a/listing_a8/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const morgan = require('morgan'); 3 | 4 | connect() 5 | .use(morgan('combined')) 6 | .use((req, res) => { 7 | res.setHeader('Content-Type', 'application/json'); 8 | res.end('Logging\n'); 9 | }) 10 | .listen(3000); 11 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_6/views/articles.ejs: -------------------------------------------------------------------------------- 1 | <% include head %> 2 | 11 | <% include foot %> 12 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-hotload-example/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Warning: Dev server only 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ch07-templates/listing7_1-2/entries.txt: -------------------------------------------------------------------------------- 1 | title: It's my birthday! 2 | date: January 12, 2012 3 | I am getting old, but thankfully I'm not in jail! 4 | --- 5 | title: Movies are pretty good 6 | date: January 2, 2012 7 | I've been watching a lot of movies lately. It's relaxing, 8 | except when they have clowns in them. 9 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_201/currency.js: -------------------------------------------------------------------------------- 1 | const canadianDollar = 0.91; 2 | 3 | function roundTwo(amount) { 4 | return Math.round(amount * 100) / 100; 5 | } 6 | 7 | exports.canadianToUS = canadian => roundTwo(canadian * canadianDollar); 8 | 9 | exports.USToCanadian = us => roundTwo(us / canadianDollar); 10 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_202/currency.js: -------------------------------------------------------------------------------- 1 | const canadianDollar = 0.91; 2 | 3 | function roundTwo(amount) { 4 | return Math.round(amount * 100) / 100; 5 | } 6 | 7 | exports.canadianToUS = canadian => roundTwo(canadian * canadianDollar); 8 | 9 | exports.USToCanadian = us => roundTwo(us / canadianDollar); 10 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_202/test_currency.js: -------------------------------------------------------------------------------- 1 | const currency = require('./currency'); 2 | console.log('50 Canadian dollars equals this amount of US dollars:'); 3 | console.log(currency.canadianToUS(50)); 4 | console.log('30 US dollars equals this amount of Canadian dollars:'); 5 | console.log(currency.USToCanadian(30)); 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 |

<%= title %>

9 |

Welcome to <%= title %>

10 | 11 | 12 | -------------------------------------------------------------------------------- /ch07-templates/listing7_1-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing7_1-2", 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": "MIT" 12 | } 13 | -------------------------------------------------------------------------------- /ch10-deployment/listing10_1/hellonode.conf: -------------------------------------------------------------------------------- 1 | author "Robert DeGrimston" 2 | description "hellonode" 3 | setuid "nonrootuser" 4 | start on (local-filesystems and net-device-up IFACE=eth0) 5 | stop on shutdown 6 | respawn 7 | console log 8 | env NODE_ENV=production 9 | exec /usr/bin/node /path/to/server.js 10 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b5/input.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Catch-22

4 |

Joseph Heller

5 |

11 November 1961

6 |
7 |
8 |

A Handful of Dust

9 |

Evelyn Waugh

10 |

1934

11 |
12 |
13 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_215/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function asyncFunction(callback) { 4 | setTimeout(callback, 200); 5 | } 6 | 7 | let color = 'blue'; 8 | 9 | (color => { 10 | asyncFunction(() => { 11 | console.log('The color is', color); 12 | }); 13 | })(color); 14 | 15 | color = 'green'; 16 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/tasks/clean.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | module.exports = function clean(grunt) { 5 | // Load task 6 | grunt.loadNpmTasks('grunt-contrib-clean'); 7 | 8 | // Options 9 | return { 10 | tmp: 'tmp', 11 | build: '.build/templates' 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var User = require('./../models/user'); 4 | 5 | /* GET users listing. */ 6 | router.get('/', function(req, res, next) { 7 | res.send('respond with a resource'); 8 | }); 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /appendix-a/listing_a6/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const bodyParser = require('body-parser'); 3 | 4 | connect() 5 | .use(bodyParser.json()) 6 | .use((req, res, next) => { 7 | res.setHeader('Content-Type', 'application/json'); 8 | res.end('Name: ' + req.body.name + '\n'); 9 | }) 10 | .listen(3000); 11 | -------------------------------------------------------------------------------- /ch09-testing/vows-todo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vows-todo", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "test.js", 6 | "scripts": { 7 | "test": "vows test/*.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "vows": "0.8.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/listing5_2/server.js: -------------------------------------------------------------------------------- 1 | const Hapi = require('hapi'); 2 | const server = new Hapi.Server(); 3 | 4 | server.connection({ 5 | host: 'localhost', 6 | port: 8000 7 | }); 8 | 9 | server.start((err) => { 10 | if (err) { 11 | throw err; 12 | } 13 | console.log('Server running at:', server.info.uri); 14 | }); 15 | -------------------------------------------------------------------------------- /appendix-a/listing_a8/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a8", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "connect": "^3.4.0", 13 | "morgan": "^1.5.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_3/server.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const setup = require('./logger.js') 3 | 4 | function hello(req, res) { 5 | res.setHeader('Content-Type', 'text/plain'); 6 | res.end('hello world'); 7 | } 8 | 9 | const app = connect() 10 | .use(setup(':method :url')) 11 | .use(hello) 12 | .listen(3000); -------------------------------------------------------------------------------- /ch07-templates/listing7_4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing7_4", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "ejs": "^2.5.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch07-templates/pug-snippets/iteration-example.js: -------------------------------------------------------------------------------- 1 | const pug = require('pug'); 2 | const fs = require('fs'); 3 | const template = fs.readFileSync('./template.pug'); 4 | const context = { 5 | messages: [ 6 | 'You have logged in successfully.', 7 | 'Welcome back!' 8 | ] 9 | }; 10 | const fn = pug.compile(template); 11 | console.log(fn(context)); -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Node in Action Listings 2 | 3 | These are the listings for [Node in Action, Second Edition](https://www.manning.com/books/node-js-in-action). 4 | 5 | To run these listings, you will need to first run `npm install` from within the listing you want to run. 6 | 7 | Some listings may have additional documentation in a corresponding readme file. 8 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_216/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_215", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "async": "2.1.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_219/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_219", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "async": "2.1.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/404.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 404 Not Found 5 | 6 | 7 | 8 | <% include menu %> 9 |

404 Not Found

10 |

The requested page does not exist.

11 | 12 | 13 | -------------------------------------------------------------------------------- /ch07-templates/ejs-snippets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ejs_snippets", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "escape.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "ejs": "^2.5.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch08-databases/listing8_19/app.db/LOG: -------------------------------------------------------------------------------- 1 | 2016/12/16-12:25:42.468827 700007073000 Recovering log #5 2 | 2016/12/16-12:25:42.469528 700007073000 Level-0 table #7: started 3 | 2016/12/16-12:25:42.471710 700007073000 Level-0 table #7: 205 bytes OK 4 | 2016/12/16-12:25:42.472838 700007073000 Delete type=0 #5 5 | 2016/12/16-12:25:42.472929 700007073000 Delete type=3 #4 6 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/tasks/copy-browser-modules.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function dustjs(grunt) { 4 | grunt.loadNpmTasks('grunt-copy-browser-modules'); 5 | 6 | return { 7 | build: { 8 | root: process.cwd(), 9 | dest: 'public/components', 10 | basePath: 'public' 11 | } 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/middleware/user.js: -------------------------------------------------------------------------------- 1 | const User = require('../models/user'); 2 | module.exports = (req, res, next) => { 3 | const uid = req.session.uid; 4 | if (!uid) return next(); 5 | User.get(uid, (err, user) => { 6 | if (err) return next(err); 7 | req.user = res.locals.user = user; 8 | next(); 9 | }); 10 | }; 11 | -------------------------------------------------------------------------------- /ch07-templates/hogan-snippet/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hogan-snippet", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "hogan.js": "^3.0.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch07-templates/pug-snippets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pug-snippets", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "pug": "^2.0.0-beta6" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch08-databases/listing8_20/app.db/LOG.old: -------------------------------------------------------------------------------- 1 | 2016/12/16-12:25:42.468827 700007073000 Recovering log #5 2 | 2016/12/16-12:25:42.469528 700007073000 Level-0 table #7: started 3 | 2016/12/16-12:25:42.471710 700007073000 Level-0 table #7: 205 bytes OK 4 | 2016/12/16-12:25:42.472838 700007073000 Delete type=0 #5 5 | 2016/12/16-12:25:42.472929 700007073000 Delete type=3 #4 6 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing6_1", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "connect": "^3.4.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing6_2", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "connect": "^3.4.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_3/logger.js: -------------------------------------------------------------------------------- 1 | function setup(format) { 2 | const regexp = /:(\w+)/g; 3 | 4 | return function createLogger(req, res, next) { 5 | const str = format.replace(regexp, (match, property) => { 6 | return req[property]; 7 | }); 8 | 9 | console.log(str); 10 | next(); 11 | } 12 | } 13 | module.exports = setup; 14 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing6_3", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "connect": "^3.4.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_4/logger.js: -------------------------------------------------------------------------------- 1 | function setup(format) { 2 | const regexp = /:(\w+)/g; 3 | 4 | return function createLogger(req, res, next) { 5 | const str = format.replace(regexp, (match, property) => { 6 | return req[property]; 7 | }); 8 | 9 | console.log(str); 10 | next(); 11 | } 12 | } 13 | 14 | module.exports = setup; -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing6_4", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "connect": "^3.4.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing6_5", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.13.4" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch08-databases/listing8_23.js: -------------------------------------------------------------------------------- 1 | const examplePreferences = { 2 | temperature: 'Celcius' 3 | }; 4 | 5 | // serialize on write 6 | localStorage.setItem('preferences', JSON.stringify(examplePreferences)); 7 | 8 | // deserialize on read 9 | const preferences = JSON.parse(localStorage.getItem('preferences')); 10 | console.log('Loaded preferences:', preferences); 11 | -------------------------------------------------------------------------------- /appendix-a/listing_a1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a1", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "connect": "^3.4.0", 13 | "cookie-parser": "^1.3.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appendix-a/listing_a4/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const bodyParser = require('body-parser'); 3 | 4 | connect() 5 | .use(bodyParser.urlencoded({ extended: false })) 6 | .use((req, res, next) => { 7 | res.setHeader('Content-Type', 'text/plain'); 8 | res.end('You sent: ' + JSON.stringify(req.body) + '\n'); 9 | }) 10 | .listen(3000); 11 | -------------------------------------------------------------------------------- /appendix-a/listing_a5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a5", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "body-parser": "^1.11.0", 13 | "connect": "^3.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appendix-a/listing_a6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a6", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "body-parser": "^1.11.0", 13 | "connect": "^3.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch07-templates/listing7_5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing7_5", 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": "MIT", 12 | "dependencies": { 13 | "ejs": "^2.4.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_1", 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 | "pg": "^6.1.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_2", 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 | "pg": "^6.1.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_3", 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 | "pg": "^6.1.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_4", 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 | "pg": "^6.1.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_5", 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 | "pg": "^6.1.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/menu.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.user) { %> 2 | 7 | <% } else { %> 8 | 12 | <% } %> 13 | -------------------------------------------------------------------------------- /ch08-databases/listing8_14/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_14", 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": "^2.6.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_15/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_15", 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": "^2.6.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_16/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_16", 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": "^2.6.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_17/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_17", 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 | "level": "^1.5.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_18/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_18", 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 | "level": "^1.5.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_19/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_19", 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 | "level": "^1.5.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_20/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_19", 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 | "level": "^1.5.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_8/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_8", 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 | "mongodb": "^2.2.16" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_9/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_9", 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 | "mongodb": "^2.2.16" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch09-testing/chai-examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chai-examples", 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 | "chai": "3.5.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch09-testing/debug-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "debug-example", 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 | "debug": "2.2.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch04-front-end/gulp-example/dist/all.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["index.jsx"],"names":[],"mappings":";;;;;;;;;;;;AAGA,mBAAS,MAAT,CACE;;;;CADF,EAEE,SAAS,cAAT,CAAwB,SAAxB,CAFF","file":"all.js","sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom';\n\nReactDOM.render(\n

Hello, world!

,\n document.getElementById('example')\n);\n\n"],"sourceRoot":"/source/"} -------------------------------------------------------------------------------- /ch06-connect-and-express/hello-world/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ch07-connect-and-express", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "connect": "^3.4.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/views/menu.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.user) { %> 2 | 7 | <% } else { %> 8 | 12 | <% } %> 13 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/views/menu.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.user) { %> 2 | 7 | <% } else { %> 8 | 12 | <% } %> 13 | -------------------------------------------------------------------------------- /ch07-templates/listing7_10/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing7_10", 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": "MIT", 12 | "dependencies": { 13 | "pug": "^2.0.0-beta6" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch07-templates/listing7_11/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing7_11", 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": "MIT", 12 | "dependencies": { 13 | "pug": "^2.0.0-beta6" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_10/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_10", 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 | "mongodb": "^2.2.16" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_13/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_13", 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 | "mongodb": "^2.2.16" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch08-databases/listing8_19/index.js: -------------------------------------------------------------------------------- 1 | const level = require('level'); 2 | 3 | const db = level('./app.db', { 4 | valueEncoding: 'json' 5 | }); 6 | 7 | db.get('this-key-does-not-exist', (err, value) => { 8 | if (err && !err.notFound) throw err; 9 | if (err && err.notFound) return console.log('Value was not found.'); 10 | console.log('Value was found:', value); 11 | }); 12 | -------------------------------------------------------------------------------- /appendix-a/listing_a13/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a13", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "basic-auth": "^1.0.0", 13 | "connect": "^3.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appendix-a/listing_a3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a3", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "connect": "^3.4.0", 13 | "qs": "^2.3.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_b4", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "jquery": "^2.1.4", 13 | "jsdom": "^6.3.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/listing5_1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing5_1", 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": "MIT", 12 | "dependencies": { 13 | "koa": "^1.2.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/listing5_2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing5_3", 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": "MIT", 12 | "dependencies": { 13 | "hapi": "^13.3.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/listing5_3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing5_3", 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": "MIT", 12 | "dependencies": { 13 | "hapi": "^13.3.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/views/menu.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.user) { %> 2 | 7 | <% } else { %> 8 | 12 | <% } %> 13 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/views/menu.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.user) { %> 2 | 7 | <% } else { %> 8 | 12 | <% } %> 13 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/views/menu.ejs: -------------------------------------------------------------------------------- 1 | <% if (locals.user) { %> 2 | 7 | <% } else { %> 8 | 12 | <% } %> 13 | -------------------------------------------------------------------------------- /ch08-databases/listing8_22/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_22", 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 | "pretty-bytes": "^4.0.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appendix-a/listing_a5/readme.md: -------------------------------------------------------------------------------- 1 | ### Request validation 2 | 3 | This example limits requests to 10 bytes, and ensures they start with "name-". 4 | 5 | Usage: 6 | 7 | ``` 8 | curl -d name=tobi http://localhost:3000 9 | ``` 10 | 11 | To see the validation errors: 12 | 13 | ``` 14 | curl -d other=tobi http://localhost:3000 15 | curl -d name=tobiiiiiiiiii http://localhost:3000 16 | ``` 17 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_b1", 3 | "version": "1.0.0", 4 | "description": "A scraping example based on cheerio and request", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test.js" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "cheerio": "^0.19.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_b2", 3 | "version": "1.0.0", 4 | "description": "A scraping example based on cheerio and request", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test.js" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "cheerio": "^0.19.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch09-testing/sinon-js-examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sinon-js-examples", 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 | "devDependencies": { 13 | "sinon": "1.17.4" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch11-command-line/listing11-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing11-1", 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": "Bradley Meck", 11 | "license": "MIT", 12 | "dependencies": { 13 | "yargs": "^4.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_217/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_217", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "htmlparser": "^1.7.7", 13 | "request": "^2.60.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/listing5_1/server.js: -------------------------------------------------------------------------------- 1 | const koa = require('koa'); 2 | const app = koa(); 3 | 4 | app.use(function *(next) { 5 | const start = new Date; 6 | yield next; 7 | const ms = new Date - start; 8 | console.log('%s %s - %s', this.method, this.url, ms); 9 | }); 10 | 11 | app.use(function *() { 12 | this.body = 'Hello World'; 13 | }); 14 | 15 | app.listen(3000); 16 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_1/server.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | 3 | function logger(req, res, next) { 4 | console.log('%s %s', req.method, req.url); 5 | next(); 6 | } 7 | 8 | function hello(req, res) { 9 | res.setHeader('Content-Type', 'text/plain'); 10 | res.end('hello world'); 11 | } 12 | 13 | connect() 14 | .use(logger) 15 | .use(hello) 16 | .listen(3000); -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/routes/entries.js: -------------------------------------------------------------------------------- 1 | const Entry = require('../models/entry'); 2 | 3 | exports.list = (req, res, next) => { 4 | const page = req.page; 5 | Entry.getRange(0, -1, (err, entries) => { 6 | if (err) return next(err); 7 | res.render('entries', { 8 | title: 'Entries', 9 | entries: entries, 10 | page 11 | }); 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /appendix-a/listing_a2/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const cookieParser = require('cookie-parser'); 3 | const secret = 'tobi is a cool ferret'; 4 | 5 | connect() 6 | .use(cookieParser(secret)) 7 | .use((req, res) => { 8 | console.log('Cookies:', req.cookies); 9 | console.log('Signed cookies:', req.signedCookies); 10 | res.end('hello\n'); 11 | }).listen(3000); 12 | -------------------------------------------------------------------------------- /appendix-a/listing_a2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a2", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "connect": "^3.4.0", 13 | "cookie-parser": "^1.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_b3", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "jquery": "^2.1.4", 13 | "jsdom": "^6.3.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_b5", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "cheerio": "^0.19.0", 13 | "moment": "^2.10.6" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/js/app.js: -------------------------------------------------------------------------------- 1 | /*global requirejs:true*/ 2 | 'use strict'; 3 | 4 | 5 | requirejs.config({ 6 | paths: {} 7 | }); 8 | 9 | 10 | require([/* Dependencies */], function () { 11 | 12 | var app = { 13 | initialize: function () { 14 | // Your code here 15 | } 16 | }; 17 | 18 | app.initialize(); 19 | 20 | }); 21 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 2 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | -------------------------------------------------------------------------------- /appendix-a/listing_a11/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a12", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "connect": "^3.4.0", 13 | "express-session": "^1.10.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /appendix-a/listing_a3/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const qs = require('qs'); 3 | 4 | connect() 5 | .use((req, res, next) => { 6 | console.log(req._parsedUrl.query); 7 | req.query = qs.parse(req._parsedUrl.query); 8 | next(); 9 | }) 10 | .use((req, res) => { 11 | console.log('query string:', req.query); 12 | res.end('\n'); 13 | }) 14 | .listen(3000); 15 | -------------------------------------------------------------------------------- /appendix-a/listing_a4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a4", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "body-parser": "^1.14.1", 13 | "connect": "^3.4.0", 14 | "cookie-parser": "^1.3.3" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/controllers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var IndexModel = require('../models/index'); 4 | 5 | 6 | module.exports = function (router) { 7 | 8 | var model = new IndexModel(); 9 | 10 | router.get('/', function (req, res) { 11 | 12 | 13 | res.render('index', model); 14 | 15 | 16 | }); 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_2/server.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | function logger(req, res, next) { 3 | console.log('%s %s', req.method, req.url); 4 | next(); 5 | } 6 | function hello(req, res) { 7 | res.setHeader('Content-Type', 'text/plain'); 8 | res.end('hello world'); 9 | } 10 | const app = connect() 11 | .use(hello) 12 | .use(logger) 13 | .listen(3000); 14 | 15 | -------------------------------------------------------------------------------- /ch08-databases/listing8_21/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing8_21", 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 | "level": "^1.5.0", 14 | "memdown": "^1.2.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch09-testing/chai-examples/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const chai = require('chai'); 3 | const assert = chai.assert; 4 | 5 | let foo = 'foo'; 6 | const tea = { flavors: ['chai', 'earl grey', 'pg tips'] }; 7 | assert.typeOf(foo, 'string'); 8 | 9 | foo = 'bar'; 10 | assert.equal(foo, 'bar'); 11 | assert.lengthOf(foo, 3); 12 | 13 | assert.property(tea, 'flavors'); 14 | assert.lengthOf(tea.flavors, 3); 15 | -------------------------------------------------------------------------------- /appendix-a/listing_a7/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a7", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "body-parser": "^1.11.0", 13 | "connect": "^3.3.4", 14 | "connect-multiparty": "^1.2.5" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/koa-router-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa-router-example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "koa": "1.2.4", 13 | "koa-router": "5.4.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch07-templates/listing7_8/index.js: -------------------------------------------------------------------------------- 1 | const hogan = require('hogan.js'); 2 | const md = require('github-flavored-markdown'); 3 | const templateSource = ` 4 | {{#markdown}}**Name**: {{name}}{{/markdown}} 5 | `; 6 | const context = { 7 | name: 'Rick LaRue', 8 | markdown: () => text => md.parse(text) 9 | }; 10 | const template = hogan.compile(templateSource); 11 | 12 | console.log(template.render(context)); -------------------------------------------------------------------------------- /ch08-databases/listing8_6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ch09-databases", 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 | "knex": "^0.12.6", 14 | "sqlite3": "^3.1.8" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch08-databases/listing8_7/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ch09-databases", 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 | "knex": "^0.12.6", 14 | "sqlite3": "^3.1.8" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch11-command-line/listing11-1/index.js: -------------------------------------------------------------------------------- 1 | const readFile = require('fs').readFile; 2 | const yargs = require('yargs'); 3 | const argv = yargs 4 | .demand('f') 5 | .nargs('f', 1) 6 | .describe('f', 'JSON file to parse') 7 | .argv; 8 | const file = argv.f; 9 | readFile(file, (err, dataBuffer) => { 10 | const value = JSON.parse(dataBuffer.toString()); 11 | console.log(JSON.stringify(value)); 12 | }); 13 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing3_1", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "author": "Alex R. Young", 11 | "license": "MIT", 12 | "dependencies": { 13 | "express": "^4.13.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/listing5_4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing5_4", 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": "MIT", 12 | "dependencies": { 13 | "hapi": "^13.3.0", 14 | "inert": "^3.2.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch09-testing/debug-stacktraces/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "debug-stacktraces", 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 | "clarify": "1.0.5", 14 | "trace": "2.3.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch09-testing/memdb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "memdb", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "dependencies": {}, 10 | "devDependencies": { 11 | "mocha": "2.4.5" 12 | }, 13 | "scripts": { 14 | "test": "mocha test" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "ISC" 19 | } 20 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b2/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const html = fs.readFileSync('./messy_html_example.html', 'utf8'); 3 | const cheerio = require('cheerio'); 4 | const $ = cheerio.load(html); 5 | 6 | const book = { 7 | title: $('table tr td a').first().text(), 8 | href: $('table tr td a').first().attr('href'), 9 | author: $('table tr td').eq(1).text() 10 | }; 11 | 12 | console.log(book); 13 | -------------------------------------------------------------------------------- /ch07-templates/listing7_8/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing7_8", 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": "MIT", 12 | "dependencies": { 13 | "github-flavored-markdown": "^1.0.1", 14 | "hogan": "^1.0.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch07-templates/listing7_9/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing7_9", 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": "MIT", 12 | "dependencies": { 13 | "github-flavored-markdown": "^1.0.1", 14 | "hogan": "^1.0.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch08-databases/listing8_7/index.js: -------------------------------------------------------------------------------- 1 | const db = require('./db'); 2 | 3 | db().then(() => { 4 | console.log('db ready'); 5 | 6 | db.Article.create({ 7 | title: 'my article', 8 | content: 'article content' 9 | }).then(() => { 10 | db.Article.all().then(articles => { 11 | console.log(articles); 12 | 13 | process.exit(); 14 | }); 15 | }); 16 | }) 17 | .catch(err => { throw err }); 18 | -------------------------------------------------------------------------------- /ch09-testing/tips/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tips", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "should": "8.3.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch09-testing/sinon-js-examples/db.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const fs = require('fs'); 3 | 4 | class Database { 5 | constructor(filename) { 6 | this.filename = filename; 7 | this.data = {}; 8 | } 9 | 10 | save(cb) { 11 | fs.writeFile(this.filename, JSON.stringify(this.data), cb); 12 | } 13 | 14 | insert(key, value) { 15 | this.data[key] = value; 16 | } 17 | } 18 | 19 | module.exports = Database; 20 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/flatiron-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flatiron-example", 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 | "flatiron": "0.4.3", 14 | "union": "0.4.6" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-kraken": { 3 | "taskModule": "grunt", 4 | "lintModule": "eslint", 5 | "description": "An example Kraken app", 6 | "author": "Alex R. Young", 7 | "templateModule": "makara", 8 | "i18n": "i18n", 9 | "componentPackager": "bower", 10 | "cssModule": "less", 11 | "jsModule": "requirejs", 12 | "useJson": null 13 | } 14 | } -------------------------------------------------------------------------------- /ch08-databases/listing8_5/index.js: -------------------------------------------------------------------------------- 1 | const pg = require('pg'); 2 | const db = new pg.Client({ database: 'articles' }); 3 | 4 | db.connect((err, client) => { 5 | if (err) throw err; 6 | console.log('Connected to database', db.database); 7 | 8 | db.query(` 9 | SELECT * FROM snippets ORDER BY id 10 | `, (err, result) => { 11 | if (err) throw err; 12 | console.log(result.rows); 13 | db.end(); 14 | }); 15 | }); -------------------------------------------------------------------------------- /ch07-templates/listing7_10/index.js: -------------------------------------------------------------------------------- 1 | const pug = require('pug'); 2 | const fs = require('fs'); 3 | const templateFile = './templates/page.pug'; 4 | const iterTemplate = fs.readFileSync(templateFile); 5 | const context = { messages: [ 6 | 'You have logged in successfully.', 7 | 'Welcome back!' 8 | ]}; 9 | const iterFn = pug.compile( 10 | iterTemplate, 11 | { filename: templateFile } 12 | ); 13 | console.log(iterFn(context)); 14 | -------------------------------------------------------------------------------- /ch07-templates/listing7_11/index.js: -------------------------------------------------------------------------------- 1 | const pug = require('pug'); 2 | const fs = require('fs'); 3 | const templateFile = './templates/page.pug'; 4 | const iterTemplate = fs.readFileSync(templateFile); 5 | const context = { messages: [ 6 | 'You have logged in successfully.', 7 | 'Welcome back!' 8 | ]}; 9 | const iterFn = pug.compile( 10 | iterTemplate, 11 | { filename: templateFile } 12 | ); 13 | console.log(iterFn(context)); 14 | -------------------------------------------------------------------------------- /appendix-a/listing_a12/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a13", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "connect": "^3.4.0", 13 | "connect-redis": "^2.2.0", 14 | "express-session": "^1.10.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/components/requirejs/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "requirejs", 3 | "version": "2.3.2", 4 | "ignore": [], 5 | "homepage": "http://requirejs.org", 6 | "authors": [ 7 | "jrburke.com" 8 | ], 9 | "description": "A file and module loader for JavaScript", 10 | "main": "require.js", 11 | "keywords": [ 12 | "AMD" 13 | ], 14 | "license": [ 15 | "MIT" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/middleware/user.js: -------------------------------------------------------------------------------- 1 | const User = require('../models/user'); 2 | 3 | module.exports = (req, res, next) => { 4 | if (req.remoteUser) { 5 | res.locals.user = req.remoteUser; 6 | } 7 | const uid = req.session.uid; 8 | if (!uid) return next(); 9 | User.get(uid, (err, user) => { 10 | if (err) return next(err); 11 | req.user = res.locals.user = user; 12 | next(); 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/pager.ejs: -------------------------------------------------------------------------------- 1 |
2 | <% if (page.count > 1) { %> 3 | <% if (page.number) { %> 4 | 5 | <% } %> 6 | <% if (page.number < page.count - 1) { %> 7 | <% if (page.number) { %> 8 |    9 | <% } %> 10 | 11 | <% } %> 12 | <% } %> 13 |
14 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_4/server.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const setup = require('./logger.js'); 3 | const errorHandler = require('./errors.js'); 4 | 5 | function hello(req, res, next) { 6 | res.setHeader('Content-Type', 'text/plain'); 7 | next(new Error('Intentional error')); 8 | } 9 | 10 | const app = connect() 11 | .use(setup(':method :url')) 12 | .use(hello) 13 | .use(errorHandler) 14 | .listen(3000); -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing6_6", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "express": "~4.13.1", 13 | "jade": "~1.11.0", 14 | "morgan": "~1.6.1", 15 | "serve-favicon": "~2.3.0" 16 | } 17 | } -------------------------------------------------------------------------------- /appendix-a/listing_a11/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const session = require('express-session'); 3 | 4 | connect() 5 | .use(session({ 6 | secret: 'example secret', 7 | resave: false, 8 | saveUninitialized: true 9 | })) 10 | .use((req, res) => { 11 | req.session.views = req.session.views || 0; 12 | req.session.views++; 13 | res.end('Views:' + req.session.views); 14 | }) 15 | .listen(3000); 16 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing3_2", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "author": "Alex R. Young", 11 | "license": "MIT", 12 | "dependencies": { 13 | "body-parser": "^1.13.2", 14 | "express": "^4.13.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing3_3", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "author": "Alex R. Young", 11 | "license": "MIT", 12 | "dependencies": { 13 | "body-parser": "^1.13.2", 14 | "express": "^4.13.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-commonjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-commonjs", 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 | "devDependencies": { 14 | "jquery": "^2.2.1", 15 | "webpack": "^1.12.14" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var app = require('./index'); 4 | var http = require('http'); 5 | 6 | 7 | var server; 8 | 9 | /* 10 | * Create and start HTTP server. 11 | */ 12 | 13 | server = http.createServer(app); 14 | server.listen(process.env.PORT || 8000); 15 | server.on('listening', function () { 16 | console.log('Server listening on http://localhost:%d', this.address().port); 17 | }); 18 | -------------------------------------------------------------------------------- /ch08-databases/listing8_3/create-tables.js: -------------------------------------------------------------------------------- 1 | const pg = require('pg'); 2 | const db = new pg.Client({ database: 'articles' }); 3 | 4 | db.connect((err, client) => { 5 | db.query(` 6 | CREATE TABLE IF NOT EXISTS snippets ( 7 | id SERIAL, 8 | PRIMARY KEY(id), 9 | body text 10 | ); 11 | ` , (err, result) => { 12 | if (err) throw err; 13 | console.log('Created table "snippets"'); 14 | db.end(); 15 | }); 16 | }); -------------------------------------------------------------------------------- /ch08-databases/listing8_4/create-tables.js: -------------------------------------------------------------------------------- 1 | const pg = require('pg'); 2 | const db = new pg.Client({ database: 'articles' }); 3 | 4 | db.connect((err, client) => { 5 | db.query(` 6 | CREATE TABLE IF NOT EXISTS snippets ( 7 | id SERIAL, 8 | PRIMARY KEY(id), 9 | body text 10 | ); 11 | ` , (err, result) => { 12 | if (err) throw err; 13 | console.log('Created table "snippets"'); 14 | db.end(); 15 | }); 16 | }); -------------------------------------------------------------------------------- /ch08-databases/listing8_5/create-tables.js: -------------------------------------------------------------------------------- 1 | const pg = require('pg'); 2 | const db = new pg.Client({ database: 'articles' }); 3 | 4 | db.connect((err, client) => { 5 | db.query(` 6 | CREATE TABLE IF NOT EXISTS snippets ( 7 | id SERIAL, 8 | PRIMARY KEY(id), 9 | body text 10 | ); 11 | ` , (err, result) => { 12 | if (err) throw err; 13 | console.log('Created table "snippets"'); 14 | db.end(); 15 | }); 16 | }); -------------------------------------------------------------------------------- /ch09-testing/selenium/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "selenium", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "wdio wdio.conf.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "wdio-mocha-framework": "0.2.13", 14 | "webdriverio": "4.0.7" 15 | }, 16 | "dependencies": { 17 | "express": "4.13.4" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch09-testing/sinon-js-examples/spies.js: -------------------------------------------------------------------------------- 1 | const sinon = require('sinon'); 2 | const Database = require('./db'); 3 | const fs = require('fs'); 4 | const database = new Database('./sample.json'); 5 | 6 | const fsWriteFileSpy = sinon.spy(fs, 'writeFile'); 7 | const saveDone = sinon.spy(); 8 | 9 | database.insert('name', 'Charles Dickens'); 10 | database.save(saveDone); 11 | 12 | sinon.assert.calledOnce(fsWriteFileSpy); 13 | 14 | fs.writeFile.restore(); 15 | -------------------------------------------------------------------------------- /appendix-a/listing_a14/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a14", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "body-parser": "^1.11.0", 13 | "connect": "^3.3.4", 14 | "csurf": "^1.6.6", 15 | "express-session": "^1.10.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/tasks/mochacli.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | module.exports = function mochacli(grunt) { 5 | // Load task 6 | grunt.loadNpmTasks('grunt-mocha-cli'); 7 | 8 | // Options 9 | return { 10 | src: ['test/**/*.js'], 11 | options: { 12 | timeout: 6000, 13 | 'check-leaks': true, 14 | ui: 'bdd', 15 | reporter: 'spec' 16 | } 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/5xx.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= status %> <%= msg %> 5 | 6 | 7 | 8 | <% include menu %> 9 |

<%= status %> Error

10 |

<%= msg %>

11 |

12 | Try refreshing the page, if this problem persists then we're already working on it! 13 |

14 | 15 | 16 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/routes/entries.js: -------------------------------------------------------------------------------- 1 | const Entry = require('../models/entry'); 2 | 3 | exports.list = (req, res, next) => { 4 | const page = req.page; 5 | Entry.getRange(0, -1, (err, entries) => { 6 | if (err) return next(err); 7 | res.render('entries', { 8 | title: 'Entries', 9 | entries: entries 10 | }); 11 | }); 12 | }; 13 | 14 | exports.form = (req, res) => { 15 | res.render('post', { title: 'Post' }); 16 | }; 17 | -------------------------------------------------------------------------------- /ch09-testing/selenium/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const port = process.env.PORT || 4000; 4 | 5 | app.get('/', (req, res) => { 6 | res.send(` 7 | 8 | 9 | My to-do list 10 | 11 | 12 |

Welcome to my awesome to-do list

13 | 14 | 15 | `); 16 | }); 17 | 18 | app.listen(port, () => { 19 | console.log('Running on port', port); 20 | }); 21 | -------------------------------------------------------------------------------- /ch11-command-line/listing11-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing11-2", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "bin": { 10 | "parse-json": "index.js" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "mississippi": "^1.2.0", 17 | "yargs": "^4.4.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/flatiron-example/server.js: -------------------------------------------------------------------------------- 1 | const flatiron = require('flatiron'); 2 | const app = flatiron.app; 3 | const port = process.env.PORT || 8080; 4 | 5 | app.use(flatiron.plugins.http); 6 | 7 | app.router.get('/', function() { 8 | this.res.writeHead(200, { 'Content-Type': 'text/plain' }); 9 | this.res.end('Hello world!\n'); 10 | }); 11 | 12 | app.start(port, () => { 13 | console.log('App started. Running at: http://localhost:%s', port); 14 | }); 15 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing6_7", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "express": "~4.13.1", 13 | "jade": "~1.11.0", 14 | "morgan": "~1.6.1", 15 | "redis": "^2.4.2", 16 | "serve-favicon": "~2.3.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_8/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing6_7", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "express": "~4.13.1", 13 | "jade": "~1.11.0", 14 | "morgan": "~1.6.1", 15 | "redis": "^2.4.2", 16 | "serve-favicon": "~2.3.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch08-databases/listing8_20/index.js: -------------------------------------------------------------------------------- 1 | const level = require('level'); 2 | 3 | const db = level('./app.db', { 4 | valueEncoding: 'json' 5 | }); 6 | 7 | const options = { 8 | keyEncoding: 'binary', 9 | valueEncoding: 'hex' 10 | }; 11 | 12 | db.put(new Uint8Array([1, 2, 3]), '0xFF0099', options, (err) => { 13 | if (err) throw err; 14 | db.get(new Uint8Array([1, 2, 3]), options, (err, value) => { 15 | if (err) throw err; 16 | console.log(value); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/koa-router-example/server.js: -------------------------------------------------------------------------------- 1 | const app = require('koa')(); 2 | const router = require('koa-router')(); 3 | 4 | router 5 | .post('/pages', function*() { 6 | this.body = 'Pages'; 7 | }) 8 | .get('/pages/:id', function*() { 9 | this.body = 'A page'; 10 | }) 11 | .put('pages-update', '/pages/:id', function*() { 12 | this.body = 'Updated page'; 13 | }); 14 | 15 | app.use(router.routes()); 16 | 17 | app.listen(process.env.PORT || 3000); 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-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 | 10 | #menu { 11 | position: absolute; 12 | top: 15px; 13 | right: 20px; 14 | font-size: 12px; 15 | color: #888; 16 | } 17 | #menu .name:after { 18 | content: ' -'; 19 | } 20 | #menu a { 21 | text-decoration: none; 22 | margin-left: 5px; 23 | color: black; 24 | } 25 | -------------------------------------------------------------------------------- /ch08-databases/listing8_13/index.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | const { MongoClient } = require('mongodb'); 3 | const hostname = os.hostname(); 4 | 5 | const members = [ 6 | `${hostname}:27018`, 7 | `${hostname}:27017`, 8 | `${hostname}:27019` 9 | ]; 10 | 11 | MongoClient.connect(`mongodb://${members.join(',')}/test?replSet=rs0`) 12 | .then(db => { 13 | db.admin().replSetGetStatus().then(status => { 14 | console.log(status); 15 | db.close(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/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 | 10 | #menu { 11 | position: absolute; 12 | top: 15px; 13 | right: 20px; 14 | font-size: 12px; 15 | color: #888; 16 | } 17 | #menu .name:after { 18 | content: ' -'; 19 | } 20 | #menu a { 21 | text-decoration: none; 22 | margin-left: 5px; 23 | color: black; 24 | } 25 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/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 | 10 | #menu { 11 | position: absolute; 12 | top: 15px; 13 | right: 20px; 14 | font-size: 12px; 15 | color: #888; 16 | } 17 | #menu .name:after { 18 | content: ' -'; 19 | } 20 | #menu a { 21 | text-decoration: none; 22 | margin-left: 5px; 23 | color: black; 24 | } 25 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/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 | 10 | #menu { 11 | position: absolute; 12 | top: 15px; 13 | right: 20px; 14 | font-size: 12px; 15 | color: #888; 16 | } 17 | #menu .name:after { 18 | content: ' -'; 19 | } 20 | #menu a { 21 | text-decoration: none; 22 | margin-left: 5px; 23 | color: black; 24 | } 25 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/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 | 10 | #menu { 11 | position: absolute; 12 | top: 15px; 13 | right: 20px; 14 | font-size: 12px; 15 | color: #888; 16 | } 17 | #menu .name:after { 18 | content: ' -'; 19 | } 20 | #menu a { 21 | text-decoration: none; 22 | margin-left: 5px; 23 | color: black; 24 | } 25 | -------------------------------------------------------------------------------- /ch09-testing/vows-todo/test/todo-test.js: -------------------------------------------------------------------------------- 1 | const vows = require('vows'); 2 | const assert = require('assert'); 3 | const Todo = require('./../todo'); 4 | 5 | vows.describe('Todo').addBatch({ 6 | 'when adding an item': { 7 | topic: () => { 8 | const todo = new Todo(); 9 | todo.add('Feed my cat'); 10 | return todo; 11 | }, 12 | 'it should exist in my todos': (er, todo) => { 13 | assert.equal(todo.length, 1); 14 | } 15 | } 16 | }).export(module); 17 | -------------------------------------------------------------------------------- /appendix-a/listing_a10/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a10", 3 | "version": "1.0.0", 4 | "description": "Using HTTP PUT, DELETE, PATCH, etc.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "body-parser": "^1.11.0", 13 | "connect": "^3.4.0", 14 | "method-override": "^2.3.1", 15 | "morgan": "^1.5.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/example-derby-app/app/index.js: -------------------------------------------------------------------------------- 1 | const app = module.exports = require('derby').createApp('hello', __filename); 2 | app.loadViews(__dirname); 3 | 4 | // Routes render on client as well as server 5 | app.get('/', (page, model) => { 6 | // Subscribe specifies the data to sync 7 | const message = model.at('hello.message'); 8 | message.subscribe(err => { 9 | if (err) return next(err); 10 | message.createNull(''); 11 | page.render(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kraken-example", 3 | "description": "An example Kraken app", 4 | "main": "index.js", 5 | "author": "Alex R. Young", 6 | "moduleType": [ 7 | "amd" 8 | ], 9 | "private": true, 10 | "ignore": [ 11 | "**/.*", 12 | "node_modules", 13 | "bower_components", 14 | "public/components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "requirejs": "^2.1.16" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch08-databases/listing8_24.js: -------------------------------------------------------------------------------- 1 | // You should be able to paste this into a browser 2 | function getAllKeys() { 3 | return Object.keys(localStorage); 4 | } 5 | 6 | function getAllKeysAndValues() { 7 | return getAllKeys() 8 | .reduce((obj, str) => { 9 | obj[str] = localStorage.getItem(str); 10 | return obj; 11 | }, {}); 12 | } 13 | 14 | // Get all values 15 | const allValues = getAllKeys().map(key => localStorage.getItem(key)); 16 | console.log('allValues:', allValues); 17 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/app/index.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | import Request from './request'; 6 | import Response from './response'; 7 | 8 | class App extends React.Component { 9 | render() { 10 | return ( 11 |
12 | 13 | 14 |
15 | ); 16 | } 17 | } 18 | 19 | ReactDOM.render(, document.getElementById('app')); 20 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/app/index.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | import Request from './request'; 6 | import Response from './response'; 7 | 8 | class App extends React.Component { 9 | render() { 10 | return ( 11 |
12 | 13 | 14 |
15 | ); 16 | } 17 | } 18 | 19 | ReactDOM.render(, document.getElementById('app')); 20 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | module.exports = { 3 | resolve: { 4 | extensions: ['', '.js', '.jsx'] 5 | }, 6 | entry: [ 7 | './app/index.jsx' 8 | ], 9 | output: { 10 | path: __dirname + '/js', 11 | filename: 'app.js' 12 | }, 13 | module: { 14 | loaders: [ 15 | { test: /\.jsx?$/, loaders: ['babel-loader'] } 16 | ] 17 | }, 18 | plugins: [ 19 | new webpack.NoErrorsPlugin() 20 | ] 21 | }; 22 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/listing5_3/server.js: -------------------------------------------------------------------------------- 1 | const Hapi = require('hapi'); 2 | const server = new Hapi.Server(); 3 | 4 | server.connection({ 5 | host: 'localhost', 6 | port: 8000 7 | }); 8 | 9 | server.route({ 10 | method: 'GET', 11 | path:'/hello', 12 | handler: (request, reply) => { 13 | return reply('hello world'); 14 | } 15 | }); 16 | 17 | server.start((err) => { 18 | if (err) { 19 | throw err; 20 | } 21 | console.log('Server running at:', server.info.uri); 22 | }); 23 | -------------------------------------------------------------------------------- /ch08-databases/listing8_22/index.js: -------------------------------------------------------------------------------- 1 | const bytes = require('pretty-bytes'); 2 | const obj = {}; 3 | for (let i = 0; i < 200000; i++) { 4 | obj[i] = { 5 | [Math.random()]: Math.random() 6 | }; 7 | } 8 | 9 | console.time('serialise'); 10 | const jsonString = JSON.stringify(obj); 11 | console.timeEnd('serialise'); 12 | console.log('Serialised Size', bytes(Buffer.byteLength(jsonString))); 13 | console.time('deserialise'); 14 | const obj2 = JSON.parse(jsonString); 15 | console.timeEnd('deserialise'); 16 | -------------------------------------------------------------------------------- /ch09-testing/selenium/test/specs/todo.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const assert = require('assert'); 3 | const webdriverio = require('webdriverio'); 4 | 5 | describe('todo tests', () => { 6 | let client; 7 | 8 | before(() => { 9 | client = webdriverio.remote(); 10 | return client.init(); 11 | }); 12 | 13 | it('todo list test', () => { 14 | return client 15 | .url('/') 16 | .getTitle() 17 | .then(title => assert.equal(title, 'My to-do list')); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /ch09-testing/vows-todo/todo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class Todo { 4 | constructor() { 5 | this.todos = []; 6 | } 7 | 8 | add(item) { 9 | if (!item) throw new Error('Todo.prototype.add requires an item'); 10 | this.todos.push(item); 11 | } 12 | 13 | deleteAll() { 14 | this.todos = []; 15 | } 16 | 17 | get length() { 18 | return this.todos.length; 19 | } 20 | 21 | doAsync(cb) { 22 | setTimeout(cb, 2000, true); 23 | } 24 | } 25 | 26 | module.exports = Todo; 27 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | module.exports = { 3 | resolve: { 4 | extensions: ['', '.js', '.jsx'] 5 | }, 6 | entry: [ 7 | './app/index.jsx' 8 | ], 9 | output: { 10 | path: __dirname + '/js', 11 | filename: 'app.js' 12 | }, 13 | module: { 14 | loaders: [ 15 | { test: /\.jsx?$/, loaders: ['babel-loader'] } 16 | ] 17 | }, 18 | plugins: [ 19 | new webpack.NoErrorsPlugin() 20 | ] 21 | }; 22 | -------------------------------------------------------------------------------- /ch12-desktop/listing12_2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World! 6 | 7 | 8 |

Hello World!

9 |

10 |     
17 |   
18 | 
19 | 


--------------------------------------------------------------------------------
/appendix-b-scraping/listing_b1/index.js:
--------------------------------------------------------------------------------
 1 | const html = `
 2 | 
 3 | 
 4 |   
5 |

Catch-22

6 |

Joseph Heller

7 |

A satirical indictment of military madness.

8 |
9 | 10 | `; 11 | const cheerio = require('cheerio'); 12 | const $ = cheerio.load(html); 13 | 14 | const book = { 15 | title: $('.book h2').text(), 16 | author: $('.book h3').text(), 17 | description: $('.book p').text() 18 | }; 19 | 20 | console.log(book); 21 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing3_4", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "author": "Alex R. Young", 11 | "license": "MIT", 12 | "dependencies": { 13 | "body-parser": "^1.13.2", 14 | "express": "^4.13.1", 15 | "node-readability": "2.2.0", 16 | "sqlite3": "3.1.8" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing3_5", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "author": "Alex R. Young", 11 | "license": "MIT", 12 | "dependencies": { 13 | "body-parser": "^1.13.2", 14 | "express": "^4.13.1", 15 | "node-readability": "2.2.0", 16 | "sqlite3": "3.1.8" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "entries-form-view", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "ejs": "^2.4.1", 13 | "express": "~4.13.1", 14 | "jade": "~1.11.0", 15 | "morgan": "~1.6.1", 16 | "redis": "^2.4.2", 17 | "serve-favicon": "~2.3.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "entries-form-submit", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "ejs": "^2.4.1", 13 | "express": "~4.13.1", 14 | "jade": "~1.11.0", 15 | "morgan": "~1.6.1", 16 | "redis": "^2.4.2", 17 | "serve-favicon": "~2.3.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "entries-form-submit", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "ejs": "^2.4.1", 13 | "express": "~4.13.1", 14 | "jade": "~1.11.0", 15 | "morgan": "~1.6.1", 16 | "redis": "^2.4.2", 17 | "serve-favicon": "~2.3.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch09-testing/listing_9_1-7/todo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class Todo { 4 | constructor() { 5 | this.todos = []; 6 | } 7 | 8 | add(item) { 9 | if (!item) throw new Error('Todo.prototype.add requires an item'); 10 | this.todos.push(item); 11 | } 12 | 13 | deleteAll() { 14 | this.todos = []; 15 | } 16 | 17 | get length() { 18 | return this.todos.length; 19 | } 20 | 21 | doAsync(cb) { 22 | setTimeout(cb, 2000, true); 23 | } 24 | } 25 | 26 | module.exports = Todo; 27 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-example/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: './app/index.jsx', 6 | output: { path: __dirname, filename: 'dist/bundle.js' }, 7 | module: { 8 | loaders: [ 9 | { 10 | test: /.jsx?$/, 11 | loader: 'babel-loader', 12 | exclude: /node_modules/, 13 | query: { 14 | presets: ['es2015', 'react'] 15 | } 16 | } 17 | ] 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/example-derby-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-derby-app", 3 | "description": "Example Derby app", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "start": "node app/server.js" 7 | }, 8 | "dependencies": { 9 | "derby": "^0.9.0", 10 | "derby-starter": "^0.4.5", 11 | "derby-debug": "^0.1.0" 12 | }, 13 | "optionalDependencies": {}, 14 | "devDependencies": {}, 15 | "main": "server.js", 16 | "author": "Alex R. Young", 17 | "license": "MIT" 18 | } 19 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_11/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_12/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_14/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch08-databases/listing8_14/index.js: -------------------------------------------------------------------------------- 1 | const redis = require('redis'); 2 | 3 | const db = redis.createClient(); 4 | 5 | db.on('connect', () => console.log('Redis client connected to server.')); 6 | db.on('ready', () => console.log('Redis server is ready.')); 7 | db.on('error', err => console.error('Redis error', err)); 8 | 9 | db.set('color', 'red', err => { 10 | if (err) throw err; 11 | }); 12 | 13 | db.get('color', (err, value) => { 14 | if (err) throw err; 15 | console.log('Got:', value); 16 | }); 17 | 18 | -------------------------------------------------------------------------------- /ch09-testing/sinon-js-examples/stub.js: -------------------------------------------------------------------------------- 1 | const sinon = require('sinon'); 2 | const Database = require('./db'); 3 | const fs = require('fs'); 4 | const database = new Database('./sample.json'); 5 | 6 | const stub = sinon.stub(fs, 'writeFile', (file, data, cb) => { 7 | cb(); 8 | }); 9 | const saveDone = sinon.spy(); 10 | 11 | database.insert('name', 'Charles Dickens'); 12 | database.save(saveDone); 13 | 14 | sinon.assert.calledOnce(stub); 15 | sinon.assert.calledOnce(saveDone); 16 | 17 | fs.writeFile.restore(); 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "entries-list-route-and-view", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "ejs": "^2.4.1", 13 | "express": "~4.13.1", 14 | "jade": "~1.11.0", 15 | "morgan": "~1.6.1", 16 | "redis": "^2.4.2", 17 | "serve-favicon": "~2.3.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_9-10/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /rename.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | const [nodePath, scriptPath, targetDir, originalName, newName] = process.argv; 4 | console.log('Finding listing folders to rename in:', targetDir); 5 | 6 | fs.readdirSync(targetDir) 7 | .filter(p => p.match(originalName)) 8 | .forEach(p => { 9 | const newPath = newName + p.replace(originalName, ''); 10 | const newFullPath = targetDir + newPath; 11 | console.log('Renaming:', p, 'to:', newPath); 12 | fs.renameSync(targetDir + p, newFullPath); 13 | }); 14 | -------------------------------------------------------------------------------- /appendix-a/listing_a9/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing_a10", 3 | "version": "1.0.0", 4 | "description": "An extended HTTP verb example that forces browsers to try to use PUT", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Alex R. Young", 10 | "license": "MIT", 11 | "dependencies": { 12 | "body-parser": "^1.11.0", 13 | "connect": "^3.4.0", 14 | "method-override": "^2.3.1", 15 | "morgan": "^1.5.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch08-databases/listing8_18/index.js: -------------------------------------------------------------------------------- 1 | const level = require('level'); 2 | 3 | const db = level('./app.db', { 4 | valueEncoding: 'json' 5 | }); 6 | 7 | const key = 'user'; 8 | const value = { name: 'Alice' }; 9 | 10 | db.put(key, value, err => { 11 | if (err) throw err; 12 | db.get(key, (err, result) => { 13 | if (err) throw err; 14 | console.log('got value:', result); 15 | db.del(key, (err) => { 16 | if (err) throw err; 17 | console.log('value was deleted'); 18 | }); 19 | }); 20 | }); 21 | 22 | -------------------------------------------------------------------------------- /ch08-databases/listing8_2/index.js: -------------------------------------------------------------------------------- 1 | const pg = require('pg'); 2 | const db = new pg.Client({ database: 'articles' }); 3 | 4 | db.connect((err, client) => { 5 | if (err) throw err; 6 | console.log('Connected to database', db.database); 7 | 8 | db.query(` 9 | CREATE TABLE IF NOT EXISTS snippets ( 10 | id SERIAL, 11 | PRIMARY KEY(id), 12 | body text 13 | ); 14 | `, (err, result) => { 15 | if (err) throw err; 16 | console.log('Created table "snippets"'); 17 | db.end(); 18 | }); 19 | }); -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_213/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const fs = require('fs'); 3 | const Watcher = require('./watcher'); 4 | const watchDir = './watch'; 5 | const processedDir = './done'; 6 | const watcher = new Watcher(watchDir, processedDir); 7 | 8 | watcher.on('process', (file) => { 9 | const watchFile = `${watchDir}/${file}`; 10 | const processedFile = `${processedDir}/${file.toLowerCase()}`; 11 | fs.rename(watchFile, processedFile, err => { 12 | if (err) throw err; 13 | }); 14 | }); 15 | 16 | watcher.start(); 17 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_15-21/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-models", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "bcrypt": "0.8.7", 10 | "body-parser": "~1.13.2", 11 | "cookie-parser": "~1.3.5", 12 | "debug": "~2.2.0", 13 | "ejs": "^2.4.1", 14 | "express": "~4.13.1", 15 | "jade": "~1.11.0", 16 | "morgan": "~1.6.1", 17 | "redis": "2.6.3", 18 | "serve-favicon": "~2.3.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_7/models/entry.js: -------------------------------------------------------------------------------- 1 | const redis = require('redis'); 2 | const db = redis.createClient(); 3 | 4 | class Entry { 5 | constructor(obj) { 6 | for (let key in obj) { 7 | this[key] = obj[key]; 8 | } 9 | } 10 | 11 | save(cb) { 12 | const entryJSON = JSON.stringify(this); 13 | db.lpush( 14 | 'entries', 15 | entryJSON, 16 | (err) => { 17 | if (err) return cb(err); 18 | cb(); 19 | } 20 | ); 21 | } 22 | } 23 | 24 | module.exports = Entry; 25 | -------------------------------------------------------------------------------- /ch02-intro-to-node/listing_216/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const async = require('async'); 3 | async.series([ 4 | callback => { 5 | setTimeout(() => { 6 | console.log('I execute first.'); 7 | callback(); 8 | }, 1000); 9 | }, 10 | callback => { 11 | setTimeout(() => { 12 | console.log('I execute next.'); 13 | callback(); 14 | }, 500); 15 | }, 16 | callback => { 17 | setTimeout(() => { 18 | console.log('I execute last.'); 19 | callback(); 20 | }, 100); 21 | } 22 | ]); 23 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/public/templates/layouts/master.dust: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {+title /} 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | {+body /} 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/views/entries.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | <% include menu %> 9 | <% entries.forEach((entry) => { %> 10 |
11 |

<%= entry.title %>

12 |

<%= entry.body %>

13 |

Posted by <%= entry.username %>

14 |
15 | <% }) %> 16 | <% include pager %> 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_4/errors.js: -------------------------------------------------------------------------------- 1 | const env = process.env.NODE_ENV || 'development'; 2 | 3 | function errorHandler(err, req, res, next) { 4 | res.statusCode = 500; 5 | switch (env) { 6 | case 'development': 7 | console.error('Error caught by errorHandler:'); 8 | console.error(err); 9 | res.setHeader('Content-Type', 'application/json'); 10 | res.end(JSON.stringify(err)); 11 | break; 12 | default: 13 | res.end('Server error'); 14 | } 15 | } 16 | 17 | module.exports = errorHandler; 18 | -------------------------------------------------------------------------------- /ch07-templates/listing7_4/templates/blog_page.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | <% entries.map(entry => { %> 11 |
<%= entry.title %>
12 | 13 |
<%= entry.body %>
14 | <% }); %> 15 | 16 | 17 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTTP Master 6 | 7 | 8 | 9 | 10 |
11 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HTTP Master 6 | 7 | 8 | 9 | 10 |
11 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/tasks/requirejs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | module.exports = function requirejs(grunt) { 5 | // Load task 6 | grunt.loadNpmTasks('grunt-contrib-requirejs'); 7 | 8 | // Options 9 | return { 10 | build: { 11 | options: { 12 | baseUrl: 'public/js', 13 | dir: '.build/js', 14 | optimize: 'uglify', 15 | modules: [ 16 | { name: 'app' } 17 | ] 18 | } 19 | } 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /ch04-front-end/gulp-example/dist/all.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _react = require('react'); 4 | 5 | var _react2 = _interopRequireDefault(_react); 6 | 7 | var _reactDom = require('react-dom'); 8 | 9 | var _reactDom2 = _interopRequireDefault(_reactDom); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | _reactDom2.default.render(_react2.default.createElement( 14 | 'h1', 15 | null, 16 | 'Hello, world!' 17 | ), document.getElementById('example')); 18 | //# sourceMappingURL=all.js.map 19 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/loopback-example/server/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "restApiRoot": "/api", 3 | "host": "0.0.0.0", 4 | "port": 3000, 5 | "remoting": { 6 | "context": false, 7 | "rest": { 8 | "normalizeHttpPath": false, 9 | "xml": false 10 | }, 11 | "json": { 12 | "strict": false, 13 | "limit": "100kb" 14 | }, 15 | "urlencoded": { 16 | "extended": true, 17 | "limit": "100kb" 18 | }, 19 | "cors": false, 20 | "handleErrors": false 21 | }, 22 | "legacyExplorer": false 23 | } 24 | -------------------------------------------------------------------------------- /ch08-databases/listing8_9/index.js: -------------------------------------------------------------------------------- 1 | const { MongoClient } = require('mongodb'); 2 | 3 | MongoClient.connect('mongodb://localhost:27017/articles') 4 | .then(db => { 5 | console.log('Client ready'); 6 | 7 | const article = { 8 | title: 'I like cake', 9 | content: 'It is quite good.' 10 | }; 11 | db.collection('articles') 12 | .insertOne(article) 13 | .then(result => { 14 | console.log(result.insertedId); 15 | console.log(article._id); 16 | db.close(); 17 | }); 18 | }, console.error); 19 | -------------------------------------------------------------------------------- /ch10-deployment/listing10_2/index.js: -------------------------------------------------------------------------------- 1 | const cluster = require('cluster'); 2 | const http = require('http'); 3 | const numCPUs = require('os').cpus().length; 4 | if (cluster.isMaster) { 5 | for (let i = 0; i < numCPUs; i++) { 6 | cluster.fork(); 7 | } 8 | cluster.on('exit', (worker, code, signal) => { 9 | console.log('Worker %s died.', worker.process.pid); 10 | }); 11 | } else { 12 | http.Server((req, res) => { 13 | res.writeHead(200); 14 | res.end('I am a worker running in process: ' + process.pid); 15 | }).listen(8000); 16 | } 17 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/later/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing3_6", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "author": "Alex R. Young", 11 | "license": "MIT", 12 | "dependencies": { 13 | "body-parser": "^1.13.2", 14 | "bootstrap": "3.3.7", 15 | "ejs": "2.5.2", 16 | "express": "^4.13.1", 17 | "node-readability": "2.2.0", 18 | "sqlite3": "3.1.8" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch03-what-is-a-node-web-app/listing3_6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listing3_6", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "author": "Alex R. Young", 11 | "license": "MIT", 12 | "dependencies": { 13 | "body-parser": "^1.13.2", 14 | "bootstrap": "3.3.7", 15 | "ejs": "2.5.2", 16 | "express": "^4.13.1", 17 | "node-readability": "2.2.0", 18 | "sqlite3": "3.1.8" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shoutbox", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "basic-auth": "^1.0.3", 10 | "bcrypt": "^0.8.5", 11 | "body-parser": "~1.13.2", 12 | "cookie-parser": "~1.3.5", 13 | "debug": "~2.2.0", 14 | "ejs": "~2.3.3", 15 | "express": "~4.13.1", 16 | "express-session": "^1.12.1", 17 | "morgan": "~1.6.1", 18 | "redis": "^2.3.0", 19 | "serve-favicon": "~2.3.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-models", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "bcrypt": "^0.8.5", 10 | "body-parser": "~1.13.2", 11 | "cookie-parser": "~1.3.5", 12 | "debug": "~2.2.0", 13 | "ejs": "^2.4.1", 14 | "express": "~4.13.1", 15 | "express-session": "^1.13.0", 16 | "jade": "~1.11.0", 17 | "morgan": "~1.6.1", 18 | "redis": "^2.4.2", 19 | "serve-favicon": "~2.3.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-login", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "bcrypt": "^0.8.5", 10 | "body-parser": "~1.13.2", 11 | "cookie-parser": "~1.3.5", 12 | "debug": "~2.2.0", 13 | "ejs": "^2.4.1", 14 | "express": "~4.13.1", 15 | "express-session": "^1.13.0", 16 | "jade": "~1.11.0", 17 | "morgan": "~1.6.1", 18 | "redis": "^2.4.2", 19 | "serve-favicon": "~2.3.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "user-middleware", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "bcrypt": "^0.8.5", 10 | "body-parser": "~1.13.2", 11 | "cookie-parser": "~1.3.5", 12 | "debug": "~2.2.0", 13 | "ejs": "^2.4.1", 14 | "express": "~4.13.1", 15 | "express-session": "^1.13.0", 16 | "jade": "~1.11.0", 17 | "morgan": "~1.6.1", 18 | "redis": "^2.4.2", 19 | "serve-favicon": "~2.3.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-hotload-example/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | 4 | module.exports = { 5 | entry: './app/index.jsx', 6 | output: { 7 | path: path.resolve(__dirname, 'dist'), 8 | filename: 'bundle.js', 9 | publicPath: '/assets/' 10 | }, 11 | module: { 12 | loaders: [ 13 | { 14 | test: /.jsx?$/, 15 | loader: 'babel-loader', 16 | exclude: /node_modules/, 17 | query: { 18 | presets: ['es2015', 'react'] 19 | } 20 | } 21 | ] 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "basic-auth": "^1.0.3", 10 | "bcrypt": "^0.8.5", 11 | "body-parser": "~1.13.2", 12 | "cookie-parser": "~1.3.5", 13 | "debug": "~2.2.0", 14 | "ejs": "^2.4.1", 15 | "express": "~4.13.1", 16 | "express-session": "^1.13.0", 17 | "jade": "~1.11.0", 18 | "morgan": "~1.6.1", 19 | "redis": "^2.4.2", 20 | "serve-favicon": "~2.3.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "basic-auth": "^1.0.3", 10 | "bcrypt": "^0.8.5", 11 | "body-parser": "~1.13.2", 12 | "cookie-parser": "~1.3.5", 13 | "debug": "~2.2.0", 14 | "ejs": "^2.4.1", 15 | "express": "~4.13.1", 16 | "express-session": "^1.13.0", 17 | "jade": "~1.11.0", 18 | "morgan": "~1.6.1", 19 | "redis": "^2.4.2", 20 | "serve-favicon": "~2.3.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /appendix-a/listing_a5/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const bodyParser = require('body-parser'); 3 | 4 | function verifyRequest(req, res, buf, encoding) { 5 | if (!buf.toString().match(/^name=/)) { 6 | throw new Error('Bad format'); 7 | } 8 | } 9 | 10 | connect() 11 | .use(bodyParser.urlencoded({ 12 | extended: false, 13 | limit: 10, 14 | verify: verifyRequest 15 | })) 16 | .use((req, res, next) => { 17 | res.setHeader('Content-Type', 'text/plain'); 18 | res.end('You sent: ' + JSON.stringify(req.body) + '\n'); 19 | }) 20 | .listen(3000); 21 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "api", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "basic-auth": "^1.0.3", 10 | "bcrypt": "^0.8.5", 11 | "body-parser": "~1.13.2", 12 | "cookie-parser": "~1.3.5", 13 | "debug": "~2.2.0", 14 | "ejs": "^2.4.1", 15 | "express": "~4.13.1", 16 | "express-session": "^1.13.0", 17 | "jade": "~1.11.0", 18 | "morgan": "~1.6.1", 19 | "redis": "^2.4.2", 20 | "serve-favicon": "~2.3.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch07-templates/listing7_11/templates/page.pug: -------------------------------------------------------------------------------- 1 | extends layout.pug 2 | 3 | block title 4 | title Messages 5 | 6 | block style 7 | link(rel="stylesheet", href=baseUrl+"themes/flick/jquery-ui.css") 8 | 9 | block scripts 10 | script(src=baseUrl+"jquery-ui.js") 11 | 12 | block content 13 | - count = 0 14 | each message in messages 15 | - count = count + 1 16 | script. 17 | $(() => { 18 | $("#message_#{count}").dialog({ 19 | height: 140, 20 | modal: true 21 | }); 22 | }); 23 | != '
' + message + '
' 24 | 25 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [ 4 | 2, 5 | 4 6 | ], 7 | "quotes": [ 8 | 2, 9 | "single" 10 | ], 11 | "linebreak-style": [ 12 | 2, 13 | "unix" 14 | ], 15 | "semi": [ 16 | 2, 17 | "always" 18 | ], 19 | "no-console": 1 20 | }, 21 | "env": { 22 | "node": true, 23 | "browser": true, 24 | "mocha": true 25 | }, 26 | "extends": "eslint:recommended" 27 | } 28 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/tasks/eslint.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function eslint(grunt) { 4 | // Load task 5 | grunt.loadNpmTasks('grunt-eslint'); 6 | 7 | // Options 8 | return { 9 | options: { 10 | configFile: '.eslintrc', 11 | rulePaths: ['node_modules/eslint/lib/rules'] 12 | }, 13 | target: ['index.js', 14 | 'server.js', 15 | 'controllers/**/*.js', 16 | 'lib/**/*.js', 17 | 'models/**/*.js', 18 | 'public/js/**/*.js' 19 | ] 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/tasks/less.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | module.exports = function less(grunt) { 5 | // Load task 6 | grunt.loadNpmTasks('grunt-contrib-less'); 7 | 8 | // Options 9 | return { 10 | build: { 11 | options: { 12 | cleancss: false 13 | }, 14 | files: [{ 15 | expand: true, 16 | cwd: 'public/css', 17 | src: ['**/*.less'], 18 | dest: '.build/css/', 19 | ext: '.css' 20 | }] 21 | } 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /ch07-templates/listing7_7/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | EJS example 4 | 5 | 8 | 9 | 10 |
11 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ch09-testing/tips/index.js: -------------------------------------------------------------------------------- 1 | exports.addPercentageToEach = (prices, percentage) => { 2 | return prices.map((total) => { 3 | total = parseFloat(total); 4 | return total + (total * percentage); 5 | }); 6 | }; 7 | 8 | exports.sum = (prices) => { 9 | return prices.reduce((currentSum, currentValue) => { 10 | return parseFloat(currentSum) + parseFloat(currentValue); 11 | }); 12 | }; 13 | 14 | exports.percentFormat = (percentage) => { 15 | return parseFloat(percentage) * 100 + '%'; 16 | }; 17 | 18 | exports.dollarFormat = (number) => { 19 | return `$${parseFloat(number).toFixed(2)}`; 20 | }; 21 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | module.exports = function (grunt) { 5 | 6 | // Load the project's grunt tasks from a directory 7 | require('grunt-config-dir')(grunt, { 8 | configDir: require('path').resolve('tasks') 9 | }); 10 | 11 | 12 | grunt.loadNpmTasks('grunt-makara-amdify'); 13 | 14 | // Register group tasks 15 | grunt.registerTask('build', ['eslint', 'eslint', 'dustjs', 'makara-amdify', 'less', 'requirejs', 'copyto']); 16 | 17 | grunt.registerTask('test', [ 'eslint', 'mochacli' ]); 18 | 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /appendix-b-scraping/listing_b3/index.js: -------------------------------------------------------------------------------- 1 | const jsdom = require('jsdom'); 2 | const html = ` 3 |
4 |

Catch-22

5 |

Joseph Heller

6 |

A satirical indictment of military madness.

7 |
8 | `; 9 | 10 | jsdom.env(html, ['./node_modules/jquery/dist/jquery.js'], scrape); 11 | 12 | function scrape(err, window) { 13 | var $ = window.$; 14 | $('.book').each(function() { 15 | var $el = $(this); 16 | console.log({ 17 | title: $el.find('h2').text(), 18 | author: $el.find('h3').text(), 19 | description: $el.find('p').text() 20 | }); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /ch04-front-end/webpack-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-example", 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 | "react": "^0.14.7", 14 | "react-dom": "^0.14.7" 15 | }, 16 | "devDependencies": { 17 | "babel-core": "^6.6.0", 18 | "babel-loader": "^6.2.4", 19 | "babel-preset-es2015": "^6.6.0", 20 | "babel-preset-react": "^6.5.0", 21 | "webpack": "^1.12.14" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch07-templates/listing7_9/index.js: -------------------------------------------------------------------------------- 1 | const hogan = require('hogan.js'); 2 | const studentTemplate = ` 3 |

4 | Name: {{name}}, 5 | Age: {{age}} years old 6 |

7 | `; 8 | const mainTemplate = ` 9 | {{#students}} 10 | {{>student}} 11 | {{/students}} 12 | `; 13 | const context = { 14 | students: [{ 15 | name: 'Jane Narwhal', 16 | age: 21 17 | }, { 18 | name: 'Rick LaRue', 19 | age: 26 20 | }] 21 | }; 22 | const template = hogan.compile(mainTemplate); 23 | const partial = hogan.compile(studentTemplate); 24 | const html = template.render(context, { student: partial }); 25 | console.log(html); 26 | -------------------------------------------------------------------------------- /ch04-front-end/gulp-example/gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const sourcemaps = require('gulp-sourcemaps'); 3 | const babel = require('gulp-babel'); 4 | const concat = require('gulp-concat'); 5 | const watch = require('gulp-watch'); 6 | 7 | gulp.task('default', () => { 8 | return gulp.src('app/*.jsx') 9 | .pipe(sourcemaps.init()) 10 | .pipe(babel({ 11 | presets: ['es2015', 'react'] 12 | })) 13 | .pipe(concat('all.js')) 14 | .pipe(sourcemaps.write('.')) 15 | .pipe(gulp.dest('dist')); 16 | }); 17 | 18 | gulp.task('watch', () => { 19 | watch('app/**.jsx', () => gulp.start('default')); 20 | }); 21 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/routes/login.js: -------------------------------------------------------------------------------- 1 | const User = require('../models/user'); 2 | 3 | exports.submit = (req, res, next) => { 4 | const data = req.body.user; 5 | User.authenticate(data.name, data.pass, (err, user) => { 6 | if (err) return next(err); 7 | if (user) { 8 | req.session.uid = user.id; 9 | res.redirect('/'); 10 | } else { 11 | res.error('Sorry! invalid credentials. '); 12 | res.redirect('back'); 13 | } 14 | }); 15 | }; 16 | 17 | exports.logout = (req, res) => { 18 | req.session.destroy((err) => { 19 | if (err) throw err; 20 | res.redirect('/'); 21 | }) 22 | }; 23 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start/app/headers.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React from 'react'; 4 | 5 | class Headers extends React.Component { 6 | render() { 7 | const headers = this.props.headers || {}; 8 | const headerRows = Object.keys(headers).map((key, i) => { 9 | return ( 10 | 11 | {key} 12 | {headers[key]} 13 | 14 | ); 15 | }); 16 | 17 | return ( 18 | 19 | {headerRows} 20 | 21 | ); 22 | } 23 | } 24 | 25 | export default Headers; 26 | -------------------------------------------------------------------------------- /ch12-desktop/electron-quick-start-print/app/headers.jsx: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React from 'react'; 4 | 5 | class Headers extends React.Component { 6 | render() { 7 | const headers = this.props.headers || {}; 8 | const headerRows = Object.keys(headers).map((key, i) => { 9 | return ( 10 | 11 | {key} 12 | {headers[key]} 13 | 14 | ); 15 | }); 16 | 17 | return ( 18 | 19 | {headerRows} 20 | 21 | ); 22 | } 23 | } 24 | 25 | export default Headers; 26 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/middleware/page.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = (cb, perpage) => { 4 | perpage = perpage || 10; 5 | return (req, res, next) => { 6 | let page = Math.max( 7 | parseInt(req.params.page || '1', 10), 8 | 1 9 | ) - 1; 10 | cb((err, total) => { 11 | if (err) return next(err); 12 | req.page = res.locals.page = { 13 | number: page, 14 | perpage: perpage, 15 | from: page * perpage, 16 | to: page * perpage + perpage - 1, 17 | total: total, 18 | count: Math.ceil(total / perpage) 19 | }; 20 | next(); 21 | }); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /ch04-front-end/es2015-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "es2015-example", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "babel": "./node_modules/.bin/babel browser.js -d build/", 9 | "uglify": "./node_modules/.bin/uglifyjs build/browser.js -o build/browser.min.js", 10 | "build": "npm run babel && npm run uglify" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "babel-cli": "^6.5.1", 17 | "babel-preset-es2015": "^6.5.0", 18 | "uglifyjs": "^2.4.10" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_33/middleware/page.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = (cb, perpage) => { 4 | perpage = perpage || 10; 5 | return (req, res, next) => { 6 | let page = Math.max( 7 | parseInt(req.params.page || '1', 10), 8 | 1 9 | ) - 1; 10 | cb((err, total) => { 11 | if (err) return next(err); 12 | req.page = res.locals.page = { 13 | number: page, 14 | perpage: perpage, 15 | from: page * perpage, 16 | to: page * perpage + perpage - 1, 17 | total: total, 18 | count: Math.ceil(total / perpage) 19 | }; 20 | next(); 21 | }); 22 | }; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_34/middleware/page.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = (cb, perpage) => { 4 | perpage = perpage || 10; 5 | return (req, res, next) => { 6 | let page = Math.max( 7 | parseInt(req.params.page || '1', 10), 8 | 1 9 | ) - 1; 10 | cb((err, total) => { 11 | if (err) return next(err); 12 | req.page = res.locals.page = { 13 | number: page, 14 | perpage: perpage, 15 | from: page * perpage, 16 | to: page * perpage + perpage - 1, 17 | total: total, 18 | count: Math.ceil(total / perpage) 19 | }; 20 | next(); 21 | }); 22 | }; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /ch09-testing/tips/test/tips.js: -------------------------------------------------------------------------------- 1 | const tips = require('..'); 2 | const should = require('should'); 3 | const tax = 0.12; 4 | const tip = 0.15; 5 | const prices = [10, 20]; 6 | const pricesWithTipAndTax = tips.addPercentageToEach(prices, tip + tax); 7 | 8 | pricesWithTipAndTax[0].should.equal(12.7); 9 | pricesWithTipAndTax[1].should.equal(25.4); 10 | 11 | const totalAmount = tips.sum(pricesWithTipAndTax).toFixed(2); 12 | totalAmount.should.equal('38.10'); 13 | 14 | const totalAmountAsCurrency = tips.dollarFormat(totalAmount); 15 | totalAmountAsCurrency.should.equal('$38.10'); 16 | 17 | const tipAsPercent = tips.percentFormat(tip); 18 | tipAsPercent.should.equal('15%'); 19 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/middleware/page.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = (cb, perpage) => { 4 | perpage = perpage || 10; 5 | return (req, res, next) => { 6 | let page = Math.max( 7 | parseInt(req.params.page || '1', 10), 8 | 1 9 | ) - 1; 10 | cb((err, total) => { 11 | if (err) return next(err); 12 | req.page = res.locals.page = { 13 | number: page, 14 | perpage: perpage, 15 | from: page * perpage, 16 | to: page * perpage + perpage - 1, 17 | total: total, 18 | count: Math.ceil(total / perpage) 19 | }; 20 | next(); 21 | }); 22 | }; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /ch05-server-side-frameworks/kraken-example/tasks/copyto.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | module.exports = function copyto(grunt) { 5 | // Load task 6 | grunt.loadNpmTasks('grunt-copy-to'); 7 | 8 | // Options 9 | return { 10 | build: { 11 | files: [{ 12 | cwd: 'public', 13 | src: ['**/*'], 14 | dest: '.build/' 15 | }], 16 | options: { 17 | ignore: [ 18 | 'public/css/**/*', 19 | 'public/js/**/*', 20 | 'public/templates/**/*' 21 | ] 22 | } 23 | } 24 | }; 25 | }; 26 | -------------------------------------------------------------------------------- /ch08-databases/listing8_16/index.js: -------------------------------------------------------------------------------- 1 | const net = require('net'); 2 | const redis = require('redis'); 3 | 4 | const server = net.createServer(socket => { 5 | const subscriber = redis.createClient(); 6 | subscriber.subscribe('main'); 7 | subscriber.on('message', (channel, message) => { 8 | socket.write(`Channel ${channel}: ${message}`); 9 | }); 10 | 11 | const publisher = redis.createClient(); 12 | socket.on('data', data => { 13 | publisher.publish('main', data); 14 | }); 15 | 16 | socket.on('end', () => { 17 | subscriber.unsubscribe('main'); 18 | subscriber.end(true); 19 | publisher.end(true); 20 | }); 21 | }); 22 | 23 | server.listen(3000); 24 | -------------------------------------------------------------------------------- /ch04-front-end/gulp-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-example", 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 | "babel-preset-react": "^6.5.0", 14 | "gulp": "^3.9.1" 15 | }, 16 | "devDependencies": { 17 | "babel-preset-es2015": "^6.5.0", 18 | "gulp-babel": "^6.1.2", 19 | "gulp-concat": "^2.6.0", 20 | "gulp-sourcemaps": "^1.6.0", 21 | "gulp-watch": "^4.3.5", 22 | "react": "^0.14.7", 23 | "react-dom": "^0.14.7" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ch06-connect-and-express/full-app/middleware/messages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const express = require('express'); 3 | 4 | function message(req) { 5 | return (msg, type) => { 6 | type = type || 'info'; 7 | let sess = req.session; 8 | sess.messages = sess.messages || []; 9 | sess.messages.push({ type: type, string: msg }); 10 | }; 11 | }; 12 | 13 | module.exports = (req, res, next) => { 14 | res.message = message(req); 15 | res.error = (msg) => { 16 | return res.message(msg, 'error'); 17 | }; 18 | res.locals.messages = req.session.messages || []; 19 | res.locals.removeMessages = () => { 20 | req.session.messages = []; 21 | }; 22 | next(); 23 | }; 24 | -------------------------------------------------------------------------------- /appendix-a/listing_a12/index.js: -------------------------------------------------------------------------------- 1 | const connect = require('connect'); 2 | const session = require('express-session'); 3 | const RedisStore = require('connect-redis')(session); 4 | const favicon = require('serve-favicon'); 5 | const options = { 6 | host: 'localhost' 7 | }; 8 | 9 | connect() 10 | .use(favicon(__dirname + '/favicon.ico')) 11 | .use(session({ 12 | store: new RedisStore(options), 13 | secret: 'keyboard cat', 14 | resave: false, 15 | saveUninitialized: true 16 | })) 17 | .use((req, res) => { 18 | req.session.views = req.session.views || 0; 19 | req.session.views++; 20 | res.end('Views: ' + req.session.views); 21 | }) 22 | .listen(3000); 23 | -------------------------------------------------------------------------------- /appendix-a/listing_a13/index.js: -------------------------------------------------------------------------------- 1 | const auth = require('basic-auth'); 2 | const connect = require('connect'); 3 | 4 | function passwordValid(credentials) { 5 | return credentials 6 | && credentials.name === 'tj' 7 | && credentials.pass === 'tobi'; 8 | } 9 | 10 | connect() 11 | .use((req, res, next) => { 12 | const credentials = auth(req); 13 | 14 | if (passwordValid(credentials)) { 15 | next(); 16 | } else { 17 | res.writeHead(401, { 18 | 'WWW-Authenticate': 'Basic realm="example"' 19 | }); 20 | res.end(); 21 | } 22 | }) 23 | .use((req, res) => { 24 | res.end('This is the secret area\n'); 25 | }) 26 | .listen(3000); 27 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_22-24/middleware/messages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const express = require('express'); 3 | 4 | function message(req) { 5 | return (msg, type) => { 6 | type = type || 'info'; 7 | let sess = req.session; 8 | sess.messages = sess.messages || []; 9 | sess.messages.push({ type: type, string: msg }); 10 | }; 11 | }; 12 | 13 | module.exports = (req, res, next) => { 14 | res.message = message(req); 15 | res.error = (msg) => { 16 | return res.message(msg, 'error'); 17 | }; 18 | res.locals.messages = req.session.messages || []; 19 | res.locals.removeMessages = () => { 20 | req.session.messages = []; 21 | }; 22 | next(); 23 | }; 24 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_25-27/middleware/messages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const express = require('express'); 3 | 4 | function message(req) { 5 | return (msg, type) => { 6 | type = type || 'info'; 7 | let sess = req.session; 8 | sess.messages = sess.messages || []; 9 | sess.messages.push({ type: type, string: msg }); 10 | }; 11 | }; 12 | 13 | module.exports = (req, res, next) => { 14 | res.message = message(req); 15 | res.error = (msg) => { 16 | return res.message(msg, 'error'); 17 | }; 18 | res.locals.messages = req.session.messages || []; 19 | res.locals.removeMessages = () => { 20 | req.session.messages = []; 21 | }; 22 | next(); 23 | }; 24 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_28-30/middleware/messages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const express = require('express'); 3 | 4 | function message(req) { 5 | return (msg, type) => { 6 | type = type || 'info'; 7 | let sess = req.session; 8 | sess.messages = sess.messages || []; 9 | sess.messages.push({ type: type, string: msg }); 10 | }; 11 | }; 12 | 13 | module.exports = (req, res, next) => { 14 | res.message = message(req); 15 | res.error = (msg) => { 16 | return res.message(msg, 'error'); 17 | }; 18 | res.locals.messages = req.session.messages || []; 19 | res.locals.removeMessages = () => { 20 | req.session.messages = []; 21 | }; 22 | next(); 23 | }; 24 | -------------------------------------------------------------------------------- /ch06-connect-and-express/listing6_31-32/middleware/messages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const express = require('express'); 3 | 4 | function message(req) { 5 | return (msg, type) => { 6 | type = type || 'info'; 7 | let sess = req.session; 8 | sess.messages = sess.messages || []; 9 | sess.messages.push({ type: type, string: msg }); 10 | }; 11 | }; 12 | 13 | module.exports = (req, res, next) => { 14 | res.message = message(req); 15 | res.error = (msg) => { 16 | return res.message(msg, 'error'); 17 | }; 18 | res.locals.messages = req.session.messages || []; 19 | res.locals.removeMessages = () => { 20 | req.session.messages = []; 21 | }; 22 | next(); 23 | }; 24 | --------------------------------------------------------------------------------