├── .gitignore ├── 7-mongoose ├── src │ ├── validations │ │ └── course │ │ │ └── addCourse.js │ ├── middleware │ │ ├── adminGuard.js │ │ ├── errorHandler.js │ │ ├── validationErrorHandler.js │ │ └── authGuard.js │ ├── routes │ │ ├── user.js │ │ ├── index.js │ │ ├── course.js │ │ └── student.js │ ├── services │ │ └── course.js │ ├── utils │ │ ├── logger.js │ │ ├── jwt.js │ │ └── db.js │ ├── models │ │ ├── course.js │ │ ├── user.js │ │ └── student.js │ ├── index.js │ └── controllers │ │ ├── user.js │ │ ├── course.js │ │ └── student.js ├── bcrypt.js └── package.json ├── 5-api-server ├── index.js ├── src │ ├── routes │ │ ├── index.js │ │ └── task.js │ ├── middleware │ │ └── cors.js │ ├── utils │ │ ├── swagger.js │ │ └── logger.js │ ├── index.js │ └── controllers │ │ └── task.js ├── .vscode │ └── launch.json ├── package.json └── note.txt ├── es6 ├── hoisting.js ├── async.md ├── index.js ├── note.md └── es6.md ├── 1-node.js ├── messageB.js ├── messageA.js ├── home.html ├── other.html ├── server.js └── index.js ├── 8-docker ├── note.md ├── dockerfile ├── index.js ├── package.json └── package-lock.json ├── 4-23nodeassignment ├── package.json ├── index.js ├── router.js └── package-lock.json ├── 3-npm ├── package.json ├── quiz.js ├── index.js └── package-lock.json ├── 6-mongodb └── note.md ├── 2-restful └── note.md └── async ├── promis-quiz.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env -------------------------------------------------------------------------------- /7-mongoose/src/validations/course/addCourse.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /5-api-server/index.js: -------------------------------------------------------------------------------- 1 | // const cors = require("cors"); 2 | 3 | // app.use(cors()); 4 | 5 | // router 6 | 7 | // GET '/tasks' 8 | -------------------------------------------------------------------------------- /es6/hoisting.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | console.log(fruit); 3 | 4 | 5 | function sum(a = 1, b = 1) { 6 | return a + b; 7 | } 8 | sum(, 1); -------------------------------------------------------------------------------- /1-node.js/messageB.js: -------------------------------------------------------------------------------- 1 | const msg = 'another msg'; 2 | 3 | function getMsg() { 4 | return msg; 5 | } 6 | 7 | module.exports = { getMsg }; 8 | -------------------------------------------------------------------------------- /1-node.js/messageA.js: -------------------------------------------------------------------------------- 1 | const msg = 'secret msg'; 2 | console.log('1234'); 3 | function getMsg() { 4 | return msg; 5 | } 6 | 7 | module.exports = { getMsg }; 8 | // module.exports = getMsg; 9 | -------------------------------------------------------------------------------- /8-docker/note.md: -------------------------------------------------------------------------------- 1 | virtualization 2 | 3 | hypervisor 4 | 5 | container 6 | 7 | dockerfile 8 | 打包文件 9 | 10 | image 11 | 镜像 12 | 13 | docker hub 14 | 15 | container 16 | 17 | network 18 | -------------------------------------------------------------------------------- /8-docker/dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14 2 | 3 | WORKDIR /app 4 | 5 | COPY package.json package.json 6 | COPY package-lock.json package-lock.json 7 | COPY index.js index.js 8 | 9 | RUN npm i 10 | 11 | CMD [ "npm", "start" ] 12 | -------------------------------------------------------------------------------- /5-api-server/src/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const taskRouter = require('./task'); 3 | 4 | const v1Router = express.Router(); 5 | 6 | v1Router.use('/tasks', taskRouter); 7 | 8 | module.exports = v1Router; 9 | -------------------------------------------------------------------------------- /8-docker/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const app = express(); 4 | 5 | app.use((req, res) => { 6 | res.send('hello'); 7 | }); 8 | 9 | app.listen(3000, () => { 10 | console.log('listening on 3000'); 11 | }); 12 | -------------------------------------------------------------------------------- /5-api-server/src/middleware/cors.js: -------------------------------------------------------------------------------- 1 | module.exports = (req, res, next) => { 2 | res.setHeader('Access-Control-Allow-Origin', '*'); 3 | res.setHeader('Access-Control-Allow-Headers', 'content-type'); 4 | res.setHeader('Access-Control-Allow-Methods', '*'); 5 | next(); 6 | }; 7 | -------------------------------------------------------------------------------- /7-mongoose/src/middleware/adminGuard.js: -------------------------------------------------------------------------------- 1 | module.exports = (req, res, next) => { 2 | if (!req.user || !req.user.role) { 3 | return res.sendStatus(403); 4 | } 5 | 6 | if (req.user.role !== 'admin') { 7 | return res.sendStatus(403); 8 | } 9 | 10 | next(); 11 | }; 12 | -------------------------------------------------------------------------------- /7-mongoose/src/routes/user.js: -------------------------------------------------------------------------------- 1 | const { Router } = require('express'); 2 | const { register, login } = require('../controllers/user'); 3 | 4 | const userRouter = Router(); 5 | 6 | userRouter.post('', register); 7 | // POST /auth 8 | userRouter.post('/login', login); 9 | 10 | module.exports = userRouter; 11 | -------------------------------------------------------------------------------- /7-mongoose/src/middleware/errorHandler.js: -------------------------------------------------------------------------------- 1 | const logger = require('../utils/logger'); 2 | 3 | module.exports = (error, req, res, next) => { 4 | // if 5 | // if 6 | logger.error(error); 7 | return res 8 | .status(500) 9 | .json({ error: 'something unexpected happened, please try again later' }); 10 | }; 11 | -------------------------------------------------------------------------------- /8-docker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "8-docker", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.18.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /4-23nodeassignment/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "4-23nodeassignment", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /7-mongoose/src/middleware/validationErrorHandler.js: -------------------------------------------------------------------------------- 1 | module.exports = (error, req, res, next) => { 2 | if (error.name === 'ValidationError') { 3 | return res.status(400).json(error); 4 | } 5 | next(error); 6 | }; 7 | 8 | // next(new Error('')) 9 | // next(new CustomError('')); 10 | // class CustomError extends Error { 11 | 12 | // } 13 | 14 | // if (error instanceof CustomError) { 15 | 16 | // } 17 | -------------------------------------------------------------------------------- /3-npm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3-npm", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "dev": "nodemon index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "express": "^4.17.3" 15 | }, 16 | "devDependencies": { 17 | "nodemon": "^2.0.15" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /5-api-server/src/utils/swagger.js: -------------------------------------------------------------------------------- 1 | const swaggerJsDoc = require('swagger-jsdoc'); 2 | 3 | module.exports = swaggerJsDoc({ 4 | definition: { 5 | openapi: '3.0.0', 6 | info: { 7 | title: 'JR tasks', 8 | version: '1.0.0', 9 | contact: { 10 | name: 'mason', 11 | email: 'exmaple.com', 12 | }, 13 | description: 'xxxxx', 14 | }, 15 | }, 16 | apis: ['src/controllers/*.js'], 17 | }); 18 | -------------------------------------------------------------------------------- /es6/async.md: -------------------------------------------------------------------------------- 1 | 异步 2 | asynchronous 3 | 同步 4 | synchronous 5 | 6 | console.log(1) 7 | setTimeout(()=>{ 8 | console.log(2) 9 | }) 10 | console.log(3) 11 | 12 | 同步 = 等待 = 阻塞 (BLOCK) 13 | 异步 = 不等待 = 非阻塞 (NON-BLOCKING) 14 | 15 | js 是一个单线程语言 16 | 17 | Input / Output 18 | I/O 19 | 20 | call stack 21 | stack overflow 22 | 23 | stack FILO 24 | queue FIFO 25 | 26 | CRUD 27 | create read update delete 28 | 增删改查 29 | 30 | CRUD Operation 31 | CRUD service/server 32 | -------------------------------------------------------------------------------- /7-mongoose/src/services/course.js: -------------------------------------------------------------------------------- 1 | const Course = require('../models/course'); 2 | // ts, injection 3 | 4 | 5 | function addStudentToCourse(studentId, courseId) { 6 | const course = await Course.findByIdAndUpdate(courseId, { 7 | student: { $push: studentId } 8 | }, { new: true }); 9 | if (!course) { 10 | throw new Error('course not found'); 11 | } 12 | return course; 13 | } 14 | 15 | 16 | module.exports = { 17 | addStudentToCourse 18 | } 19 | -------------------------------------------------------------------------------- /7-mongoose/src/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const studentRouter = require('./student'); 3 | const courseRouter = require('./course'); 4 | const userRouter = require('./user'); 5 | const authGuard = require('../middleware/authGuard'); 6 | 7 | const v1Router = express.Router(); 8 | 9 | v1Router.use('/students', authGuard, studentRouter); 10 | v1Router.use('/courses', courseRouter); 11 | v1Router.use('/users', userRouter); 12 | 13 | module.exports = v1Router; 14 | -------------------------------------------------------------------------------- /1-node.js/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |

Home Page

11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /1-node.js/other.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |

Other Page

