├── .gitignore ├── heroku_intro ├── Procfile ├── package.json └── app.js ├── core_modules ├── data.txt └── fs-example.js ├── heroku_with_mongodb ├── Procfile ├── views │ ├── todos │ │ ├── show.pug │ │ ├── new.pug │ │ ├── index.pug │ │ └── edit.pug │ ├── instructors │ │ ├── show.pug │ │ ├── new.pug │ │ ├── edit.pug │ │ └── index.pug │ ├── error.pug │ └── base.pug ├── routers │ ├── index.js │ ├── instructors.js │ └── todos.js ├── models │ ├── todo.js │ ├── instructor.js │ └── index.js ├── package.json └── app.js ├── mongoose_intro ├── models │ ├── index.js │ └── instructor.js ├── views │ ├── show.pug │ ├── base.pug │ ├── new.pug │ ├── index.pug │ └── edit.pug ├── package.json ├── app.js └── routes │ └── instructors.js ├── mongoose_crud ├── router │ ├── index.js │ └── instructors.js ├── views │ ├── show.pug │ ├── error.pug │ ├── base.pug │ ├── new.pug │ ├── index.pug │ └── edit.pug ├── models │ ├── instructor.js │ └── index.js ├── package.json ├── app.js └── package-lock.json ├── passport_local ├── views │ ├── index.pug │ ├── error.pug │ ├── base.pug │ ├── login.pug │ └── new.pug ├── models │ ├── index.js │ └── user.js ├── middleware │ └── auth.js ├── package.json ├── app.js └── routes │ └── users.js ├── passport_oauth ├── views │ ├── index.pug │ ├── error.pug │ └── base.pug ├── models │ ├── index.js │ └── user.js ├── middleware │ └── auth.js ├── package.json └── app.js ├── cookies_sessions ├── views │ ├── index.pug │ ├── error.pug │ ├── base.pug │ ├── login.pug │ └── new.pug ├── models │ ├── index.js │ └── user.js ├── package.json ├── routes │ └── users.js └── app.js ├── cookies_sessions_auth ├── views │ ├── index.pug │ ├── error.pug │ ├── base.pug │ ├── login.pug │ └── new.pug ├── models │ ├── index.js │ └── user.js ├── middleware │ └── auth.js ├── package.json ├── routes │ └── users.js └── app.js ├── express_router ├── views │ ├── show.pug │ ├── base.pug │ ├── new.pug │ ├── index.pug │ └── edit.pug ├── package.json ├── app.js └── router │ └── index.js ├── password_hashing_bcrypt ├── views │ ├── index.pug │ ├── error.pug │ ├── base.pug │ ├── login.pug │ └── new.pug ├── models │ ├── index.js │ └── user.js ├── package.json ├── routes │ └── users.js └── app.js ├── nodemailer ├── views │ ├── index.pug │ ├── base.pug │ └── new.pug ├── package.json └── app.js ├── express_restful_routing ├── views │ ├── show.pug │ ├── base.pug │ ├── new.pug │ ├── index.pug │ └── edit.pug ├── package.json └── app.js ├── mongoose_associations ├── views │ ├── todos │ │ ├── show.pug │ │ ├── new.pug │ │ ├── index.pug │ │ └── edit.pug │ ├── instructors │ │ ├── show.pug │ │ ├── new.pug │ │ ├── edit.pug │ │ └── index.pug │ ├── error.pug │ └── base.pug ├── routers │ ├── index.js │ ├── instructors.js │ └── todos.js ├── models │ ├── todo.js │ ├── instructor.js │ └── index.js ├── package.json └── app.js ├── pug_intro ├── views │ ├── base.pug │ └── index.pug ├── app.js └── package.json ├── express_forms ├── views │ ├── base.pug │ ├── form-with-get.pug │ └── form-with-post.pug ├── package.json ├── app.js └── package-lock.json ├── json_apis ├── models │ ├── index.js │ └── user.js ├── package.json ├── app.js └── routes │ └── users.js ├── json_apis_auth ├── models │ ├── index.js │ └── user.js ├── package.json ├── app.js ├── middleware │ └── auth.js └── routes │ ├── users.js │ └── auth.js ├── testing_json_apis ├── models │ ├── index.js │ └── user.js ├── package.json ├── app.js ├── middleware │ └── auth.js ├── routes │ ├── users.js │ └── auth.js └── test │ └── userRoutesSpec.js ├── .editorconfig ├── express_intro ├── package.json └── app.js ├── web_scraping ├── app.js └── package.json ├── socket_io ├── package.json ├── index.html ├── app.js └── public │ └── script.js └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env -------------------------------------------------------------------------------- /heroku_intro/Procfile: -------------------------------------------------------------------------------- 1 | web: node app.js 2 | -------------------------------------------------------------------------------- /core_modules/data.txt: -------------------------------------------------------------------------------- 1 | first 2 | second 3 | third 4 | -------------------------------------------------------------------------------- /heroku_with_mongodb/Procfile: -------------------------------------------------------------------------------- 1 | web: node app.js 2 | -------------------------------------------------------------------------------- /mongoose_intro/models/index.js: -------------------------------------------------------------------------------- 1 | exports.Instructor = require('./instructor'); 2 | -------------------------------------------------------------------------------- /mongoose_crud/router/index.js: -------------------------------------------------------------------------------- 1 | exports.instructorsRouter = require('./instructors'); 2 | -------------------------------------------------------------------------------- /passport_local/views/index.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Welcome! -------------------------------------------------------------------------------- /passport_oauth/views/index.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Welcome! -------------------------------------------------------------------------------- /cookies_sessions/views/index.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Welcome! -------------------------------------------------------------------------------- /cookies_sessions_auth/views/index.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Welcome! -------------------------------------------------------------------------------- /express_router/views/show.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{instructor.name} -------------------------------------------------------------------------------- /mongoose_crud/views/show.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{instructor.name} -------------------------------------------------------------------------------- /mongoose_intro/views/show.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{instructor.name} -------------------------------------------------------------------------------- /password_hashing_bcrypt/views/index.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Welcome! -------------------------------------------------------------------------------- /nodemailer/views/index.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | a(href="/new") Send an email! -------------------------------------------------------------------------------- /express_restful_routing/views/show.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{instructor.name} -------------------------------------------------------------------------------- /heroku_with_mongodb/views/todos/show.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | h1 #{todo.task} -------------------------------------------------------------------------------- /mongoose_associations/views/todos/show.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | h1 #{todo.task} -------------------------------------------------------------------------------- /cookies_sessions/views/error.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 #{error} 5 | div #{message} -------------------------------------------------------------------------------- /passport_local/views/error.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 #{error} 5 | div #{message} -------------------------------------------------------------------------------- /passport_oauth/views/error.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 #{error} 5 | div #{message} -------------------------------------------------------------------------------- /cookies_sessions_auth/views/error.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 #{error} 5 | div #{message} -------------------------------------------------------------------------------- /heroku_with_mongodb/views/instructors/show.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{instructor.name} -------------------------------------------------------------------------------- /mongoose_associations/views/instructors/show.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{instructor.name} -------------------------------------------------------------------------------- /password_hashing_bcrypt/views/error.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 #{error} 5 | div #{message} -------------------------------------------------------------------------------- /mongoose_crud/views/error.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{error.title} 5 | p #{error.message} 6 | -------------------------------------------------------------------------------- /heroku_with_mongodb/views/error.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{error.title} 5 | p #{error.message} 6 | -------------------------------------------------------------------------------- /mongoose_associations/views/error.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 #{error.title} 5 | p #{error.message} 6 | -------------------------------------------------------------------------------- /heroku_with_mongodb/routers/index.js: -------------------------------------------------------------------------------- 1 | exports.instructorsRouter = require('./instructors'); 2 | exports.todosRouter = require('./todos'); 3 | -------------------------------------------------------------------------------- /mongoose_associations/routers/index.js: -------------------------------------------------------------------------------- 1 | exports.instructorsRouter = require('./instructors'); 2 | exports.todosRouter = require('./todos'); 3 | -------------------------------------------------------------------------------- /nodemailer/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content -------------------------------------------------------------------------------- /express_router/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content -------------------------------------------------------------------------------- /mongoose_crud/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content -------------------------------------------------------------------------------- /mongoose_intro/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content -------------------------------------------------------------------------------- /pug_intro/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /express_forms/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /cookies_sessions/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /express_restful_routing/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content -------------------------------------------------------------------------------- /password_hashing_bcrypt/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /heroku_with_mongodb/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | a(href="/") Go home 8 | block content -------------------------------------------------------------------------------- /mongoose_associations/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | a(href="/") Go home 8 | block content -------------------------------------------------------------------------------- /pug_intro/views/index.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 Here are the instructors! 5 | ul 6 | each instructor in instructors 7 | li Hello #{instructor} -------------------------------------------------------------------------------- /express_router/views/new.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action="/instructors" method="POST") 5 | input(type="text", name="name") 6 | input(type="submit", value="Submit!") -------------------------------------------------------------------------------- /mongoose_crud/views/new.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action="/instructors" method="POST") 5 | input(type="text", name="name") 6 | input(type="submit", value="Submit!") -------------------------------------------------------------------------------- /mongoose_intro/views/new.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action="/instructors" method="POST") 5 | input(type="text", name="name") 6 | input(type="submit", value="Submit!") -------------------------------------------------------------------------------- /passport_local/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | if(message) 8 | p #{message} 9 | block content 10 | -------------------------------------------------------------------------------- /passport_oauth/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | if(message) 8 | p #{message} 9 | block content 10 | -------------------------------------------------------------------------------- /express_restful_routing/views/new.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action="/instructors" method="POST") 5 | input(type="text" name="name") 6 | input(type="submit" value="Submit!") 7 | -------------------------------------------------------------------------------- /cookies_sessions_auth/views/base.pug: -------------------------------------------------------------------------------- 1 | 2 | html(lang="en") 3 | head 4 | meta(charset="UTF-8") 5 | title Document 6 | body 7 | if(message) 8 | p #{message} 9 | block content 10 | -------------------------------------------------------------------------------- /json_apis/models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | mongoose.set('debug', true); 3 | mongoose.connect('mongodb://localhost/users-api') 4 | mongoose.Promise = Promise; 5 | 6 | module.exports.User = require("./user") -------------------------------------------------------------------------------- /json_apis/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | 3 | var userSchema = new mongoose.Schema({ 4 | username: String 5 | }) 6 | 7 | var User = mongoose.model('User', userSchema); 8 | 9 | module.exports = User; -------------------------------------------------------------------------------- /heroku_with_mongodb/views/instructors/new.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | form(action="/instructors" method="POST") 5 | input(type="text", name="name") 6 | input(type="submit", value="Submit!") -------------------------------------------------------------------------------- /mongoose_associations/views/instructors/new.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | form(action="/instructors" method="POST") 5 | input(type="text", name="name") 6 | input(type="submit", value="Submit!") -------------------------------------------------------------------------------- /json_apis_auth/models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | mongoose.set('debug', true); 3 | mongoose.connect('mongodb://localhost/users-api-auth') 4 | mongoose.Promise = Promise; 5 | 6 | module.exports.User = require("./user") -------------------------------------------------------------------------------- /passport_local/models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | mongoose.set('debug', true) 3 | mongoose.connect('mongodb://localhost/passport_local') 4 | mongoose.Promise = Promise 5 | 6 | module.exports.User = require("./user") -------------------------------------------------------------------------------- /cookies_sessions/models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | mongoose.set('debug', true) 3 | mongoose.connect('mongodb://localhost/cookies_sessions') 4 | mongoose.Promise = Promise 5 | 6 | module.exports.User = require("./user") -------------------------------------------------------------------------------- /core_modules/fs-example.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | fs.appendFile('data.txt', `${process.argv[2]}\n`, function(err) { 4 | fs.readFile('data.txt', function(err, data) { 5 | console.log(data.toString()); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /passport_oauth/models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | mongoose.set('debug', true) 3 | mongoose.connect('mongodb://localhost/passport_facebook') 4 | mongoose.Promise = Promise 5 | 6 | module.exports.User = require("./user") -------------------------------------------------------------------------------- /password_hashing_bcrypt/models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | mongoose.set('debug', true) 3 | mongoose.connect('mongodb://localhost/bcrypt_app') 4 | mongoose.Promise = Promise 5 | 6 | module.exports.User = require("./user") -------------------------------------------------------------------------------- /cookies_sessions_auth/models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | mongoose.set('debug', true) 3 | mongoose.connect('mongodb://localhost/cookies_auth_app') 4 | mongoose.Promise = Promise 5 | 6 | module.exports.User = require("./user") -------------------------------------------------------------------------------- /heroku_with_mongodb/views/todos/new.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | form(action=`/instructors/${instructor.id}/todos` method="POST") 5 | input(type="text", name="task") 6 | input(type="submit", value="Submit!") -------------------------------------------------------------------------------- /nodemailer/views/new.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action="/" method="POST") 5 | input(type="text" name="to") 6 | input(type="text" name="subject") 7 | input(type="submit" value="Send email!") 8 | -------------------------------------------------------------------------------- /mongoose_associations/views/todos/new.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | form(action=`/instructors/${instructor.id}/todos` method="POST") 5 | input(type="text", name="task") 6 | input(type="submit", value="Submit!") -------------------------------------------------------------------------------- /testing_json_apis/models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | mongoose.set('debug', true); 3 | mongoose.connect('mongodb://localhost/users-api-auth-testing') 4 | mongoose.Promise = Promise; 5 | 6 | module.exports.User = require("./user") -------------------------------------------------------------------------------- /express_forms/views/form-with-get.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action='/submit-form-with-get') 5 | input(type="text", name="first") 6 | input(type="text", name="last") 7 | input(type="submit", value="Done!") -------------------------------------------------------------------------------- /express_forms/views/form-with-post.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action='/submit-form-with-post' method="post") 5 | input(type="text", name="first") 6 | input(type="text", name="last") 7 | input(type="submit", value="Done!") -------------------------------------------------------------------------------- /mongoose_crud/models/instructor.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const instructorSchema = new mongoose.Schema({ 4 | name: String 5 | }); 6 | 7 | const Instructor = mongoose.model('Instructor', instructorSchema); 8 | 9 | module.exports = Instructor; 10 | -------------------------------------------------------------------------------- /cookies_sessions/views/login.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Log In 5 | form(action='/users/login', method="POST") 6 | input(type="text" name="username") 7 | input(type="password" name="password") 8 | input(type="submit" value = "Log in!") -------------------------------------------------------------------------------- /passport_local/views/login.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Log In 5 | form(action='/users/login', method="POST") 6 | input(type="text" name="username") 7 | input(type="password" name="password") 8 | input(type="submit" value = "Log in!") -------------------------------------------------------------------------------- /cookies_sessions/views/new.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Sign Up 5 | form(action='/users/signup', method="POST") 6 | input(type="text" name="username") 7 | input(type="password" name="password") 8 | input(type="submit" value = "Log in!") 9 | -------------------------------------------------------------------------------- /cookies_sessions_auth/views/login.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Log In 5 | form(action='/users/login', method="POST") 6 | input(type="text" name="username") 7 | input(type="password" name="password") 8 | input(type="submit" value = "Log in!") -------------------------------------------------------------------------------- /passport_local/views/new.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Sign Up 5 | form(action='/users/signup', method="POST") 6 | input(type="text" name="username") 7 | input(type="password" name="password") 8 | input(type="submit" value = "Log in!") 9 | -------------------------------------------------------------------------------- /cookies_sessions_auth/views/new.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Sign Up 5 | form(action='/users/signup', method="POST") 6 | input(type="text" name="username") 7 | input(type="password" name="password") 8 | input(type="submit" value = "Log in!") 9 | -------------------------------------------------------------------------------- /password_hashing_bcrypt/views/login.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Log In 5 | form(action='/users/login', method="POST") 6 | input(type="text" name="username") 7 | input(type="password" name="password") 8 | input(type="submit" value = "Log in!") -------------------------------------------------------------------------------- /password_hashing_bcrypt/views/new.pug: -------------------------------------------------------------------------------- 1 | extend base.pug 2 | 3 | block content 4 | h1 Sign Up 5 | form(action='/users/signup', method="POST") 6 | input(type="text" name="username") 7 | input(type="password" name="password") 8 | input(type="submit" value = "Log in!") 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 2 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.js] 15 | indent_style = space 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /express_router/views/index.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 See all the instructors! 5 | a(href="/instructors/new") make a new one! 6 | ul 7 | each instructor in instructors 8 | li #{instructor.name}   9 | a(href=`/instructors/${instructor.id}/edit`) Edit -------------------------------------------------------------------------------- /heroku_with_mongodb/models/todo.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | var todoSchema = new mongoose.Schema({ 4 | task: String, 5 | instructor: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | ref: 'Instructor' 8 | } 9 | }); 10 | 11 | module.exports = mongoose.model('Todo', todoSchema); 12 | -------------------------------------------------------------------------------- /mongoose_associations/models/todo.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | var todoSchema = new mongoose.Schema({ 4 | task: String, 5 | instructor: { 6 | type: mongoose.Schema.Types.ObjectId, 7 | ref: 'Instructor' 8 | } 9 | }); 10 | 11 | module.exports = mongoose.model('Todo', todoSchema); 12 | -------------------------------------------------------------------------------- /mongoose_crud/views/index.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 See all the instructors! 5 | a(href="/instructors/new") make a new one! 6 | ul 7 | each instructor in instructors 8 | li #{instructor.name}   9 | a(href=`/instructors/${instructor.id}/edit`) Edit -------------------------------------------------------------------------------- /mongoose_intro/views/index.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 See all the instructors! 5 | a(href="/instructors/new") make a new one! 6 | ul 7 | each instructor in instructors 8 | li #{instructor.name}   9 | a(href=`/instructors/${instructor.id}/edit`) Edit -------------------------------------------------------------------------------- /express_restful_routing/views/index.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | h1 See all the instructors! 5 | a(href="/instructors/new") make a new one! 6 | ul 7 | each instructor in instructors 8 | li #{instructor.name}   9 | a(href=`/instructors/${instructor.id}/edit`) Edit -------------------------------------------------------------------------------- /heroku_with_mongodb/models/instructor.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const instructorSchema = new mongoose.Schema({ 4 | name: String, 5 | todos: [ 6 | { 7 | type: mongoose.Schema.Types.ObjectId, 8 | ref: 'Todo' 9 | } 10 | ] 11 | }); 12 | 13 | module.exports = mongoose.model('Instructor', instructorSchema); 14 | -------------------------------------------------------------------------------- /mongoose_associations/models/instructor.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const instructorSchema = new mongoose.Schema({ 4 | name: String, 5 | todos: [ 6 | { 7 | type: mongoose.Schema.Types.ObjectId, 8 | ref: 'Todo' 9 | } 10 | ] 11 | }); 12 | 13 | module.exports = mongoose.model('Instructor', instructorSchema); 14 | -------------------------------------------------------------------------------- /express_intro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_intro", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.14.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /heroku_intro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_intro", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.14.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /heroku_with_mongodb/views/todos/index.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | h1 See all the todos for #{instructor.name}! 5 | a(href=`/instructors/${instructor.id}/todos/new`) Make a new one! 6 | ul 7 | each todo in instructor.todos 8 | li #{todo.task}   9 | a(href=`/instructors/${instructor.id}/todos/${todo.id}/edit`) Edit -------------------------------------------------------------------------------- /mongoose_associations/views/todos/index.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | h1 See all the todos for #{instructor.name}! 5 | a(href=`/instructors/${instructor.id}/todos/new`) Make a new one! 6 | ul 7 | each todo in instructor.todos 8 | li #{todo.task}   9 | a(href=`/instructors/${instructor.id}/todos/${todo.id}/edit`) Edit -------------------------------------------------------------------------------- /express_router/views/edit.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action=`/instructors/${instructor.id}?_method=PATCH` method="POST") 5 | input(type="text", name="name" value=`${instructor.name}`) 6 | input(type="submit", value="Submit!") 7 | form(action=`/instructors/${instructor.id}?_method=DELETE` method="POST") 8 | input(type="submit", value="X") -------------------------------------------------------------------------------- /mongoose_crud/views/edit.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action=`/instructors/${instructor.id}?_method=PATCH` method="POST") 5 | input(type="text", name="name" value=`${instructor.name}`) 6 | input(type="submit", value="Submit!") 7 | form(action=`/instructors/${instructor.id}?_method=DELETE` method="POST") 8 | input(type="submit", value="X") -------------------------------------------------------------------------------- /mongoose_intro/views/edit.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action=`/instructors/${instructor.id}?_method=PATCH` method="POST") 5 | input(type="text", name="name" value=`${instructor.name}`) 6 | input(type="submit", value="Submit!") 7 | form(action=`/instructors/${instructor.id}?_method=DELETE` method="POST") 8 | input(type="submit", value="X") -------------------------------------------------------------------------------- /pug_intro/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | 4 | const instructors = ['Elie', 'Tim', 'Matt']; 5 | 6 | app.set('view engine', 'pug'); 7 | 8 | app.get('/', function(req, res) { 9 | return res.render('index', { instructors }); 10 | }); 11 | 12 | app.listen(3000, function() { 13 | console.log('Server is listening on port 3000'); 14 | }); 15 | -------------------------------------------------------------------------------- /pug_intro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pug_intro", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.14.1", 14 | "pug": "^2.0.0-beta11" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /express_restful_routing/views/edit.pug: -------------------------------------------------------------------------------- 1 | extends base.pug 2 | 3 | block content 4 | form(action=`/instructors/${instructor.id}?_method=PATCH` method="POST") 5 | input(type="text" name="name" value=`${instructor.name}`) 6 | input(type="submit" value="Submit!") 7 | form(action=`/instructors/${instructor.id}?_method=DELETE` method="POST") 8 | input(type="submit" value="X") 9 | -------------------------------------------------------------------------------- /web_scraping/app.js: -------------------------------------------------------------------------------- 1 | var request = require("request") 2 | var cheerio = require("cheerio") 3 | 4 | request('https://news.ycombinator.com', function (error, response, body) { 5 | if (!error && response.statusCode == 200) { 6 | var $ = cheerio.load(body); 7 | $('a.storylink').each(function(idx,val) { 8 | console.log($(val).text(), $(val).attr('href')) 9 | }) 10 | } 11 | }); -------------------------------------------------------------------------------- /heroku_with_mongodb/views/instructors/edit.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | form(action=`/instructors/${instructor.id}?_method=PATCH` method="POST") 5 | input(type="text", name="name" value=`${instructor.name}`) 6 | input(type="submit", value="Submit!") 7 | form(action=`/instructors/${instructor.id}?_method=DELETE` method="POST") 8 | input(type="submit", value="X") -------------------------------------------------------------------------------- /mongoose_associations/views/instructors/edit.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | form(action=`/instructors/${instructor.id}?_method=PATCH` method="POST") 5 | input(type="text", name="name" value=`${instructor.name}`) 6 | input(type="submit", value="Submit!") 7 | form(action=`/instructors/${instructor.id}?_method=DELETE` method="POST") 8 | input(type="submit", value="X") -------------------------------------------------------------------------------- /express_intro/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | 4 | app.get('/', function(request, response) { 5 | return response.send('Hello World!'); 6 | }); 7 | 8 | app.get('/user/:name', function(request, response) { 9 | return response.send(`Hello ${request.params.name}`); 10 | }); 11 | 12 | app.listen(3000, function() { 13 | console.log('Server is listening on port 3000'); 14 | }); 15 | -------------------------------------------------------------------------------- /heroku_with_mongodb/views/instructors/index.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | h1 See all the instructors! 5 | a(href="/instructors/new") make a new one! 6 | ul 7 | each instructor in instructors 8 | li #{instructor.name}   9 | a(href=`/instructors/${instructor.id}/edit`) Edit   10 | a(href=`/instructors/${instructor.id}/todos`) See Todos -------------------------------------------------------------------------------- /json_apis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json_apis", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.16.1", 14 | "express": "^4.14.1", 15 | "mongoose": "^4.8.4" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /express_forms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_forms", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.18.2", 14 | "express": "^4.16.2", 15 | "pug": "^2.0.0-rc.4" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /mongoose_associations/views/instructors/index.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | h1 See all the instructors! 5 | a(href="/instructors/new") make a new one! 6 | ul 7 | each instructor in instructors 8 | li #{instructor.name}   9 | a(href=`/instructors/${instructor.id}/edit`) Edit   10 | a(href=`/instructors/${instructor.id}/todos`) See Todos -------------------------------------------------------------------------------- /heroku_with_mongodb/views/todos/edit.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | form(action=`/instructors/${todo.instructor.id}/todos/${todo.id}?_method=PATCH` method="POST") 5 | input(type="text", name="task" value=`${todo.task}`) 6 | input(type="submit", value="Submit!") 7 | form(action=`/instructors/${todo.instructor.id}/todos/${todo.id}?_method=DELETE` method="POST") 8 | input(type="submit", value="X") -------------------------------------------------------------------------------- /mongoose_associations/views/todos/edit.pug: -------------------------------------------------------------------------------- 1 | extends ../base.pug 2 | 3 | block content 4 | form(action=`/instructors/${todo.instructor.id}/todos/${todo.id}?_method=PATCH` method="POST") 5 | input(type="text", name="task" value=`${todo.task}`) 6 | input(type="submit", value="Submit!") 7 | form(action=`/instructors/${todo.instructor.id}/todos/${todo.id}?_method=DELETE` method="POST") 8 | input(type="submit", value="X") -------------------------------------------------------------------------------- /nodemailer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodemailer", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "dependencies": { 7 | "dotenv": "^4.0.0", 8 | "nodemailer-mailgun-transport": "^1.2.4" 9 | }, 10 | "devDependencies": {}, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC" 17 | } 18 | -------------------------------------------------------------------------------- /mongoose_crud/models/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | mongoose.Promise = Promise; 4 | mongoose.set('debug', true); 5 | mongoose 6 | .connect('mongodb://localhost/mongoose_intro') 7 | .then(() => { 8 | console.log('Successfully connected to DB.'); 9 | }) 10 | .catch(err => { 11 | console.error(`Error connecting to database: ${err.message}`); 12 | }); 13 | 14 | exports.Instructor = require('./instructor'); 15 | -------------------------------------------------------------------------------- /socket_io/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "socket_io", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "dependencies": { 7 | "express": "^4.14.1", 8 | "locus": "^2.0.1", 9 | "socket.io": "^1.7.3" 10 | }, 11 | "devDependencies": {}, 12 | "scripts": { 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /web_scraping/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web_scraping", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "cheerio": "^0.22.0", 8 | "locus": "^2.0.1", 9 | "request": "^2.79.0" 10 | }, 11 | "devDependencies": {}, 12 | "scripts": { 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /heroku_intro/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | 4 | app.get('/', (request, response) => { 5 | return response.send('Hello World!'); 6 | }); 7 | 8 | app.get('/user/:name', (request, response) => { 9 | return response.send(`Hello ${request.params.name}`); 10 | }); 11 | 12 | const PORT = process.env.PORT || 3000; 13 | app.listen(PORT, () => { 14 | console.log(`Server is listening on port ${PORT}`); 15 | }); 16 | -------------------------------------------------------------------------------- /mongoose_intro/models/instructor.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const instructorSchema = new mongoose.Schema( 4 | { 5 | first: String, 6 | last: String, 7 | programmingLanguages: [String], 8 | favoriteSubjects: [String] 9 | }, 10 | { timestamps: true } // automatically add createdAt and updatedAt 11 | ); 12 | 13 | const Instructor = mongoose.model('Instructor', instructorSchema); 14 | 15 | module.exports = Instructor; 16 | -------------------------------------------------------------------------------- /passport_local/middleware/auth.js: -------------------------------------------------------------------------------- 1 | exports.loginRequired = function(req,res,next){ 2 | if(!req.isAuthenticated()){ 3 | req.flash('error', 'Please log in!') 4 | res.redirect('/users/login') 5 | } else { 6 | next(); 7 | } 8 | } 9 | 10 | exports.ensureCorrectUser = function(req,res,next){ 11 | if(req.user.id !== req.params.id){ 12 | req.flash('error', 'Unauthorized!') 13 | res.redirect('/users') 14 | } 15 | } -------------------------------------------------------------------------------- /passport_oauth/middleware/auth.js: -------------------------------------------------------------------------------- 1 | exports.loginRequired = function(req,res,next){ 2 | if(!req.isAuthenticated()){ 3 | req.flash('error', 'Please log in!') 4 | res.redirect('/users/login') 5 | } else { 6 | next(); 7 | } 8 | } 9 | 10 | exports.ensureCorrectUser = function(req,res,next){ 11 | if(req.user.id !== req.params.id){ 12 | req.flash('error', 'Unauthorized!') 13 | res.redirect('/users') 14 | } 15 | } -------------------------------------------------------------------------------- /passport_oauth/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var findOrCreate = require('mongoose-findorcreate'); 3 | var bcrypt = require("bcrypt"); 4 | 5 | var userSchema = new mongoose.Schema({ 6 | facebook_id: { 7 | type: String, 8 | required: true 9 | } 10 | }); 11 | 12 | userSchema.plugin(findOrCreate); // give us a findOrCreate method! 13 | 14 | 15 | var User = mongoose.model('User', userSchema); 16 | module.exports = User; 17 | -------------------------------------------------------------------------------- /cookies_sessions_auth/middleware/auth.js: -------------------------------------------------------------------------------- 1 | exports.loginRequired = function(req,res,next){ 2 | if(!req.session.user_id){ 3 | req.flash('error', 'Please log in!') 4 | res.redirect('/users/login') 5 | } else { 6 | next(); 7 | } 8 | } 9 | 10 | exports.ensureCorrectUser = function(req,res,next){ 11 | if(req.session.user_id !== req.params.id){ 12 | req.flash('error', 'Unauthorized!') 13 | res.redirect('/users') 14 | } 15 | } -------------------------------------------------------------------------------- /express_restful_routing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_restful_routing", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.16.1", 14 | "express": "^4.14.1", 15 | "method-override": "^2.3.7", 16 | "pug": "^2.0.0-beta11" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /heroku_with_mongodb/models/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | mongoose.Promise = Promise; 4 | mongoose.set('debug', true); 5 | mongoose 6 | .connect('mongodb://localhost/mongoose_intro') 7 | .then(() => { 8 | console.log('Successfully connected to DB.'); 9 | }) 10 | .catch(err => { 11 | console.error(`Error connecting to database: ${err.message}`); 12 | }); 13 | 14 | exports.Instructor = require('./instructor'); 15 | exports.Todo = require('./todo'); 16 | -------------------------------------------------------------------------------- /json_apis/app.js: -------------------------------------------------------------------------------- 1 | var express = require("express") 2 | var app = express() 3 | var bodyParser = require("body-parser"); 4 | var userRoutes = require("./routes/users") 5 | 6 | app.use(bodyParser.json()); 7 | app.use(bodyParser.urlencoded({extended:true})); 8 | 9 | app.get("/", function(req,res){ 10 | res.send("start with /api/users"); 11 | }); 12 | 13 | app.use('/api/users', userRoutes) 14 | 15 | app.listen(3000, function(){ 16 | console.log("Server is listening on port 3000"); 17 | }); 18 | -------------------------------------------------------------------------------- /mongoose_associations/models/index.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | mongoose.Promise = Promise; 4 | mongoose.set('debug', true); 5 | mongoose 6 | .connect('mongodb://localhost/mongoose_intro') 7 | .then(() => { 8 | console.log('Successfully connected to DB.'); 9 | }) 10 | .catch(err => { 11 | console.error(`Error connecting to database: ${err.message}`); 12 | }); 13 | 14 | exports.Instructor = require('./instructor'); 15 | exports.Todo = require('./todo'); 16 | -------------------------------------------------------------------------------- /express_router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_restful_routing", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.16.1", 14 | "express": "^4.14.1", 15 | "method-override": "^2.3.7", 16 | "morgan": "^1.8.1", 17 | "pug": "^2.0.0-beta11" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /socket_io/index.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | 6 |

