├── .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 |
--------------------------------------------------------------------------------