11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /5-api-server/src/routes/task.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { 3 | getAllTasks, 4 | getTaskById, 5 | addTask, 6 | updateTaskById, 7 | deleteTaskById, 8 | } = require('../controllers/task'); 9 | 10 | const taskRouter = express.Router(); 11 | 12 | taskRouter.get('', getAllTasks); 13 | 14 | taskRouter.get('/:id', getTaskById); 15 | 16 | taskRouter.post('', addTask); 17 | 18 | taskRouter.put('/:id', updateTaskById); 19 | 20 | taskRouter.delete('/:id', deleteTaskById); 21 | 22 | module.exports = taskRouter; 23 | -------------------------------------------------------------------------------- /7-mongoose/src/routes/course.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { 3 | getAllCourses, 4 | getCourseById, 5 | updateCourseById, 6 | deleteCourseById, 7 | addCourse, 8 | } = require('../controllers/Course'); 9 | 10 | const courseRouter = express.Router(); 11 | 12 | courseRouter.get('', getAllCourses); 13 | courseRouter.get('/:id', getCourseById); 14 | courseRouter.put('/:id', updateCourseById); 15 | courseRouter.delete('/:id', deleteCourseById); 16 | courseRouter.post('', addCourse); 17 | 18 | module.exports = courseRouter; 19 | -------------------------------------------------------------------------------- /7-mongoose/bcrypt.js: -------------------------------------------------------------------------------- 1 | const bcrypt = require('bcrypt'); 2 | 3 | const password = '123'; 4 | 5 | // const salt = bcrypt.genSaltSync(12); 6 | const salt = '$2b$12$IoPobvmSVnkpz.Jjw/U6s.'; 7 | // $2b$12$IoPobvmSVnkpz.Jjw/U6s. 8 | // $2b$12$IoPobvmSVnkpz.Jjw/U6s. /atUSDA.iRS3vlM1eBSMU5GZ0KK4Dyi 9 | 10 | const result = bcrypt.hashSync(password, salt); 11 | console.log(result); 12 | 13 | // console.log(result); 14 | 15 | // $2b$12$YuhzGVsj98RB2C8b//VZG.7GOsadAWa3kUxV/YEPMnLhwMudPqlO6 16 | // $2b$12$DTIBs095c8BUv/RIGY69nejHHvzwmOjmvOj6yGU/qPYzcnU2nSLUW 17 | -------------------------------------------------------------------------------- /5-api-server/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "pwa-node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "skipFiles": [ 12 | "/**" 13 | ], 14 | "program": "${workspaceFolder}/5-api-server/src/controllers/task.js" 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /5-api-server/src/utils/logger.js: -------------------------------------------------------------------------------- 1 | const winston = require('winston'); 2 | 3 | const logger = winston.createLogger({ 4 | level: process.env.LOGGER_LEVEL || 'info', 5 | // winston.format.simple() 6 | format: winston.format.combine( 7 | winston.format.colorize(), 8 | winston.format.timestamp({ 9 | format: 'YYYY-MM-DD HH:mm:ss', 10 | }), 11 | winston.format.printf( 12 | (info) => `${info.timestamp} ${info.level}: ${info.message}` 13 | ) 14 | ), 15 | transports: [new winston.transports.Console()], 16 | }); 17 | 18 | module.exports = logger; 19 | -------------------------------------------------------------------------------- /7-mongoose/src/utils/logger.js: -------------------------------------------------------------------------------- 1 | const winston = require('winston'); 2 | 3 | const logger = winston.createLogger({ 4 | level: process.env.LOGGER_LEVEL || 'info', 5 | // winston.format.simple() 6 | format: winston.format.combine( 7 | winston.format.colorize(), 8 | winston.format.timestamp({ 9 | format: 'YYYY-MM-DD HH:mm:ss', 10 | }), 11 | winston.format.printf( 12 | (info) => `${info.timestamp} ${info.level}: ${info.message}` 13 | ) 14 | ), 15 | transports: [new winston.transports.Console()], 16 | }); 17 | 18 | module.exports = logger; 19 | -------------------------------------------------------------------------------- /7-mongoose/src/utils/jwt.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | 3 | const { JWT_KEY } = process.env; 4 | 5 | function generateToken(payload) { 6 | return jwt.sign(payload, JWT_KEY, { expiresIn: '1h' }); 7 | } 8 | 9 | function validateToken(token) { 10 | // return jwt.verify(token, JWT_KEY); 11 | try { 12 | return jwt.verify(token, JWT_KEY); // return payload 13 | } catch (e) { 14 | return null; 15 | } 16 | } 17 | 18 | // try { 19 | 20 | // validateToken() 21 | // } catch () { 22 | 23 | // } 24 | 25 | module.exports = { generateToken, validateToken }; 26 | -------------------------------------------------------------------------------- /5-api-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "4-23nodeassignment", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "nodemon src/index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "cors": "^2.8.5", 14 | "dotenv": "^16.0.1", 15 | "express": "^4.17.3", 16 | "helmet": "^5.1.0", 17 | "morgan": "^1.10.0", 18 | "swagger-jsdoc": "^6.2.1", 19 | "swagger-ui-express": "^4.4.0", 20 | "winston": "^3.7.2" 21 | }, 22 | "devDependencies": { 23 | "nodemon": "^2.0.16" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /7-mongoose/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "4-23nodeassignment", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "nodemon src/index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcrypt": "^5.0.1", 14 | "cors": "^2.8.5", 15 | "dotenv": "^16.0.1", 16 | "express": "^4.17.3", 17 | "express-async-errors": "^3.1.1", 18 | "helmet": "^5.1.0", 19 | "joi": "^17.6.0", 20 | "jsonwebtoken": "^8.5.1", 21 | "mongoose": "^6.3.5", 22 | "morgan": "^1.10.0", 23 | "winston": "^3.7.2" 24 | }, 25 | "devDependencies": { 26 | "nodemon": "^2.0.16" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /7-mongoose/src/middleware/authGuard.js: -------------------------------------------------------------------------------- 1 | const { validateToken } = require('../utils/jwt'); 2 | 3 | module.exports = (req, res, next) => { 4 | // Authorization: Bearer {token} 5 | const authorizationHeader = req.header('Authorization'); 6 | if (!authorizationHeader) { 7 | return res.sendStatus(401); 8 | } 9 | const tokenArray = authorizationHeader.split(' '); 10 | if (tokenArray.length !== 2 || tokenArray[0] !== 'Bearer') { 11 | return res.sendStatus(401); 12 | } 13 | 14 | const payload = validateToken(tokenArray[1]); 15 | if (!payload) { 16 | return res.sendStatus(401); 17 | } 18 | req.user = payload; 19 | 20 | return next(); 21 | }; 22 | 23 | // Role based 24 | // Attribute based (operation) 25 | -------------------------------------------------------------------------------- /1-node.js/server.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const homePage = fs.readFileSync(path.join(__dirname, 'home.html')); 5 | const otherPage = fs.readFileSync(path.join(__dirname, 'other.html')); 6 | 7 | const server = http.createServer((req, res) => { 8 | console.log(req.url, req.headers, req.method); 9 | 10 | if (req.url === '/') { 11 | // res.setHeader('Content-Type', 'text/html'); 12 | res.write(homePage); 13 | res.end(); 14 | return; 15 | } 16 | if (req.url === '/other') { 17 | // res.setHeader('Content-Type', 'text/html'); 18 | res.write(otherPage); 19 | res.end(); 20 | return; 21 | } 22 | }); 23 | server.listen(8080); 24 | 25 | // 3000, 8000, 8080, 9000, 4200, 26 | -------------------------------------------------------------------------------- /7-mongoose/src/models/course.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | // _id: String, name, description, students 4 | module.exports = model( 5 | 'Course', 6 | new Schema({ 7 | // course code 8 | _id: { 9 | type: String, 10 | uppercase: true, 11 | alias: 'code', 12 | }, 13 | name: { 14 | type: String, 15 | required: true, 16 | }, 17 | description: { 18 | type: String, 19 | default: 'this is a description', 20 | }, 21 | students: [ 22 | { 23 | type: Schema.Types.ObjectId, 24 | ref: 'Student', 25 | }, 26 | // { 27 | // _id: { 28 | // type: Schema.Types.ObjectId, 29 | // ref: 'Student', 30 | // }, 31 | // firstName: String, 32 | // }, 33 | ], 34 | }) 35 | ); 36 | -------------------------------------------------------------------------------- /3-npm/quiz.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const app = express(); 4 | 5 | function m1(req, res, next) { 6 | console.log('m1 called'); 7 | next(); 8 | } 9 | 10 | function m2(req, res, next) { 11 | console.log('m2 called'); 12 | next(); 13 | } 14 | 15 | function m3(req, res, next) { 16 | console.log('m3 called'); 17 | next(); 18 | } 19 | 20 | function m4(req, res, next) { 21 | console.log('m4 called'); 22 | next(); 23 | } 24 | 25 | // quiz 26 | // GET /v1/tasks/1 27 | // GET /v1/tasks 28 | 29 | // middleware chain 30 | // []; 31 | 32 | // event bubbling 33 | 34 | app.use(m1); 35 | app.use('/v1', m2); 36 | app.get('/v1/tasks', m3); 37 | app.get('/v1/tasks', m4); 38 | app.get('/v1/tasks/:id', (req, res) => { 39 | res.json(req.params); 40 | }); 41 | 42 | app.listen(3000, () => console.log('listen on 3000')); 43 | -------------------------------------------------------------------------------- /5-api-server/note.txt: -------------------------------------------------------------------------------- 1 | -- package.json 2 | -- package-lock.json 3 | -- src 4 | |-- index.js 入口文件 (server.js, app.js) 5 | |-- routes 6 | |-- tasks.js (taskRouter) (task.route.js) 7 | |-- users.js (userRouter) 8 | |-- index.js (把上面所有的router导入进来,再做一个统一的导出) 9 | |-- controllers (逻辑处理部分) 10 | |-- tasks.js (taskController) (task.controller.js) 11 | |-- users.js 12 | |-- models 13 | |-- task.js (Task.js) 数据库中Task这个数据的格式设计 - ORM (object relational mapping), 跟数据库交互 14 | |-- middleware 15 | |-- error-middleware 16 | |-- xxxErrorHandler.js 17 | |-- authGuard 18 | |-- cors 19 | |-- utils (Helper function, shared function,db) 20 | |-- db 21 | |-- config 项目配置(环境变量的处理) 22 | 23 | 24 | routes 和 controllers 合并 25 | services 26 | 27 | src 28 | - users 29 | -- user.controller.js 30 | -- user.model.js 31 | - tasks 32 | -------------------------------------------------------------------------------- /7-mongoose/src/utils/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const logger = require('./logger'); 3 | 4 | function connectToDB() { 5 | const connectionString = process.env.CONNECTION_STRING; 6 | if (!connectionString) { 7 | // throw Error() 8 | logger.error('connection string not defined'); 9 | // 正常退出 10 | // 非正常退出 11 | // 人为正常退出 process.exit(0) 12 | // 人为非正常退出 13 | process.exit(1); 14 | } 15 | const db = mongoose.connection; 16 | db.on('connected', () => { 17 | logger.info(`DB connected, ${connectionString}`); 18 | }); 19 | 20 | db.on('error', (error) => { 21 | logger.error(error.message); 22 | process.exit(2); 23 | }); 24 | 25 | db.on('disconnected', () => { 26 | logger.info('db connection lost'); 27 | }); 28 | return mongoose.connect(connectionString); 29 | } 30 | 31 | module.exports = connectToDB; 32 | -------------------------------------------------------------------------------- /4-23nodeassignment/index.js: -------------------------------------------------------------------------------- 1 | // 导入express包 2 | const express = require('express'); 3 | const app = express(); 4 | 5 | const PORT = 3000; 6 | 7 | // body-parser 8 | // 4.xxx -> body-parser included in express 9 | app.use(express.json()); // JSON 10 | // app.use(express.urlencoded({ extended: true })); 11 | 12 | // json: function(req, res, next) { } 13 | // json: () => { 14 | // // high order function 15 | // // curring function 16 | // return (req, res, next) => { 17 | 18 | // } 19 | // } 20 | // app.use(express.json()); 21 | 22 | // 导入路由 23 | const { router } = require('./router'); 24 | 25 | // 注册路由 26 | app.use(router); 27 | 28 | // 捕获错误并返回提示信息 29 | // app.use((err, req, res, next) => { 30 | // if (err) { 31 | // res.send('操作错误,请更正后再试。'); 32 | // } else next(); 33 | // }); 34 | 35 | app.listen(PORT, () => { 36 | console.log(`server is running at ${PORT}`); 37 | }); 38 | -------------------------------------------------------------------------------- /7-mongoose/src/index.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const express = require('express'); 3 | require('express-async-errors'); 4 | const morgan = require('morgan'); 5 | const cors = require('cors'); 6 | const helmet = require('helmet'); 7 | 8 | const v1Router = require('./routes'); 9 | const logger = require('./utils/logger'); 10 | const connectToDB = require('./utils/db'); 11 | const errorHandler = require('./middleware/errorHandler'); 12 | const validationErrorHandler = require('./middleware/validationErrorHandler'); 13 | 14 | const PORT = process.env.PORT || 3000; 15 | 16 | const app = express(); 17 | 18 | app.use(helmet()); 19 | app.use(morgan('dev')); 20 | app.use(express.json()); 21 | app.use(cors()); 22 | 23 | app.use('/v1', v1Router); 24 | 25 | app.use(validationErrorHandler); 26 | app.use(errorHandler); 27 | 28 | connectToDB(); 29 | 30 | app.listen(PORT, () => { 31 | logger.info(`server listening on port: ${PORT}`); 32 | }); 33 | -------------------------------------------------------------------------------- /5-api-server/src/index.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const express = require('express'); 3 | const morgan = require('morgan'); 4 | // const cors = require('./middleware/cors'); 5 | const cors = require('cors'); 6 | const helmet = require('helmet'); 7 | const swaggerUi = require('swagger-ui-express'); 8 | 9 | const v1Router = require('./routes'); 10 | const logger = require('./utils/logger'); 11 | const swaggerJsDoc = require('./utils/swagger'); 12 | 13 | const PORT = process.env.PORT || 3000; 14 | 15 | const app = express(); 16 | 17 | app.use(helmet()); 18 | app.use(morgan('dev')); 19 | app.use(express.json()); 20 | app.use(cors()); 21 | app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerJsDoc)); 22 | 23 | // GET /v1/tasks 24 | // app.use('/v1') 25 | // GET /tasks 26 | app.use(v1Router); 27 | 28 | app.listen(PORT, () => { 29 | logger.info(`server listening on port: ${PORT}`); 30 | }); 31 | 32 | // /health_check 33 | // /healthz 34 | // on-call 35 | -------------------------------------------------------------------------------- /7-mongoose/src/models/user.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | const bcrypt = require('bcrypt'); 3 | 4 | const schema = new Schema({ 5 | username: { 6 | type: String, 7 | required: true, 8 | }, 9 | password: { 10 | type: String, 11 | required: true, 12 | }, 13 | role: { 14 | type: String, 15 | }, 16 | }); 17 | 18 | schema.methods.hashPassword = async function () { 19 | this.password = await bcrypt.hash(this.password, 12); 20 | }; 21 | 22 | schema.methods.validatePassword = async function (password) { 23 | return bcrypt.compare(password, this.password); 24 | }; 25 | 26 | const Model = model('User', schema); 27 | 28 | module.exports = Model; 29 | 30 | /** 31 | * 加密,解密,哈希 32 | * encrypt, decrypt, hash 33 | * 34 | * x -> X 35 | * X -> x 36 | * 37 | * x -> Y 38 | * Y !-> x 39 | * 40 | * x' -> Y 41 | * 42 | * football -> xxxx 43 | * aaaaaaa -> bbbbbb 44 | * 45 | * 加盐 46 | * salt 47 | * football -salt1-> xxxx1salt1 48 | * football -salt2-> xxxx2salt2 49 | * 50 | */ 51 | -------------------------------------------------------------------------------- /1-node.js/index.js: -------------------------------------------------------------------------------- 1 | // console.log('hello world'); 2 | 3 | // // REPL 4 | 5 | // const moduleA = { exports: {} }; 6 | // const moduleB = { exports: {} }; 7 | // // const msg = 'secret msg'; 8 | // // const msg = 'another msg'; 9 | // (function (module) { 10 | // const msg = 'secret msg'; 11 | 12 | // function getMsg() { 13 | // return msg; 14 | // } 15 | 16 | // module.exports = { getMsg }; 17 | // })(moduleA); 18 | 19 | // (function (module) { 20 | // const msg = 'another msg'; 21 | 22 | // function getMsg() { 23 | // return msg; 24 | // } 25 | 26 | // module.exports = { getMsg }; 27 | // })(moduleB); 28 | 29 | // moduleA.exports.getMsg(); 30 | // moduleB.exports.getMsg(); 31 | // { 32 | // key: value 33 | // } 34 | 35 | // { 36 | // key: value 37 | // } 38 | 39 | const getMsgA = require('./messageA'); 40 | // const { getMsg: getMsgA } = require('./messageA'); 41 | const { getMsg: getMsgB } = require('./messageB'); 42 | getMsgA.getMsg(); 43 | getMsgB(); 44 | console.log(__dirname); 45 | console.log(__filename); 46 | // __dirname 47 | // __filename 48 | -------------------------------------------------------------------------------- /7-mongoose/src/routes/student.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const { 3 | getAllStudents, 4 | getStudentById, 5 | updateStudentById, 6 | deleteStudentById, 7 | addStudent, 8 | addStudentToCourse, 9 | removeStudentFromCourse, 10 | } = require('../controllers/student'); 11 | const adminGuard = require('../middleware/adminGuard'); 12 | 13 | const studentRouter = express.Router(); 14 | 15 | // curring function 16 | // high order function 17 | // function tryCatch(routeHandler) { 18 | // return async (req, res, next) => { 19 | // try { 20 | // await routeHandler(req, res, next); 21 | // } catch (e) { 22 | // // res.json(e); 23 | // next(e); 24 | // } 25 | // }; 26 | // } 27 | 28 | studentRouter.get('', getAllStudents); 29 | studentRouter.get('/:id', getStudentById); 30 | studentRouter.put('/:id', updateStudentById); 31 | studentRouter.delete('/:id', deleteStudentById); 32 | studentRouter.post('', adminGuard, addStudent); 33 | studentRouter.post('/:id/courses/:code', addStudentToCourse); 34 | studentRouter.delete('/:id/courses/:code', removeStudentFromCourse); 35 | 36 | module.exports = studentRouter; 37 | -------------------------------------------------------------------------------- /7-mongoose/src/controllers/user.js: -------------------------------------------------------------------------------- 1 | const User = require('../models/user'); 2 | const { generateToken } = require('../utils/jwt'); 3 | 4 | async function register(req, res) { 5 | const { username, password } = req.body; 6 | // validation 7 | // check if username duplicate 8 | // add uniq index to username 9 | const user = new User({ username, password }); 10 | // hash password 11 | await user.hashPassword(); 12 | await user.save(); 13 | const token = await generateToken({ username }); 14 | 15 | return res.json({ token }); 16 | } 17 | 18 | // fail fast 19 | 20 | async function login(req, res) { 21 | const { username, password } = req.body; 22 | const existingUser = await User.findOne({ username }).exec(); 23 | if (!existingUser) { 24 | return res.status(401).json({ error: 'invalid username or password' }); 25 | } 26 | 27 | const isPasswordValid = await existingUser.validatePassword(password); 28 | if (!isPasswordValid) { 29 | return res.status(401).json({ error: 'invalid username or password' }); 30 | } 31 | const token = await generateToken({ username, role: existingUser.role }); 32 | return res.json({ token }); 33 | } 34 | 35 | module.exports = { 36 | register, 37 | login, 38 | }; 39 | -------------------------------------------------------------------------------- /es6/index.js: -------------------------------------------------------------------------------- 1 | const obj = { 2 | greet() {}, 3 | greet1: function () {}, 4 | greet2: () => {}, 5 | }; 6 | 7 | // object literal 8 | const obj = {}; 9 | obj.greet = function () {}; 10 | obj.greet1 = function () {}; 11 | obj.greet2 = () => {}; 12 | 13 | // push, pop, shift, unshift 14 | // splice 15 | 16 | const array = [ 17 | { name: 'mason', age: 18 }, 18 | { name: 'james', age: 20 }, 19 | ]; 20 | 21 | array.find((i) => i.name === 'mason'); 22 | // { name: 'mason', age: 18 } 23 | 24 | // class inheritance 25 | // prototype pattern 26 | // 代理 delegate 27 | 28 | // Fruit getPrice() 29 | // apple.getPrice() 30 | 31 | function Person(name) { 32 | this.name = name; 33 | this.toString = function () { 34 | console.log('name: ' + this.name); 35 | }; 36 | } 37 | 38 | function Person(name) { 39 | this.name = name; 40 | this.toString = function () { 41 | console.log('name: ' + this.name); 42 | }; 43 | return undefined; 44 | } 45 | 46 | const obj = Person('mason'); 47 | obj === undefined; 48 | 49 | function Person(name) { 50 | const person = {}; 51 | // 原型链的关联 52 | person.name = name; 53 | person.toString = function () { 54 | console.log('name: ' + this.name); 55 | }; 56 | return person; 57 | } 58 | -------------------------------------------------------------------------------- /7-mongoose/src/models/student.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | const Joi = require('joi'); 3 | 4 | // firstName, lastName, email, courses 5 | 6 | const schema = new Schema({ 7 | // _id: { 8 | // type: Number, 9 | // } 10 | firstName: { 11 | type: String, 12 | required: true, 13 | minlength: 2, 14 | maxlength: 10, 15 | }, 16 | lastName: { 17 | type: String, 18 | required: true, 19 | }, 20 | email: { 21 | type: String, 22 | required: true, 23 | validate: { 24 | validator: (email) => { 25 | // regex 26 | // Joi 27 | // validator.js 28 | // express-validator 29 | // const validation = Joi.string().email().validate(email); 30 | // const { error } = validation; 31 | // if (error) { 32 | // return false; 33 | // } 34 | // return true; 35 | // 如果返回false,才是验证失败 36 | return !Joi.string().email().validate(email).error; 37 | }, 38 | msg: 'Invalid email format', 39 | }, 40 | }, 41 | courses: [ 42 | { 43 | type: String, 44 | ref: 'Course', 45 | }, 46 | ], 47 | }); 48 | 49 | const Model = model('Student', schema); 50 | 51 | module.exports = Model; 52 | -------------------------------------------------------------------------------- /es6/note.md: -------------------------------------------------------------------------------- 1 | ECMAScript 2 | ES 3 | 4 | Ecma international 5 | 6 | ES5 2009 7 | ES6 2015 8 | ES7 2016 9 | ES2022 10 | ES6+ 11 | 12 | Babel 13 | 14 | function scope 15 | globe scope 16 | block scope 块级作用域 17 | 18 | foo(); 19 | 20 | function foo(){ 21 | var fruit = 'apple'; 22 | } 23 | 24 | const obj = {}; 25 | 26 | value vs reference 27 | pass by value vs pass by reference 28 | 29 | function expression 30 | const foo = function(){}; 31 | 32 | function declaration 33 | function foo(){} 34 | 35 | back tick 36 | `` 37 | '' 38 | 39 | 解构赋值 40 | 41 | const fruit = {name: 'apple', price: 12, color: 'green'}; 42 | const {name, ...rest} = fruit; 43 | rest = {price: 12, color: 'green'}; 44 | 45 | shallow/deep clone 46 | const fruit = {name: 'apple', price: 12, color: 'green', location: {city: 'brisbane'}}; 47 | const newFruit = {...fruit}; 48 | 49 | newFruit.name = 'pear'; 50 | fruit.name => 'apple' 51 | newFruit.location.city = 'sydney'; 52 | fruit.location.city => sydney; 53 | 54 | lodash 55 | 56 | const add = (x, y) => { 57 | return {sum: x + y}; 58 | }; 59 | // equals 60 | const add = (x, y) => ({sum: x + y}); 61 | 62 | lexical scope 63 | 64 | context 65 | 66 | const calendar = { 67 | currentDay: 6, 68 | nextDay() { 69 | const cb = () => { 70 | this.currentDay++; 71 | console.log(this.currentDay); 72 | }; 73 | setTimeout(cb); 74 | }, 75 | }; 76 | calendar.nextDay(); 77 | -------------------------------------------------------------------------------- /6-mongodb/note.md: -------------------------------------------------------------------------------- 1 | SQL non-SQL 2 | 3 | SQL structured query language 4 | 关系型数据库 5 | 6 | non-sql 7 | no-sql 8 | not only sql 9 | 10 | SQL 11 | MySQL 12 | PostgresQL 13 | SQLite 14 | 15 | non-SQL 16 | 17 | document-oriented -> mongodb 18 | key-value -> redis 19 | graph-oriented -> neo4j 20 | column-family -> cassandra 21 | 22 | mongo 23 | humongous 24 | 25 | { 26 | \_id: ObjectId, 27 | 28 | } 29 | 30 | BSON - Binary JSON 31 | 32 | [ 33 | { 34 | _id: xxx1, 35 | name: yyy, 36 | age: 10, 37 | dob: xxxx 38 | }, 39 | { 40 | _id: xxx2, 41 | username: yyy 42 | } 43 | ] 44 | 45 | [0,100] 0....100 46 | (0, 100) 1...99 47 | 48 | A, B 49 | A B 1:1 50 | B A 1:1 51 | 52 | A B 1:N 53 | B A 1:1 54 | 55 | A B 1:N 56 | B A 1:N 57 | 58 | A1 B1 59 | A2 B2 60 | 61 | A1 B1 62 | A1 B2 63 | A2 B1 64 | A2 B2 65 | M:N 66 | 67 | students 68 | teachers 69 | courses 70 | 71 | C -> S 1:N 72 | S -> C 1:N 73 | C - S M:N 74 | T -> C 1:1 75 | C -> T 1:1 76 | 77 | T -> C 1:1 78 | C -> T 1:N 79 | 80 | S1,S2, 81 | C1,C2 82 | 83 | students collection 84 | [ 85 | { 86 | \_id: "S1", 87 | courses: [ 88 | { 89 | _id: "C1", 90 | name: "New Course 1", 91 | }, 92 | { 93 | _id: "C2", 94 | } 95 | ] 96 | }, 97 | { 98 | \_id: "S2", 99 | courses: [ 100 | { 101 | _id: "C1", 102 | name: "New Course 1", 103 | }, 104 | { 105 | _id: "C2", 106 | } 107 | ] 108 | } 109 | ] 110 | 111 | [ 112 | { 113 | _id: "C1", 114 | name: "New Course 1", 115 | }, 116 | { 117 | _id: "C2", 118 | } 119 | ] 120 | 121 | [ 122 | d1,d2,d3,d4 123 | ] 124 | 125 | airplane 126 | 127 | mapping 128 | [ 129 | {name: 'apple', mapping: d3},d1,d2,d4 130 | ] 131 | 132 | 10000 10000 133 | 10000 10 134 | 135 | [d1,d2,d3] 136 | [d1,d3] first pipe 137 | [d1,d3,d4] second pipe 138 | [d1',d3',d4'] third pipe 139 | [d1',d3',d4'] 140 | -------------------------------------------------------------------------------- /2-restful/note.md: -------------------------------------------------------------------------------- 1 | HTTP 2 | 3 | 0.9 4 | 1.0 5 | 1.1 - 6 | 2 - 7 | 3 8 | HTTP 9 | HTTP2 -> HTTPS 10 | 11 | TCP - UDP 12 | 13 | URL uniform resource identifier 统一资源标识符 14 | 15 | mongodb 16 | file 17 | smtp 18 | ftp 19 | http 20 | 21 | ip whitelisting 22 | 23 | https 443 24 | http 80 25 | 26 | GET -> 获取数据 -> Read 27 | POST -> 数据添加 -> Create 28 | PUT -> 更新数据,数据替换 -> Update 29 | DELETE -> 删除数据 -> Delete 30 | PATCH -> 更新数据,只更新部分数据 31 | 32 | CRUD -> 增删改查 33 | 34 | request: 35 | METHOD PATH PROTOCOL 36 | root 37 | 38 | response: 39 | PROTOCOL Status code(状态码) 40 | 41 | https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Messages#http_%E8%AF%B7%E6%B1%82 42 | 报文 43 | 44 | client [browser, server, cmd line] 45 | server 46 | 47 | preflight 48 | 49 | x-custom-header 50 | 51 | C - P - S 52 | C - S 53 | https://s.com 54 | https://p.com/?url=https://s.com 55 | 56 | 204 no content 57 | 209 conflicts 58 | 59 | 序列化与反序列化 60 | 61 | public api server 62 | web server 63 | 64 | api server 65 | 66 | GET /books 67 | 68 | 无状态 69 | A,B 70 | B,A 71 | 72 | rpc 73 | 74 | Restful api 设计规范(建议) 75 | 76 | 1. versioning (版本) 77 | example.com/api/v1 78 | example.com/v1 79 | example.com/v2/books 80 | 81 | 2. url 里,尽量使用名词 noun,不要使用动词, 资源尽量使用复数形式 82 | GET /v1/books 83 | GET /v1/getBooks x 84 | 85 | 3. 保证 GET 不会对资源进行修改(污染) 86 | GET /v1/books (只读数据,而不做更新或添加) 87 | 88 | 4. url 推荐使用嵌套结构 89 | GET /posts/:postId/comments 90 | GET /posts/{postId}/comments 91 | GET /posts/post123/comments 92 | 93 | 5. 对返回的数据进行分页(注意返回的大小) 94 | 1000 个数据 95 | 把数据分层 100 页,每页 10 个 96 | GET /v1/books -> 10 个数据 97 | GET /v1/books?page=2&pageSize=100 -> 100 个数据 98 | 99 | 6. 使用正确的 status code 来表示返回的结果 100 | 101 | 7. 尽量返回人性化的文本信息(错误信息) 102 | {"error":"invalid password"} 103 | {"error": 1001} // error code 104 | 105 | sequence diagram 106 | 107 | monolith server 108 | -------------------------------------------------------------------------------- /async/promis-quiz.md: -------------------------------------------------------------------------------- 1 | 1 2 | 3 | ```js 4 | setTimeout(() => console.log(1)); 5 | Promise.resolve().then(() => console.log(2)); 6 | setTimeout(() => { 7 | console.log(3); 8 | Promise.resolve().then(() => console.log(3.1)); 9 | }); 10 | setTimeout(() => console.log(4)); 11 | Promise.resolve().then(() => { 12 | console.log(5); 13 | Promise.resolve().then(() => console.log(5.1)); 14 | setTimeout(() => console.log(5.2)); 15 | }); 16 | Promise.resolve().then(() => console.log(6)); 17 | ``` 18 | 19 | 2 20 | 21 | ```js 22 | Promise.resolve().then(() => console.log(1)); 23 | Promise.resolve().catch(() => console.log(2)); 24 | Promise.resolve() 25 | .then(() => console.log(3)) 26 | .then(() => console.log(3.1)); 27 | Promise.reject().catch(() => console.log(4)); 28 | Promise.resolve() 29 | .then(() => console.log(5)) 30 | .catch(() => console.log(5.1)); 31 | Promise.resolve() 32 | .catch(() => console.log(6)) 33 | .then(() => console.log(6.1)); 34 | Promise.reject() 35 | .then(() => console.log(7)) 36 | .catch(() => console.log(7.1)); 37 | Promise.reject() 38 | .catch(() => console.log(8)) 39 | .then(() => console.log(8.1)); 40 | ``` 41 | 42 | 3 43 | 44 | ```js 45 | setTimeout(() => console.log(1)); 46 | new Promise((res, rej) => { 47 | console.log(2); 48 | setTimeout(() => console.log(2.1)); 49 | res(); 50 | }).then(() => console.log(2.2)); 51 | setTimeout(() => { 52 | console.log(3); 53 | new Promise((res, rej) => { 54 | console.log(3.1); 55 | setTimeout(() => console.log(3.2)); 56 | rej(); 57 | }) 58 | .then(() => console.log(3.3)) 59 | .catch(() => console.log(3.4)); 60 | }); 61 | Promise.resolve().then(() => console.log(4)); 62 | setTimeout(() => { 63 | console.log(5); 64 | setTimeout(() => console.log(5.1)); 65 | Promise.resolve().then(() => { 66 | setTimeout(() => console.log(5.2)); 67 | console.log(5.3); 68 | }); 69 | }); 70 | ``` 71 | 72 | 4 73 | 74 | ```js 75 | async function foo() { 76 | console.log(1); 77 | await bar(); 78 | console.log(2); 79 | } 80 | 81 | async function bar() { 82 | console.log(3); 83 | const a = await 4; 84 | console.log(a); 85 | } 86 | 87 | console.log(5); 88 | foo(); 89 | console.log(6); 90 | ``` 91 | -------------------------------------------------------------------------------- /7-mongoose/src/controllers/course.js: -------------------------------------------------------------------------------- 1 | const Course = require('../models/course'); 2 | const Joi = require('joi'); 3 | 4 | async function getAllCourses(req, res) { 5 | // try { 6 | const courses = await Course.find().exec(); 7 | return res.json(courses); 8 | // } catch (e) { 9 | 10 | // 11 | // } 12 | 13 | // Course.find().exec().then((res)=>{}).catch((err)=>{}) 14 | 15 | // Course.find((error, result) => { 16 | // if (error) { 17 | // return .... 18 | // } 19 | // // result handling 20 | // }) 21 | } 22 | 23 | async function getCourseById(req, res) { 24 | const { id } = req.params; 25 | const course = await Course.findById(id) 26 | .populate('students', { firstName: 1 }) 27 | .exec(); 28 | if (!course) { 29 | return res.status(404).json({ error: 'Course not found' }); 30 | } 31 | return res.json(course); 32 | } 33 | 34 | async function addCourse(req, res) { 35 | // const { code, name, description } = req.body; 36 | const schema = Joi.object({ 37 | name: Joi.string().min(2).max(10).required(), 38 | // COMP1001 SCI2002 39 | code: Joi.string() 40 | .regex(/^[a-zA-Z]+[0-9]+$/) 41 | .required(), 42 | description: Joi.string(), 43 | }); 44 | const { code, name, description } = await schema.validateAsync(req.body, { 45 | allowUnknown: true, 46 | stripUnknown: true, 47 | }); 48 | 49 | const existingCourse = await Course.findById(code).exec(); 50 | if (existingCourse) { 51 | return res.status(409).json({ error: 'duplicate course code' }); 52 | } 53 | const course = new Course({ name, code, description }); 54 | await course.save(); 55 | return res.status(201).json(course); 56 | } 57 | 58 | async function updateCourseById(req, res) { 59 | const { id } = req.params; 60 | const { name, description } = req.body; 61 | const course = await Course.findByIdAndUpdate( 62 | id, 63 | { name, description }, 64 | { new: true } 65 | ).exec(); 66 | if (!course) { 67 | return res.status(404).json({ error: 'Course not found' }); 68 | } 69 | return res.json(course); 70 | } 71 | 72 | async function deleteCourseById(req, res) { 73 | const { id } = req.params; 74 | const course = await Course.findByIdAndDelete(id).exec(); 75 | if (!course) { 76 | return res.status(404).json({ error: 'Course not found' }); 77 | } 78 | return res.sendStatus(204); 79 | } 80 | 81 | module.exports = { 82 | getAllCourses, 83 | getCourseById, 84 | updateCourseById, 85 | deleteCourseById, 86 | addCourse, 87 | }; 88 | 89 | // app - CMS content management system 90 | -------------------------------------------------------------------------------- /async/index.js: -------------------------------------------------------------------------------- 1 | function fetchData(url, cb) { 2 | setTimeout(() => { 3 | console.log('cb', url); 4 | cb(url); 5 | }); 6 | } 7 | 8 | const cb = (data1) => { 9 | // 10 | // 11 | // 12 | // 13 | // if () {} 14 | const cb2 = (data2) => { 15 | fetchData('example.com/3', (data3) => { 16 | fetchData('example.com/4', (data4) => {}); 17 | }); 18 | }; 19 | fetchData('example.com/2', cb2); 20 | }; 21 | // callback hell 22 | fetchData('example.com/1', cb); 23 | 24 | // Promise 25 | /** 26 | * 三种状态 27 | * pending resolved(fulfilled) rejected 28 | * 29 | * 状态不可逆 30 | * pending -> resolved 31 | * pending -> rejected 32 | * 33 | * 34 | */ 35 | // resolve 36 | // reject 37 | // const promise = new Promise((res, rej) => { 38 | // res([]); 39 | // // rej({}) 40 | // }) 41 | 42 | // // promise chain 43 | // promise.then((data) => { 44 | // // data = []; 45 | 46 | // return {}; 47 | // // return new Promise() // async call 48 | // }).then(() => { 49 | 50 | // }).catch((err) => { 51 | // // err = {} 52 | // return {}; // promise 53 | // }).then().catch() 54 | 55 | function fetchDataPromise(url) { 56 | return new Promise((res, rej) => { 57 | // setTimeout(() => { 58 | console.log('promise', url); 59 | rej(url); 60 | // if () { 61 | // rej() 62 | // } 63 | // }); 64 | }); 65 | } 66 | 67 | const isLoading = false; 68 | 69 | isLoading = true; 70 | const promise = fetchDataPromise('example.com/1'); 71 | promise 72 | .then((data1) => { 73 | return fetchDataPromise('example.com/2'); 74 | }) 75 | .then((data2) => { 76 | return fetchDataPromise('example.com/3'); 77 | }) 78 | .then((data3) => { 79 | return fetchDataPromise('example.com/4'); 80 | }) 81 | .then((data4) => { 82 | return fetchDataPromise('example.com/5'); 83 | }) 84 | .catch((err) => { 85 | console.log(err); 86 | }) 87 | .finally(() => { 88 | isLoading = false; 89 | }); 90 | 91 | // promise queue / micro task queue 92 | // macro task queue 93 | // [p2], [cb1] 94 | 95 | // async await 96 | // syntax sugar 97 | 98 | async function main() { 99 | // fetchDataPromise().then().then() 100 | try { 101 | // 102 | const result = await fetchDataPromise(); 103 | // 104 | const result2 = await fetchDataPromise(); 105 | } catch (e) { 106 | console.log(e); 107 | } finally { 108 | } 109 | // ... 110 | } 111 | 112 | main(); 113 | // (async () => { 114 | // const result = await fetchDataPromise(); 115 | // })() 116 | -------------------------------------------------------------------------------- /4-23nodeassignment/router.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | // 数据暂存 5 | const tasks = []; 6 | let id = 1; 7 | // let flag = false; 8 | 9 | // {data: , error:, status: } 10 | // 获取全部任务 11 | router.get('/tasks', (req, res) => { 12 | // // 判断是否有任务,没有则返回相关信息并跳出查询 13 | // if (tasks.length === 0) { 14 | // res.send('当前还没有任务,请新建任务后再查询。'); 15 | // return; 16 | // } 17 | // array.filter() 18 | // ''.includes('') 19 | 20 | let tempArr = []; 21 | for (let i = 0; i < tasks.length; i++) { 22 | if (typeof tasks[i] !== 'string') { 23 | tempArr.push(tasks[i]); 24 | } 25 | } 26 | // 如果有,返回全部任务 27 | res.send(tempArr); 28 | }); 29 | 30 | // 获取指定任务 31 | router.get('/tasks/:id', (req, res) => { 32 | // 任务id是否存在 33 | if (req.params.id > 0 && req.params.id <= tasks.length) { 34 | // 判断任务是否已经完成 35 | if (tasks[req.params.id - 1].done) { 36 | res.send(`你查询的id为${req.params.id}的任务已完成。`); 37 | return; 38 | } 39 | // 存在,返回指定任务 40 | res.send(tasks[req.params.id - 1]); // 这里想用array.filter()/find()来实现,但一直返回空值,只能先用笨办法 41 | } else { 42 | // 不存在,返回无此任务的信息 43 | res.status(404).send(`你查询的id为${req.params.id}的任务不存在。`); 44 | } 45 | }); 46 | 47 | // 添加任务 48 | router.post('/tasks', (req, res) => { 49 | // 生成任务描述 50 | let taskString = 'tasks No.' + id; 51 | // 向数组添加任务数据 52 | tasks.push({ id: id++, description: taskString, done: false }); 53 | // ++id, id++ 54 | // id自增 55 | // id++; 56 | res.status(201).send(tasks); 57 | }); 58 | 59 | // 更新指定任务 60 | router.put('/tasks/:id', (req, res) => { 61 | const { description, done } = req.body; 62 | const elementIndex = array.findIndex((i) => Number(id) === i.id); 63 | tasks[elementIndex].description = description; 64 | // negation 65 | // const a = '123'; !a => false 66 | tasks[elementIndex].done = !!done; 67 | if (req.params.id > 0 && req.params.id <= tasks.length) { 68 | // tasks[req.params.id - 1].done = !flag; 69 | res.send(tasks[req.params.id - 1]); 70 | } else { 71 | res.status(404).send(`你要更新的id为${req.params.id}的任务不存在。`); 72 | } 73 | }); 74 | 75 | // 删除指定任务 76 | router.delete('/tasks/:id', (req, res) => { 77 | // id -> string 78 | // === false -> string === number 79 | // array.find() 80 | if (req.params.id > 0 && req.params.id <= tasks.length) { 81 | tasks.splice( 82 | req.params.id - 1, 83 | 1, 84 | `id为${req.params.id}任务不存在或已删除` 85 | ); 86 | res.status(204).send(`你删除的任务id为${req.params.id}`); 87 | } else { 88 | res.status(404).send(`你要删除的id为${req.params.id}的任务不存在。`); 89 | } 90 | }); 91 | 92 | module.exports = { router }; 93 | -------------------------------------------------------------------------------- /5-api-server/src/controllers/task.js: -------------------------------------------------------------------------------- 1 | const tasks = []; 2 | class Task { 3 | constructor(id, description) { 4 | this.id = id; 5 | this.description = description; 6 | this.done = false; 7 | } 8 | } 9 | let _id = 1; 10 | 11 | // yaml 12 | 13 | /** 14 | * @swagger 15 | * components: 16 | * schemas: 17 | * Task: 18 | * type: Object 19 | * required: 20 | * - description 21 | * properties: 22 | * id: 23 | * type: string 24 | * description: auto generated unique identifier 25 | * description: 26 | * type: string 27 | * description: description of the task 28 | * done: 29 | * type: boolean 30 | * description: status of the task 31 | * example: 32 | * id: 1 33 | * description: task 1 34 | * done: false 35 | */ 36 | 37 | /** 38 | * @swagger 39 | * /tasks: 40 | * get: 41 | * summary: return all tasks 42 | * tags: [Tasks] 43 | * parameters: 44 | * - name: description 45 | * in: query 46 | * description: filter tasks by description 47 | * schema: 48 | * type: string 49 | * responses: 50 | * 200: 51 | * description: array of tasks 52 | * content: 53 | * application/json: 54 | * schema: 55 | * type: array 56 | * items: 57 | * $ref: '#/components/schemas/Task' 58 | * 59 | */ 60 | const getAllTasks = (req, res) => { 61 | const { description } = req.query; 62 | if (description) { 63 | const filteredTasks = tasks.filter((e) => 64 | e.description.includes(description) 65 | ); 66 | res.json(filteredTasks); 67 | return; 68 | } 69 | res.json(tasks); 70 | return; 71 | }; 72 | 73 | const getTaskById = (req, res) => { 74 | const { id } = req.params; 75 | // var != null -> null / undefined 76 | // +id 77 | // NaN -> not a number 78 | const task = tasks.find((e) => e.id === Number(id)); 79 | if (!task) { 80 | res.status(404).json({ error: 'Task not found' }); 81 | return; 82 | } 83 | res.json(task); 84 | // task ? res.json(task) : res.status(404).json({ error: 'Task not found' }); 85 | // return; 86 | }; 87 | 88 | const addTask = (req, res) => { 89 | const { description } = req.body; 90 | const task = new Task(_id++, description); 91 | tasks.push(task); 92 | res.status(201).json(task); 93 | return; 94 | }; 95 | 96 | const updateTaskById = (req, res) => { 97 | const { id } = req.params; 98 | // req.body = {description: 'xxxx'}; 99 | const { description, done } = req.body; 100 | 101 | const task = tasks.find((e) => e.id === Number(id)); 102 | if (!task) { 103 | res.status(404).json('Task not found'); 104 | return; 105 | } 106 | if (description) { 107 | task.description = description; 108 | } 109 | if (done) { 110 | task.done = !!done; 111 | } 112 | res.json(task); 113 | return; 114 | }; 115 | 116 | const deleteTaskById = (req, res) => { 117 | const { id } = req.params; 118 | const index = tasks.findIndex((i) => i.id === Number(id)); 119 | if (index === -1) { 120 | res.status(404).json({ error: 'Task not found' }); 121 | return; 122 | } 123 | tasks.splice(index, 1); 124 | res.sendStatus(204); 125 | return; 126 | }; 127 | 128 | module.exports = { 129 | getAllTasks, 130 | getTaskById, 131 | updateTaskById, 132 | deleteTaskById, 133 | addTask, 134 | }; 135 | -------------------------------------------------------------------------------- /7-mongoose/src/controllers/student.js: -------------------------------------------------------------------------------- 1 | const Course = require('../models/course'); 2 | const Student = require('../models/student'); 3 | 4 | // dependency injection 5 | // decorators 6 | 7 | // subscribe, unsubscribe 8 | 9 | // debounce 200ms 10 | 11 | async function getAllStudents(req, res) { 12 | // db.students.find() 13 | // query 14 | // query chain 15 | // .sort().limit() -> pagination 16 | const students = await Student.find() 17 | .select({ firstName: 1, lastName: 1 }) 18 | .exec(); 19 | // const query = Student.find(); 20 | // if (process.env.NODE_ENV === 'production') { 21 | // query.select('firstName lastName'); 22 | // } 23 | // const students = await query.exec(); 24 | 25 | /** 26 | * { 27 | * data: [], 28 | * error: "", 29 | * message: "" 30 | * } 31 | * 32 | * res.json({ data: students }) 33 | */ 34 | return res.json(students); 35 | } 36 | 37 | async function getStudentById(req, res) { 38 | const { id } = req.params; 39 | const student = await Student.findById(id).exec(); 40 | if (!student) { 41 | return res.status(404).json({ error: 'student not found' }); 42 | } 43 | return res.json(student); 44 | } 45 | 46 | async function addStudent(req, res) { 47 | const { firstName, lastName, email } = req.body; 48 | // data validation 49 | const student = new Student({ firstName, lastName, email }); 50 | // try { 51 | 52 | await student.save(); 53 | return res.status(201).json(student); 54 | // } catch (e) { 55 | // next(e); 56 | // return res.status(400).json(e); 57 | // } 58 | } 59 | 60 | async function updateStudentById(req, res) { 61 | const { id } = req.params; 62 | const { firstName, lastName, email } = req.body; 63 | // data validation 64 | const student = await Student.findByIdAndUpdate( 65 | id, 66 | { firstName, lastName, email }, 67 | { new: true } 68 | ).exec(); 69 | if (!student) { 70 | // return next(new DocumentNotFound('student', '_id')); 71 | return res.status(404).json({ error: 'student not found' }); 72 | } 73 | return res.json(student); 74 | } 75 | 76 | async function deleteStudentById(req, res) { 77 | const { id } = req.params; 78 | const student = await Student.findByIdAndDelete(id).exec(); 79 | if (!student) { 80 | return res.status(404).json({ error: 'student not found' }); 81 | } 82 | await Course.updateMany({ students: id }, { $pull: { students: id } }).exec(); 83 | return res.sendStatus(204); 84 | } 85 | 86 | async function addStudentToCourse(req, res) { 87 | // get student and course id 88 | const { id, code } = req.params; 89 | const course = await Course.findById(code).exec(); 90 | let student = await Student.findById(id).exec(); 91 | if (!student || !course) { 92 | return res.status(404).json({ error: 'student or course not found' }); 93 | } 94 | // student.courses.addToSet(code); 95 | // await student.save(); 96 | // const courseName = course.name; 97 | student = await Student.findByIdAndUpdate( 98 | id, 99 | { $push: { courses: code } }, 100 | { new: true } 101 | ).exec(); 102 | course.students.addToSet(id); 103 | await course.save(); 104 | 105 | return res.json(student); 106 | } 107 | 108 | async function removeStudentFromCourse(req, res) { 109 | // get student and course id 110 | const { id, code } = req.params; 111 | const course = await Course.findById(code).exec(); 112 | let student = await Student.findById(id).exec(); 113 | if (!student || !course) { 114 | return res.status(404).json({ error: 'student or course not found' }); 115 | } 116 | // student.courses.includes(code) 117 | student = await Student.findByIdAndUpdate( 118 | id, 119 | { $pull: { courses: code } }, 120 | { new: true } 121 | ).exec(); 122 | await Course.findByIdAndUpdate(code, { $pull: { students: id } }).exec(); 123 | 124 | return res.json(student); 125 | } 126 | 127 | module.exports = { 128 | getAllStudents, 129 | getStudentById, 130 | updateStudentById, 131 | deleteStudentById, 132 | addStudent, 133 | addStudentToCourse, 134 | removeStudentFromCourse, 135 | }; 136 | -------------------------------------------------------------------------------- /3-npm/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const app = express(); 4 | 5 | // application level middleware 6 | app.use(express.json()); 7 | // use applies to all methods 8 | 9 | // app.get('/', m1); 10 | // app.get('/', m1,m2,m3,m4, (req, res) => { 11 | 12 | const tasks = []; 13 | 14 | let id = 1; 15 | 16 | // request -> GET /v1/tasks 17 | // app.get('/v1/tasks') 18 | // match 19 | 20 | // request -> GET /v1/tasks 21 | // app.post('/v1/tasks') 22 | // not match 23 | 24 | // request -> GET /v1/tasks 25 | // app.get('/v1') 26 | // not match 27 | 28 | // request -> GET /v1/tasks 29 | // regex, * 30 | // app.use('/v1/tasks') 31 | // /v1/tasks /v1/tasks/:id /v1/tasks/xxxxxx 32 | // match 33 | 34 | // { 35 | // "id": 1, 36 | // "description": "task No.1", 37 | // "done": false - 默认false 38 | // } 39 | 40 | // req, res, next 41 | // application.method(path, callback function - route handler) 42 | app.get('/', (req, res) => { 43 | // if (true) { 44 | // res.send('hello world!!!!!!!!!'); 45 | // return; 46 | // } 47 | // 1 48 | // res.send('hello world'); 49 | // return; 50 | // 2 51 | return res.send('hello world'); 52 | // res.json({name: "mason"}) (默认 200 status code) 53 | // 只返回 status code 54 | // res.sendStatus(204); 55 | // 只设置status code 56 | // res.status(201).json({}) 57 | }); 58 | 59 | /** 60 | * 从request里取数据 61 | * 1. body -> POST, PUT, PATCH 62 | * req.body (必须使用express.json() middleware) 63 | * 2. query param -> GET (?) 64 | * req.query 65 | * 3. route param -> GET, POST, PUT, DELETE (大多数情况都是id) 66 | * /:id 67 | */ 68 | app.post('/:id', (req, res) => { 69 | // req.body = {name: "mason"} 70 | // const name = req.body.name; 71 | const { name } = req.body; 72 | // console.log(name) // "mason" 73 | const { title } = req.query; 74 | const { id } = req.params; 75 | 76 | // let key = 'a'; 77 | // key = 'b'; 78 | // const obj = {[key]:name} 79 | 80 | res.send({ name, title, id }); 81 | // {name: name} -> {name} 82 | }); 83 | // app.put 84 | // app.delete 85 | 86 | const authGuard = (req, res, next) => { 87 | // get token from request header 88 | // extract user info from token or from db 89 | req.user = userInfo; 90 | next(); 91 | }; 92 | 93 | const m1 = (req, res, next) => { 94 | // req.user -> userInfo 95 | // if (error exists) { 96 | // next(new Error('xxx')); 97 | // return; 98 | // } 99 | // if token not exist { 100 | // res.json({ error: "token not found" }); 101 | // xxxxx can be string, can be object {type:xxx, message:xxxx}, can be new Error(''); 102 | // next(new Error('error')); 103 | // next(xxxx); (no need) 104 | // return; 105 | // } 106 | next(); 107 | }; 108 | 109 | // only target validation error 110 | const errorM1 = (error, req, res, next) => { 111 | // if (error.type === 'validationError') { 112 | // res.status(400).json({ error: error.message }); 113 | // return; 114 | // } 115 | // if (error instanceof CustomError) { 116 | // res.status(400).json({ error: error.message }); 117 | // return; 118 | // } 119 | next(error); 120 | }; 121 | 122 | const errorHandler = (err, req, res, next) => { 123 | console.log(err); // logging lib -> db -> log -> logging platform 124 | res.status(500).json({ error: 'please try later' }); 125 | }; 126 | 127 | // next(new CustomError('')); 128 | class CustomError extends Error {} 129 | 130 | // const error = new ValidationError(); 131 | class ValidationError extends CustomError { 132 | constructor() { 133 | super(); 134 | } 135 | } 136 | 137 | const taskRouter = express.Router(); 138 | // mini-app 139 | taskRouter.get('/', (req, res) => { 140 | res.json([1, 2, 3]); 141 | }); 142 | 143 | // route handler 144 | const v1Router = express.Router(); 145 | v1Router.use('/tasks', taskRouter); 146 | app.use('/v1', v1Router); 147 | 148 | app.use(errorM1); 149 | // app.use(errorM2); 150 | app.use(errorHandler); 151 | 152 | app.listen(3000); 153 | 154 | // template engine 155 | 156 | const cors = (req, res, next) => { 157 | res.setHeader('Access-Control-Allow-Origin', '*'); 158 | res.setHeader('Access-Control-Allow-Headers', 'content-type'); 159 | res.setHeader('Access-Control-Allow-Methods', '*'); 160 | next(); 161 | }; 162 | 163 | app.use(cors); 164 | 165 | // function cors(){} 166 | 167 | // const taskRouter = express.Router(); 168 | // // mini-app 169 | // taskRouter.get('/', (req, res) => { 170 | // res.json([1, 2, 3]); 171 | // }); 172 | 173 | // // route handler 174 | // const v1Router = express.Router(); 175 | // v1Router.use('/tasks', taskRouter); 176 | // app.use('/v1', v1Router); 177 | 178 | // GET /v1/tasks 179 | -------------------------------------------------------------------------------- /4-23nodeassignment/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "4-23nodeassignment", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.8", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 10 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 11 | "requires": { 12 | "mime-types": "~2.1.34", 13 | "negotiator": "0.6.3" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 20 | }, 21 | "body-parser": { 22 | "version": "1.19.2", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", 24 | "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", 25 | "requires": { 26 | "bytes": "3.1.2", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "~1.1.2", 30 | "http-errors": "1.8.1", 31 | "iconv-lite": "0.4.24", 32 | "on-finished": "~2.3.0", 33 | "qs": "6.9.7", 34 | "raw-body": "2.4.3", 35 | "type-is": "~1.6.18" 36 | } 37 | }, 38 | "bytes": { 39 | "version": "3.1.2", 40 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 41 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 42 | }, 43 | "content-disposition": { 44 | "version": "0.5.4", 45 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 46 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 47 | "requires": { 48 | "safe-buffer": "5.2.1" 49 | } 50 | }, 51 | "content-type": { 52 | "version": "1.0.4", 53 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 54 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 55 | }, 56 | "cookie": { 57 | "version": "0.4.2", 58 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", 59 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" 60 | }, 61 | "cookie-signature": { 62 | "version": "1.0.6", 63 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 64 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 65 | }, 66 | "debug": { 67 | "version": "2.6.9", 68 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 69 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 70 | "requires": { 71 | "ms": "2.0.0" 72 | } 73 | }, 74 | "depd": { 75 | "version": "1.1.2", 76 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 77 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 78 | }, 79 | "destroy": { 80 | "version": "1.0.4", 81 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 82 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 83 | }, 84 | "ee-first": { 85 | "version": "1.1.1", 86 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 87 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 88 | }, 89 | "encodeurl": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 92 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 93 | }, 94 | "escape-html": { 95 | "version": "1.0.3", 96 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 97 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 98 | }, 99 | "etag": { 100 | "version": "1.8.1", 101 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 102 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 103 | }, 104 | "express": { 105 | "version": "4.17.3", 106 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", 107 | "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", 108 | "requires": { 109 | "accepts": "~1.3.8", 110 | "array-flatten": "1.1.1", 111 | "body-parser": "1.19.2", 112 | "content-disposition": "0.5.4", 113 | "content-type": "~1.0.4", 114 | "cookie": "0.4.2", 115 | "cookie-signature": "1.0.6", 116 | "debug": "2.6.9", 117 | "depd": "~1.1.2", 118 | "encodeurl": "~1.0.2", 119 | "escape-html": "~1.0.3", 120 | "etag": "~1.8.1", 121 | "finalhandler": "~1.1.2", 122 | "fresh": "0.5.2", 123 | "merge-descriptors": "1.0.1", 124 | "methods": "~1.1.2", 125 | "on-finished": "~2.3.0", 126 | "parseurl": "~1.3.3", 127 | "path-to-regexp": "0.1.7", 128 | "proxy-addr": "~2.0.7", 129 | "qs": "6.9.7", 130 | "range-parser": "~1.2.1", 131 | "safe-buffer": "5.2.1", 132 | "send": "0.17.2", 133 | "serve-static": "1.14.2", 134 | "setprototypeof": "1.2.0", 135 | "statuses": "~1.5.0", 136 | "type-is": "~1.6.18", 137 | "utils-merge": "1.0.1", 138 | "vary": "~1.1.2" 139 | } 140 | }, 141 | "finalhandler": { 142 | "version": "1.1.2", 143 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 144 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 145 | "requires": { 146 | "debug": "2.6.9", 147 | "encodeurl": "~1.0.2", 148 | "escape-html": "~1.0.3", 149 | "on-finished": "~2.3.0", 150 | "parseurl": "~1.3.3", 151 | "statuses": "~1.5.0", 152 | "unpipe": "~1.0.0" 153 | } 154 | }, 155 | "forwarded": { 156 | "version": "0.2.0", 157 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 158 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 159 | }, 160 | "fresh": { 161 | "version": "0.5.2", 162 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 163 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 164 | }, 165 | "http-errors": { 166 | "version": "1.8.1", 167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", 168 | "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", 169 | "requires": { 170 | "depd": "~1.1.2", 171 | "inherits": "2.0.4", 172 | "setprototypeof": "1.2.0", 173 | "statuses": ">= 1.5.0 < 2", 174 | "toidentifier": "1.0.1" 175 | } 176 | }, 177 | "iconv-lite": { 178 | "version": "0.4.24", 179 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 180 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 181 | "requires": { 182 | "safer-buffer": ">= 2.1.2 < 3" 183 | } 184 | }, 185 | "inherits": { 186 | "version": "2.0.4", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 188 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 189 | }, 190 | "ipaddr.js": { 191 | "version": "1.9.1", 192 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 193 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 194 | }, 195 | "media-typer": { 196 | "version": "0.3.0", 197 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 198 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 199 | }, 200 | "merge-descriptors": { 201 | "version": "1.0.1", 202 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 203 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 204 | }, 205 | "methods": { 206 | "version": "1.1.2", 207 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 208 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 209 | }, 210 | "mime": { 211 | "version": "1.6.0", 212 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 213 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 214 | }, 215 | "mime-db": { 216 | "version": "1.52.0", 217 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 218 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 219 | }, 220 | "mime-types": { 221 | "version": "2.1.35", 222 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 223 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 224 | "requires": { 225 | "mime-db": "1.52.0" 226 | } 227 | }, 228 | "ms": { 229 | "version": "2.0.0", 230 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 231 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 232 | }, 233 | "negotiator": { 234 | "version": "0.6.3", 235 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 236 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 237 | }, 238 | "on-finished": { 239 | "version": "2.3.0", 240 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 241 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 242 | "requires": { 243 | "ee-first": "1.1.1" 244 | } 245 | }, 246 | "parseurl": { 247 | "version": "1.3.3", 248 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 249 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 250 | }, 251 | "path-to-regexp": { 252 | "version": "0.1.7", 253 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 254 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 255 | }, 256 | "proxy-addr": { 257 | "version": "2.0.7", 258 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 259 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 260 | "requires": { 261 | "forwarded": "0.2.0", 262 | "ipaddr.js": "1.9.1" 263 | } 264 | }, 265 | "qs": { 266 | "version": "6.9.7", 267 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", 268 | "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" 269 | }, 270 | "range-parser": { 271 | "version": "1.2.1", 272 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 273 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 274 | }, 275 | "raw-body": { 276 | "version": "2.4.3", 277 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", 278 | "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", 279 | "requires": { 280 | "bytes": "3.1.2", 281 | "http-errors": "1.8.1", 282 | "iconv-lite": "0.4.24", 283 | "unpipe": "1.0.0" 284 | } 285 | }, 286 | "safe-buffer": { 287 | "version": "5.2.1", 288 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 289 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 290 | }, 291 | "safer-buffer": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 294 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 295 | }, 296 | "send": { 297 | "version": "0.17.2", 298 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", 299 | "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", 300 | "requires": { 301 | "debug": "2.6.9", 302 | "depd": "~1.1.2", 303 | "destroy": "~1.0.4", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "fresh": "0.5.2", 308 | "http-errors": "1.8.1", 309 | "mime": "1.6.0", 310 | "ms": "2.1.3", 311 | "on-finished": "~2.3.0", 312 | "range-parser": "~1.2.1", 313 | "statuses": "~1.5.0" 314 | }, 315 | "dependencies": { 316 | "ms": { 317 | "version": "2.1.3", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 319 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 320 | } 321 | } 322 | }, 323 | "serve-static": { 324 | "version": "1.14.2", 325 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", 326 | "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", 327 | "requires": { 328 | "encodeurl": "~1.0.2", 329 | "escape-html": "~1.0.3", 330 | "parseurl": "~1.3.3", 331 | "send": "0.17.2" 332 | } 333 | }, 334 | "setprototypeof": { 335 | "version": "1.2.0", 336 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 337 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 338 | }, 339 | "statuses": { 340 | "version": "1.5.0", 341 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 342 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 343 | }, 344 | "toidentifier": { 345 | "version": "1.0.1", 346 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 347 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 348 | }, 349 | "type-is": { 350 | "version": "1.6.18", 351 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 352 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 353 | "requires": { 354 | "media-typer": "0.3.0", 355 | "mime-types": "~2.1.24" 356 | } 357 | }, 358 | "unpipe": { 359 | "version": "1.0.0", 360 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 361 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 362 | }, 363 | "utils-merge": { 364 | "version": "1.0.1", 365 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 366 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 367 | }, 368 | "vary": { 369 | "version": "1.1.2", 370 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 371 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 372 | } 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /es6/es6.md: -------------------------------------------------------------------------------- 1 | # ES6+ 2 | 3 | - [var vs let and const](#let-and-const) 4 | - [Template String](#template-string) 5 | - [Spread operator](#spread-operator) 6 | - [Destructuring](#destructuring) 7 | - [Default parameters](#default-parameters) 8 | - [Arrow function](#arrow-function) 9 | - [this](#this) 10 | - [Common array operations](#common-array-operations) 11 | - [Set](#set) 12 | - [Classes](#classes) 13 | - [Closure](#closure) 14 | 15 | ## var vs let and const 16 | 17 | They all used for variable declaration, the main difference is the scope. 18 | 19 | ### var 20 | 21 | #### Scope 22 | 23 | var is function scoped, it means if the variable is declared within a function, it can be accessed within the function. Similarly, if var is used outside of the function, the variable can be accessed in via window object. (in the browser) 24 | 25 | ```js 26 | var apple = 'apple'; 27 | function foo() { 28 | var pear = 'pear'; 29 | console.log(apple); // apple 30 | console.log(pear); // pear 31 | } 32 | console.log(apple); // apple 33 | console.log(pear); // Uncaught ReferenceError: pear is not defined 34 | ``` 35 | 36 | #### Re-declare and update 37 | 38 | ```js 39 | var fruit = 'apple'; 40 | var fruit = 'pear'; 41 | console.log(fruit); // pear 42 | fruit = 'grape'; 43 | console.log(fruit); // grape 44 | ``` 45 | 46 | #### Hoisting 47 | 48 | ```js 49 | console.log(fruit); // undefined 50 | var fruit = 'apple'; 51 | ``` 52 | 53 | equals 54 | 55 | ```js 56 | var fruit; 57 | console.log(fruit); // undefined 58 | fruit = 'apple'; 59 | ``` 60 | 61 | #### Problem 62 | 63 | ```js 64 | var fruit = 'apple'; 65 | if (true) { 66 | // think about this is in another file 67 | var fruit = 'pear'; 68 | } 69 | console.log(fruit); // pear 70 | ``` 71 | 72 | ### let 73 | 74 | #### Scope 75 | 76 | let is block scoped. A block is a chunk of code wrapped by currly brackets `{}` 77 | for example: 78 | `function() {// this is a block}` 79 | `if(true) {// this is also a block}` 80 | let's reuse the example above but replace the keyword with _let_ 81 | 82 | ```js 83 | let fruit = 'apple'; 84 | if (true) { 85 | let fruit = 'pear'; 86 | } 87 | console.log(fruit); // apple 88 | ``` 89 | 90 | #### Re-declare and update 91 | 92 | ```js 93 | let fruit = 'apple'; 94 | // let fruit = "pear"; // Uncaught SyntaxError: Identifier 'fruit' has already been declared 95 | fruit = 'grape'; 96 | console.log(fruit); // grape 97 | ``` 98 | 99 | #### Hoisting 100 | 101 | ```js 102 | console.log(fruit); // Uncaught ReferenceError: Cannot access 'fruit' before initialization 103 | let fruit = 'apple'; 104 | ``` 105 | 106 | Different to _var_, let is hoisted, but the vairable is not initialized 107 | 108 | ### const 109 | 110 | Scope and the hoisting is the same as _let_ 111 | 112 | #### Re-declare 113 | 114 | ```js 115 | const fruit = 'apple'; 116 | // const fruit = "pear"; // Uncaught SyntaxError: Identifier 'fruit' has already been declared 117 | fruit = 'grape'; // Uncaught TypeError: Assignment to constant variable. 118 | console.log(fruit); 119 | ``` 120 | 121 | #### Update 122 | 123 | ```js 124 | const fruit = { name: 'apple', color: 'red' }; 125 | // fruit = {name: "apple", color: "green"}; // Uncaught TypeError: Assignment to constant variable. 126 | fruit.color = 'green'; 127 | console.log(fruit); // {name: "apple", color: "green"} 128 | ``` 129 | 130 | similar in array 131 | 132 | ```js 133 | const fruits = []; 134 | // fruits = ["apple"]; // Error 135 | fruits.push('apple'); 136 | console.log(fruits); // ["apple"] 137 | ``` 138 | 139 | ### Others 140 | 141 | ```js 142 | console.log(fruit); // Uncaught ReferenceError: fruit is not defined 143 | ``` 144 | 145 | ### Quiz 146 | 147 | 1. What's the output of the following code 148 | 149 | ```js 150 | var i = 5; 151 | for (var i = 0; i < 3; i++) { 152 | console.log(i); 153 | } 154 | console.log(i); 155 | ``` 156 | 157 | 2. What's the output of the following code 158 | 159 | ```js 160 | let i = 5; 161 | for (let i = 0; i < 3; i++) { 162 | console.log(i); 163 | } 164 | console.log(i); 165 | ``` 166 | 167 | 3. 168 | 169 | ```js 170 | var arr = [10, 12, 15, 21]; 171 | for (var i = 0; i < arr.length; i++) { 172 | setTimeout(function () { 173 | console.log('Index: ' + i + ', element: ' + arr[i]); 174 | }, 1000); 175 | } 176 | ``` 177 | 178 | ### Conclusion 179 | 180 | | keyword | scope | re-declare | update | hoisting | 181 | | ------- | -------- | ---------- | ------ | --------------------- | 182 | | var | function | Yes | Yes | Yes (undefined) | 183 | | let | block | No | Yes | Yes (not initialized) | 184 | | const | block | No | No | Yes (not initialized) | 185 | 186 | Extra reading source 187 | [Var, Let, and Const – What's the Difference?](https://www.freecodecamp.org/news/var-let-and-const-whats-the-difference/) 188 | 189 | ## Template String 190 | 191 | Also named, template literal, string interpolation 192 | 193 | ```js 194 | const name = 'mason'; 195 | const age = 104; 196 | // es5 197 | console.log('My name is ' + name + ", and I'm " + age + ' years old'); 198 | 199 | //es6 200 | console.log(`My name is ${name}, and I\'m ${age} years old`); 201 | ``` 202 | 203 | ## Spread operator 204 | 205 | ```js 206 | const array = [1, 2]; 207 | const newArray = [...array, 3, 4]; 208 | console.log(newArray); // [1, 2, 3, 4] 209 | ``` 210 | 211 | ```js 212 | const fruit = { name: 'apple', color: 'green' }; 213 | let newFruit = { ...fruit, color: 'red' }; 214 | console.log(newFruit); // {name: "apple", color: "red"} 215 | newFruit = { color: 'red', ...fruit }; 216 | console.log(newFruit); // {color: "green", name: "apple"} 217 | ``` 218 | 219 | ## Destructuring 220 | 221 | Object destructuring extracts property from object and assigns it to variables. 222 | One way would be using the dot notation 223 | 224 | ```js 225 | const fruit = { name: 'apple', color: 'red' }; 226 | const name = fruit.name; // apple 227 | const color = fruit.color; // red 228 | ``` 229 | 230 | With the new syntax, we don't need to repeatly refer to the `fruit` object 231 | 232 | ```js 233 | const fruit = { name: 'apple', color: 'red' }; 234 | const { name, color } = fruit; 235 | console.log(name); // apple 236 | console.log(color); // red 237 | ``` 238 | 239 | we can also rename the variable 240 | 241 | ```js 242 | const fruit = { name: 'apple', color: 'red' }; 243 | const { name: fruitName, color: fruitColor } = fruit; 244 | console.log(fruitName); // apple 245 | console.log(fruitColor); // red 246 | ``` 247 | 248 | or desctructing an array 249 | 250 | ```js 251 | const fruits = [ 252 | { name: 'apple', color: 'red' }, 253 | { name: 'pear', color: 'green' }, 254 | ]; 255 | const [apple, pear] = fruits; 256 | console.log(apple); // {name: "apple", color: "red"} 257 | console.log(pear); // {name: "pear", color: "green"} 258 | const [{ color: appleColor }, { color: pearColor }] = fruits; 259 | console.log(appleColor); // red 260 | console.log(pearColor); // green 261 | ``` 262 | 263 | more complicated use cases 264 | 265 | ```js 266 | const [foo, [[bar], baz]] = [1, [[2], 3]]; 267 | console.log(foo); // 1 268 | console.log(bar); // 2 269 | console.log(baz); // 3 270 | ``` 271 | 272 | ```js 273 | const [, , third] = ['foo', 'bar', 'baz']; 274 | console.log(third); // "baz" 275 | ``` 276 | 277 | ```js 278 | const [head, ...tail] = [1, 2, 3, 4]; 279 | console.log(head); // 1 280 | console.log(tail); // [2, 3, 4] 281 | // Rest element must be last element 282 | ``` 283 | 284 | ```js 285 | const [missing = true] = []; 286 | console.log(missing); // true 287 | ``` 288 | 289 | ## Default parameters 290 | 291 | ```js 292 | function sum(a = 1, b = 1) { 293 | return a + b; 294 | } 295 | console.log(sum()); // 2 296 | console.log(sum(undefined, 2)); // 3 297 | console.log(sum(3, 4)); // 7 298 | ``` 299 | 300 | ## Arrow function 301 | 302 | ```js 303 | const add = function (x, y) { 304 | return x + y; 305 | }; 306 | // vs 307 | const add = (x, y) => { 308 | return x + y; 309 | }; 310 | // equals 311 | const add = (x, y) => x + y; 312 | ``` 313 | 314 | ### Callback 315 | 316 | Explain in a simple way, pass the function as a parameter and when some _event_ happened (addEventListener), execute this function. 317 | Frequently used for async or sequential purpose 318 | 319 | ```js 320 | function logger(param) { 321 | console.log(param); 322 | } 323 | function sum(x, y, callback) { 324 | setTimeout(function () { 325 | const total = x + y; 326 | callback(total); 327 | }, 1000); 328 | } 329 | sum(1, 2, logger); 330 | ``` 331 | 332 | ### Callback with arrow function 333 | 334 | ```js 335 | setTimeout(function () { 336 | console.log('normal function'); 337 | }, 1000); 338 | 339 | setTimeout(() => { 340 | console.log('arrow function'); 341 | }, 1000); 342 | ``` 343 | 344 | ## Closure 345 | 346 | Closures are everywhere in JS. A closure is when a function has access to its lexical scope even when it is called outside of it. Closures are created every time a function is created, at function creation time. 347 | 348 | A few complex but common closure cases: 349 | 350 | 1. a function was passed to another function as param 351 | 352 | ```js 353 | // we normally don't write this code 354 | const number = 1; 355 | function foo() { 356 | console.log(number); 357 | } 358 | function bar(fn) { 359 | const number = 2; 360 | fn(); 361 | } 362 | bar(foo); // 1 363 | ``` 364 | 365 | 2. a function was returned by another function 366 | 367 | ```js 368 | function foo() { 369 | const number = 1; 370 | return () => { 371 | console.log(number); 372 | }; 373 | } 374 | const number = 100; 375 | foo()(); // 1 376 | ``` 377 | 378 | We can use this technique to hide some data. 379 | 380 | ```js 381 | function createCounter() { 382 | let counter = 0; 383 | const increment = () => { 384 | counter++; 385 | }; 386 | const getCount = () => { 387 | return counter; 388 | }; 389 | return { 390 | increment, 391 | getCount, 392 | }; 393 | } 394 | const counter = createCounter(); 395 | counter.increment(); 396 | console.log(counter.getCount()); 397 | ``` 398 | 399 | ### IIFEs 400 | 401 | Immediately Invoked Function Expressions 402 | Commonly used to avoid polluting the global namespace and modules! 403 | 404 | ```js 405 | (function () { 406 | // some variable in it's own scope 407 | })(); 408 | ``` 409 | 410 | ## this 411 | 412 | In most cases, the value of `this` is determined by how a function is called (runtime binding). It can't be set by assignment during execution, and it may be different each time the function is called. [[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)]\* \*[strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) is enabled by default in ES6 modules 413 | 414 | ### _this_ keyword in normal functions 415 | 416 | ```js 417 | function foo() { 418 | console.log(this); 419 | } 420 | foo(); // window 421 | ``` 422 | 423 | ### _this_ keyword in normal functions with bind, call, apply 424 | 425 | ```js 426 | // a1,a2 427 | foo.call({ number: 1 }); // {number: 1} 428 | // [a1,a2] 429 | foo.apply({ number: 2 }); // {number: 2} 430 | // bind returns a new function 431 | const bar = foo.bind({ number: 3 }); 432 | bar(); // {number:3} 433 | ``` 434 | 435 | ### _this_ keyword in an object and callback functions 436 | 437 | ```js 438 | const calendar = { 439 | currentDay: 6, 440 | nextDay() { 441 | this.currentDay++; 442 | console.log(this.currentDay); 443 | }, 444 | }; 445 | calendar.nextDay(); 446 | ``` 447 | 448 | ```js 449 | const calendar = { 450 | currentDay: 6, 451 | nextDay() { 452 | setTimeout(function () { 453 | this.currentDay++; 454 | console.log(this.currentDay); 455 | }); // .bind(this) 456 | }, 457 | }; 458 | calendar.nextDay(); 459 | ``` 460 | 461 | In arrow function, `this` points to the enclosing lexical context's `this`. 462 | 463 | ```js 464 | const calendar = { 465 | currentDay: 6, 466 | nextDay() { 467 | setTimeout(() => { 468 | this.currentDay++; 469 | console.log(this.currentDay); 470 | }); 471 | }, 472 | }; 473 | calendar.nextDay(); 474 | ``` 475 | 476 | ```js 477 | const calendar = { 478 | currentDay: 6, 479 | normal: function () { 480 | console.log(1, this); 481 | setTimeout(function () { 482 | console.log(2, this); 483 | }); 484 | }, 485 | arrow: function () { 486 | console.log(3, this); 487 | setTimeout(() => { 488 | console.log(4, this); 489 | }); 490 | }, 491 | }; 492 | calendar.normal(); 493 | calendar.arrow(); 494 | ``` 495 | 496 | ### quiz 497 | 498 | ```js 499 | const object = { 500 | message: 'Hello, World!', 501 | 502 | getMessage() { 503 | const message = 'Hello, Earth!'; 504 | return this.message; 505 | }, 506 | }; 507 | 508 | console.log(object.getMessage()); // ?? 509 | ``` 510 | 511 | ```js 512 | const object = { 513 | who: 'World', 514 | 515 | greet() { 516 | return `Hello, ${this.who}!`; 517 | }, 518 | 519 | farewell: () => { 520 | return `Goodbye, ${this.who}!`; 521 | }, 522 | }; 523 | 524 | console.log(object.greet()); // ?? 525 | console.log(object.farewell()); // ?? 526 | ``` 527 | 528 | ```js 529 | const object = { 530 | who: 'mason', 531 | cb() { 532 | console.log(`Hello, ${this.who}!`); 533 | }, 534 | }; 535 | 536 | function foo(cb) { 537 | cb(); 538 | } 539 | 540 | foo(object.cb); // ?? 541 | object.cb(); // ?? 542 | ``` 543 | 544 | ## Common array operations 545 | 546 | ### Manipulation 547 | 548 | ```js 549 | const fruits = ['apple']; 550 | 551 | fruits.push('pear'); 552 | console.log(fruits); // ["apple", "pear"] 553 | fruits.unshift('grape'); 554 | console.log(fruits); // ["grape", "apple", "pear"] 555 | // splice(x,y,newAdded) 556 | // remove y items from index x, and add newAdded 557 | fruits.splice(1, 1, 'watermelon', 'peach'); 558 | console.log(fruits); // ["grape", "watermelon", "peach", "pear"] 559 | let fruit = fruits.pop(); 560 | console.log(fruit); // pear 561 | console.log(fruits); // ["grape", "watermelon", "peach"] 562 | fruit = fruits.shift(); 563 | console.log(fruit); // grape 564 | console.log(fruits); // ["watermelon", "peach"] 565 | ``` 566 | 567 | ### Iteration 568 | 569 | #### for loop 570 | 571 | ```js 572 | const fruits = ['apple', 'pear']; 573 | for (let index = 0; index < fruits.length; index++) { 574 | const fruit = fruits[index]; 575 | console.log(fruit); 576 | } 577 | // apple 578 | // pear 579 | ``` 580 | 581 | #### for...of 582 | 583 | ```js 584 | const fruits = ['apple', 'pear']; 585 | for (let fruit of fruits) { 586 | console.log(fruit); 587 | } 588 | // apple 589 | // pear 590 | 591 | // for...in -> 0, 1 usually used in object 592 | ``` 593 | 594 | #### forEach 595 | 596 | ```js 597 | const fruits = ['apple', 'pear']; 598 | fruits.forEach((fruit) => console.log(fruit)); 599 | // apple 600 | // pear 601 | // cannot use break here 602 | ``` 603 | 604 | ### Map 605 | 606 | ```js 607 | const fruits = ['apple', 'pear']; 608 | const newFruits = fruits.map((fruit) => ({ 609 | name: fruit, 610 | price: 10, 611 | })); 612 | console.log(newFruits); 613 | // [{name: "apple", price: 10},{name: "pear", price: 10}] 614 | ``` 615 | 616 | ### Reduce 617 | 618 | ```js 619 | const numbers = [1, 2, 3]; 620 | const sum = numbers.reduce((accumulator, number) => accumulator + number, 0); 621 | console.log(sum); // 6 622 | ``` 623 | 624 | ### Search 625 | 626 | ```js 627 | const numbers = [1, 2, 3, 4, 5]; 628 | console.log(numbers.includes(2)); // true 629 | // Array.some 630 | console.log(numbers.indexOf(2)); // 1 631 | // Array.findIndex 632 | ``` 633 | 634 | ```js 635 | const numbers = [1, 2, 3, 4, 5]; 636 | const odds = numbers.filter((i) => i % 2); 637 | console.log(odds); // [1,3,5] 638 | 639 | const fruits = [ 640 | { 641 | name: 'apple', 642 | color: 'red', 643 | }, 644 | { 645 | name: 'pear', 646 | color: 'green', 647 | }, 648 | { 649 | name: 'grape', 650 | color: 'green', 651 | }, 652 | ]; 653 | const filteredFruits = fruits.filter((i) => i.color === 'green'); 654 | console.log(filteredFruits); 655 | // [{name: "pear", color: "green"}, {name: "grape", color: "green"}] 656 | ``` 657 | 658 | ```js 659 | const fruits = [ 660 | { 661 | name: 'apple', 662 | color: 'red', 663 | }, 664 | { 665 | name: 'pear', 666 | color: 'green', 667 | }, 668 | { 669 | name: 'grape', 670 | color: 'green', 671 | }, 672 | ]; 673 | const greenFruit = fruits.find((i) => i.color === 'green'); 674 | console.log(greenFruit); 675 | // {name: "pear", color: "green"} 676 | ``` 677 | 678 | #### Extra reading source 679 | 680 | [link](https://dmitripavlutin.com/operations-on-arrays-javascript/) 681 | 682 | ## Set 683 | 684 | Set is a data structure, we use it to store _unique_ values. 685 | 686 | ```js 687 | const set = new Set([1, 2, 3, 4, 4]); 688 | console.log(set); // Set(4) {1, 2, 3, 4} 689 | set.add(5); 690 | console.log(set); // Set(5) {1, 2, 3, 4, 5} 691 | set.add(1); 692 | console.log(set); // Set(5) {1, 2, 3, 4, 5} 693 | console.log(set.has(5)); // true 694 | set.delete(1); 695 | console.log(set.has(1)); // false 696 | console.log(set.size); // 4 697 | ``` 698 | 699 | ```js 700 | const array = [1, 2, 2, 3, 4, 4]; 701 | const uniqueArray = [...new Set(array)]; 702 | console.log(uniqueArray); // [1, 2, 3, 4] 703 | ``` 704 | 705 | ## Classes 706 | 707 | Classes are a template for creating objects. Classes are in fact functions, class is only a syntax sugar. 708 | 709 | ```js 710 | function Person(name) { 711 | this.name = name; 712 | this.toString = function () { 713 | console.log('name: ' + this.name); 714 | }; 715 | } 716 | var mason = new Person('mason'); 717 | mason.toString(); // name: mason 718 | ``` 719 | 720 | ```js 721 | class Person { 722 | constructor(name) { 723 | this.name = name; 724 | } 725 | toString() { 726 | console.log(`name: ${this.name}`); 727 | } 728 | } 729 | const mason = new Person('mason'); 730 | mason.toString(); // name: mason 731 | ``` 732 | 733 | ### extends 734 | 735 | ```js 736 | class Teacher extends Person { 737 | constructor(name) { 738 | super(name); 739 | } 740 | teach() { 741 | console.log(`${this.name} is teaching`); 742 | } 743 | } 744 | 745 | const mason = new Teacher('mason'); 746 | mason.teach(); // mason is teaching 747 | mason.toString(); // name: mason -> BUT how? 748 | ``` 749 | 750 | ```js 751 | // is mason constructed by Teacher? 752 | mason instanceof Teacher; // true 753 | mason instanceof Person; // true 754 | mason instanceof Object; // true 755 | ``` 756 | 757 | ## quiz 758 | 759 | ```js 760 | function Pet(name) { 761 | this.name = name; 762 | this.getName = () => this.name; 763 | } 764 | 765 | const cat = new Pet('Fluffy'); 766 | 767 | console.log(cat.getName()); // Fluffy 768 | 769 | const { getName } = cat; 770 | console.log(getName()); // Fluffy 771 | ``` 772 | 773 | ```js 774 | var scope = 'global scope'; 775 | function checkscope() { 776 | var scope = 'local scope'; 777 | function f() { 778 | return scope; 779 | } 780 | return f(); 781 | } 782 | checkscope(); // local 783 | ``` 784 | 785 | ```js 786 | var scope = 'global scope'; 787 | function checkscope() { 788 | var scope = 'local scope'; 789 | function f() { 790 | return scope; 791 | } 792 | return f; 793 | } 794 | checkscope()(); // local 795 | ``` 796 | 797 | Quiz questions references 798 | [1](https://dmitripavlutin.com/javascript-this-interview-questions/#question-1-variable-vs-property) 799 | -------------------------------------------------------------------------------- /8-docker/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "8-docker", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.8", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 10 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 11 | "requires": { 12 | "mime-types": "~2.1.34", 13 | "negotiator": "0.6.3" 14 | } 15 | }, 16 | "array-flatten": { 17 | "version": "1.1.1", 18 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 19 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 20 | }, 21 | "body-parser": { 22 | "version": "1.20.0", 23 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", 24 | "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", 25 | "requires": { 26 | "bytes": "3.1.2", 27 | "content-type": "~1.0.4", 28 | "debug": "2.6.9", 29 | "depd": "2.0.0", 30 | "destroy": "1.2.0", 31 | "http-errors": "2.0.0", 32 | "iconv-lite": "0.4.24", 33 | "on-finished": "2.4.1", 34 | "qs": "6.10.3", 35 | "raw-body": "2.5.1", 36 | "type-is": "~1.6.18", 37 | "unpipe": "1.0.0" 38 | } 39 | }, 40 | "bytes": { 41 | "version": "3.1.2", 42 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 43 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 44 | }, 45 | "call-bind": { 46 | "version": "1.0.2", 47 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 48 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 49 | "requires": { 50 | "function-bind": "^1.1.1", 51 | "get-intrinsic": "^1.0.2" 52 | } 53 | }, 54 | "content-disposition": { 55 | "version": "0.5.4", 56 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 57 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 58 | "requires": { 59 | "safe-buffer": "5.2.1" 60 | } 61 | }, 62 | "content-type": { 63 | "version": "1.0.4", 64 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 65 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 66 | }, 67 | "cookie": { 68 | "version": "0.5.0", 69 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 70 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" 71 | }, 72 | "cookie-signature": { 73 | "version": "1.0.6", 74 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 75 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 76 | }, 77 | "debug": { 78 | "version": "2.6.9", 79 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 80 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 81 | "requires": { 82 | "ms": "2.0.0" 83 | } 84 | }, 85 | "depd": { 86 | "version": "2.0.0", 87 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 88 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 89 | }, 90 | "destroy": { 91 | "version": "1.2.0", 92 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 93 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 94 | }, 95 | "ee-first": { 96 | "version": "1.1.1", 97 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 98 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 99 | }, 100 | "encodeurl": { 101 | "version": "1.0.2", 102 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 103 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 104 | }, 105 | "escape-html": { 106 | "version": "1.0.3", 107 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 108 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 109 | }, 110 | "etag": { 111 | "version": "1.8.1", 112 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 113 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 114 | }, 115 | "express": { 116 | "version": "4.18.1", 117 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", 118 | "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", 119 | "requires": { 120 | "accepts": "~1.3.8", 121 | "array-flatten": "1.1.1", 122 | "body-parser": "1.20.0", 123 | "content-disposition": "0.5.4", 124 | "content-type": "~1.0.4", 125 | "cookie": "0.5.0", 126 | "cookie-signature": "1.0.6", 127 | "debug": "2.6.9", 128 | "depd": "2.0.0", 129 | "encodeurl": "~1.0.2", 130 | "escape-html": "~1.0.3", 131 | "etag": "~1.8.1", 132 | "finalhandler": "1.2.0", 133 | "fresh": "0.5.2", 134 | "http-errors": "2.0.0", 135 | "merge-descriptors": "1.0.1", 136 | "methods": "~1.1.2", 137 | "on-finished": "2.4.1", 138 | "parseurl": "~1.3.3", 139 | "path-to-regexp": "0.1.7", 140 | "proxy-addr": "~2.0.7", 141 | "qs": "6.10.3", 142 | "range-parser": "~1.2.1", 143 | "safe-buffer": "5.2.1", 144 | "send": "0.18.0", 145 | "serve-static": "1.15.0", 146 | "setprototypeof": "1.2.0", 147 | "statuses": "2.0.1", 148 | "type-is": "~1.6.18", 149 | "utils-merge": "1.0.1", 150 | "vary": "~1.1.2" 151 | } 152 | }, 153 | "finalhandler": { 154 | "version": "1.2.0", 155 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 156 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 157 | "requires": { 158 | "debug": "2.6.9", 159 | "encodeurl": "~1.0.2", 160 | "escape-html": "~1.0.3", 161 | "on-finished": "2.4.1", 162 | "parseurl": "~1.3.3", 163 | "statuses": "2.0.1", 164 | "unpipe": "~1.0.0" 165 | } 166 | }, 167 | "forwarded": { 168 | "version": "0.2.0", 169 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 170 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 171 | }, 172 | "fresh": { 173 | "version": "0.5.2", 174 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 175 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 176 | }, 177 | "function-bind": { 178 | "version": "1.1.1", 179 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 180 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 181 | }, 182 | "get-intrinsic": { 183 | "version": "1.1.2", 184 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", 185 | "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", 186 | "requires": { 187 | "function-bind": "^1.1.1", 188 | "has": "^1.0.3", 189 | "has-symbols": "^1.0.3" 190 | } 191 | }, 192 | "has": { 193 | "version": "1.0.3", 194 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 195 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 196 | "requires": { 197 | "function-bind": "^1.1.1" 198 | } 199 | }, 200 | "has-symbols": { 201 | "version": "1.0.3", 202 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 203 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 204 | }, 205 | "http-errors": { 206 | "version": "2.0.0", 207 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 208 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 209 | "requires": { 210 | "depd": "2.0.0", 211 | "inherits": "2.0.4", 212 | "setprototypeof": "1.2.0", 213 | "statuses": "2.0.1", 214 | "toidentifier": "1.0.1" 215 | } 216 | }, 217 | "iconv-lite": { 218 | "version": "0.4.24", 219 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 220 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 221 | "requires": { 222 | "safer-buffer": ">= 2.1.2 < 3" 223 | } 224 | }, 225 | "inherits": { 226 | "version": "2.0.4", 227 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 228 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 229 | }, 230 | "ipaddr.js": { 231 | "version": "1.9.1", 232 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 233 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 234 | }, 235 | "media-typer": { 236 | "version": "0.3.0", 237 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 238 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 239 | }, 240 | "merge-descriptors": { 241 | "version": "1.0.1", 242 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 243 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 244 | }, 245 | "methods": { 246 | "version": "1.1.2", 247 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 248 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 249 | }, 250 | "mime": { 251 | "version": "1.6.0", 252 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 253 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 254 | }, 255 | "mime-db": { 256 | "version": "1.52.0", 257 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 258 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 259 | }, 260 | "mime-types": { 261 | "version": "2.1.35", 262 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 263 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 264 | "requires": { 265 | "mime-db": "1.52.0" 266 | } 267 | }, 268 | "ms": { 269 | "version": "2.0.0", 270 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 271 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 272 | }, 273 | "negotiator": { 274 | "version": "0.6.3", 275 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 276 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 277 | }, 278 | "object-inspect": { 279 | "version": "1.12.2", 280 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 281 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" 282 | }, 283 | "on-finished": { 284 | "version": "2.4.1", 285 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 286 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 287 | "requires": { 288 | "ee-first": "1.1.1" 289 | } 290 | }, 291 | "parseurl": { 292 | "version": "1.3.3", 293 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 294 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 295 | }, 296 | "path-to-regexp": { 297 | "version": "0.1.7", 298 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 299 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 300 | }, 301 | "proxy-addr": { 302 | "version": "2.0.7", 303 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 304 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 305 | "requires": { 306 | "forwarded": "0.2.0", 307 | "ipaddr.js": "1.9.1" 308 | } 309 | }, 310 | "qs": { 311 | "version": "6.10.3", 312 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", 313 | "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", 314 | "requires": { 315 | "side-channel": "^1.0.4" 316 | } 317 | }, 318 | "range-parser": { 319 | "version": "1.2.1", 320 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 321 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 322 | }, 323 | "raw-body": { 324 | "version": "2.5.1", 325 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 326 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 327 | "requires": { 328 | "bytes": "3.1.2", 329 | "http-errors": "2.0.0", 330 | "iconv-lite": "0.4.24", 331 | "unpipe": "1.0.0" 332 | } 333 | }, 334 | "safe-buffer": { 335 | "version": "5.2.1", 336 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 337 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 338 | }, 339 | "safer-buffer": { 340 | "version": "2.1.2", 341 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 342 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 343 | }, 344 | "send": { 345 | "version": "0.18.0", 346 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 347 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 348 | "requires": { 349 | "debug": "2.6.9", 350 | "depd": "2.0.0", 351 | "destroy": "1.2.0", 352 | "encodeurl": "~1.0.2", 353 | "escape-html": "~1.0.3", 354 | "etag": "~1.8.1", 355 | "fresh": "0.5.2", 356 | "http-errors": "2.0.0", 357 | "mime": "1.6.0", 358 | "ms": "2.1.3", 359 | "on-finished": "2.4.1", 360 | "range-parser": "~1.2.1", 361 | "statuses": "2.0.1" 362 | }, 363 | "dependencies": { 364 | "ms": { 365 | "version": "2.1.3", 366 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 367 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 368 | } 369 | } 370 | }, 371 | "serve-static": { 372 | "version": "1.15.0", 373 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 374 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 375 | "requires": { 376 | "encodeurl": "~1.0.2", 377 | "escape-html": "~1.0.3", 378 | "parseurl": "~1.3.3", 379 | "send": "0.18.0" 380 | } 381 | }, 382 | "setprototypeof": { 383 | "version": "1.2.0", 384 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 385 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 386 | }, 387 | "side-channel": { 388 | "version": "1.0.4", 389 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 390 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 391 | "requires": { 392 | "call-bind": "^1.0.0", 393 | "get-intrinsic": "^1.0.2", 394 | "object-inspect": "^1.9.0" 395 | } 396 | }, 397 | "statuses": { 398 | "version": "2.0.1", 399 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 400 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 401 | }, 402 | "toidentifier": { 403 | "version": "1.0.1", 404 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 405 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 406 | }, 407 | "type-is": { 408 | "version": "1.6.18", 409 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 410 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 411 | "requires": { 412 | "media-typer": "0.3.0", 413 | "mime-types": "~2.1.24" 414 | } 415 | }, 416 | "unpipe": { 417 | "version": "1.0.0", 418 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 419 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 420 | }, 421 | "utils-merge": { 422 | "version": "1.0.1", 423 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 424 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 425 | }, 426 | "vary": { 427 | "version": "1.1.2", 428 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 429 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" 430 | } 431 | } 432 | } 433 | -------------------------------------------------------------------------------- /3-npm/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3-npm", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@sindresorhus/is": { 8 | "version": "0.14.0", 9 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 10 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 11 | "dev": true 12 | }, 13 | "@szmarczak/http-timer": { 14 | "version": "1.1.2", 15 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 16 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 17 | "dev": true, 18 | "requires": { 19 | "defer-to-connect": "^1.0.1" 20 | } 21 | }, 22 | "abbrev": { 23 | "version": "1.1.1", 24 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 25 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 26 | "dev": true 27 | }, 28 | "accepts": { 29 | "version": "1.3.8", 30 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 31 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 32 | "requires": { 33 | "mime-types": "~2.1.34", 34 | "negotiator": "0.6.3" 35 | } 36 | }, 37 | "ansi-align": { 38 | "version": "3.0.1", 39 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", 40 | "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", 41 | "dev": true, 42 | "requires": { 43 | "string-width": "^4.1.0" 44 | } 45 | }, 46 | "ansi-regex": { 47 | "version": "5.0.1", 48 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 49 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 50 | "dev": true 51 | }, 52 | "ansi-styles": { 53 | "version": "4.3.0", 54 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 55 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 56 | "dev": true, 57 | "requires": { 58 | "color-convert": "^2.0.1" 59 | } 60 | }, 61 | "anymatch": { 62 | "version": "3.1.2", 63 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 64 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 65 | "dev": true, 66 | "requires": { 67 | "normalize-path": "^3.0.0", 68 | "picomatch": "^2.0.4" 69 | } 70 | }, 71 | "array-flatten": { 72 | "version": "1.1.1", 73 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 74 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 75 | }, 76 | "balanced-match": { 77 | "version": "1.0.2", 78 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 79 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 80 | "dev": true 81 | }, 82 | "binary-extensions": { 83 | "version": "2.2.0", 84 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 85 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 86 | "dev": true 87 | }, 88 | "body-parser": { 89 | "version": "1.19.2", 90 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", 91 | "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", 92 | "requires": { 93 | "bytes": "3.1.2", 94 | "content-type": "~1.0.4", 95 | "debug": "2.6.9", 96 | "depd": "~1.1.2", 97 | "http-errors": "1.8.1", 98 | "iconv-lite": "0.4.24", 99 | "on-finished": "~2.3.0", 100 | "qs": "6.9.7", 101 | "raw-body": "2.4.3", 102 | "type-is": "~1.6.18" 103 | } 104 | }, 105 | "boxen": { 106 | "version": "5.1.2", 107 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", 108 | "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", 109 | "dev": true, 110 | "requires": { 111 | "ansi-align": "^3.0.0", 112 | "camelcase": "^6.2.0", 113 | "chalk": "^4.1.0", 114 | "cli-boxes": "^2.2.1", 115 | "string-width": "^4.2.2", 116 | "type-fest": "^0.20.2", 117 | "widest-line": "^3.1.0", 118 | "wrap-ansi": "^7.0.0" 119 | } 120 | }, 121 | "brace-expansion": { 122 | "version": "1.1.11", 123 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 124 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 125 | "dev": true, 126 | "requires": { 127 | "balanced-match": "^1.0.0", 128 | "concat-map": "0.0.1" 129 | } 130 | }, 131 | "braces": { 132 | "version": "3.0.2", 133 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 134 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 135 | "dev": true, 136 | "requires": { 137 | "fill-range": "^7.0.1" 138 | } 139 | }, 140 | "bytes": { 141 | "version": "3.1.2", 142 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 143 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 144 | }, 145 | "cacheable-request": { 146 | "version": "6.1.0", 147 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 148 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 149 | "dev": true, 150 | "requires": { 151 | "clone-response": "^1.0.2", 152 | "get-stream": "^5.1.0", 153 | "http-cache-semantics": "^4.0.0", 154 | "keyv": "^3.0.0", 155 | "lowercase-keys": "^2.0.0", 156 | "normalize-url": "^4.1.0", 157 | "responselike": "^1.0.2" 158 | }, 159 | "dependencies": { 160 | "get-stream": { 161 | "version": "5.2.0", 162 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 163 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 164 | "dev": true, 165 | "requires": { 166 | "pump": "^3.0.0" 167 | } 168 | }, 169 | "lowercase-keys": { 170 | "version": "2.0.0", 171 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 172 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 173 | "dev": true 174 | } 175 | } 176 | }, 177 | "camelcase": { 178 | "version": "6.3.0", 179 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 180 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 181 | "dev": true 182 | }, 183 | "chalk": { 184 | "version": "4.1.2", 185 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 186 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 187 | "dev": true, 188 | "requires": { 189 | "ansi-styles": "^4.1.0", 190 | "supports-color": "^7.1.0" 191 | }, 192 | "dependencies": { 193 | "has-flag": { 194 | "version": "4.0.0", 195 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 196 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 197 | "dev": true 198 | }, 199 | "supports-color": { 200 | "version": "7.2.0", 201 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 202 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 203 | "dev": true, 204 | "requires": { 205 | "has-flag": "^4.0.0" 206 | } 207 | } 208 | } 209 | }, 210 | "chokidar": { 211 | "version": "3.5.3", 212 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 213 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 214 | "dev": true, 215 | "requires": { 216 | "anymatch": "~3.1.2", 217 | "braces": "~3.0.2", 218 | "fsevents": "~2.3.2", 219 | "glob-parent": "~5.1.2", 220 | "is-binary-path": "~2.1.0", 221 | "is-glob": "~4.0.1", 222 | "normalize-path": "~3.0.0", 223 | "readdirp": "~3.6.0" 224 | } 225 | }, 226 | "ci-info": { 227 | "version": "2.0.0", 228 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", 229 | "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", 230 | "dev": true 231 | }, 232 | "cli-boxes": { 233 | "version": "2.2.1", 234 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", 235 | "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", 236 | "dev": true 237 | }, 238 | "clone-response": { 239 | "version": "1.0.2", 240 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 241 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 242 | "dev": true, 243 | "requires": { 244 | "mimic-response": "^1.0.0" 245 | } 246 | }, 247 | "color-convert": { 248 | "version": "2.0.1", 249 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 250 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 251 | "dev": true, 252 | "requires": { 253 | "color-name": "~1.1.4" 254 | } 255 | }, 256 | "color-name": { 257 | "version": "1.1.4", 258 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 259 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 260 | "dev": true 261 | }, 262 | "concat-map": { 263 | "version": "0.0.1", 264 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 265 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 266 | "dev": true 267 | }, 268 | "configstore": { 269 | "version": "5.0.1", 270 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", 271 | "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", 272 | "dev": true, 273 | "requires": { 274 | "dot-prop": "^5.2.0", 275 | "graceful-fs": "^4.1.2", 276 | "make-dir": "^3.0.0", 277 | "unique-string": "^2.0.0", 278 | "write-file-atomic": "^3.0.0", 279 | "xdg-basedir": "^4.0.0" 280 | } 281 | }, 282 | "content-disposition": { 283 | "version": "0.5.4", 284 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 285 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 286 | "requires": { 287 | "safe-buffer": "5.2.1" 288 | } 289 | }, 290 | "content-type": { 291 | "version": "1.0.4", 292 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 293 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 294 | }, 295 | "cookie": { 296 | "version": "0.4.2", 297 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", 298 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" 299 | }, 300 | "cookie-signature": { 301 | "version": "1.0.6", 302 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 303 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 304 | }, 305 | "crypto-random-string": { 306 | "version": "2.0.0", 307 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", 308 | "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", 309 | "dev": true 310 | }, 311 | "debug": { 312 | "version": "2.6.9", 313 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 314 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 315 | "requires": { 316 | "ms": "2.0.0" 317 | } 318 | }, 319 | "decompress-response": { 320 | "version": "3.3.0", 321 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 322 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 323 | "dev": true, 324 | "requires": { 325 | "mimic-response": "^1.0.0" 326 | } 327 | }, 328 | "deep-extend": { 329 | "version": "0.6.0", 330 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 331 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", 332 | "dev": true 333 | }, 334 | "defer-to-connect": { 335 | "version": "1.1.3", 336 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 337 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 338 | "dev": true 339 | }, 340 | "depd": { 341 | "version": "1.1.2", 342 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 343 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 344 | }, 345 | "destroy": { 346 | "version": "1.0.4", 347 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 348 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 349 | }, 350 | "dot-prop": { 351 | "version": "5.3.0", 352 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", 353 | "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", 354 | "dev": true, 355 | "requires": { 356 | "is-obj": "^2.0.0" 357 | } 358 | }, 359 | "duplexer3": { 360 | "version": "0.1.4", 361 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 362 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 363 | "dev": true 364 | }, 365 | "ee-first": { 366 | "version": "1.1.1", 367 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 368 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 369 | }, 370 | "emoji-regex": { 371 | "version": "8.0.0", 372 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 373 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 374 | "dev": true 375 | }, 376 | "encodeurl": { 377 | "version": "1.0.2", 378 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 379 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 380 | }, 381 | "end-of-stream": { 382 | "version": "1.4.4", 383 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 384 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 385 | "dev": true, 386 | "requires": { 387 | "once": "^1.4.0" 388 | } 389 | }, 390 | "escape-goat": { 391 | "version": "2.1.1", 392 | "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", 393 | "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", 394 | "dev": true 395 | }, 396 | "escape-html": { 397 | "version": "1.0.3", 398 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 399 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 400 | }, 401 | "etag": { 402 | "version": "1.8.1", 403 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 404 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 405 | }, 406 | "express": { 407 | "version": "4.17.3", 408 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", 409 | "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", 410 | "requires": { 411 | "accepts": "~1.3.8", 412 | "array-flatten": "1.1.1", 413 | "body-parser": "1.19.2", 414 | "content-disposition": "0.5.4", 415 | "content-type": "~1.0.4", 416 | "cookie": "0.4.2", 417 | "cookie-signature": "1.0.6", 418 | "debug": "2.6.9", 419 | "depd": "~1.1.2", 420 | "encodeurl": "~1.0.2", 421 | "escape-html": "~1.0.3", 422 | "etag": "~1.8.1", 423 | "finalhandler": "~1.1.2", 424 | "fresh": "0.5.2", 425 | "merge-descriptors": "1.0.1", 426 | "methods": "~1.1.2", 427 | "on-finished": "~2.3.0", 428 | "parseurl": "~1.3.3", 429 | "path-to-regexp": "0.1.7", 430 | "proxy-addr": "~2.0.7", 431 | "qs": "6.9.7", 432 | "range-parser": "~1.2.1", 433 | "safe-buffer": "5.2.1", 434 | "send": "0.17.2", 435 | "serve-static": "1.14.2", 436 | "setprototypeof": "1.2.0", 437 | "statuses": "~1.5.0", 438 | "type-is": "~1.6.18", 439 | "utils-merge": "1.0.1", 440 | "vary": "~1.1.2" 441 | } 442 | }, 443 | "fill-range": { 444 | "version": "7.0.1", 445 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 446 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 447 | "dev": true, 448 | "requires": { 449 | "to-regex-range": "^5.0.1" 450 | } 451 | }, 452 | "finalhandler": { 453 | "version": "1.1.2", 454 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 455 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 456 | "requires": { 457 | "debug": "2.6.9", 458 | "encodeurl": "~1.0.2", 459 | "escape-html": "~1.0.3", 460 | "on-finished": "~2.3.0", 461 | "parseurl": "~1.3.3", 462 | "statuses": "~1.5.0", 463 | "unpipe": "~1.0.0" 464 | } 465 | }, 466 | "forwarded": { 467 | "version": "0.2.0", 468 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 469 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 470 | }, 471 | "fresh": { 472 | "version": "0.5.2", 473 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 474 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 475 | }, 476 | "fsevents": { 477 | "version": "2.3.2", 478 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 479 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 480 | "dev": true, 481 | "optional": true 482 | }, 483 | "get-stream": { 484 | "version": "4.1.0", 485 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 486 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 487 | "dev": true, 488 | "requires": { 489 | "pump": "^3.0.0" 490 | } 491 | }, 492 | "glob-parent": { 493 | "version": "5.1.2", 494 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 495 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 496 | "dev": true, 497 | "requires": { 498 | "is-glob": "^4.0.1" 499 | } 500 | }, 501 | "global-dirs": { 502 | "version": "3.0.0", 503 | "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", 504 | "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", 505 | "dev": true, 506 | "requires": { 507 | "ini": "2.0.0" 508 | } 509 | }, 510 | "got": { 511 | "version": "9.6.0", 512 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 513 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 514 | "dev": true, 515 | "requires": { 516 | "@sindresorhus/is": "^0.14.0", 517 | "@szmarczak/http-timer": "^1.1.2", 518 | "cacheable-request": "^6.0.0", 519 | "decompress-response": "^3.3.0", 520 | "duplexer3": "^0.1.4", 521 | "get-stream": "^4.1.0", 522 | "lowercase-keys": "^1.0.1", 523 | "mimic-response": "^1.0.1", 524 | "p-cancelable": "^1.0.0", 525 | "to-readable-stream": "^1.0.0", 526 | "url-parse-lax": "^3.0.0" 527 | } 528 | }, 529 | "graceful-fs": { 530 | "version": "4.2.10", 531 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", 532 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", 533 | "dev": true 534 | }, 535 | "has-flag": { 536 | "version": "3.0.0", 537 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 538 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 539 | "dev": true 540 | }, 541 | "has-yarn": { 542 | "version": "2.1.0", 543 | "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", 544 | "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", 545 | "dev": true 546 | }, 547 | "http-cache-semantics": { 548 | "version": "4.1.0", 549 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 550 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 551 | "dev": true 552 | }, 553 | "http-errors": { 554 | "version": "1.8.1", 555 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", 556 | "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", 557 | "requires": { 558 | "depd": "~1.1.2", 559 | "inherits": "2.0.4", 560 | "setprototypeof": "1.2.0", 561 | "statuses": ">= 1.5.0 < 2", 562 | "toidentifier": "1.0.1" 563 | } 564 | }, 565 | "iconv-lite": { 566 | "version": "0.4.24", 567 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 568 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 569 | "requires": { 570 | "safer-buffer": ">= 2.1.2 < 3" 571 | } 572 | }, 573 | "ignore-by-default": { 574 | "version": "1.0.1", 575 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 576 | "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", 577 | "dev": true 578 | }, 579 | "import-lazy": { 580 | "version": "2.1.0", 581 | "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", 582 | "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", 583 | "dev": true 584 | }, 585 | "imurmurhash": { 586 | "version": "0.1.4", 587 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 588 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 589 | "dev": true 590 | }, 591 | "inherits": { 592 | "version": "2.0.4", 593 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 594 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 595 | }, 596 | "ini": { 597 | "version": "2.0.0", 598 | "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", 599 | "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", 600 | "dev": true 601 | }, 602 | "ipaddr.js": { 603 | "version": "1.9.1", 604 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 605 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 606 | }, 607 | "is-binary-path": { 608 | "version": "2.1.0", 609 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 610 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 611 | "dev": true, 612 | "requires": { 613 | "binary-extensions": "^2.0.0" 614 | } 615 | }, 616 | "is-ci": { 617 | "version": "2.0.0", 618 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", 619 | "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", 620 | "dev": true, 621 | "requires": { 622 | "ci-info": "^2.0.0" 623 | } 624 | }, 625 | "is-extglob": { 626 | "version": "2.1.1", 627 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 628 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 629 | "dev": true 630 | }, 631 | "is-fullwidth-code-point": { 632 | "version": "3.0.0", 633 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 634 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 635 | "dev": true 636 | }, 637 | "is-glob": { 638 | "version": "4.0.3", 639 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 640 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 641 | "dev": true, 642 | "requires": { 643 | "is-extglob": "^2.1.1" 644 | } 645 | }, 646 | "is-installed-globally": { 647 | "version": "0.4.0", 648 | "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", 649 | "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", 650 | "dev": true, 651 | "requires": { 652 | "global-dirs": "^3.0.0", 653 | "is-path-inside": "^3.0.2" 654 | } 655 | }, 656 | "is-npm": { 657 | "version": "5.0.0", 658 | "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", 659 | "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", 660 | "dev": true 661 | }, 662 | "is-number": { 663 | "version": "7.0.0", 664 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 665 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 666 | "dev": true 667 | }, 668 | "is-obj": { 669 | "version": "2.0.0", 670 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", 671 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", 672 | "dev": true 673 | }, 674 | "is-path-inside": { 675 | "version": "3.0.3", 676 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", 677 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", 678 | "dev": true 679 | }, 680 | "is-typedarray": { 681 | "version": "1.0.0", 682 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 683 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 684 | "dev": true 685 | }, 686 | "is-yarn-global": { 687 | "version": "0.3.0", 688 | "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", 689 | "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", 690 | "dev": true 691 | }, 692 | "json-buffer": { 693 | "version": "3.0.0", 694 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 695 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 696 | "dev": true 697 | }, 698 | "keyv": { 699 | "version": "3.1.0", 700 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 701 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 702 | "dev": true, 703 | "requires": { 704 | "json-buffer": "3.0.0" 705 | } 706 | }, 707 | "latest-version": { 708 | "version": "5.1.0", 709 | "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", 710 | "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", 711 | "dev": true, 712 | "requires": { 713 | "package-json": "^6.3.0" 714 | } 715 | }, 716 | "lowercase-keys": { 717 | "version": "1.0.1", 718 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 719 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 720 | "dev": true 721 | }, 722 | "lru-cache": { 723 | "version": "6.0.0", 724 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 725 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 726 | "dev": true, 727 | "requires": { 728 | "yallist": "^4.0.0" 729 | } 730 | }, 731 | "make-dir": { 732 | "version": "3.1.0", 733 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 734 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 735 | "dev": true, 736 | "requires": { 737 | "semver": "^6.0.0" 738 | }, 739 | "dependencies": { 740 | "semver": { 741 | "version": "6.3.0", 742 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 743 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 744 | "dev": true 745 | } 746 | } 747 | }, 748 | "media-typer": { 749 | "version": "0.3.0", 750 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 751 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 752 | }, 753 | "merge-descriptors": { 754 | "version": "1.0.1", 755 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 756 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 757 | }, 758 | "methods": { 759 | "version": "1.1.2", 760 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 761 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 762 | }, 763 | "mime": { 764 | "version": "1.6.0", 765 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 766 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 767 | }, 768 | "mime-db": { 769 | "version": "1.52.0", 770 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 771 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 772 | }, 773 | "mime-types": { 774 | "version": "2.1.35", 775 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 776 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 777 | "requires": { 778 | "mime-db": "1.52.0" 779 | } 780 | }, 781 | "mimic-response": { 782 | "version": "1.0.1", 783 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 784 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 785 | "dev": true 786 | }, 787 | "minimatch": { 788 | "version": "3.1.2", 789 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 790 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 791 | "dev": true, 792 | "requires": { 793 | "brace-expansion": "^1.1.7" 794 | } 795 | }, 796 | "minimist": { 797 | "version": "1.2.6", 798 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", 799 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", 800 | "dev": true 801 | }, 802 | "ms": { 803 | "version": "2.0.0", 804 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 805 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 806 | }, 807 | "negotiator": { 808 | "version": "0.6.3", 809 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 810 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 811 | }, 812 | "nodemon": { 813 | "version": "2.0.15", 814 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", 815 | "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", 816 | "dev": true, 817 | "requires": { 818 | "chokidar": "^3.5.2", 819 | "debug": "^3.2.7", 820 | "ignore-by-default": "^1.0.1", 821 | "minimatch": "^3.0.4", 822 | "pstree.remy": "^1.1.8", 823 | "semver": "^5.7.1", 824 | "supports-color": "^5.5.0", 825 | "touch": "^3.1.0", 826 | "undefsafe": "^2.0.5", 827 | "update-notifier": "^5.1.0" 828 | }, 829 | "dependencies": { 830 | "debug": { 831 | "version": "3.2.7", 832 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 833 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 834 | "dev": true, 835 | "requires": { 836 | "ms": "^2.1.1" 837 | } 838 | }, 839 | "ms": { 840 | "version": "2.1.3", 841 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 842 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 843 | "dev": true 844 | } 845 | } 846 | }, 847 | "nopt": { 848 | "version": "1.0.10", 849 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 850 | "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", 851 | "dev": true, 852 | "requires": { 853 | "abbrev": "1" 854 | } 855 | }, 856 | "normalize-path": { 857 | "version": "3.0.0", 858 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 859 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 860 | "dev": true 861 | }, 862 | "normalize-url": { 863 | "version": "4.5.1", 864 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", 865 | "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", 866 | "dev": true 867 | }, 868 | "on-finished": { 869 | "version": "2.3.0", 870 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 871 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 872 | "requires": { 873 | "ee-first": "1.1.1" 874 | } 875 | }, 876 | "once": { 877 | "version": "1.4.0", 878 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 879 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 880 | "dev": true, 881 | "requires": { 882 | "wrappy": "1" 883 | } 884 | }, 885 | "p-cancelable": { 886 | "version": "1.1.0", 887 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 888 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 889 | "dev": true 890 | }, 891 | "package-json": { 892 | "version": "6.5.0", 893 | "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", 894 | "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", 895 | "dev": true, 896 | "requires": { 897 | "got": "^9.6.0", 898 | "registry-auth-token": "^4.0.0", 899 | "registry-url": "^5.0.0", 900 | "semver": "^6.2.0" 901 | }, 902 | "dependencies": { 903 | "semver": { 904 | "version": "6.3.0", 905 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 906 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 907 | "dev": true 908 | } 909 | } 910 | }, 911 | "parseurl": { 912 | "version": "1.3.3", 913 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 914 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 915 | }, 916 | "path-to-regexp": { 917 | "version": "0.1.7", 918 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 919 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 920 | }, 921 | "picomatch": { 922 | "version": "2.3.1", 923 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 924 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 925 | "dev": true 926 | }, 927 | "prepend-http": { 928 | "version": "2.0.0", 929 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 930 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 931 | "dev": true 932 | }, 933 | "proxy-addr": { 934 | "version": "2.0.7", 935 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 936 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 937 | "requires": { 938 | "forwarded": "0.2.0", 939 | "ipaddr.js": "1.9.1" 940 | } 941 | }, 942 | "pstree.remy": { 943 | "version": "1.1.8", 944 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 945 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 946 | "dev": true 947 | }, 948 | "pump": { 949 | "version": "3.0.0", 950 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 951 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 952 | "dev": true, 953 | "requires": { 954 | "end-of-stream": "^1.1.0", 955 | "once": "^1.3.1" 956 | } 957 | }, 958 | "pupa": { 959 | "version": "2.1.1", 960 | "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", 961 | "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", 962 | "dev": true, 963 | "requires": { 964 | "escape-goat": "^2.0.0" 965 | } 966 | }, 967 | "qs": { 968 | "version": "6.9.7", 969 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", 970 | "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" 971 | }, 972 | "range-parser": { 973 | "version": "1.2.1", 974 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 975 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 976 | }, 977 | "raw-body": { 978 | "version": "2.4.3", 979 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", 980 | "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", 981 | "requires": { 982 | "bytes": "3.1.2", 983 | "http-errors": "1.8.1", 984 | "iconv-lite": "0.4.24", 985 | "unpipe": "1.0.0" 986 | } 987 | }, 988 | "rc": { 989 | "version": "1.2.8", 990 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 991 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 992 | "dev": true, 993 | "requires": { 994 | "deep-extend": "^0.6.0", 995 | "ini": "~1.3.0", 996 | "minimist": "^1.2.0", 997 | "strip-json-comments": "~2.0.1" 998 | }, 999 | "dependencies": { 1000 | "ini": { 1001 | "version": "1.3.8", 1002 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 1003 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", 1004 | "dev": true 1005 | } 1006 | } 1007 | }, 1008 | "readdirp": { 1009 | "version": "3.6.0", 1010 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1011 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1012 | "dev": true, 1013 | "requires": { 1014 | "picomatch": "^2.2.1" 1015 | } 1016 | }, 1017 | "registry-auth-token": { 1018 | "version": "4.2.1", 1019 | "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", 1020 | "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", 1021 | "dev": true, 1022 | "requires": { 1023 | "rc": "^1.2.8" 1024 | } 1025 | }, 1026 | "registry-url": { 1027 | "version": "5.1.0", 1028 | "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", 1029 | "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", 1030 | "dev": true, 1031 | "requires": { 1032 | "rc": "^1.2.8" 1033 | } 1034 | }, 1035 | "responselike": { 1036 | "version": "1.0.2", 1037 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 1038 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 1039 | "dev": true, 1040 | "requires": { 1041 | "lowercase-keys": "^1.0.0" 1042 | } 1043 | }, 1044 | "safe-buffer": { 1045 | "version": "5.2.1", 1046 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1047 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1048 | }, 1049 | "safer-buffer": { 1050 | "version": "2.1.2", 1051 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1052 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1053 | }, 1054 | "semver": { 1055 | "version": "5.7.1", 1056 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1057 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1058 | "dev": true 1059 | }, 1060 | "semver-diff": { 1061 | "version": "3.1.1", 1062 | "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", 1063 | "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", 1064 | "dev": true, 1065 | "requires": { 1066 | "semver": "^6.3.0" 1067 | }, 1068 | "dependencies": { 1069 | "semver": { 1070 | "version": "6.3.0", 1071 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1072 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1073 | "dev": true 1074 | } 1075 | } 1076 | }, 1077 | "send": { 1078 | "version": "0.17.2", 1079 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", 1080 | "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", 1081 | "requires": { 1082 | "debug": "2.6.9", 1083 | "depd": "~1.1.2", 1084 | "destroy": "~1.0.4", 1085 | "encodeurl": "~1.0.2", 1086 | "escape-html": "~1.0.3", 1087 | "etag": "~1.8.1", 1088 | "fresh": "0.5.2", 1089 | "http-errors": "1.8.1", 1090 | "mime": "1.6.0", 1091 | "ms": "2.1.3", 1092 | "on-finished": "~2.3.0", 1093 | "range-parser": "~1.2.1", 1094 | "statuses": "~1.5.0" 1095 | }, 1096 | "dependencies": { 1097 | "ms": { 1098 | "version": "2.1.3", 1099 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1100 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1101 | } 1102 | } 1103 | }, 1104 | "serve-static": { 1105 | "version": "1.14.2", 1106 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", 1107 | "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", 1108 | "requires": { 1109 | "encodeurl": "~1.0.2", 1110 | "escape-html": "~1.0.3", 1111 | "parseurl": "~1.3.3", 1112 | "send": "0.17.2" 1113 | } 1114 | }, 1115 | "setprototypeof": { 1116 | "version": "1.2.0", 1117 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1118 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1119 | }, 1120 | "signal-exit": { 1121 | "version": "3.0.7", 1122 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 1123 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", 1124 | "dev": true 1125 | }, 1126 | "statuses": { 1127 | "version": "1.5.0", 1128 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1129 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1130 | }, 1131 | "string-width": { 1132 | "version": "4.2.3", 1133 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1134 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1135 | "dev": true, 1136 | "requires": { 1137 | "emoji-regex": "^8.0.0", 1138 | "is-fullwidth-code-point": "^3.0.0", 1139 | "strip-ansi": "^6.0.1" 1140 | } 1141 | }, 1142 | "strip-ansi": { 1143 | "version": "6.0.1", 1144 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1145 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1146 | "dev": true, 1147 | "requires": { 1148 | "ansi-regex": "^5.0.1" 1149 | } 1150 | }, 1151 | "strip-json-comments": { 1152 | "version": "2.0.1", 1153 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1154 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1155 | "dev": true 1156 | }, 1157 | "supports-color": { 1158 | "version": "5.5.0", 1159 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1160 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1161 | "dev": true, 1162 | "requires": { 1163 | "has-flag": "^3.0.0" 1164 | } 1165 | }, 1166 | "to-readable-stream": { 1167 | "version": "1.0.0", 1168 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 1169 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 1170 | "dev": true 1171 | }, 1172 | "to-regex-range": { 1173 | "version": "5.0.1", 1174 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1175 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1176 | "dev": true, 1177 | "requires": { 1178 | "is-number": "^7.0.0" 1179 | } 1180 | }, 1181 | "toidentifier": { 1182 | "version": "1.0.1", 1183 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1184 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1185 | }, 1186 | "touch": { 1187 | "version": "3.1.0", 1188 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 1189 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 1190 | "dev": true, 1191 | "requires": { 1192 | "nopt": "~1.0.10" 1193 | } 1194 | }, 1195 | "type-fest": { 1196 | "version": "0.20.2", 1197 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 1198 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 1199 | "dev": true 1200 | }, 1201 | "type-is": { 1202 | "version": "1.6.18", 1203 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1204 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1205 | "requires": { 1206 | "media-typer": "0.3.0", 1207 | "mime-types": "~2.1.24" 1208 | } 1209 | }, 1210 | "typedarray-to-buffer": { 1211 | "version": "3.1.5", 1212 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 1213 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 1214 | "dev": true, 1215 | "requires": { 1216 | "is-typedarray": "^1.0.0" 1217 | } 1218 | }, 1219 | "undefsafe": { 1220 | "version": "2.0.5", 1221 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1222 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 1223 | "dev": true 1224 | }, 1225 | "unique-string": { 1226 | "version": "2.0.0", 1227 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", 1228 | "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", 1229 | "dev": true, 1230 | "requires": { 1231 | "crypto-random-string": "^2.0.0" 1232 | } 1233 | }, 1234 | "unpipe": { 1235 | "version": "1.0.0", 1236 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1237 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1238 | }, 1239 | "update-notifier": { 1240 | "version": "5.1.0", 1241 | "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", 1242 | "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", 1243 | "dev": true, 1244 | "requires": { 1245 | "boxen": "^5.0.0", 1246 | "chalk": "^4.1.0", 1247 | "configstore": "^5.0.1", 1248 | "has-yarn": "^2.1.0", 1249 | "import-lazy": "^2.1.0", 1250 | "is-ci": "^2.0.0", 1251 | "is-installed-globally": "^0.4.0", 1252 | "is-npm": "^5.0.0", 1253 | "is-yarn-global": "^0.3.0", 1254 | "latest-version": "^5.1.0", 1255 | "pupa": "^2.1.1", 1256 | "semver": "^7.3.4", 1257 | "semver-diff": "^3.1.1", 1258 | "xdg-basedir": "^4.0.0" 1259 | }, 1260 | "dependencies": { 1261 | "semver": { 1262 | "version": "7.3.7", 1263 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", 1264 | "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", 1265 | "dev": true, 1266 | "requires": { 1267 | "lru-cache": "^6.0.0" 1268 | } 1269 | } 1270 | } 1271 | }, 1272 | "url-parse-lax": { 1273 | "version": "3.0.0", 1274 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 1275 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 1276 | "dev": true, 1277 | "requires": { 1278 | "prepend-http": "^2.0.0" 1279 | } 1280 | }, 1281 | "utils-merge": { 1282 | "version": "1.0.1", 1283 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1284 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1285 | }, 1286 | "vary": { 1287 | "version": "1.1.2", 1288 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1289 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1290 | }, 1291 | "widest-line": { 1292 | "version": "3.1.0", 1293 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", 1294 | "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", 1295 | "dev": true, 1296 | "requires": { 1297 | "string-width": "^4.0.0" 1298 | } 1299 | }, 1300 | "wrap-ansi": { 1301 | "version": "7.0.0", 1302 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1303 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1304 | "dev": true, 1305 | "requires": { 1306 | "ansi-styles": "^4.0.0", 1307 | "string-width": "^4.1.0", 1308 | "strip-ansi": "^6.0.0" 1309 | } 1310 | }, 1311 | "wrappy": { 1312 | "version": "1.0.2", 1313 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1314 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1315 | "dev": true 1316 | }, 1317 | "write-file-atomic": { 1318 | "version": "3.0.3", 1319 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 1320 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 1321 | "dev": true, 1322 | "requires": { 1323 | "imurmurhash": "^0.1.4", 1324 | "is-typedarray": "^1.0.0", 1325 | "signal-exit": "^3.0.2", 1326 | "typedarray-to-buffer": "^3.1.5" 1327 | } 1328 | }, 1329 | "xdg-basedir": { 1330 | "version": "4.0.0", 1331 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", 1332 | "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", 1333 | "dev": true 1334 | }, 1335 | "yallist": { 1336 | "version": "4.0.0", 1337 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1338 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 1339 | "dev": true 1340 | } 1341 | } 1342 | } 1343 | --------------------------------------------------------------------------------