Here are the chatters!

7 |
8 | 9 |
10 | 11 |

Here are the messages!

12 | 13 |
14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /mongoose_crud/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_restful_routing", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.16.1", 14 | "express": "^4.14.1", 15 | "method-override": "^2.3.7", 16 | "mongoose": "^4.8.3", 17 | "morgan": "^1.8.1", 18 | "pug": "^2.0.0-beta11" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /mongoose_intro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_restful_routing", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.16.1", 14 | "express": "^4.14.1", 15 | "method-override": "^2.3.7", 16 | "mongoose": "^4.8.3", 17 | "morgan": "^1.8.1", 18 | "pug": "^2.0.0-beta11" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /json_apis_auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json_apis", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^1.0.2", 14 | "body-parser": "^1.16.1", 15 | "dotenv": "^4.0.0", 16 | "express": "^4.14.1", 17 | "jsonwebtoken": "^7.3.0", 18 | "locus": "^2.0.1", 19 | "mongoose": "^4.8.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /heroku_with_mongodb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_restful_routing", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.16.1", 14 | "express": "^4.14.1", 15 | "locus": "^2.0.1", 16 | "method-override": "^2.3.7", 17 | "mongoose": "^4.8.3", 18 | "morgan": "^1.8.1", 19 | "pug": "^2.0.0-beta11" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mongoose_associations/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_restful_routing", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "body-parser": "^1.16.1", 14 | "express": "^4.14.1", 15 | "locus": "^2.0.1", 16 | "method-override": "^2.3.7", 17 | "mongoose": "^4.8.3", 18 | "morgan": "^1.8.1", 19 | "pug": "^2.0.0-beta11" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /password_hashing_bcrypt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "password_hashing_bcrypt", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^1.0.2", 14 | "body-parser": "^1.16.1", 15 | "express": "^4.14.1", 16 | "locus": "^2.0.1", 17 | "method-override": "^2.3.7", 18 | "mongoose": "^4.8.4", 19 | "morgan": "^1.8.1", 20 | "pug": "^2.0.0-beta11" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /cookies_sessions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "password_hashing_bcrypt", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^1.0.2", 14 | "body-parser": "^1.16.1", 15 | "cookie-session": "^2.0.0-beta.1", 16 | "dotenv": "^4.0.0", 17 | "express": "^4.14.1", 18 | "locus": "^2.0.1", 19 | "method-override": "^2.3.7", 20 | "mongoose": "^4.8.4", 21 | "morgan": "^1.8.1", 22 | "pug": "^2.0.0-beta11" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /json_apis_auth/app.js: -------------------------------------------------------------------------------- 1 | var express = require("express") 2 | var app = express() 3 | var bodyParser = require("body-parser"); 4 | var userRoutes = require("./routes/users") 5 | var authRoutes = require("./routes/auth") 6 | var authMiddleware = require("./middleware/auth") 7 | 8 | app.use(bodyParser.json()); 9 | app.use(bodyParser.urlencoded({extended:true})); 10 | 11 | app.get("/", function(req,res){ 12 | res.send("start with /api/users"); 13 | }); 14 | 15 | app.use('/api/users', authMiddleware.loginRequired, userRoutes) 16 | app.use('/api/auth', authRoutes) 17 | 18 | app.listen(3000, function(){ 19 | console.log("Server is listening on port 3000"); 20 | }); 21 | -------------------------------------------------------------------------------- /testing_json_apis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json_apis", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^1.0.2", 14 | "body-parser": "^1.16.1", 15 | "dotenv": "^4.0.0", 16 | "express": "^4.14.1", 17 | "jsonwebtoken": "^7.3.0", 18 | "locus": "^2.0.1", 19 | "mongoose": "^4.8.4" 20 | }, 21 | "devDependencies": { 22 | "chai": "^3.5.0", 23 | "mocha": "^3.2.0", 24 | "supertest": "^3.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /testing_json_apis/app.js: -------------------------------------------------------------------------------- 1 | var express = require("express") 2 | var app = express() 3 | var bodyParser = require("body-parser"); 4 | var userRoutes = require("./routes/users") 5 | var authRoutes = require("./routes/auth") 6 | var authMiddleware = require("./middleware/auth") 7 | 8 | app.use(bodyParser.json()); 9 | app.use(bodyParser.urlencoded({extended:true})); 10 | 11 | app.get("/", function(req,res){ 12 | res.send("start with /api/users"); 13 | }); 14 | 15 | app.use('/api/users', authMiddleware.loginRequired, userRoutes) 16 | app.use('/api/auth', authRoutes) 17 | 18 | app.listen(3000, function(){ 19 | console.log("Server is listening on port 3000"); 20 | }); 21 | 22 | module.exports = app; -------------------------------------------------------------------------------- /cookies_sessions_auth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "password_hashing_bcrypt", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^1.0.2", 14 | "body-parser": "^1.16.1", 15 | "connect-flash": "^0.1.1", 16 | "cookie-session": "^2.0.0-beta.1", 17 | "dotenv": "^4.0.0", 18 | "express": "^4.14.1", 19 | "locus": "^2.0.1", 20 | "method-override": "^2.3.7", 21 | "mongoose": "^4.8.4", 22 | "morgan": "^1.8.1", 23 | "pug": "^2.0.0-beta11" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /express_router/app.js: -------------------------------------------------------------------------------- 1 | const bodyParser = require('body-parser'); 2 | const express = require('express'); 3 | const methodOverride = require('method-override'); 4 | const morgan = require('morgan'); 5 | 6 | const app = express(); 7 | 8 | app.set('view engine', 'pug'); 9 | app.use(bodyParser.urlencoded({ extended: true })); 10 | app.use(methodOverride('_method')); 11 | app.use(morgan('tiny')); 12 | 13 | // requiring routes middleware 14 | const instructorRoutes = require('./router'); 15 | app.use('/instructors', instructorRoutes); 16 | 17 | app.get('/', (req, res) => { 18 | return res.redirect('/instructors'); 19 | }); 20 | 21 | app.listen(3000, () => { 22 | console.log('Server is listening on port 3000'); 23 | }); 24 | -------------------------------------------------------------------------------- /passport_local/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "password_hashing_bcrypt", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^1.0.2", 14 | "body-parser": "^1.16.1", 15 | "connect-flash": "^0.1.1", 16 | "cookie-session": "^2.0.0-beta.1", 17 | "dotenv": "^4.0.0", 18 | "express": "^4.14.1", 19 | "locus": "^2.0.1", 20 | "method-override": "^2.3.7", 21 | "mongoose": "^4.8.4", 22 | "morgan": "^1.8.1", 23 | "passport": "^0.3.2", 24 | "passport-local": "^1.0.0", 25 | "pug": "^2.0.0-beta11" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /passport_oauth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "password_hashing_bcrypt", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^1.0.2", 14 | "body-parser": "^1.16.1", 15 | "connect-flash": "^0.1.1", 16 | "cookie-session": "^2.0.0-beta.1", 17 | "dotenv": "^4.0.0", 18 | "express": "^4.14.1", 19 | "locus": "^2.0.1", 20 | "method-override": "^2.3.7", 21 | "mongoose": "^4.8.4", 22 | "mongoose-findorcreate": "^1.0.0", 23 | "morgan": "^1.8.1", 24 | "passport": "^0.3.2", 25 | "passport-facebook": "^2.1.1", 26 | "pug": "^2.0.0-beta11" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /express_forms/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const bodyParser = require('body-parser'); 3 | 4 | const app = express(); 5 | 6 | app.set('view engine', 'pug'); 7 | app.use(bodyParser.urlencoded({ extended: true })); 8 | 9 | app.get('/', function(req, res) { 10 | return res.redirect('/form-with-get'); 11 | }); 12 | 13 | app.get('/form-with-get', function(req, res) { 14 | return res.render('form-with-get'); 15 | }); 16 | 17 | app.get('/form-with-post', function(req, res) { 18 | return res.render('form-with-post'); 19 | }); 20 | 21 | app.get('/submit-form-with-get', function(req, res) { 22 | return res.send(req.query); 23 | }); 24 | 25 | app.post('/submit-form-with-post', function(req, res) { 26 | return res.send(req.body); 27 | }); 28 | 29 | app.listen(3000, function() { 30 | console.log('Server is listening on port 3000'); 31 | }); 32 | -------------------------------------------------------------------------------- /socket_io/app.js: -------------------------------------------------------------------------------- 1 | var express = require("express"), 2 | app = express(); 3 | app.use(express.static(__dirname + '/public')) 4 | var server = require("http").createServer(app); 5 | var io = require("socket.io")(server); 6 | 7 | io.on('connection', function(socket){ 8 | socket.on('join', function(name){ 9 | socket.username = name 10 | io.sockets.emit("addChatter", name); 11 | }); 12 | 13 | socket.on('messages', function(message){ 14 | username = socket.username 15 | io.sockets.emit("messages", {username,message}); 16 | }); 17 | 18 | socket.on('disconnect', function(name){ 19 | io.sockets.emit("removeChatter", socket.username); 20 | }); 21 | }); 22 | 23 | app.get('/', function(req,res){ 24 | res.sendFile(__dirname + '/index.html'); 25 | }); 26 | 27 | server.listen(8080, function(){ 28 | console.log('Server started on port 8080') 29 | }); 30 | -------------------------------------------------------------------------------- /heroku_with_mongodb/app.js: -------------------------------------------------------------------------------- 1 | // npm packages 2 | const express = require('express'); 3 | const methodOverride = require('method-override'); 4 | const bodyParser = require('body-parser'); 5 | const morgan = require('morgan'); 6 | 7 | // app imports 8 | const { instructorsRouter, todosRouter } = require('./routers'); 9 | 10 | // global variables 11 | const app = express(); 12 | 13 | // app config 14 | app.set('view engine', 'pug'); 15 | app.use(express.static(__dirname + '/public')); 16 | app.use(bodyParser.urlencoded({ extended: true })); 17 | app.use(methodOverride('_method')); 18 | app.use(morgan('tiny')); 19 | 20 | app.get('/', (req, res) => res.redirect('/instructors')); 21 | app.use('/instructors', instructorsRouter); 22 | app.use('/instructors/:instructorId/todos', todosRouter); 23 | 24 | app.listen(3000, () => { 25 | console.log('Server is listening on port 3000'); 26 | }); 27 | -------------------------------------------------------------------------------- /socket_io/public/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | var socket = io.connect('http://localhost:8080'); 3 | 4 | var username = prompt("whats your name?"); 5 | socket.emit('join', username); 6 | 7 | $("#chatForm").on('submit', function(e){ 8 | e.preventDefault(); 9 | var message = $("#message").val(); 10 | socket.emit('messages',message) 11 | $("#message").val(""); 12 | }) 13 | 14 | socket.on('messages', function(data){ 15 | $message = $("
  • ", { 16 | text: `${data.username} says ${data.message}` 17 | }) 18 | $("#messagesContainer").append($message); 19 | }) 20 | 21 | socket.on('addChatter', function(name){ 22 | var $chatter = $("
  • ", { 23 | text: name, 24 | attr: { 25 | 'data-name':name 26 | } 27 | }) 28 | $("#chatters").append($chatter) 29 | }) 30 | 31 | socket.on("removeChatter", function(name){ 32 | debugger 33 | $("#chatters li[data-name=" + name +"]").remove() 34 | }) 35 | }) -------------------------------------------------------------------------------- /mongoose_crud/app.js: -------------------------------------------------------------------------------- 1 | // npm packages 2 | const express = require('express'); 3 | const methodOverride = require('method-override'); 4 | const bodyParser = require('body-parser'); 5 | const morgan = require('morgan'); 6 | 7 | // app imports 8 | const { instructorsRouter } = require('./router'); 9 | 10 | // globals 11 | const app = express(); 12 | const PORT = 3000; 13 | 14 | app.set('view engine', 'pug'); 15 | app.use(bodyParser.urlencoded({ extended: true })); 16 | app.use(methodOverride('_method')); 17 | app.use(morgan('tiny')); 18 | 19 | app.get('/', (req, res) => res.redirect('/instructors')); 20 | app.use('/instructors', instructorsRouter); 21 | 22 | // global error handler 23 | app.use((err, req, res, next) => 24 | res.status(err.status || 500).render('error', { 25 | message: err.message || 'Something went wrong!', 26 | title: err.title || 'Internal Server Error' 27 | }) 28 | ); 29 | 30 | app.listen(PORT, () => { 31 | console.log(`Server is listening on port ${PORT}`); 32 | }); 33 | -------------------------------------------------------------------------------- /json_apis/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | var db = require("../models") 4 | 5 | router.get('/', function(req,res){ 6 | db.User.find().then(function(users){ 7 | res.status(200).send(users) 8 | }); 9 | }); 10 | 11 | router.get('/:id', function(req,res){ 12 | db.User.findById(req.params.id).then(function(user){ 13 | res.status(200).send(user) 14 | }); 15 | }); 16 | 17 | router.post('/', function(req,res){ 18 | db.User.create(req.body).then(function(user){ 19 | res.status(201).send(user) 20 | }); 21 | }); 22 | 23 | router.patch('/:id', function(req,res){ 24 | db.User.findByIdAndUpdate(req.params.id, req.body).then(function(user){ 25 | res.status(200).send(user) 26 | }); 27 | }); 28 | 29 | router.delete('/:id', function(req,res){ 30 | db.User.findByIdAndRemove(req.params.id).then(function(user){ 31 | res.status(204).send(user) 32 | }); 33 | }); 34 | 35 | module.exports = router; -------------------------------------------------------------------------------- /json_apis_auth/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var bcrypt = require("bcrypt"); 3 | 4 | var userSchema = new mongoose.Schema({ 5 | username: { 6 | type: String, 7 | required: true, 8 | unique: true 9 | }, 10 | password: { 11 | type: String, 12 | required: true 13 | } 14 | }); 15 | 16 | userSchema.pre('save', function(next){ 17 | var user = this; 18 | 19 | if (!user.isModified('password')) return next(); 20 | 21 | bcrypt.hash(user.password, 10).then(function(hashedPassword) { 22 | user.password = hashedPassword 23 | next(); 24 | }, function(err){ 25 | return next(err) 26 | }) 27 | }); 28 | 29 | userSchema.methods.comparePassword = function(candidatePassword, next) { 30 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { 31 | if(err) return next(err); 32 | next(null, isMatch); 33 | }); 34 | }; 35 | 36 | var User = mongoose.model('User', userSchema); 37 | module.exports = User; -------------------------------------------------------------------------------- /testing_json_apis/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var bcrypt = require("bcrypt"); 3 | 4 | var userSchema = new mongoose.Schema({ 5 | username: { 6 | type: String, 7 | required: true, 8 | unique: true 9 | }, 10 | password: { 11 | type: String, 12 | required: true 13 | } 14 | }); 15 | 16 | userSchema.pre('save', function(next){ 17 | var user = this; 18 | 19 | if (!user.isModified('password')) return next(); 20 | 21 | bcrypt.hash(user.password, 10).then(function(hashedPassword) { 22 | user.password = hashedPassword 23 | next(); 24 | }, function(err){ 25 | return next(err) 26 | }) 27 | }); 28 | 29 | userSchema.methods.comparePassword = function(candidatePassword, next) { 30 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { 31 | if(err) return next(err); 32 | next(null, isMatch); 33 | }); 34 | }; 35 | 36 | var User = mongoose.model('User', userSchema); 37 | module.exports = User; -------------------------------------------------------------------------------- /password_hashing_bcrypt/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | var db = require("../models"); 4 | 5 | router.get('/', function(req,res){ 6 | res.send('logged in!') 7 | }); 8 | 9 | router.get('/login', function(req,res){ 10 | res.render('login') 11 | }); 12 | 13 | router.get('/signup', function(req,res){ 14 | res.render('new') 15 | }); 16 | 17 | router.post('/login', function(req,res){ 18 | db.User.findOne({username: req.body.username}).then(function(user){ 19 | user.comparePassword(req.body.password, function(err, isMatch){ 20 | if(isMatch){ 21 | res.redirect('/users') 22 | } else { 23 | res.redirect('/users/login') 24 | } 25 | }) 26 | }, function(err){ 27 | res.send(err) 28 | }) 29 | }); 30 | 31 | router.post('/signup', function(req,res){ 32 | db.User.create(req.body).then(function(user){ 33 | res.redirect('/users/login') 34 | }) 35 | }); 36 | 37 | module.exports = router; -------------------------------------------------------------------------------- /json_apis_auth/middleware/auth.js: -------------------------------------------------------------------------------- 1 | require('dotenv').load() 2 | var jwt = require("jsonwebtoken") 3 | 4 | exports.loginRequired = function(req,res,next){ 5 | try { 6 | var token = req.headers.authorization.split(" ")[1] 7 | jwt.verify(token, process.env.SECRET_KEY, function(err, decoded) { 8 | if(decoded){ 9 | next(); 10 | } else { 11 | res.status(401).send('Please log in first') 12 | } 13 | }); 14 | } catch(e){ 15 | res.status(401).send('Please log in first') 16 | } 17 | } 18 | 19 | exports.ensureCorrectUser = function(req,res,next){ 20 | try { 21 | var token = req.headers.authorization.split(" ")[1] 22 | jwt.verify(token, process.env.SECRET_KEY, function(err, decoded) { 23 | if(decoded.user_id === req.params.id){ 24 | next(); 25 | } else { 26 | res.status(401).send('Unauthorized') 27 | } 28 | }); 29 | } catch(e){ 30 | res.status(401).send('Unauthorized') 31 | } 32 | } -------------------------------------------------------------------------------- /testing_json_apis/middleware/auth.js: -------------------------------------------------------------------------------- 1 | require('dotenv').load() 2 | var jwt = require("jsonwebtoken") 3 | 4 | exports.loginRequired = function(req,res,next){ 5 | try { 6 | var token = req.headers.authorization.split(" ")[1] 7 | jwt.verify(token, process.env.SECRET_KEY, function(err, decoded) { 8 | if(decoded){ 9 | next(); 10 | } else { 11 | res.status(401).send('Please log in first') 12 | } 13 | }); 14 | } catch(e){ 15 | res.status(401).send('Please log in first') 16 | } 17 | } 18 | 19 | exports.ensureCorrectUser = function(req,res,next){ 20 | try { 21 | var token = req.headers.authorization.split(" ")[1] 22 | jwt.verify(token, process.env.SECRET_KEY, function(err, decoded) { 23 | if(decoded.user_id === req.params.id){ 24 | next(); 25 | } else { 26 | res.status(401).send('Unauthorized') 27 | } 28 | }); 29 | } catch(e){ 30 | res.status(401).send('Unauthorized') 31 | } 32 | } -------------------------------------------------------------------------------- /json_apis_auth/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | var db = require("../models") 4 | var auth = require('../middleware/auth') 5 | 6 | router.get('/', function(req,res){ 7 | db.User.find().then(function(users){ 8 | res.status(200).send(users) 9 | }); 10 | }); 11 | 12 | router.get('/:id', function(req,res){ 13 | db.User.findById(req.params.id).then(function(user){ 14 | res.status(200).send(user) 15 | }); 16 | }); 17 | 18 | router.post('/', function(req,res){ 19 | db.User.create(req.body).then(function(user){ 20 | res.status(201).send(user) 21 | }); 22 | }); 23 | 24 | router.patch('/:id', auth.ensureCorrectUser, function(req,res){ 25 | db.User.findByIdAndUpdate(req.params.id, req.body, {new:true}).then(function(user){ 26 | res.status(200).send(user) 27 | }); 28 | }); 29 | 30 | router.delete('/:id', auth.ensureCorrectUser, function(req,res){ 31 | db.User.findByIdAndRemove(req.params.id).then(function(user){ 32 | res.status(204).send(user) 33 | }); 34 | }); 35 | 36 | module.exports = router; -------------------------------------------------------------------------------- /testing_json_apis/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | var db = require("../models") 4 | var auth = require('../middleware/auth') 5 | 6 | router.get('/', function(req,res){ 7 | db.User.find().then(function(users){ 8 | res.status(200).send(users) 9 | }); 10 | }); 11 | 12 | router.get('/:id', function(req,res){ 13 | db.User.findById(req.params.id).then(function(user){ 14 | res.status(200).send(user) 15 | }); 16 | }); 17 | 18 | router.post('/', function(req,res){ 19 | db.User.create(req.body).then(function(user){ 20 | res.status(201).send(user) 21 | }); 22 | }); 23 | 24 | router.patch('/:id', auth.ensureCorrectUser, function(req,res){ 25 | db.User.findByIdAndUpdate(req.params.id, req.body, {new:true}).then(function(user){ 26 | res.status(200).send(user) 27 | }); 28 | }); 29 | 30 | router.delete('/:id', auth.ensureCorrectUser, function(req,res){ 31 | db.User.findByIdAndRemove(req.params.id).then(function(user){ 32 | res.status(204).send(user) 33 | }); 34 | }); 35 | 36 | module.exports = router; -------------------------------------------------------------------------------- /mongoose_associations/app.js: -------------------------------------------------------------------------------- 1 | // npm packages 2 | const express = require('express'); 3 | const methodOverride = require('method-override'); 4 | const bodyParser = require('body-parser'); 5 | const morgan = require('morgan'); 6 | 7 | // app imports 8 | const { instructorsRouter, todosRouter } = require('./routers'); 9 | 10 | // global variables 11 | const app = express(); 12 | const PORT = 3000; 13 | 14 | // app config 15 | app.set('view engine', 'pug'); 16 | app.use(express.static(__dirname + '/public')); 17 | app.use(bodyParser.urlencoded({ extended: true })); 18 | app.use(methodOverride('_method')); 19 | app.use(morgan('tiny')); 20 | 21 | app.get('/', (req, res) => res.redirect('/instructors')); 22 | app.use('/instructors', instructorsRouter); 23 | app.use('/instructors/:instructorId/todos', todosRouter); 24 | 25 | // global error handler 26 | app.use((err, req, res, next) => 27 | res.status(err.status || 500).render('error', { 28 | message: err.message || 'Something went wrong!', 29 | title: err.title || 'Internal Server Error' 30 | }) 31 | ); 32 | 33 | app.listen(PORT, () => { 34 | console.log(`Server is listening on port ${PORT}`); 35 | }); 36 | -------------------------------------------------------------------------------- /passport_local/app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').load(); 2 | var express = require("express") 3 | var app = express() 4 | var methodOverride = require("method-override") 5 | var morgan = require("morgan") 6 | var bodyParser = require("body-parser"); 7 | var userRoutes = require("./routes/users"); 8 | var session = require("cookie-session"); 9 | var flash = require("connect-flash") 10 | var passport = require("passport"); 11 | 12 | app.set("view engine", "pug"); 13 | app.use(express.static(__dirname + "/public")); 14 | app.use(morgan("tiny")) 15 | app.use(bodyParser.urlencoded({extended:true})); 16 | app.use(methodOverride("_method")); 17 | app.use(session({secret:process.env.SECRET_KEY})) 18 | 19 | app.use(passport.initialize()); 20 | app.use(passport.session()); 21 | app.use(flash()); 22 | 23 | 24 | app.get("/", function(req,res){ 25 | res.redirect("/users/login"); 26 | }); 27 | 28 | // send flash messages to all routes 29 | app.use(function(req, res, next){ 30 | res.locals.message = req.flash('message'); 31 | next(); 32 | }); 33 | 34 | app.use('/users', userRoutes) 35 | 36 | app.listen(3000, function(){ 37 | console.log("Server is listening on port 3000"); 38 | }); 39 | -------------------------------------------------------------------------------- /mongoose_intro/app.js: -------------------------------------------------------------------------------- 1 | // npm packages 2 | const bodyParser = require('body-parser'); 3 | const express = require('express'); 4 | const methodOverride = require('method-override'); 5 | const morgan = require('morgan'); 6 | 7 | // globals 8 | const app = express(); 9 | const instructorRoutes = require('./routes/instructors'); 10 | 11 | /* 12 | ---Database Config--- 13 | This section can be placed into models/index.js or into a different folder, 14 | e.g. "models" or "settings", just make sure it connects when your server starts. 15 | */ 16 | const mongoose = require('mongoose'); 17 | mongoose.set('debug', true); 18 | mongoose.connect('mongodb://localhost/mongoose_intro', { 19 | useMongoClient: true 20 | }); 21 | 22 | // settings 23 | app.set('view engine', 'pug'); 24 | 25 | // middleware 26 | app.use(bodyParser.urlencoded({ extended: true })); 27 | app.use(methodOverride('_method')); 28 | app.use(morgan('tiny')); 29 | 30 | // route handlers 31 | app.use('/instructors', instructorRoutes); 32 | app.get('/', (req, res) => { 33 | return res.redirect('/instructors'); 34 | }); 35 | 36 | // server init 37 | app.listen(5000, () => { 38 | console.log('Server is listening on port 5000'); 39 | }); 40 | -------------------------------------------------------------------------------- /testing_json_apis/routes/auth.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | var db = require("../models") 4 | var jwt = require('jsonwebtoken'); 5 | 6 | router.post('/login', function(req,res){ 7 | db.User.findOne({username: req.body.username}).then(function(user){ 8 | user.comparePassword(req.body.password, function(err, isMatch){ 9 | if(isMatch){ 10 | var token = jwt.sign({ user_id: user.id}, process.env.SECRET_KEY); 11 | res.status(200).send({token}) 12 | } else { 13 | res.status(400).send('Invalid Credentials') 14 | } 15 | }) 16 | }, function(err){ 17 | res.status(400).send('Invalid Credentials') 18 | }) 19 | }); 20 | 21 | router.post('/signup', function(req,res){ 22 | db.User.create(req.body).then(function(user){ 23 | var token = jwt.sign({ user_id: user.id}, process.env.SECRET_KEY); 24 | res.status(201).send({token}) 25 | }) 26 | }); 27 | 28 | router.get('/logout', function(req,res){ 29 | req.session.user_id = null; 30 | req.flash('message', 'logged out!') 31 | res.redirect('/users/login') 32 | }) 33 | 34 | module.exports = router; 35 | -------------------------------------------------------------------------------- /cookies_sessions/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | var db = require("../models"); 4 | 5 | router.get('/', function(req,res){ 6 | res.send('logged in!') 7 | }); 8 | 9 | router.get('/login', function(req,res){ 10 | res.render('login') 11 | }); 12 | 13 | router.get('/signup', function(req,res){ 14 | res.render('new') 15 | }); 16 | 17 | router.post('/login', function(req,res){ 18 | db.User.findOne({username: req.body.username}).then(function(user){ 19 | user.comparePassword(req.body.password, function(err, isMatch){ 20 | if(isMatch){ 21 | req.session.user_id = user.id 22 | res.redirect('/users') 23 | } else { 24 | res.redirect('/users/login') 25 | } 26 | }) 27 | }, function(err){ 28 | res.send(err) 29 | }) 30 | }); 31 | 32 | router.post('/signup', function(req,res){ 33 | db.User.create(req.body).then(function(user){ 34 | res.redirect('/users/login') 35 | }) 36 | }); 37 | 38 | router.get('/logout', function(req,res){ 39 | req.session.user_id = null; 40 | res.redirect('/users/login') 41 | }) 42 | 43 | module.exports = router; -------------------------------------------------------------------------------- /json_apis_auth/routes/auth.js: -------------------------------------------------------------------------------- 1 | require('dotenv').load() 2 | 3 | var express = require("express"); 4 | var router = express.Router(); 5 | var db = require("../models") 6 | var jwt = require('jsonwebtoken'); 7 | 8 | router.post('/login', function(req,res){ 9 | db.User.findOne({username: req.body.username}).then(function(user){ 10 | user.comparePassword(req.body.password, function(err, isMatch){ 11 | if(isMatch){ 12 | var token = jwt.sign({ user_id: user.id}, process.env.SECRET_KEY); 13 | res.status(200).send({token}) 14 | } else { 15 | res.status(400).send('Invalid Credentials') 16 | } 17 | }) 18 | }, function(err){ 19 | res.status(400).send('Invalid Credentials') 20 | }) 21 | }); 22 | 23 | router.post('/signup', function(req,res){ 24 | db.User.create(req.body).then(function(user){ 25 | var token = jwt.sign({ user_id: user.id}, process.env.SECRET_KEY); 26 | res.status(200).send({token}) 27 | }) 28 | }); 29 | 30 | router.get('/logout', function(req,res){ 31 | req.session.user_id = null; 32 | req.flash('message', 'logged out!') 33 | res.redirect('/users/login') 34 | }) 35 | 36 | module.exports = router; 37 | -------------------------------------------------------------------------------- /nodemailer/app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').load(); 2 | 3 | var express = require("express") 4 | var app = express() 5 | var bodyParser = require("body-parser"); 6 | var nodemailer = require('nodemailer'); 7 | var mg = require('nodemailer-mailgun-transport'); 8 | 9 | app.set("view engine", "pug"); 10 | app.use(bodyParser.urlencoded({extended:true})); 11 | 12 | 13 | var auth = { 14 | auth: { 15 | api_key: process.env.SECRET_KEY, 16 | domain: process.env.DOMAIN 17 | } 18 | } 19 | 20 | var nodemailerMailgun = nodemailer.createTransport(mg(auth)); 21 | 22 | app.get("/", function(req,res){ 23 | res.render("index"); 24 | }); 25 | 26 | app.get("/new", function(req,res){ 27 | res.render("new"); 28 | }); 29 | 30 | app.post('/', function(req,res){ 31 | var mailOpts = { 32 | from: 'elie@yourdomain.com', 33 | to: req.body.to, 34 | subject: req.body.subject, 35 | text : 'test message form mailgun', 36 | html : 'test message form mailgun' 37 | }; 38 | 39 | nodemailerMailgun.sendMail(mailOpts, function (err, response) { 40 | if (err) res.send(err) 41 | else { 42 | res.send('email sent!') 43 | } 44 | }); 45 | }); 46 | 47 | app.listen(3000, function(){ 48 | console.log("Server is listening on port 3000"); 49 | }); -------------------------------------------------------------------------------- /mongoose_intro/routes/instructors.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | var id = 1; 5 | var instructors = []; 6 | 7 | router.get('/', (req, res) => { 8 | return res.render('index', { instructors }); 9 | }); 10 | 11 | router.get('/new', (req, res) => { 12 | return res.render('new'); 13 | }); 14 | 15 | router.get('/:id', (req, res) => { 16 | var instructor = instructors.find(v => v.id === Number(req.params.id)); 17 | return res.render('show', { instructor }); 18 | }); 19 | 20 | router.get('/:id/edit', (req, res) => { 21 | var instructor = instructors.find(v => v.id === Number(req.params.id)); 22 | return res.render('edit', { instructor }); 23 | }); 24 | 25 | router.post('', (req, res) => { 26 | instructors.push(Object.assign({}, req.body, { id })); 27 | id++; 28 | return res.redirect('/instructors'); 29 | }); 30 | 31 | router.patch('/:id', (req, res) => { 32 | var instructor = instructors.find(v => v.id === Number(req.params.id)); 33 | instructor.name = req.body.name; 34 | return res.redirect('/instructors'); 35 | }); 36 | 37 | router.delete('/:id', (req, res) => { 38 | var instructorIdx = instructors.findIndex( 39 | v => v.id === Number(req.params.id) 40 | ); 41 | instructors.splice(instructorIdx, 1); 42 | return res.redirect('/instructors'); 43 | }); 44 | 45 | module.exports = router; 46 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Examples for Rithm Node Curriculum 2 | 3 | ### Node and Express Fundamentals 4 | 5 | - [01 - Core Modules](./core_modules) 6 | - [02 - Express Intro](./express_intro) 7 | - [03 - Pug Intro](./pug_intro) 8 | - [04 - Express Forms](./express_forms) 9 | - [05 - Express RESTful Routing](./express_restful_routing) 10 | - [06 - Express Router](./express_router) 11 | - [07 - Mongoose Intro](./mongoose_intro) 12 | - [08 - Mongoose CRUD](./mongoose_crud) 13 | - [09 - Mongoose Associations](./mongoose_associations) 14 | - [10 - Heroku Intro](./heroku_intro) 15 | - [11 - Heroku with MongoDB](./heroku_with_mongodb) 16 | 17 | ### Intermediate Node and Express 18 | 19 | - [01 - Password Hashing with bcrypt](./password_hashing_bcrypt) 20 | - [02 - Login with cookies and sessions](./cookies_sessions) 21 | - [03 - Authentication + Authorization with sessions](./cookies_sessions_auth) 22 | - [04 - Authentication with Passport Local](./passport_local) 23 | - [05 - OAuth with Passport](./passport_oauth) 24 | - [06 - JSON APIs](./json_apis) 25 | - [07 - Authentication with JSON APIs](./json_apis_auth) 26 | - [08 - Testing with JSON APIs](./testing_json_apis) 27 | - [09 - Socket.io](./socket_io) 28 | - [10 - Nodemailer](./nodemailer) 29 | - [11 - Web Scraping](./web_scraping) 30 | 31 | To run any of these examples, fork and clone the repository and `cd` into any folder and run `npm install` and either `node app.js` or `nodemon`. 32 | -------------------------------------------------------------------------------- /cookies_sessions_auth/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | var db = require("../models"); 4 | var authMiddleware = require("../middleware/auth") 5 | 6 | router.get('/', authMiddleware.loginRequired, function(req,res){ 7 | res.render('index') 8 | }); 9 | 10 | router.get('/login', function(req,res){ 11 | res.render('login') 12 | }); 13 | 14 | router.get('/signup', function(req,res){ 15 | res.render('new') 16 | }); 17 | 18 | router.post('/login', function(req,res){ 19 | db.User.findOne({username: req.body.username}).then(function(user){ 20 | user.comparePassword(req.body.password, function(err, isMatch){ 21 | if(isMatch){ 22 | req.session.user_id = user.id 23 | req.flash('message', 'logged in!') 24 | res.redirect('/users') 25 | } else { 26 | req.flash('message', 'invalid credentials!') 27 | res.redirect('/users/login') 28 | } 29 | }) 30 | }, function(err){ 31 | res.send(err) 32 | }) 33 | }); 34 | 35 | router.post('/signup', function(req,res){ 36 | db.User.create(req.body).then(function(user){ 37 | res.redirect('/users/login') 38 | }) 39 | }); 40 | 41 | router.get('/logout', function(req,res){ 42 | req.session.user_id = null; 43 | req.flash('message', 'logged out!') 44 | res.redirect('/users/login') 45 | }) 46 | 47 | module.exports = router; -------------------------------------------------------------------------------- /express_router/router/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const router = express.Router(); 4 | 5 | var id = 1; 6 | const instructors = []; 7 | 8 | router 9 | .route('') 10 | .get((req, res) => { 11 | return res.render('index', { instructors }); 12 | }) 13 | .post((req, res) => { 14 | instructors.push({ id, ...req.body }); // ... is object spread operator 15 | id++; 16 | return res.redirect('/instructors'); 17 | }); 18 | 19 | router 20 | .route('/new') 21 | .get((req, res) => { 22 | return res.render('new'); 23 | }); 24 | 25 | router 26 | .route('/:id') 27 | .get((req, res) => { 28 | const instructor = instructors.find(v => v.id === Number(req.params.id)); 29 | return res.render('show', { instructor }); 30 | }) 31 | .patch((req, res) => { 32 | const instructor = instructors.find(v => v.id === Number(req.params.id)); 33 | instructor.name = req.body.name; 34 | return res.redirect('/instructors'); 35 | }) 36 | .delete((req, res) => { 37 | const instructorIdx = instructors.findIndex( 38 | v => v.id === Number(req.params.id) 39 | ); 40 | instructors.splice(instructorIdx, 1); 41 | return res.redirect('/instructors'); 42 | }); 43 | 44 | router 45 | .route('/:id/edit') 46 | .get((req, res) => { 47 | const instructor = instructors.find(v => v.id === Number(req.params.id)); 48 | return res.render('edit', { instructor }); 49 | }); 50 | 51 | module.exports = router; 52 | -------------------------------------------------------------------------------- /heroku_with_mongodb/routers/instructors.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { Instructor } = require('../models'); 4 | 5 | router 6 | .route('/') 7 | .get((req, res, next) => { 8 | Instructor.find() 9 | .then(instructors => res.render('instructors/index', { instructors })) 10 | .catch(err => next(err)); 11 | }) 12 | .post((req, res, next) => 13 | Instructor.create(req.body) 14 | .then(() => res.redirect('/')) 15 | .catch(err => next(err)) 16 | ); 17 | 18 | router.route('/new').get((req, res) => res.render('instructors/new')); 19 | 20 | router 21 | .route('/:id') 22 | .get((req, res, next) => 23 | Instructor.findById(req.params.id) 24 | .then(instructor => res.render('instructors/show', { instructor })) 25 | .catch(err => next(err)) 26 | ) 27 | .patch((req, res, next) => 28 | Instructor.findByIdAndUpdate(req.params.id, req.body) 29 | .then(() => res.redirect('/instructors')) 30 | .catch(err => next(err)) 31 | ) 32 | .delete((req, res, next) => 33 | Instructor.findByIdAndRemove(req.params.id) 34 | .then(() => res.redirect('/instructors')) 35 | .catch(err => next(err)) 36 | ); 37 | 38 | router.route('/:id/edit').get((req, res, next) => 39 | Instructor.findById(req.params.id) 40 | .then(instructor => res.render('instructors/edit', { instructor })) 41 | .catch(err => next(err)) 42 | ); 43 | 44 | module.exports = router; 45 | -------------------------------------------------------------------------------- /mongoose_associations/routers/instructors.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { Instructor } = require('../models'); 4 | 5 | router 6 | .route('/') 7 | .get((req, res, next) => { 8 | Instructor.find() 9 | .then(instructors => res.render('instructors/index', { instructors })) 10 | .catch(err => next(err)); 11 | }) 12 | .post((req, res, next) => 13 | Instructor.create(req.body) 14 | .then(() => res.redirect('/')) 15 | .catch(err => next(err)) 16 | ); 17 | 18 | router.route('/new').get((req, res) => res.render('instructors/new')); 19 | 20 | router 21 | .route('/:id') 22 | .get((req, res, next) => 23 | Instructor.findById(req.params.id) 24 | .then(instructor => res.render('instructors/show', { instructor })) 25 | .catch(err => next(err)) 26 | ) 27 | .patch((req, res, next) => 28 | Instructor.findByIdAndUpdate(req.params.id, req.body) 29 | .then(() => res.redirect('/instructors')) 30 | .catch(err => next(err)) 31 | ) 32 | .delete((req, res, next) => 33 | Instructor.findByIdAndRemove(req.params.id) 34 | .then(() => res.redirect('/instructors')) 35 | .catch(err => next(err)) 36 | ); 37 | 38 | router.route('/:id/edit').get((req, res, next) => 39 | Instructor.findById(req.params.id) 40 | .then(instructor => res.render('instructors/edit', { instructor })) 41 | .catch(err => next(err)) 42 | ); 43 | 44 | module.exports = router; 45 | -------------------------------------------------------------------------------- /password_hashing_bcrypt/app.js: -------------------------------------------------------------------------------- 1 | var express = require("express") 2 | var app = express() 3 | var methodOverride = require("method-override") 4 | var morgan = require("morgan") 5 | var bodyParser = require("body-parser"); 6 | var userRoutes = require("./routes/users") 7 | 8 | app.set("view engine", "pug"); 9 | app.use(express.static(__dirname + "/public")); 10 | app.use(morgan("tiny")) 11 | app.use(bodyParser.urlencoded({extended:true})); 12 | app.use(methodOverride("_method")); 13 | 14 | app.get("/", function(req,res){ 15 | res.redirect("/users/login"); 16 | }); 17 | 18 | app.use('/users', userRoutes) 19 | 20 | // catch 404 and forward to error handler 21 | app.use(function(req, res, next) { 22 | var err = new Error('Not Found'); 23 | err.status = 404; 24 | next(err); 25 | }); 26 | 27 | // error handlers 28 | 29 | // development error handler 30 | // will print stacktrace 31 | if (app.get('env') === 'development') { 32 | app.use(function(err, req, res, next) { 33 | res.status(err.status || 500); 34 | res.render('error', { 35 | message: err.message, 36 | error: err 37 | }); 38 | }); 39 | } 40 | 41 | // production error handler 42 | // no stacktraces leaked to user 43 | app.use(function(err, req, res, next) { 44 | res.status(err.status || 500); 45 | res.render('error', { 46 | message: err.message, 47 | error: {} 48 | }); 49 | }); 50 | 51 | 52 | app.listen(3000, function(){ 53 | console.log("Server is listening on port 3000"); 54 | }); 55 | -------------------------------------------------------------------------------- /mongoose_crud/router/instructors.js: -------------------------------------------------------------------------------- 1 | // npm packages 2 | const express = require('express'); 3 | 4 | // app imports 5 | const { Instructor } = require('../models'); 6 | 7 | // globals 8 | const router = express.Router(); 9 | 10 | router 11 | .route('') 12 | .get((req, res, next) => 13 | Instructor.find() 14 | .then(instructors => res.render('index', { instructors })) 15 | .catch(err => next(err)) 16 | ) 17 | .post((req, res, next) => { 18 | const newInst = new Instructor(req.body); 19 | return newInst 20 | .save() 21 | .then(() => res.redirect('/')) 22 | .catch(err => next(err)); 23 | }); 24 | 25 | router.route('/new').get((req, res) => { 26 | return res.render('new'); 27 | }); 28 | 29 | router 30 | .route('/:id') 31 | .get((req, res, next) => 32 | Instructor.findById(req.params.id) 33 | .then(instructor => res.render('show', { instructor })) 34 | .catch(err => next(err)) 35 | ) 36 | .patch((req, res, next) => 37 | Instructor.findByIdAndUpdate(req.params.id, req.body) 38 | .then(() => res.redirect('/instructors')) 39 | .catch(err => next(err)) 40 | ) 41 | .delete((req, res, next) => 42 | Instructor.findByIdAndRemove(req.params.id) 43 | .then(() => res.redirect('/instructors')) 44 | .catch(err => next(err)) 45 | ); 46 | 47 | router.get('/:id/edit', (req, res, next) => 48 | Instructor.findById(req.params.id) 49 | .then(instructor => res.render('edit', { instructor })) 50 | .catch(err => next(err)) 51 | ); 52 | 53 | module.exports = router; 54 | -------------------------------------------------------------------------------- /cookies_sessions/app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').load(); 2 | 3 | var express = require("express") 4 | var app = express() 5 | var methodOverride = require("method-override") 6 | var morgan = require("morgan") 7 | var bodyParser = require("body-parser"); 8 | var userRoutes = require("./routes/users"); 9 | var session = require("cookie-session"); 10 | 11 | app.set("view engine", "pug"); 12 | app.use(express.static(__dirname + "/public")); 13 | app.use(morgan("tiny")) 14 | app.use(bodyParser.urlencoded({extended:true})); 15 | app.use(methodOverride("_method")); 16 | app.use(session({secret:process.env.SECRET_KEY})) 17 | 18 | app.get("/", function(req,res){ 19 | res.redirect("/users/login"); 20 | }); 21 | 22 | app.use('/users', userRoutes) 23 | 24 | // catch 404 and forward to error handler 25 | app.use(function(req, res, next) { 26 | var err = new Error('Not Found'); 27 | err.status = 404; 28 | next(err); 29 | }); 30 | 31 | // error handlers 32 | 33 | // development error handler 34 | // will print stacktrace 35 | if (app.get('env') === 'development') { 36 | app.use(function(err, req, res, next) { 37 | res.status(err.status || 500); 38 | res.render('error', { 39 | message: err.message, 40 | error: err 41 | }); 42 | }); 43 | } 44 | 45 | // production error handler 46 | // no stacktraces leaked to user 47 | app.use(function(err, req, res, next) { 48 | res.status(err.status || 500); 49 | res.render('error', { 50 | message: err.message, 51 | error: {} 52 | }); 53 | }); 54 | 55 | 56 | app.listen(3000, function(){ 57 | console.log("Server is listening on port 3000"); 58 | }); 59 | -------------------------------------------------------------------------------- /cookies_sessions_auth/app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').load(); 2 | var express = require("express") 3 | var app = express() 4 | var methodOverride = require("method-override") 5 | var morgan = require("morgan") 6 | var bodyParser = require("body-parser"); 7 | var userRoutes = require("./routes/users"); 8 | var session = require("cookie-session"); 9 | var flash = require("connect-flash") 10 | 11 | app.set("view engine", "pug"); 12 | app.use(express.static(__dirname + "/public")); 13 | app.use(morgan("tiny")) 14 | app.use(bodyParser.urlencoded({extended:true})); 15 | app.use(methodOverride("_method")); 16 | app.use(session({secret:process.env.SECRET_KEY})) 17 | app.use(flash()); 18 | 19 | app.get("/", function(req,res){ 20 | res.redirect("/users/login"); 21 | }); 22 | 23 | // send flash messages to all routes 24 | app.use(function(req, res, next){ 25 | res.locals.message = req.flash('message'); 26 | next(); 27 | }); 28 | 29 | 30 | app.use('/users', userRoutes) 31 | 32 | // catch 404 and forward to error handler 33 | app.use(function(req, res, next) { 34 | var err = new Error('Not Found'); 35 | err.status = 404; 36 | next(err); 37 | }); 38 | 39 | // error handlers 40 | 41 | // development error handler 42 | // will print stacktrace 43 | if (app.get('env') === 'development') { 44 | app.use(function(err, req, res, next) { 45 | res.status(err.status || 500); 46 | res.render('error', { 47 | message: err.message, 48 | error: err 49 | }); 50 | }); 51 | } 52 | 53 | // production error handler 54 | // no stacktraces leaked to user 55 | app.use(function(err, req, res, next) { 56 | res.status(err.status || 500); 57 | res.render('error', { 58 | message: err.message, 59 | error: {} 60 | }); 61 | }); 62 | 63 | 64 | app.listen(3000, function(){ 65 | console.log("Server is listening on port 3000"); 66 | }); 67 | -------------------------------------------------------------------------------- /express_restful_routing/app.js: -------------------------------------------------------------------------------- 1 | // npm packages 2 | const bodyParser = require('body-parser'); 3 | const express = require('express'); 4 | const methodOverride = require('method-override'); 5 | 6 | // globals 7 | const app = express(); 8 | var id = 1; 9 | const instructors = []; 10 | 11 | // settings & middleware 12 | app.set('view engine', 'pug'); 13 | app.use(bodyParser.urlencoded({ extended: true })); 14 | app.use(methodOverride('_method')); 15 | 16 | // routes 17 | app.get('/', (req, res) => { 18 | return res.redirect('/instructors'); 19 | }); 20 | 21 | app.get('/instructors', (req, res) => { 22 | return res.render('index', { instructors }); 23 | }); 24 | 25 | app.get('/instructors/new', (req, res) => { 26 | return res.render('new'); 27 | }); 28 | 29 | app.get('/instructors/:id', (req, res) => { 30 | const instructor = instructors.find(v => v.id === Number(req.params.id)); 31 | return res.render('show', { instructor }); 32 | }); 33 | 34 | app.get('/instructors/:id/edit', (req, res) => { 35 | const instructor = instructors.find(v => v.id === Number(req.params.id)); 36 | return res.render('edit', { instructor }); 37 | }); 38 | 39 | app.post('/instructors', (req, res) => { 40 | instructors.push(Object.assign({}, req.body, { id })); 41 | id++; 42 | return res.redirect('/instructors'); 43 | }); 44 | 45 | app.patch('/instructors/:id', (req, res) => { 46 | const instructor = instructors.find(v => v.id === Number(req.params.id)); 47 | instructor.name = req.body.name; 48 | return res.redirect('/instructors'); 49 | }); 50 | 51 | app.delete('/instructors/:id', (req, res) => { 52 | const instructorIdx = instructors.findIndex( 53 | v => v.id === Number(req.params.id) 54 | ); 55 | instructors.splice(instructorIdx, 1); 56 | return res.redirect('/instructors'); 57 | }); 58 | 59 | app.listen(3001, () => { 60 | console.log('Server is listening on port 3000'); 61 | }); 62 | -------------------------------------------------------------------------------- /heroku_with_mongodb/routers/todos.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const router = express.Router({ mergeParams: true }); // preserve parent route parameters 4 | 5 | const { Instructor, Todo } = require('../models'); 6 | 7 | router 8 | .route('/') 9 | .get((req, res, next) => 10 | Instructor.findById(req.params.instructorId) 11 | .populate('todos') 12 | .exec() 13 | .then(instructor => res.render('todos/index', { instructor })) 14 | .catch(err => next(err)) 15 | ) 16 | .post((req, res, next) => { 17 | // build new todo document 18 | const newTodo = new Todo(req.body); 19 | newTodo.instructor = req.params.instructorId; 20 | // find instructor document 21 | return Instructor.findById(req.params.instructorId) 22 | .then(instructor => 23 | // save new todo document 24 | newTodo 25 | .save() 26 | .then(createdTodo => { 27 | // add new todo ID to instructor document 28 | instructor.todos.push(createdTodo._id); 29 | return instructor 30 | .save() 31 | .then(() => res.redirect(`/instructors/${instructor.id}/todos`)) 32 | .catch(err => next(err)); 33 | }) 34 | .catch(err => next(err)) 35 | ) 36 | .catch(err => next(err)); 37 | }); 38 | 39 | router.get('/new', (req, res, next) => 40 | Instructor.findById(req.params.instructorId) 41 | .then(instructor => res.render('todos/new', { instructor })) 42 | .catch(err => next(err)) 43 | ); 44 | 45 | router 46 | .route('/:id') 47 | .get((req, res, next) => { 48 | Todo.findById(req.params.id) 49 | .populate('instructor') 50 | .then(todo => res.render('todos/show', { todo })) 51 | .catch(err => next(err)); 52 | }) 53 | .patch((req, res, next) => 54 | Todo.findByIdAndUpdate(req.params.id, req.body) 55 | .then(() => res.redirect(`/instructors/${req.params.instructorId}/todos`)) 56 | .catch(err => next(err)) 57 | ) 58 | .delete((req, res, next) => 59 | Todo.findByIdAndRemove(req.params.id) 60 | .then(() => res.redirect(`/instructors/${req.params.instructorId}/todos`)) 61 | .catch(err => next(err)) 62 | ); 63 | 64 | router.get('/:id/edit', (req, res, next) => 65 | Todo.findById(req.params.id) 66 | .populate('instructor') 67 | .then(todo => res.render('todos/edit', { todo })) 68 | .catch(err => next(err)) 69 | ); 70 | 71 | module.exports = router; 72 | -------------------------------------------------------------------------------- /mongoose_associations/routers/todos.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const router = express.Router({ mergeParams: true }); // preserve parent route parameters 4 | 5 | const { Instructor, Todo } = require('../models'); 6 | 7 | router 8 | .route('/') 9 | .get((req, res, next) => 10 | Instructor.findById(req.params.instructorId) 11 | .populate('todos') 12 | .exec() 13 | .then(instructor => res.render('todos/index', { instructor })) 14 | .catch(err => next(err)) 15 | ) 16 | .post((req, res, next) => { 17 | // build new todo document 18 | const newTodo = new Todo(req.body); 19 | newTodo.instructor = req.params.instructorId; 20 | // find instructor document 21 | return Instructor.findById(req.params.instructorId) 22 | .then(instructor => 23 | // save new todo document 24 | newTodo 25 | .save() 26 | .then(createdTodo => { 27 | // add new todo ID to instructor document 28 | instructor.todos.push(createdTodo._id); 29 | return instructor 30 | .save() 31 | .then(() => res.redirect(`/instructors/${instructor.id}/todos`)) 32 | .catch(err => next(err)); 33 | }) 34 | .catch(err => next(err)) 35 | ) 36 | .catch(err => next(err)); 37 | }); 38 | 39 | router.get('/new', (req, res, next) => 40 | Instructor.findById(req.params.instructorId) 41 | .then(instructor => res.render('todos/new', { instructor })) 42 | .catch(err => next(err)) 43 | ); 44 | 45 | router 46 | .route('/:id') 47 | .get((req, res, next) => { 48 | Todo.findById(req.params.id) 49 | .populate('instructor') 50 | .then(todo => res.render('todos/show', { todo })) 51 | .catch(err => next(err)); 52 | }) 53 | .patch((req, res, next) => 54 | Todo.findByIdAndUpdate(req.params.id, req.body) 55 | .then(() => res.redirect(`/instructors/${req.params.instructorId}/todos`)) 56 | .catch(err => next(err)) 57 | ) 58 | .delete((req, res, next) => 59 | Todo.findByIdAndRemove(req.params.id) 60 | .then(() => res.redirect(`/instructors/${req.params.instructorId}/todos`)) 61 | .catch(err => next(err)) 62 | ); 63 | 64 | router.get('/:id/edit', (req, res, next) => 65 | Todo.findById(req.params.id) 66 | .populate('instructor') 67 | .then(todo => res.render('todos/edit', { todo })) 68 | .catch(err => next(err)) 69 | ); 70 | 71 | module.exports = router; 72 | -------------------------------------------------------------------------------- /cookies_sessions/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var bcrypt = require("bcrypt"); 3 | 4 | var userSchema = new mongoose.Schema({ 5 | username: { 6 | type: String, 7 | // usernames should always be required 8 | required: true, 9 | // and most importantly unique! We will need to be able to uniquely 10 | // identify a user when we discuss logging in 11 | unique: true 12 | }, 13 | password: { 14 | type: String, 15 | // passwords do not have to be unique, but we really need them to exist 16 | required: true 17 | } 18 | }); 19 | 20 | // the callback function (2nd parameter below) accepts a parameter which we are calling "next". This is ALSO a callback function that needs to be executed when we would like to move on from this pre-save hook. If we do not invoke the "next" function, our server will hang. 21 | userSchema.pre('save', function(next){ 22 | // we do not want to lose the correct context of the keyword `this`, so let's cache it in a variable called user 23 | var user = this; 24 | // if the user's password has not been modified, do not continue with hashing their password....this is for updating a user. If a user does not update their password, do not create a new password hash! 25 | if (!user.isModified('password')) return next(); 26 | 27 | // if the user has modified their password, let's hash it 28 | bcrypt.hash(user.password, 10).then(function(hashedPassword) { 29 | // then let's set their password to not be the plain text one anymore, but the newly hashed password 30 | user.password = hashedPassword 31 | // then we save the user in the db! 32 | next(); 33 | }, function(err){ 34 | // or we continue and pass in an error that has happened (which our express error handler will catch) 35 | return next(err) 36 | }) 37 | }); 38 | 39 | // now let's write an instance method for all of our user documents which will be used to compare a plain text password with a hashed password in the database. Notice the second parameter to this function is a callback function called "next". Just like the code above, we need to run next() to move on. 40 | userSchema.methods.comparePassword = function(candidatePassword, next) { 41 | // when this method is called, compare the plain text password with the password in the database. 42 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { 43 | if(err) return next(err); 44 | // isMatch is a boolean which we will pass to our next function 45 | next(null, isMatch); 46 | }); 47 | }; 48 | 49 | var User = mongoose.model('User', userSchema); 50 | module.exports = User; -------------------------------------------------------------------------------- /passport_local/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var bcrypt = require("bcrypt"); 3 | 4 | var userSchema = new mongoose.Schema({ 5 | username: { 6 | type: String, 7 | // usernames should always be required 8 | required: true, 9 | // and most importantly unique! We will need to be able to uniquely 10 | // identify a user when we discuss logging in 11 | unique: true 12 | }, 13 | password: { 14 | type: String, 15 | // passwords do not have to be unique, but we really need them to exist 16 | required: true 17 | } 18 | }); 19 | 20 | // the callback function (2nd parameter below) accepts a parameter which we are calling "next". This is ALSO a callback function that needs to be executed when we would like to move on from this pre-save hook. If we do not invoke the "next" function, our server will hang. 21 | userSchema.pre('save', function(next){ 22 | // we do not want to lose the correct context of the keyword `this`, so let's cache it in a variable called user 23 | var user = this; 24 | // if the user's password has not been modified, do not continue with hashing their password....this is for updating a user. If a user does not update their password, do not create a new password hash! 25 | if (!user.isModified('password')) return next(); 26 | 27 | // if the user has modified their password, let's hash it 28 | bcrypt.hash(user.password, 10).then(function(hashedPassword) { 29 | // then let's set their password to not be the plain text one anymore, but the newly hashed password 30 | user.password = hashedPassword 31 | // then we save the user in the db! 32 | next(); 33 | }, function(err){ 34 | // or we continue and pass in an error that has happened (which our express error handler will catch) 35 | return next(err) 36 | }) 37 | }); 38 | 39 | // now let's write an instance method for all of our user documents which will be used to compare a plain text password with a hashed password in the database. Notice the second parameter to this function is a callback function called "next". Just like the code above, we need to run next() to move on. 40 | userSchema.methods.comparePassword = function(candidatePassword, next) { 41 | // when this method is called, compare the plain text password with the password in the database. 42 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { 43 | if(err) return next(err); 44 | // isMatch is a boolean which we will pass to our next function 45 | next(null, isMatch); 46 | }); 47 | }; 48 | 49 | var User = mongoose.model('User', userSchema); 50 | module.exports = User; -------------------------------------------------------------------------------- /cookies_sessions_auth/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var bcrypt = require("bcrypt"); 3 | 4 | var userSchema = new mongoose.Schema({ 5 | username: { 6 | type: String, 7 | // usernames should always be required 8 | required: true, 9 | // and most importantly unique! We will need to be able to uniquely 10 | // identify a user when we discuss logging in 11 | unique: true 12 | }, 13 | password: { 14 | type: String, 15 | // passwords do not have to be unique, but we really need them to exist 16 | required: true 17 | } 18 | }); 19 | 20 | // the callback function (2nd parameter below) accepts a parameter which we are calling "next". This is ALSO a callback function that needs to be executed when we would like to move on from this pre-save hook. If we do not invoke the "next" function, our server will hang. 21 | userSchema.pre('save', function(next){ 22 | // we do not want to lose the correct context of the keyword `this`, so let's cache it in a variable called user 23 | var user = this; 24 | // if the user's password has not been modified, do not continue with hashing their password....this is for updating a user. If a user does not update their password, do not create a new password hash! 25 | if (!user.isModified('password')) return next(); 26 | 27 | // if the user has modified their password, let's hash it 28 | bcrypt.hash(user.password, 10).then(function(hashedPassword) { 29 | // then let's set their password to not be the plain text one anymore, but the newly hashed password 30 | user.password = hashedPassword 31 | // then we save the user in the db! 32 | next(); 33 | }, function(err){ 34 | // or we continue and pass in an error that has happened (which our express error handler will catch) 35 | return next(err) 36 | }) 37 | }); 38 | 39 | // now let's write an instance method for all of our user documents which will be used to compare a plain text password with a hashed password in the database. Notice the second parameter to this function is a callback function called "next". Just like the code above, we need to run next() to move on. 40 | userSchema.methods.comparePassword = function(candidatePassword, next) { 41 | // when this method is called, compare the plain text password with the password in the database. 42 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { 43 | if(err) return next(err); 44 | // isMatch is a boolean which we will pass to our next function 45 | next(null, isMatch); 46 | }); 47 | }; 48 | 49 | var User = mongoose.model('User', userSchema); 50 | module.exports = User; -------------------------------------------------------------------------------- /password_hashing_bcrypt/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var bcrypt = require("bcrypt"); 3 | 4 | var userSchema = new mongoose.Schema({ 5 | username: { 6 | type: String, 7 | // usernames should always be required 8 | required: true, 9 | // and most importantly unique! We will need to be able to uniquely 10 | // identify a user when we discuss logging in 11 | unique: true 12 | }, 13 | password: { 14 | type: String, 15 | // passwords do not have to be unique, but we really need them to exist 16 | required: true 17 | } 18 | }); 19 | 20 | // the callback function (2nd parameter below) accepts a parameter which we are calling "next". This is ALSO a callback function that needs to be executed when we would like to move on from this pre-save hook. If we do not invoke the "next" function, our server will hang. 21 | userSchema.pre('save', function(next){ 22 | // we do not want to lose the correct context of the keyword `this`, so let's cache it in a variable called user 23 | var user = this; 24 | // if the user's password has not been modified, do not continue with hashing their password....this is for updating a user. If a user does not update their password, do not create a new password hash! 25 | if (!user.isModified('password')) return next(); 26 | 27 | // if the user has modified their password, let's hash it 28 | bcrypt.hash(user.password, 10).then(function(hashedPassword) { 29 | // then let's set their password to not be the plain text one anymore, but the newly hashed password 30 | user.password = hashedPassword 31 | // then we save the user in the db! 32 | next(); 33 | }, function(err){ 34 | // or we continue and pass in an error that has happened (which our express error handler will catch) 35 | return next(err) 36 | }) 37 | }); 38 | 39 | // now let's write an instance method for all of our user documents which will be used to compare a plain text password with a hashed password in the database. Notice the second parameter to this function is a callback function called "next". Just like the code above, we need to run next() to move on. 40 | userSchema.methods.comparePassword = function(candidatePassword, next) { 41 | // when this method is called, compare the plain text password with the password in the database. 42 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { 43 | if(err) return next(err); 44 | // isMatch is a boolean which we will pass to our next function 45 | next(null, isMatch); 46 | }); 47 | }; 48 | 49 | var User = mongoose.model('User', userSchema); 50 | module.exports = User; -------------------------------------------------------------------------------- /testing_json_apis/test/userRoutesSpec.js: -------------------------------------------------------------------------------- 1 | const request = require('supertest'); 2 | const app = require('../app') 3 | 4 | var expect = require("chai").expect 5 | 6 | var mongoose = require("mongoose"); 7 | mongoose.Promise = Promise 8 | var db = require('../models/') 9 | var token; 10 | 11 | var auth = {}; 12 | 13 | function loginUser(auth) { 14 | return function(done) { 15 | request(app) 16 | .post('/api/auth/login') 17 | .send({ 18 | username: 'test', 19 | password: 'secret' 20 | }) 21 | .expect(200) 22 | .end(onResponse); 23 | 24 | function onResponse(err, res) { 25 | auth.token = res.body.token; 26 | return done(); 27 | } 28 | }; 29 | } 30 | 31 | beforeEach(function(done){ 32 | db.User.create({username:'test', password:'secret'}).then(function(user) { 33 | auth.current_user = user 34 | done(); 35 | }); 36 | }); 37 | 38 | beforeEach(loginUser(auth)); 39 | 40 | afterEach(function(done){ 41 | db.User.remove({}).then(function() { 42 | done(); 43 | }); 44 | }); 45 | 46 | describe('POST /auth/signup', function() { 47 | it('responds with JSON when created', function(done) { 48 | request(app) 49 | .post('/api/auth/signup') 50 | .send({username: 'elie', password:'secret'}) 51 | .set('Accept', 'application/json') 52 | .expect(201, done); 53 | }); 54 | }); 55 | describe('POST /auth/login', function() { 56 | it('responds with JSON', function(done) { 57 | request(app) 58 | .post('/api/auth/login') 59 | .send({username: 'test', password:'secret'}) 60 | .set('Accept', 'application/json') 61 | .expect(200, done); 62 | }); 63 | }); 64 | 65 | describe('GET /users', function() { 66 | it('responds with JSON', function(done) { 67 | request(app) 68 | .get('/api/users') 69 | .set('Authorization', 'bearer: ' + auth.token) 70 | .expect(200, done); 71 | }); 72 | }); 73 | 74 | describe('GET /users/:id', function() { 75 | it('responds with JSON', function(done) { 76 | request(app) 77 | .get(`/api/users/${auth.current_user.id}`) 78 | .set('Authorization', 'bearer: ' + auth.token) 79 | .expect(200, done); 80 | }); 81 | }); 82 | 83 | describe('PATCH /users/:id', function() { 84 | it('responds with JSON', function(done) { 85 | request(app) 86 | .patch(`/api/users/${auth.current_user.id}`) 87 | .send({ 88 | username:'bob' 89 | }) 90 | .set('Authorization', 'bearer: ' + auth.token) 91 | .expect(200, done); 92 | }); 93 | }); 94 | 95 | describe('DELETE /users/:id', function() { 96 | it('responds with JSON', function(done) { 97 | request(app) 98 | .delete(`/api/users/${auth.current_user.id}`) 99 | .set('Authorization', 'bearer: ' + auth.token) 100 | .expect(204, done); 101 | }); 102 | }); 103 | 104 | 105 | -------------------------------------------------------------------------------- /passport_oauth/app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').load(); 2 | var express = require("express") 3 | var app = express() 4 | var methodOverride = require("method-override") 5 | var morgan = require("morgan") 6 | var bodyParser = require("body-parser"); 7 | var session = require("cookie-session"); 8 | var flash = require("connect-flash") 9 | var passport = require("passport"); 10 | var db = require("./models"); 11 | var FacebookStrategy = require('passport-facebook').Strategy; 12 | 13 | 14 | app.set("view engine", "pug"); 15 | 16 | app.use(express.static(__dirname + "/public")); 17 | app.use(morgan("tiny")) 18 | app.use(bodyParser.urlencoded({extended:true})); 19 | app.use(methodOverride("_method")); 20 | app.use(session({secret:process.env.SECRET_KEY})) 21 | 22 | app.use(passport.initialize()); 23 | app.use(passport.session()); 24 | app.use(flash()); 25 | 26 | function loginRequired(req,res,next){ 27 | if(req.isUnauthenticated()){ 28 | res.redirect('/') 29 | } else { 30 | next() 31 | } 32 | } 33 | 34 | app.get("/", function(req,res){ 35 | res.send('Go to /auth/facebook') 36 | }); 37 | 38 | app.get("/welcome", loginRequired, function(req,res){ 39 | res.send('Logged In!') 40 | }); 41 | 42 | app.get('/auth/facebook', passport.authenticate('facebook')); 43 | 44 | // Facebook will redirect the user to this URL after approval. Finish the 45 | // authentication process by attempting to obtain an access token. If 46 | // access was granted, the user will be logged in. Otherwise, 47 | // authentication has failed. 48 | app.get('/auth/facebook/callback', 49 | passport.authenticate('facebook', { successRedirect: '/welcome', 50 | failureRedirect: '/login' })); 51 | 52 | 53 | // send flash messages to all routes 54 | app.use(function(req, res, next){ 55 | res.locals.message = req.flash('message'); 56 | next(); 57 | }); 58 | 59 | passport.use(new FacebookStrategy({ 60 | // these should ALL be values coming from a .env file 61 | clientID: process.env.FACEBOOK_APP_ID, 62 | clientSecret: process.env.FACEBOOK_APP_SECRET, 63 | // when you deploy your application you can add an environment variable for CALLBACK_URL, right now let's stick with localhost:3000/auth/facebook/callback 64 | callbackURL: process.env.CALLBACK_URL || "http://localhost:3000/auth/facebook/callback" 65 | }, 66 | // in the verify callback we will get an accessToken to make authenticated requests on the users behalf along with a refreshToken which is used in some authentication strategies to refresh an expired accessToken. We also are given an object called "profile" which has data on the authenticated user 67 | function(accessToken, refreshToken, profile, done) { 68 | db.User.findOrCreate({facebook_id: profile.id}, function(err,user) { 69 | if(err) return done(err) 70 | done(null, user); 71 | }); 72 | } 73 | )); 74 | 75 | passport.serializeUser(function(user, done) { 76 | done(null, user.id); 77 | }); 78 | 79 | passport.deserializeUser(function(id, done) { 80 | db.User.findById(id, function(err, user) { 81 | done(err, user); 82 | }); 83 | }); 84 | 85 | 86 | app.get('/logout', function(req,res){ 87 | req.logout() 88 | req.flash('message', 'logged out!') 89 | res.send('logged out!') 90 | }) 91 | 92 | app.listen(3000, function(){ 93 | console.log("Server is listening on port 3000"); 94 | }); 95 | -------------------------------------------------------------------------------- /passport_local/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var router = express.Router(); 3 | var db = require("../models"); 4 | var authMiddleware = require("../middleware/auth") 5 | var passport = require('passport') 6 | var LocalStrategy = require('passport-local').Strategy; 7 | 8 | passport.use(new LocalStrategy( 9 | // the first parameter is an optional object with options 10 | { 11 | // when using the local strategy you MUST name your keys usernameField and passwordField. By default they will have values of "username" and "password", but if you are using something like an email instead of a username or have different name attribute values in your form, modifying the optional object is essential for authentication to work. 12 | usernameField: 'username', 13 | passwordField: 'password', 14 | // by default this option is set to false, but when specified to true, the first parameter of the verify callback will be the request object. This is quite useful if you want to see if your application has multiple strategies and you want to see if a user is already logged in with an existing strategy, if they are you can simply associate the new strategy with them (eg. they have put in their username/password, but then try to authenticate again through twitter) 15 | passReqToCallback: true, 16 | }, 17 | // the second parameter to the constructor function is known as the verify callback. Since we have set passReqToCallback as true, the first parameter is the request object. The second parameter is the username which comes from user entered data in a form, the third second parameter is the plain text password which comes from user entered data in a form. The fourth parameter is a callback function that will be invoked depending on the result of the verify callback. 18 | function verifyCallback(req, username, password, done) { 19 | // find a user in the database based on their username 20 | db.User.findOne({ username: username }, function (err, user) { 21 | // if there is an error with the DB connection (NOT related to finding the user successfully or not, return the callback with the error) 22 | if (err) return done(err); 23 | // if the user is not found in the database or if the password is not valid, do not return an error (set the first parameter to the done callback as null), but do set the second parameter to be false so that the failureRedirect will be reached. 24 | 25 | // validPassword is a method WE have to create for every object created from our Mongoose model (we call these instance methods or "methods" in Mongoose) 26 | if (!user) { 27 | return done(null, false); 28 | } 29 | user.comparePassword(password, function(err,isMatch){ 30 | if(isMatch){ 31 | return done(null, user); 32 | } else { 33 | return done(null, false); 34 | } 35 | }) 36 | // if the user has put in the correct username and password, move onto the next step and serialize! Pass into the serialization function as the first parameter the user who was successfull found (we will need it's id to store in the session and cookie) 37 | 38 | }); 39 | } 40 | )); 41 | 42 | // this code is ONLY run if the verify callback returns the done callback with no errors and a truthy value as the second parameter. This code only runs once per session and runs a callback function which we can assume will not have any errors (null as the first parameter) and the data we want to put in the session (only the user.id). The successCallback is run next! 43 | passport.serializeUser(function(user, done) { 44 | done(null, user.id); 45 | }); 46 | 47 | // once a user has been authenticated and serialized, we now find that user in the database on every request. This allows passport to have some useful methods on the request object like req.user (the current user logged in) and req.isAuthenticated() (returns true if the user is logged in or false if not) 48 | passport.deserializeUser(function(id, done) { 49 | db.User.findById(id).then(function(user) { 50 | done(null, user); 51 | }); 52 | }); 53 | 54 | router.get('/', authMiddleware.loginRequired, function(req,res){ 55 | res.render('index') 56 | }); 57 | 58 | router.get('/login', function(req,res){ 59 | res.render('login') 60 | }); 61 | 62 | router.get('/signup', function(req,res){ 63 | res.render('new') 64 | }); 65 | 66 | router.post('/login', 67 | passport.authenticate('local', { successRedirect: '/users', 68 | failureRedirect: '/users/login'})); 69 | 70 | 71 | router.post('/signup', function(req,res){ 72 | db.User.create(req.body).then(function(user){ 73 | req.logIn(user, function(err) { 74 | return res.redirect(`/users`); 75 | }); 76 | }, function(err){ 77 | return next(err); 78 | }); 79 | }); 80 | 81 | router.get('/logout', function(req,res){ 82 | req.logout() 83 | req.flash('message', 'logged out!') 84 | res.redirect('/users/login') 85 | }) 86 | 87 | module.exports = router; -------------------------------------------------------------------------------- /express_forms/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_forms", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.4", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", 10 | "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", 11 | "requires": { 12 | "mime-types": "2.1.17", 13 | "negotiator": "0.6.1" 14 | } 15 | }, 16 | "acorn": { 17 | "version": "3.3.0", 18 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 19 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" 20 | }, 21 | "acorn-globals": { 22 | "version": "3.1.0", 23 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", 24 | "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", 25 | "requires": { 26 | "acorn": "4.0.13" 27 | }, 28 | "dependencies": { 29 | "acorn": { 30 | "version": "4.0.13", 31 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 32 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" 33 | } 34 | } 35 | }, 36 | "align-text": { 37 | "version": "0.1.4", 38 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 39 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 40 | "requires": { 41 | "kind-of": "3.2.2", 42 | "longest": "1.0.1", 43 | "repeat-string": "1.6.1" 44 | } 45 | }, 46 | "amdefine": { 47 | "version": "1.0.1", 48 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 49 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" 50 | }, 51 | "array-flatten": { 52 | "version": "1.1.1", 53 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 54 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 55 | }, 56 | "asap": { 57 | "version": "2.0.6", 58 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 59 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 60 | }, 61 | "body-parser": { 62 | "version": "1.18.2", 63 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", 64 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", 65 | "requires": { 66 | "bytes": "3.0.0", 67 | "content-type": "1.0.4", 68 | "debug": "2.6.9", 69 | "depd": "1.1.1", 70 | "http-errors": "1.6.2", 71 | "iconv-lite": "0.4.19", 72 | "on-finished": "2.3.0", 73 | "qs": "6.5.1", 74 | "raw-body": "2.3.2", 75 | "type-is": "1.6.15" 76 | } 77 | }, 78 | "bytes": { 79 | "version": "3.0.0", 80 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 81 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 82 | }, 83 | "camelcase": { 84 | "version": "1.2.1", 85 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 86 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" 87 | }, 88 | "center-align": { 89 | "version": "0.1.3", 90 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 91 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 92 | "requires": { 93 | "align-text": "0.1.4", 94 | "lazy-cache": "1.0.4" 95 | } 96 | }, 97 | "character-parser": { 98 | "version": "2.2.0", 99 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", 100 | "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", 101 | "requires": { 102 | "is-regex": "1.0.4" 103 | } 104 | }, 105 | "clean-css": { 106 | "version": "3.4.28", 107 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", 108 | "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", 109 | "requires": { 110 | "commander": "2.8.1", 111 | "source-map": "0.4.4" 112 | } 113 | }, 114 | "cliui": { 115 | "version": "2.1.0", 116 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 117 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 118 | "requires": { 119 | "center-align": "0.1.3", 120 | "right-align": "0.1.3", 121 | "wordwrap": "0.0.2" 122 | } 123 | }, 124 | "commander": { 125 | "version": "2.8.1", 126 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", 127 | "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", 128 | "requires": { 129 | "graceful-readlink": "1.0.1" 130 | } 131 | }, 132 | "constantinople": { 133 | "version": "3.1.0", 134 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz", 135 | "integrity": "sha1-dWnKqKo/jVk11i4fqW+fcCzYHHk=", 136 | "requires": { 137 | "acorn": "3.3.0", 138 | "is-expression": "2.1.0" 139 | } 140 | }, 141 | "content-disposition": { 142 | "version": "0.5.2", 143 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 144 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 145 | }, 146 | "content-type": { 147 | "version": "1.0.4", 148 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 149 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 150 | }, 151 | "cookie": { 152 | "version": "0.3.1", 153 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 154 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 155 | }, 156 | "cookie-signature": { 157 | "version": "1.0.6", 158 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 159 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 160 | }, 161 | "debug": { 162 | "version": "2.6.9", 163 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 164 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 165 | "requires": { 166 | "ms": "2.0.0" 167 | } 168 | }, 169 | "decamelize": { 170 | "version": "1.2.0", 171 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 172 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 173 | }, 174 | "depd": { 175 | "version": "1.1.1", 176 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 177 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 178 | }, 179 | "destroy": { 180 | "version": "1.0.4", 181 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 182 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 183 | }, 184 | "doctypes": { 185 | "version": "1.1.0", 186 | "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", 187 | "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" 188 | }, 189 | "ee-first": { 190 | "version": "1.1.1", 191 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 192 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 193 | }, 194 | "encodeurl": { 195 | "version": "1.0.1", 196 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", 197 | "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" 198 | }, 199 | "escape-html": { 200 | "version": "1.0.3", 201 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 202 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 203 | }, 204 | "etag": { 205 | "version": "1.8.1", 206 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 207 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 208 | }, 209 | "express": { 210 | "version": "4.16.2", 211 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", 212 | "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", 213 | "requires": { 214 | "accepts": "1.3.4", 215 | "array-flatten": "1.1.1", 216 | "body-parser": "1.18.2", 217 | "content-disposition": "0.5.2", 218 | "content-type": "1.0.4", 219 | "cookie": "0.3.1", 220 | "cookie-signature": "1.0.6", 221 | "debug": "2.6.9", 222 | "depd": "1.1.1", 223 | "encodeurl": "1.0.1", 224 | "escape-html": "1.0.3", 225 | "etag": "1.8.1", 226 | "finalhandler": "1.1.0", 227 | "fresh": "0.5.2", 228 | "merge-descriptors": "1.0.1", 229 | "methods": "1.1.2", 230 | "on-finished": "2.3.0", 231 | "parseurl": "1.3.2", 232 | "path-to-regexp": "0.1.7", 233 | "proxy-addr": "2.0.2", 234 | "qs": "6.5.1", 235 | "range-parser": "1.2.0", 236 | "safe-buffer": "5.1.1", 237 | "send": "0.16.1", 238 | "serve-static": "1.13.1", 239 | "setprototypeof": "1.1.0", 240 | "statuses": "1.3.1", 241 | "type-is": "1.6.15", 242 | "utils-merge": "1.0.1", 243 | "vary": "1.1.2" 244 | }, 245 | "dependencies": { 246 | "setprototypeof": { 247 | "version": "1.1.0", 248 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 249 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 250 | }, 251 | "statuses": { 252 | "version": "1.3.1", 253 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 254 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 255 | } 256 | } 257 | }, 258 | "finalhandler": { 259 | "version": "1.1.0", 260 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", 261 | "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", 262 | "requires": { 263 | "debug": "2.6.9", 264 | "encodeurl": "1.0.1", 265 | "escape-html": "1.0.3", 266 | "on-finished": "2.3.0", 267 | "parseurl": "1.3.2", 268 | "statuses": "1.3.1", 269 | "unpipe": "1.0.0" 270 | }, 271 | "dependencies": { 272 | "statuses": { 273 | "version": "1.3.1", 274 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 275 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 276 | } 277 | } 278 | }, 279 | "forwarded": { 280 | "version": "0.1.2", 281 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 282 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 283 | }, 284 | "fresh": { 285 | "version": "0.5.2", 286 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 287 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 288 | }, 289 | "function-bind": { 290 | "version": "1.1.1", 291 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 292 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 293 | }, 294 | "graceful-readlink": { 295 | "version": "1.0.1", 296 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 297 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" 298 | }, 299 | "has": { 300 | "version": "1.0.1", 301 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", 302 | "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", 303 | "requires": { 304 | "function-bind": "1.1.1" 305 | } 306 | }, 307 | "http-errors": { 308 | "version": "1.6.2", 309 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 310 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 311 | "requires": { 312 | "depd": "1.1.1", 313 | "inherits": "2.0.3", 314 | "setprototypeof": "1.0.3", 315 | "statuses": "1.4.0" 316 | } 317 | }, 318 | "iconv-lite": { 319 | "version": "0.4.19", 320 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 321 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 322 | }, 323 | "inherits": { 324 | "version": "2.0.3", 325 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 326 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 327 | }, 328 | "ipaddr.js": { 329 | "version": "1.5.2", 330 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", 331 | "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" 332 | }, 333 | "is-buffer": { 334 | "version": "1.1.6", 335 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 336 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 337 | }, 338 | "is-expression": { 339 | "version": "2.1.0", 340 | "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-2.1.0.tgz", 341 | "integrity": "sha1-kb6dR968/vB3l36XIr5tz7RGXvA=", 342 | "requires": { 343 | "acorn": "3.3.0", 344 | "object-assign": "4.1.1" 345 | } 346 | }, 347 | "is-promise": { 348 | "version": "2.1.0", 349 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 350 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 351 | }, 352 | "is-regex": { 353 | "version": "1.0.4", 354 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 355 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 356 | "requires": { 357 | "has": "1.0.1" 358 | } 359 | }, 360 | "js-stringify": { 361 | "version": "1.0.2", 362 | "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", 363 | "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" 364 | }, 365 | "jstransformer": { 366 | "version": "1.0.0", 367 | "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", 368 | "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", 369 | "requires": { 370 | "is-promise": "2.1.0", 371 | "promise": "7.3.1" 372 | } 373 | }, 374 | "kind-of": { 375 | "version": "3.2.2", 376 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 377 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 378 | "requires": { 379 | "is-buffer": "1.1.6" 380 | } 381 | }, 382 | "lazy-cache": { 383 | "version": "1.0.4", 384 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 385 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" 386 | }, 387 | "longest": { 388 | "version": "1.0.1", 389 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 390 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" 391 | }, 392 | "media-typer": { 393 | "version": "0.3.0", 394 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 395 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 396 | }, 397 | "merge-descriptors": { 398 | "version": "1.0.1", 399 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 400 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 401 | }, 402 | "methods": { 403 | "version": "1.1.2", 404 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 405 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 406 | }, 407 | "mime": { 408 | "version": "1.4.1", 409 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 410 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 411 | }, 412 | "mime-db": { 413 | "version": "1.30.0", 414 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 415 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" 416 | }, 417 | "mime-types": { 418 | "version": "2.1.17", 419 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 420 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 421 | "requires": { 422 | "mime-db": "1.30.0" 423 | } 424 | }, 425 | "ms": { 426 | "version": "2.0.0", 427 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 428 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 429 | }, 430 | "negotiator": { 431 | "version": "0.6.1", 432 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 433 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 434 | }, 435 | "object-assign": { 436 | "version": "4.1.1", 437 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 438 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 439 | }, 440 | "on-finished": { 441 | "version": "2.3.0", 442 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 443 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 444 | "requires": { 445 | "ee-first": "1.1.1" 446 | } 447 | }, 448 | "parseurl": { 449 | "version": "1.3.2", 450 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 451 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 452 | }, 453 | "path-parse": { 454 | "version": "1.0.5", 455 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", 456 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" 457 | }, 458 | "path-to-regexp": { 459 | "version": "0.1.7", 460 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 461 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 462 | }, 463 | "promise": { 464 | "version": "7.3.1", 465 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", 466 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", 467 | "requires": { 468 | "asap": "2.0.6" 469 | } 470 | }, 471 | "proxy-addr": { 472 | "version": "2.0.2", 473 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", 474 | "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", 475 | "requires": { 476 | "forwarded": "0.1.2", 477 | "ipaddr.js": "1.5.2" 478 | } 479 | }, 480 | "pug": { 481 | "version": "2.0.0-rc.4", 482 | "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0-rc.4.tgz", 483 | "integrity": "sha512-SL7xovj6E2Loq9N0UgV6ynjMLW4urTFY/L/Fprhvz13Xc5vjzkjZjI1QHKq31200+6PSD8PyU6MqrtCTJj6/XA==", 484 | "requires": { 485 | "pug-code-gen": "2.0.0", 486 | "pug-filters": "2.1.5", 487 | "pug-lexer": "3.1.0", 488 | "pug-linker": "3.0.3", 489 | "pug-load": "2.0.9", 490 | "pug-parser": "4.0.0", 491 | "pug-runtime": "2.0.3", 492 | "pug-strip-comments": "1.0.2" 493 | } 494 | }, 495 | "pug-attrs": { 496 | "version": "2.0.2", 497 | "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.2.tgz", 498 | "integrity": "sha1-i+KyIlVo/6ddG4Zpgr/59BEa/8s=", 499 | "requires": { 500 | "constantinople": "3.1.0", 501 | "js-stringify": "1.0.2", 502 | "pug-runtime": "2.0.3" 503 | } 504 | }, 505 | "pug-code-gen": { 506 | "version": "2.0.0", 507 | "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.0.tgz", 508 | "integrity": "sha512-E4oiJT+Jn5tyEIloj8dIJQognbiNNp0i0cAJmYtQTFS0soJ917nlIuFtqVss3IXMEyQKUew3F4gIkBpn18KbVg==", 509 | "requires": { 510 | "constantinople": "3.1.0", 511 | "doctypes": "1.1.0", 512 | "js-stringify": "1.0.2", 513 | "pug-attrs": "2.0.2", 514 | "pug-error": "1.3.2", 515 | "pug-runtime": "2.0.3", 516 | "void-elements": "2.0.1", 517 | "with": "5.1.1" 518 | } 519 | }, 520 | "pug-error": { 521 | "version": "1.3.2", 522 | "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.2.tgz", 523 | "integrity": "sha1-U659nSm7A89WRJOgJhCfVMR/XyY=" 524 | }, 525 | "pug-filters": { 526 | "version": "2.1.5", 527 | "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-2.1.5.tgz", 528 | "integrity": "sha512-xkw71KtrC4sxleKiq+cUlQzsiLn8pM5+vCgkChW2E6oNOzaqTSIBKIQ5cl4oheuDzvJYCTSYzRaVinMUrV4YLQ==", 529 | "requires": { 530 | "clean-css": "3.4.28", 531 | "constantinople": "3.1.0", 532 | "jstransformer": "1.0.0", 533 | "pug-error": "1.3.2", 534 | "pug-walk": "1.1.5", 535 | "resolve": "1.5.0", 536 | "uglify-js": "2.8.29" 537 | } 538 | }, 539 | "pug-lexer": { 540 | "version": "3.1.0", 541 | "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-3.1.0.tgz", 542 | "integrity": "sha1-/QhzdtSmdbT1n4/vQiiDQ06VgaI=", 543 | "requires": { 544 | "character-parser": "2.2.0", 545 | "is-expression": "3.0.0", 546 | "pug-error": "1.3.2" 547 | }, 548 | "dependencies": { 549 | "acorn": { 550 | "version": "4.0.13", 551 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 552 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" 553 | }, 554 | "is-expression": { 555 | "version": "3.0.0", 556 | "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", 557 | "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", 558 | "requires": { 559 | "acorn": "4.0.13", 560 | "object-assign": "4.1.1" 561 | } 562 | } 563 | } 564 | }, 565 | "pug-linker": { 566 | "version": "3.0.3", 567 | "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.3.tgz", 568 | "integrity": "sha512-DCKczglCXOzJ1lr4xUj/lVHYvS+lGmR2+KTCjZjtIpdwaN7lNOoX2SW6KFX5X4ElvW+6ThwB+acSUg08UJFN5A==", 569 | "requires": { 570 | "pug-error": "1.3.2", 571 | "pug-walk": "1.1.5" 572 | } 573 | }, 574 | "pug-load": { 575 | "version": "2.0.9", 576 | "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.9.tgz", 577 | "integrity": "sha512-BDdZOCru4mg+1MiZwRQZh25+NTRo/R6/qArrdWIf308rHtWA5N9kpoUskRe4H6FslaQujC+DigH9LqlBA4gf6Q==", 578 | "requires": { 579 | "object-assign": "4.1.1", 580 | "pug-walk": "1.1.5" 581 | } 582 | }, 583 | "pug-parser": { 584 | "version": "4.0.0", 585 | "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-4.0.0.tgz", 586 | "integrity": "sha512-ocEUFPdLG9awwFj0sqi1uiZLNvfoodCMULZzkRqILryIWc/UUlDlxqrKhKjAIIGPX/1SNsvxy63+ayEGocGhQg==", 587 | "requires": { 588 | "pug-error": "1.3.2", 589 | "token-stream": "0.0.1" 590 | } 591 | }, 592 | "pug-runtime": { 593 | "version": "2.0.3", 594 | "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.3.tgz", 595 | "integrity": "sha1-mBYmB7D86eJU1CfzOYelrucWi9o=" 596 | }, 597 | "pug-strip-comments": { 598 | "version": "1.0.2", 599 | "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.2.tgz", 600 | "integrity": "sha1-0xOvoBvMN0mA4TmeI+vy65vchRM=", 601 | "requires": { 602 | "pug-error": "1.3.2" 603 | } 604 | }, 605 | "pug-walk": { 606 | "version": "1.1.5", 607 | "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.5.tgz", 608 | "integrity": "sha512-rJlH1lXerCIAtImXBze3dtKq/ykZMA4rpO9FnPcIgsWcxZLOvd8zltaoeOVFyBSSqCkhhJWbEbTMga8UxWUUSA==" 609 | }, 610 | "qs": { 611 | "version": "6.5.1", 612 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 613 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" 614 | }, 615 | "range-parser": { 616 | "version": "1.2.0", 617 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 618 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 619 | }, 620 | "raw-body": { 621 | "version": "2.3.2", 622 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 623 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 624 | "requires": { 625 | "bytes": "3.0.0", 626 | "http-errors": "1.6.2", 627 | "iconv-lite": "0.4.19", 628 | "unpipe": "1.0.0" 629 | } 630 | }, 631 | "repeat-string": { 632 | "version": "1.6.1", 633 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 634 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 635 | }, 636 | "resolve": { 637 | "version": "1.5.0", 638 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", 639 | "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", 640 | "requires": { 641 | "path-parse": "1.0.5" 642 | } 643 | }, 644 | "right-align": { 645 | "version": "0.1.3", 646 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 647 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 648 | "requires": { 649 | "align-text": "0.1.4" 650 | } 651 | }, 652 | "safe-buffer": { 653 | "version": "5.1.1", 654 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 655 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 656 | }, 657 | "send": { 658 | "version": "0.16.1", 659 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", 660 | "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", 661 | "requires": { 662 | "debug": "2.6.9", 663 | "depd": "1.1.1", 664 | "destroy": "1.0.4", 665 | "encodeurl": "1.0.1", 666 | "escape-html": "1.0.3", 667 | "etag": "1.8.1", 668 | "fresh": "0.5.2", 669 | "http-errors": "1.6.2", 670 | "mime": "1.4.1", 671 | "ms": "2.0.0", 672 | "on-finished": "2.3.0", 673 | "range-parser": "1.2.0", 674 | "statuses": "1.3.1" 675 | }, 676 | "dependencies": { 677 | "statuses": { 678 | "version": "1.3.1", 679 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 680 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 681 | } 682 | } 683 | }, 684 | "serve-static": { 685 | "version": "1.13.1", 686 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", 687 | "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", 688 | "requires": { 689 | "encodeurl": "1.0.1", 690 | "escape-html": "1.0.3", 691 | "parseurl": "1.3.2", 692 | "send": "0.16.1" 693 | } 694 | }, 695 | "setprototypeof": { 696 | "version": "1.0.3", 697 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 698 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 699 | }, 700 | "source-map": { 701 | "version": "0.4.4", 702 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 703 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 704 | "requires": { 705 | "amdefine": "1.0.1" 706 | } 707 | }, 708 | "statuses": { 709 | "version": "1.4.0", 710 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 711 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 712 | }, 713 | "token-stream": { 714 | "version": "0.0.1", 715 | "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", 716 | "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" 717 | }, 718 | "type-is": { 719 | "version": "1.6.15", 720 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", 721 | "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", 722 | "requires": { 723 | "media-typer": "0.3.0", 724 | "mime-types": "2.1.17" 725 | } 726 | }, 727 | "uglify-js": { 728 | "version": "2.8.29", 729 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 730 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 731 | "requires": { 732 | "source-map": "0.5.7", 733 | "uglify-to-browserify": "1.0.2", 734 | "yargs": "3.10.0" 735 | }, 736 | "dependencies": { 737 | "source-map": { 738 | "version": "0.5.7", 739 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 740 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 741 | } 742 | } 743 | }, 744 | "uglify-to-browserify": { 745 | "version": "1.0.2", 746 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 747 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 748 | "optional": true 749 | }, 750 | "unpipe": { 751 | "version": "1.0.0", 752 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 753 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 754 | }, 755 | "utils-merge": { 756 | "version": "1.0.1", 757 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 758 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 759 | }, 760 | "vary": { 761 | "version": "1.1.2", 762 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 763 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 764 | }, 765 | "void-elements": { 766 | "version": "2.0.1", 767 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", 768 | "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" 769 | }, 770 | "window-size": { 771 | "version": "0.1.0", 772 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 773 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" 774 | }, 775 | "with": { 776 | "version": "5.1.1", 777 | "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", 778 | "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", 779 | "requires": { 780 | "acorn": "3.3.0", 781 | "acorn-globals": "3.1.0" 782 | } 783 | }, 784 | "wordwrap": { 785 | "version": "0.0.2", 786 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 787 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" 788 | }, 789 | "yargs": { 790 | "version": "3.10.0", 791 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 792 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 793 | "requires": { 794 | "camelcase": "1.2.1", 795 | "cliui": "2.1.0", 796 | "decamelize": "1.2.0", 797 | "window-size": "0.1.0" 798 | } 799 | } 800 | } 801 | } 802 | -------------------------------------------------------------------------------- /mongoose_crud/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_restful_routing", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.4", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", 10 | "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", 11 | "requires": { 12 | "mime-types": "2.1.17", 13 | "negotiator": "0.6.1" 14 | } 15 | }, 16 | "acorn": { 17 | "version": "3.3.0", 18 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 19 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" 20 | }, 21 | "acorn-globals": { 22 | "version": "3.1.0", 23 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", 24 | "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", 25 | "requires": { 26 | "acorn": "4.0.13" 27 | }, 28 | "dependencies": { 29 | "acorn": { 30 | "version": "4.0.13", 31 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 32 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" 33 | } 34 | } 35 | }, 36 | "align-text": { 37 | "version": "0.1.4", 38 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 39 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 40 | "requires": { 41 | "kind-of": "3.2.2", 42 | "longest": "1.0.1", 43 | "repeat-string": "1.6.1" 44 | } 45 | }, 46 | "amdefine": { 47 | "version": "1.0.1", 48 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 49 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" 50 | }, 51 | "array-flatten": { 52 | "version": "1.1.1", 53 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 54 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 55 | }, 56 | "asap": { 57 | "version": "2.0.6", 58 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 59 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 60 | }, 61 | "async": { 62 | "version": "2.1.4", 63 | "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", 64 | "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", 65 | "requires": { 66 | "lodash": "4.17.4" 67 | } 68 | }, 69 | "basic-auth": { 70 | "version": "2.0.0", 71 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", 72 | "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", 73 | "requires": { 74 | "safe-buffer": "5.1.1" 75 | } 76 | }, 77 | "bluebird": { 78 | "version": "3.5.0", 79 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", 80 | "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" 81 | }, 82 | "body-parser": { 83 | "version": "1.18.2", 84 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", 85 | "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", 86 | "requires": { 87 | "bytes": "3.0.0", 88 | "content-type": "1.0.4", 89 | "debug": "2.6.9", 90 | "depd": "1.1.1", 91 | "http-errors": "1.6.2", 92 | "iconv-lite": "0.4.19", 93 | "on-finished": "2.3.0", 94 | "qs": "6.5.1", 95 | "raw-body": "2.3.2", 96 | "type-is": "1.6.15" 97 | } 98 | }, 99 | "bson": { 100 | "version": "1.0.4", 101 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", 102 | "integrity": "sha1-k8ENOeqltYQVy8QFLz5T5WKwtyw=" 103 | }, 104 | "buffer-shims": { 105 | "version": "1.0.0", 106 | "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", 107 | "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" 108 | }, 109 | "bytes": { 110 | "version": "3.0.0", 111 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 112 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 113 | }, 114 | "camelcase": { 115 | "version": "1.2.1", 116 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 117 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" 118 | }, 119 | "center-align": { 120 | "version": "0.1.3", 121 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 122 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 123 | "requires": { 124 | "align-text": "0.1.4", 125 | "lazy-cache": "1.0.4" 126 | } 127 | }, 128 | "character-parser": { 129 | "version": "2.2.0", 130 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", 131 | "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", 132 | "requires": { 133 | "is-regex": "1.0.4" 134 | } 135 | }, 136 | "clean-css": { 137 | "version": "3.4.28", 138 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", 139 | "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", 140 | "requires": { 141 | "commander": "2.8.1", 142 | "source-map": "0.4.4" 143 | } 144 | }, 145 | "cliui": { 146 | "version": "2.1.0", 147 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 148 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 149 | "requires": { 150 | "center-align": "0.1.3", 151 | "right-align": "0.1.3", 152 | "wordwrap": "0.0.2" 153 | } 154 | }, 155 | "commander": { 156 | "version": "2.8.1", 157 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", 158 | "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", 159 | "requires": { 160 | "graceful-readlink": "1.0.1" 161 | } 162 | }, 163 | "constantinople": { 164 | "version": "3.1.0", 165 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.0.tgz", 166 | "integrity": "sha1-dWnKqKo/jVk11i4fqW+fcCzYHHk=", 167 | "requires": { 168 | "acorn": "3.3.0", 169 | "is-expression": "2.1.0" 170 | } 171 | }, 172 | "content-disposition": { 173 | "version": "0.5.2", 174 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 175 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 176 | }, 177 | "content-type": { 178 | "version": "1.0.4", 179 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 180 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 181 | }, 182 | "cookie": { 183 | "version": "0.3.1", 184 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 185 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 186 | }, 187 | "cookie-signature": { 188 | "version": "1.0.6", 189 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 190 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 191 | }, 192 | "core-util-is": { 193 | "version": "1.0.2", 194 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 195 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 196 | }, 197 | "debug": { 198 | "version": "2.6.9", 199 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 200 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 201 | "requires": { 202 | "ms": "2.0.0" 203 | } 204 | }, 205 | "decamelize": { 206 | "version": "1.2.0", 207 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 208 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 209 | }, 210 | "depd": { 211 | "version": "1.1.1", 212 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 213 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 214 | }, 215 | "destroy": { 216 | "version": "1.0.4", 217 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 218 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 219 | }, 220 | "doctypes": { 221 | "version": "1.1.0", 222 | "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", 223 | "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" 224 | }, 225 | "ee-first": { 226 | "version": "1.1.1", 227 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 228 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 229 | }, 230 | "encodeurl": { 231 | "version": "1.0.1", 232 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", 233 | "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" 234 | }, 235 | "es6-promise": { 236 | "version": "3.2.1", 237 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", 238 | "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" 239 | }, 240 | "escape-html": { 241 | "version": "1.0.3", 242 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 243 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 244 | }, 245 | "etag": { 246 | "version": "1.8.1", 247 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 248 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 249 | }, 250 | "express": { 251 | "version": "4.16.2", 252 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", 253 | "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", 254 | "requires": { 255 | "accepts": "1.3.4", 256 | "array-flatten": "1.1.1", 257 | "body-parser": "1.18.2", 258 | "content-disposition": "0.5.2", 259 | "content-type": "1.0.4", 260 | "cookie": "0.3.1", 261 | "cookie-signature": "1.0.6", 262 | "debug": "2.6.9", 263 | "depd": "1.1.1", 264 | "encodeurl": "1.0.1", 265 | "escape-html": "1.0.3", 266 | "etag": "1.8.1", 267 | "finalhandler": "1.1.0", 268 | "fresh": "0.5.2", 269 | "merge-descriptors": "1.0.1", 270 | "methods": "1.1.2", 271 | "on-finished": "2.3.0", 272 | "parseurl": "1.3.2", 273 | "path-to-regexp": "0.1.7", 274 | "proxy-addr": "2.0.2", 275 | "qs": "6.5.1", 276 | "range-parser": "1.2.0", 277 | "safe-buffer": "5.1.1", 278 | "send": "0.16.1", 279 | "serve-static": "1.13.1", 280 | "setprototypeof": "1.1.0", 281 | "statuses": "1.3.1", 282 | "type-is": "1.6.15", 283 | "utils-merge": "1.0.1", 284 | "vary": "1.1.2" 285 | }, 286 | "dependencies": { 287 | "setprototypeof": { 288 | "version": "1.1.0", 289 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 290 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 291 | }, 292 | "statuses": { 293 | "version": "1.3.1", 294 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 295 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 296 | } 297 | } 298 | }, 299 | "finalhandler": { 300 | "version": "1.1.0", 301 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", 302 | "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", 303 | "requires": { 304 | "debug": "2.6.9", 305 | "encodeurl": "1.0.1", 306 | "escape-html": "1.0.3", 307 | "on-finished": "2.3.0", 308 | "parseurl": "1.3.2", 309 | "statuses": "1.3.1", 310 | "unpipe": "1.0.0" 311 | }, 312 | "dependencies": { 313 | "statuses": { 314 | "version": "1.3.1", 315 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 316 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 317 | } 318 | } 319 | }, 320 | "forwarded": { 321 | "version": "0.1.2", 322 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 323 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 324 | }, 325 | "fresh": { 326 | "version": "0.5.2", 327 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 328 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 329 | }, 330 | "function-bind": { 331 | "version": "1.1.1", 332 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 333 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 334 | }, 335 | "graceful-readlink": { 336 | "version": "1.0.1", 337 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 338 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" 339 | }, 340 | "has": { 341 | "version": "1.0.1", 342 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", 343 | "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", 344 | "requires": { 345 | "function-bind": "1.1.1" 346 | } 347 | }, 348 | "hooks-fixed": { 349 | "version": "2.0.2", 350 | "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.2.tgz", 351 | "integrity": "sha512-YurCM4gQSetcrhwEtpQHhQ4M7Zo7poNGqY4kQGeBS6eZtOcT3tnNs01ThFa0jYBByAiYt1MjMjP/YApG0EnAvQ==" 352 | }, 353 | "http-errors": { 354 | "version": "1.6.2", 355 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 356 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 357 | "requires": { 358 | "depd": "1.1.1", 359 | "inherits": "2.0.3", 360 | "setprototypeof": "1.0.3", 361 | "statuses": "1.4.0" 362 | } 363 | }, 364 | "iconv-lite": { 365 | "version": "0.4.19", 366 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 367 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 368 | }, 369 | "inherits": { 370 | "version": "2.0.3", 371 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 372 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 373 | }, 374 | "ipaddr.js": { 375 | "version": "1.5.2", 376 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", 377 | "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" 378 | }, 379 | "is-buffer": { 380 | "version": "1.1.6", 381 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 382 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 383 | }, 384 | "is-expression": { 385 | "version": "2.1.0", 386 | "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-2.1.0.tgz", 387 | "integrity": "sha1-kb6dR968/vB3l36XIr5tz7RGXvA=", 388 | "requires": { 389 | "acorn": "3.3.0", 390 | "object-assign": "4.1.1" 391 | } 392 | }, 393 | "is-promise": { 394 | "version": "2.1.0", 395 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 396 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 397 | }, 398 | "is-regex": { 399 | "version": "1.0.4", 400 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 401 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 402 | "requires": { 403 | "has": "1.0.1" 404 | } 405 | }, 406 | "isarray": { 407 | "version": "1.0.0", 408 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 409 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 410 | }, 411 | "js-stringify": { 412 | "version": "1.0.2", 413 | "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", 414 | "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" 415 | }, 416 | "jstransformer": { 417 | "version": "1.0.0", 418 | "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", 419 | "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", 420 | "requires": { 421 | "is-promise": "2.1.0", 422 | "promise": "7.3.1" 423 | } 424 | }, 425 | "kareem": { 426 | "version": "1.5.0", 427 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.5.0.tgz", 428 | "integrity": "sha1-4+QQHZ3P3imXadr0tNtk2JXRdEg=" 429 | }, 430 | "kind-of": { 431 | "version": "3.2.2", 432 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 433 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 434 | "requires": { 435 | "is-buffer": "1.1.6" 436 | } 437 | }, 438 | "lazy-cache": { 439 | "version": "1.0.4", 440 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 441 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" 442 | }, 443 | "lodash": { 444 | "version": "4.17.4", 445 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 446 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 447 | }, 448 | "lodash.get": { 449 | "version": "4.4.2", 450 | "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 451 | "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" 452 | }, 453 | "longest": { 454 | "version": "1.0.1", 455 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 456 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" 457 | }, 458 | "media-typer": { 459 | "version": "0.3.0", 460 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 461 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 462 | }, 463 | "merge-descriptors": { 464 | "version": "1.0.1", 465 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 466 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 467 | }, 468 | "method-override": { 469 | "version": "2.3.10", 470 | "resolved": "https://registry.npmjs.org/method-override/-/method-override-2.3.10.tgz", 471 | "integrity": "sha1-49r41d7hDdLc59SuiNYrvud0drQ=", 472 | "requires": { 473 | "debug": "2.6.9", 474 | "methods": "1.1.2", 475 | "parseurl": "1.3.2", 476 | "vary": "1.1.2" 477 | } 478 | }, 479 | "methods": { 480 | "version": "1.1.2", 481 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 482 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 483 | }, 484 | "mime": { 485 | "version": "1.4.1", 486 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 487 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 488 | }, 489 | "mime-db": { 490 | "version": "1.30.0", 491 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 492 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" 493 | }, 494 | "mime-types": { 495 | "version": "2.1.17", 496 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 497 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 498 | "requires": { 499 | "mime-db": "1.30.0" 500 | } 501 | }, 502 | "mongodb": { 503 | "version": "2.2.33", 504 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.33.tgz", 505 | "integrity": "sha1-tTfEcdNKZlG0jzb9vyl1A0Dgi1A=", 506 | "requires": { 507 | "es6-promise": "3.2.1", 508 | "mongodb-core": "2.1.17", 509 | "readable-stream": "2.2.7" 510 | } 511 | }, 512 | "mongodb-core": { 513 | "version": "2.1.17", 514 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.17.tgz", 515 | "integrity": "sha1-pBizN6FKFJkPtRC5I97mqBMXPfg=", 516 | "requires": { 517 | "bson": "1.0.4", 518 | "require_optional": "1.0.1" 519 | } 520 | }, 521 | "mongoose": { 522 | "version": "4.13.6", 523 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.13.6.tgz", 524 | "integrity": "sha512-H+loD0D8UCwGmbOzWV7rZAf6/efRr9CPGB1Bess/IIjiWvpRQNo4zH4UHkueKoEbMWdnSYenjdEL8A0Q8p7JXg==", 525 | "requires": { 526 | "async": "2.1.4", 527 | "bson": "1.0.4", 528 | "hooks-fixed": "2.0.2", 529 | "kareem": "1.5.0", 530 | "lodash.get": "4.4.2", 531 | "mongodb": "2.2.33", 532 | "mpath": "0.3.0", 533 | "mpromise": "0.5.5", 534 | "mquery": "2.3.3", 535 | "ms": "2.0.0", 536 | "muri": "1.3.0", 537 | "regexp-clone": "0.0.1", 538 | "sliced": "1.0.1" 539 | } 540 | }, 541 | "morgan": { 542 | "version": "1.9.0", 543 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", 544 | "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", 545 | "requires": { 546 | "basic-auth": "2.0.0", 547 | "debug": "2.6.9", 548 | "depd": "1.1.1", 549 | "on-finished": "2.3.0", 550 | "on-headers": "1.0.1" 551 | } 552 | }, 553 | "mpath": { 554 | "version": "0.3.0", 555 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", 556 | "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" 557 | }, 558 | "mpromise": { 559 | "version": "0.5.5", 560 | "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz", 561 | "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" 562 | }, 563 | "mquery": { 564 | "version": "2.3.3", 565 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-2.3.3.tgz", 566 | "integrity": "sha512-NC8L14kn+qxJbbJ1gbcEMDxF0sC3sv+1cbRReXXwVvowcwY1y9KoVZFq0ebwARibsadu8lx8nWGvm3V0Pf0ZWQ==", 567 | "requires": { 568 | "bluebird": "3.5.0", 569 | "debug": "2.6.9", 570 | "regexp-clone": "0.0.1", 571 | "sliced": "0.0.5" 572 | }, 573 | "dependencies": { 574 | "sliced": { 575 | "version": "0.0.5", 576 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", 577 | "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" 578 | } 579 | } 580 | }, 581 | "ms": { 582 | "version": "2.0.0", 583 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 584 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 585 | }, 586 | "muri": { 587 | "version": "1.3.0", 588 | "resolved": "https://registry.npmjs.org/muri/-/muri-1.3.0.tgz", 589 | "integrity": "sha512-FiaFwKl864onHFFUV/a2szAl7X0fxVlSKNdhTf+BM8i8goEgYut8u5P9MqQqIYwvaMxjzVESsoEm/2kfkFH1rg==" 590 | }, 591 | "negotiator": { 592 | "version": "0.6.1", 593 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 594 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 595 | }, 596 | "object-assign": { 597 | "version": "4.1.1", 598 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 599 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 600 | }, 601 | "on-finished": { 602 | "version": "2.3.0", 603 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 604 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 605 | "requires": { 606 | "ee-first": "1.1.1" 607 | } 608 | }, 609 | "on-headers": { 610 | "version": "1.0.1", 611 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", 612 | "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" 613 | }, 614 | "parseurl": { 615 | "version": "1.3.2", 616 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 617 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 618 | }, 619 | "path-parse": { 620 | "version": "1.0.5", 621 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", 622 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" 623 | }, 624 | "path-to-regexp": { 625 | "version": "0.1.7", 626 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 627 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 628 | }, 629 | "process-nextick-args": { 630 | "version": "1.0.7", 631 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 632 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 633 | }, 634 | "promise": { 635 | "version": "7.3.1", 636 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", 637 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", 638 | "requires": { 639 | "asap": "2.0.6" 640 | } 641 | }, 642 | "proxy-addr": { 643 | "version": "2.0.2", 644 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", 645 | "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", 646 | "requires": { 647 | "forwarded": "0.1.2", 648 | "ipaddr.js": "1.5.2" 649 | } 650 | }, 651 | "pug": { 652 | "version": "2.0.0-rc.4", 653 | "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.0-rc.4.tgz", 654 | "integrity": "sha512-SL7xovj6E2Loq9N0UgV6ynjMLW4urTFY/L/Fprhvz13Xc5vjzkjZjI1QHKq31200+6PSD8PyU6MqrtCTJj6/XA==", 655 | "requires": { 656 | "pug-code-gen": "2.0.0", 657 | "pug-filters": "2.1.5", 658 | "pug-lexer": "3.1.0", 659 | "pug-linker": "3.0.3", 660 | "pug-load": "2.0.9", 661 | "pug-parser": "4.0.0", 662 | "pug-runtime": "2.0.3", 663 | "pug-strip-comments": "1.0.2" 664 | } 665 | }, 666 | "pug-attrs": { 667 | "version": "2.0.2", 668 | "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.2.tgz", 669 | "integrity": "sha1-i+KyIlVo/6ddG4Zpgr/59BEa/8s=", 670 | "requires": { 671 | "constantinople": "3.1.0", 672 | "js-stringify": "1.0.2", 673 | "pug-runtime": "2.0.3" 674 | } 675 | }, 676 | "pug-code-gen": { 677 | "version": "2.0.0", 678 | "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.0.tgz", 679 | "integrity": "sha512-E4oiJT+Jn5tyEIloj8dIJQognbiNNp0i0cAJmYtQTFS0soJ917nlIuFtqVss3IXMEyQKUew3F4gIkBpn18KbVg==", 680 | "requires": { 681 | "constantinople": "3.1.0", 682 | "doctypes": "1.1.0", 683 | "js-stringify": "1.0.2", 684 | "pug-attrs": "2.0.2", 685 | "pug-error": "1.3.2", 686 | "pug-runtime": "2.0.3", 687 | "void-elements": "2.0.1", 688 | "with": "5.1.1" 689 | } 690 | }, 691 | "pug-error": { 692 | "version": "1.3.2", 693 | "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.2.tgz", 694 | "integrity": "sha1-U659nSm7A89WRJOgJhCfVMR/XyY=" 695 | }, 696 | "pug-filters": { 697 | "version": "2.1.5", 698 | "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-2.1.5.tgz", 699 | "integrity": "sha512-xkw71KtrC4sxleKiq+cUlQzsiLn8pM5+vCgkChW2E6oNOzaqTSIBKIQ5cl4oheuDzvJYCTSYzRaVinMUrV4YLQ==", 700 | "requires": { 701 | "clean-css": "3.4.28", 702 | "constantinople": "3.1.0", 703 | "jstransformer": "1.0.0", 704 | "pug-error": "1.3.2", 705 | "pug-walk": "1.1.5", 706 | "resolve": "1.5.0", 707 | "uglify-js": "2.8.29" 708 | } 709 | }, 710 | "pug-lexer": { 711 | "version": "3.1.0", 712 | "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-3.1.0.tgz", 713 | "integrity": "sha1-/QhzdtSmdbT1n4/vQiiDQ06VgaI=", 714 | "requires": { 715 | "character-parser": "2.2.0", 716 | "is-expression": "3.0.0", 717 | "pug-error": "1.3.2" 718 | }, 719 | "dependencies": { 720 | "acorn": { 721 | "version": "4.0.13", 722 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 723 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" 724 | }, 725 | "is-expression": { 726 | "version": "3.0.0", 727 | "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", 728 | "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", 729 | "requires": { 730 | "acorn": "4.0.13", 731 | "object-assign": "4.1.1" 732 | } 733 | } 734 | } 735 | }, 736 | "pug-linker": { 737 | "version": "3.0.3", 738 | "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.3.tgz", 739 | "integrity": "sha512-DCKczglCXOzJ1lr4xUj/lVHYvS+lGmR2+KTCjZjtIpdwaN7lNOoX2SW6KFX5X4ElvW+6ThwB+acSUg08UJFN5A==", 740 | "requires": { 741 | "pug-error": "1.3.2", 742 | "pug-walk": "1.1.5" 743 | } 744 | }, 745 | "pug-load": { 746 | "version": "2.0.9", 747 | "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.9.tgz", 748 | "integrity": "sha512-BDdZOCru4mg+1MiZwRQZh25+NTRo/R6/qArrdWIf308rHtWA5N9kpoUskRe4H6FslaQujC+DigH9LqlBA4gf6Q==", 749 | "requires": { 750 | "object-assign": "4.1.1", 751 | "pug-walk": "1.1.5" 752 | } 753 | }, 754 | "pug-parser": { 755 | "version": "4.0.0", 756 | "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-4.0.0.tgz", 757 | "integrity": "sha512-ocEUFPdLG9awwFj0sqi1uiZLNvfoodCMULZzkRqILryIWc/UUlDlxqrKhKjAIIGPX/1SNsvxy63+ayEGocGhQg==", 758 | "requires": { 759 | "pug-error": "1.3.2", 760 | "token-stream": "0.0.1" 761 | } 762 | }, 763 | "pug-runtime": { 764 | "version": "2.0.3", 765 | "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.3.tgz", 766 | "integrity": "sha1-mBYmB7D86eJU1CfzOYelrucWi9o=" 767 | }, 768 | "pug-strip-comments": { 769 | "version": "1.0.2", 770 | "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.2.tgz", 771 | "integrity": "sha1-0xOvoBvMN0mA4TmeI+vy65vchRM=", 772 | "requires": { 773 | "pug-error": "1.3.2" 774 | } 775 | }, 776 | "pug-walk": { 777 | "version": "1.1.5", 778 | "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.5.tgz", 779 | "integrity": "sha512-rJlH1lXerCIAtImXBze3dtKq/ykZMA4rpO9FnPcIgsWcxZLOvd8zltaoeOVFyBSSqCkhhJWbEbTMga8UxWUUSA==" 780 | }, 781 | "qs": { 782 | "version": "6.5.1", 783 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", 784 | "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" 785 | }, 786 | "range-parser": { 787 | "version": "1.2.0", 788 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 789 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 790 | }, 791 | "raw-body": { 792 | "version": "2.3.2", 793 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 794 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 795 | "requires": { 796 | "bytes": "3.0.0", 797 | "http-errors": "1.6.2", 798 | "iconv-lite": "0.4.19", 799 | "unpipe": "1.0.0" 800 | } 801 | }, 802 | "readable-stream": { 803 | "version": "2.2.7", 804 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", 805 | "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", 806 | "requires": { 807 | "buffer-shims": "1.0.0", 808 | "core-util-is": "1.0.2", 809 | "inherits": "2.0.3", 810 | "isarray": "1.0.0", 811 | "process-nextick-args": "1.0.7", 812 | "string_decoder": "1.0.3", 813 | "util-deprecate": "1.0.2" 814 | } 815 | }, 816 | "regexp-clone": { 817 | "version": "0.0.1", 818 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", 819 | "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" 820 | }, 821 | "repeat-string": { 822 | "version": "1.6.1", 823 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 824 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 825 | }, 826 | "require_optional": { 827 | "version": "1.0.1", 828 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 829 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 830 | "requires": { 831 | "resolve-from": "2.0.0", 832 | "semver": "5.4.1" 833 | } 834 | }, 835 | "resolve": { 836 | "version": "1.5.0", 837 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", 838 | "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", 839 | "requires": { 840 | "path-parse": "1.0.5" 841 | } 842 | }, 843 | "resolve-from": { 844 | "version": "2.0.0", 845 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 846 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 847 | }, 848 | "right-align": { 849 | "version": "0.1.3", 850 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 851 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 852 | "requires": { 853 | "align-text": "0.1.4" 854 | } 855 | }, 856 | "safe-buffer": { 857 | "version": "5.1.1", 858 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 859 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 860 | }, 861 | "semver": { 862 | "version": "5.4.1", 863 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", 864 | "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" 865 | }, 866 | "send": { 867 | "version": "0.16.1", 868 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", 869 | "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", 870 | "requires": { 871 | "debug": "2.6.9", 872 | "depd": "1.1.1", 873 | "destroy": "1.0.4", 874 | "encodeurl": "1.0.1", 875 | "escape-html": "1.0.3", 876 | "etag": "1.8.1", 877 | "fresh": "0.5.2", 878 | "http-errors": "1.6.2", 879 | "mime": "1.4.1", 880 | "ms": "2.0.0", 881 | "on-finished": "2.3.0", 882 | "range-parser": "1.2.0", 883 | "statuses": "1.3.1" 884 | }, 885 | "dependencies": { 886 | "statuses": { 887 | "version": "1.3.1", 888 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", 889 | "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" 890 | } 891 | } 892 | }, 893 | "serve-static": { 894 | "version": "1.13.1", 895 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", 896 | "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", 897 | "requires": { 898 | "encodeurl": "1.0.1", 899 | "escape-html": "1.0.3", 900 | "parseurl": "1.3.2", 901 | "send": "0.16.1" 902 | } 903 | }, 904 | "setprototypeof": { 905 | "version": "1.0.3", 906 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 907 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 908 | }, 909 | "sliced": { 910 | "version": "1.0.1", 911 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", 912 | "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" 913 | }, 914 | "source-map": { 915 | "version": "0.4.4", 916 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 917 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 918 | "requires": { 919 | "amdefine": "1.0.1" 920 | } 921 | }, 922 | "statuses": { 923 | "version": "1.4.0", 924 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 925 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 926 | }, 927 | "string_decoder": { 928 | "version": "1.0.3", 929 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 930 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 931 | "requires": { 932 | "safe-buffer": "5.1.1" 933 | } 934 | }, 935 | "token-stream": { 936 | "version": "0.0.1", 937 | "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", 938 | "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" 939 | }, 940 | "type-is": { 941 | "version": "1.6.15", 942 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", 943 | "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", 944 | "requires": { 945 | "media-typer": "0.3.0", 946 | "mime-types": "2.1.17" 947 | } 948 | }, 949 | "uglify-js": { 950 | "version": "2.8.29", 951 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 952 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 953 | "requires": { 954 | "source-map": "0.5.7", 955 | "uglify-to-browserify": "1.0.2", 956 | "yargs": "3.10.0" 957 | }, 958 | "dependencies": { 959 | "source-map": { 960 | "version": "0.5.7", 961 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 962 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 963 | } 964 | } 965 | }, 966 | "uglify-to-browserify": { 967 | "version": "1.0.2", 968 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 969 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 970 | "optional": true 971 | }, 972 | "unpipe": { 973 | "version": "1.0.0", 974 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 975 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 976 | }, 977 | "util-deprecate": { 978 | "version": "1.0.2", 979 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 980 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 981 | }, 982 | "utils-merge": { 983 | "version": "1.0.1", 984 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 985 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 986 | }, 987 | "vary": { 988 | "version": "1.1.2", 989 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 990 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 991 | }, 992 | "void-elements": { 993 | "version": "2.0.1", 994 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", 995 | "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" 996 | }, 997 | "window-size": { 998 | "version": "0.1.0", 999 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 1000 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" 1001 | }, 1002 | "with": { 1003 | "version": "5.1.1", 1004 | "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", 1005 | "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", 1006 | "requires": { 1007 | "acorn": "3.3.0", 1008 | "acorn-globals": "3.1.0" 1009 | } 1010 | }, 1011 | "wordwrap": { 1012 | "version": "0.0.2", 1013 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 1014 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" 1015 | }, 1016 | "yargs": { 1017 | "version": "3.10.0", 1018 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 1019 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 1020 | "requires": { 1021 | "camelcase": "1.2.1", 1022 | "cliui": "2.1.0", 1023 | "decamelize": "1.2.0", 1024 | "window-size": "0.1.0" 1025 | } 1026 | } 1027 | } 1028 | } 1029 | --------------------------------------------------------------------------------