├── lesson-1
├── .gitignore
├── README.md
├── index.html
├── node start
│ └── index.js
├── node-CommonJS-module
│ ├── .gitignore
│ ├── date
│ │ ├── getCurrentMonth.js
│ │ ├── index.js
│ │ └── isLeapYear.js
│ ├── index.js
│ ├── package.json
│ └── users.js
├── node-module-es6-mjs
│ ├── .gitignore
│ ├── index.mjs
│ ├── package.json
│ └── users.mjs
├── node-module-es6-type
│ ├── .gitignore
│ ├── index.js
│ ├── package.json
│ └── users.js
├── npm-example
│ ├── .gitignore
│ ├── index.js
│ └── package.json
└── slides
│ ├── JS-V8-setTimeout-work.jpg
│ ├── JS-V8-work.jpg
│ ├── Nodejs-structure.jpg
│ ├── add-vanilla-js-library-problems.jpg
│ ├── motivation-picture.png
│ ├── npm-structure.jpg
│ └── project-create-steps.jpg
├── lesson-10
├── index.html
├── slides
│ ├── QA-work.jpg
│ ├── Test-driven-development-ru.png
│ ├── developing-with-test.jpg
│ ├── piramida.drawio.png
│ ├── test-first-schema.jpg
│ ├── test-instruments.png
│ └── test-schema.jpg
└── test-function-example
│ ├── app.js
│ ├── controllers
│ └── products
│ │ ├── getAll.js
│ │ ├── getAll.test.js
│ │ └── index.js
│ ├── funcs
│ ├── index.js
│ ├── isLeapYear.js
│ └── isLeapYear.test.js
│ ├── index.html
│ └── package.json
├── lesson-11
├── auth-example
│ ├── .env
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ │ └── server.js
│ ├── controllers
│ │ ├── auth
│ │ │ ├── index.js
│ │ │ ├── login.js
│ │ │ ├── logout.js
│ │ │ └── register.js
│ │ ├── index.js
│ │ ├── products
│ │ │ ├── add.js
│ │ │ ├── getAll.js
│ │ │ ├── getById.js
│ │ │ ├── index.js
│ │ │ ├── removeById.js
│ │ │ ├── updateById.js
│ │ │ └── updateStatus.js
│ │ └── users
│ │ │ ├── getCurrent.js
│ │ │ ├── index.js
│ │ │ └── verifyEmail.js
│ ├── env.example
│ ├── helpers
│ │ ├── index.js
│ │ └── sendEmail.js
│ ├── middlewares
│ │ ├── auth.js
│ │ ├── ctrlWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── index.js
│ │ ├── product.js
│ │ └── user.js
│ ├── nodemon.json
│ ├── package.json
│ ├── readme.md
│ └── routes
│ │ └── api
│ │ ├── auth.js
│ │ ├── products.js
│ │ └── users.js
├── index.html
├── nodemailer
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── sendgrid
│ ├── .gitignore
│ ├── app.js
│ ├── helpers
│ │ ├── index.js
│ │ └── sendEmail.js
│ └── package.json
└── slides
│ ├── mailing-schema.jpg
│ ├── nodemailer.jpg
│ └── sendgrid-schema.jpg
├── lesson-12
├── README.md
├── index.html
├── slides
│ ├── different-between-websockets-and-http.jpg
│ ├── web-socket-client-server-schema.jpg
│ ├── web-socket-personal-client-object.jpg
│ ├── websocket-main-features.jpg
│ └── websocket-projects.jpg
├── web-socket-chat-example
│ ├── .gitignore
│ ├── app.js
│ ├── frontend
│ │ ├── index.html
│ │ └── style.css
│ └── package.json
└── websocket-basic-example
│ ├── .gitignore
│ ├── app.js
│ ├── frontend.html
│ └── package.json
├── lesson-2
├── README.md
├── commander-example
│ ├── .gitignore
│ ├── app.js
│ ├── package.json
│ └── products
│ │ ├── add.js
│ │ ├── filePath.js
│ │ ├── getAll.js
│ │ ├── getById.js
│ │ ├── index.js
│ │ ├── products.json
│ │ ├── removeById.js
│ │ ├── updateById.js
│ │ └── updateProducts.js
├── index.html
├── process.argv-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── slides
│ └── work-with-files-examples.jpg
├── work-with-files
│ ├── .gitignore
│ ├── app.js
│ ├── files
│ │ └── file.txt
│ └── package.json
├── work-with-json-files
│ ├── .gitignore
│ ├── app.js
│ ├── package.json
│ └── products
│ │ ├── add.js
│ │ ├── filePath.js
│ │ ├── getAll.js
│ │ ├── getById.js
│ │ ├── index.js
│ │ ├── products.json
│ │ ├── removeById.js
│ │ ├── updateById.js
│ │ └── updateProducts.js
└── yargs-example
│ ├── .gitignore
│ ├── app.js
│ ├── package.json
│ └── products
│ ├── add.js
│ ├── filePath.js
│ ├── getAll.js
│ ├── getById.js
│ ├── index.js
│ ├── products.json
│ ├── removeById.js
│ ├── updateById.js
│ └── updateProducts.js
├── lesson-3
├── .gitignore
├── README.md
├── express-example-1
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── express-example-2
│ ├── .gitignore
│ ├── app.js
│ ├── package.json
│ ├── products.js
│ └── views
│ │ └── products.ejs
├── express-example-3
│ ├── .gitignore
│ ├── app.js
│ ├── index.html
│ ├── package.json
│ ├── products.js
│ └── server.log
├── express-example-4
│ ├── .gitignore
│ ├── app.js
│ ├── data
│ │ └── products.js
│ ├── package.json
│ └── routes
│ │ └── api
│ │ └── products.js
├── http-server-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── index.html
└── slides
│ ├── Client-Server-schema.jpg
│ ├── REST-API
│ ├── CRUD.jpg
│ ├── HTTP-methods.jpg
│ ├── REST-API-additional-rules.jpg
│ ├── REST-API-basic-rules.jpg
│ ├── Server-response-code.jpg
│ └── old-routes-example.jpg
│ ├── fullstack-developer-cors-problem-2.jpg
│ ├── fullstack-developer-cors-problem.jpg
│ ├── middleware-work-schema-details-2.jpg
│ ├── middleware-work-schema-details-3.jpg
│ ├── middleware-work-schema-details.jpg
│ ├── middleware-work-schema.jpg
│ └── what-is-it-cors.jpg
├── lesson-4
├── index.html
├── nodejs-homework-template-master-2
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ │ └── server.js
│ ├── controllers
│ │ ├── index.js
│ │ └── products
│ │ │ ├── add.js
│ │ │ ├── getAll.js
│ │ │ ├── getById.js
│ │ │ ├── index.js
│ │ │ ├── removeById.js
│ │ │ └── updateById.js
│ ├── middlewares
│ │ ├── ctrlWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── model
│ │ └── products
│ │ │ ├── add.js
│ │ │ ├── filePath.js
│ │ │ ├── getAll.js
│ │ │ ├── getById.js
│ │ │ ├── index.js
│ │ │ ├── products.json
│ │ │ ├── removeById.js
│ │ │ ├── updateById.js
│ │ │ └── updateProducts.js
│ ├── nodemon.json
│ ├── package.json
│ ├── readme.md
│ ├── routes
│ │ └── api
│ │ │ └── products.js
│ └── schemas
│ │ ├── index.js
│ │ └── product.js
└── nodejs-homework-template-master
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ └── server.js
│ ├── model
│ └── products
│ │ ├── add.js
│ │ ├── filePath.js
│ │ ├── getAll.js
│ │ ├── getById.js
│ │ ├── index.js
│ │ ├── products.json
│ │ ├── removeById.js
│ │ ├── updateById.js
│ │ └── updateProducts.js
│ ├── nodemon.json
│ ├── package.json
│ ├── readme.md
│ └── routes
│ └── api
│ └── products.js
├── lesson-5
├── index.html
├── mongodb-project
│ ├── .env.example
│ ├── .gitignore
│ ├── app.js
│ ├── controllers
│ │ ├── index.js
│ │ └── products
│ │ │ ├── add.js
│ │ │ ├── getAll.js
│ │ │ └── index.js
│ ├── middlewares
│ │ ├── ctrlWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── index.js
│ │ └── product.js
│ ├── package.json
│ └── routes
│ │ └── api
│ │ └── products.js
├── process-env-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── products.json
├── readme.md
└── slides
│ ├── backend-structure.jpg
│ ├── database-types.jpg
│ ├── documents-database-schema.jpg
│ ├── dotenv-work-schema.jpg
│ ├── mongodb-database-structure.jpg
│ ├── remote-database.jpg
│ ├── schema-model-collection.jpg
│ └── schema-model-example.jpg
├── lesson-6
└── nodejs-homework-template-master
│ ├── .env
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ └── server.js
│ ├── controllers
│ ├── index.js
│ └── products
│ │ ├── add.js
│ │ ├── getAll.js
│ │ ├── getById.js
│ │ ├── index.js
│ │ ├── removeById.js
│ │ ├── updateById.js
│ │ └── updateStatus.js
│ ├── env.example
│ ├── middlewares
│ ├── ctrlWrapper.js
│ ├── index.js
│ └── validation.js
│ ├── models
│ ├── index.js
│ └── product.js
│ ├── nodemon.json
│ ├── package.json
│ ├── readme.md
│ └── routes
│ └── api
│ └── products.js
├── lesson-7
├── .gitignore
├── README.md
├── auth-example
│ ├── .env
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ │ └── server.js
│ ├── controllers
│ │ ├── auth
│ │ │ ├── index.js
│ │ │ ├── login.js
│ │ │ └── register.js
│ │ ├── index.js
│ │ └── products
│ │ │ ├── add.js
│ │ │ ├── getAll.js
│ │ │ ├── getById.js
│ │ │ ├── index.js
│ │ │ ├── removeById.js
│ │ │ ├── updateById.js
│ │ │ └── updateStatus.js
│ ├── env.example
│ ├── middlewares
│ │ ├── ctrlWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── index.js
│ │ ├── product.js
│ │ └── user.js
│ ├── nodemon.json
│ ├── package.json
│ ├── readme.md
│ └── routes
│ │ └── api
│ │ ├── auth.js
│ │ └── products.js
├── hash-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── index.html
├── jsonwebtoken-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
└── slides
│ ├── HTTP-common-schema.jpg
│ ├── HTTP-personal-request-schema.jpg
│ ├── JWT-token-schema.jpg
│ ├── frontend-backend-requests-with-token.jpg
│ ├── hash-schema.jpg
│ ├── jwt-token-real-life-example.jpg
│ ├── logout-examples.jpg
│ ├── process.env-and-deploy.jpg
│ ├── register-auth-steps.jpg
│ └── reigster-auth-create-steps.jpg
├── lesson-8
├── auth-example
│ ├── .env
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ │ └── server.js
│ ├── controllers
│ │ ├── auth
│ │ │ ├── index.js
│ │ │ ├── login.js
│ │ │ ├── logout.js
│ │ │ └── register.js
│ │ ├── index.js
│ │ ├── products
│ │ │ ├── add.js
│ │ │ ├── getAll.js
│ │ │ ├── getById.js
│ │ │ ├── index.js
│ │ │ ├── removeById.js
│ │ │ ├── updateById.js
│ │ │ └── updateStatus.js
│ │ └── users
│ │ │ ├── getCurrent.js
│ │ │ └── index.js
│ ├── env.example
│ ├── middlewares
│ │ ├── auth.js
│ │ ├── ctrlWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── index.js
│ │ ├── product.js
│ │ └── user.js
│ ├── nodemon.json
│ ├── package.json
│ ├── readme.md
│ └── routes
│ │ └── api
│ │ ├── auth.js
│ │ ├── products.js
│ │ └── users.js
├── index.html
└── slides
│ ├── HTTP-common-schema.jpg
│ ├── HTTP-personal-request-schema.jpg
│ ├── JWT-token-schema.jpg
│ ├── frontend-backend-requests-with-token.jpg
│ ├── hash-schema.jpg
│ ├── jwt-token-real-life-example.jpg
│ ├── logout-examples.jpg
│ ├── process.env-and-deploy.jpg
│ ├── register-auth-steps.jpg
│ └── reigster-auth-create-steps.jpg
└── lesson-9
├── 2085-1.png
├── auth-example
├── .env
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── app.js
├── bin
│ └── server.js
├── controllers
│ ├── auth
│ │ ├── index.js
│ │ ├── login.js
│ │ ├── logout.js
│ │ └── register.js
│ ├── index.js
│ ├── products
│ │ ├── add.js
│ │ ├── getAll.js
│ │ ├── getById.js
│ │ ├── index.js
│ │ ├── removeById.js
│ │ ├── updateById.js
│ │ └── updateStatus.js
│ └── users
│ │ ├── getCurrent.js
│ │ ├── index.js
│ │ └── updateAvatar.js
├── env.example
├── middlewares
│ ├── auth.js
│ ├── ctrlWrapper.js
│ ├── index.js
│ ├── upload.js
│ └── validation.js
├── models
│ ├── index.js
│ ├── product.js
│ └── user.js
├── nodemon.json
├── package.json
├── public
│ └── avatars
│ │ └── 61afac845d2f14829dd3b79a_2085-1.png
├── readme.md
├── routes
│ └── api
│ │ ├── auth.js
│ │ ├── products.js
│ │ └── users.js
└── temp
│ └── .gitkeep
├── multer-example
├── .gitignore
├── app.js
├── frontend.html
├── index.html
├── package.json
├── public
│ └── products
│ │ └── 2085-1.png
└── temp
│ └── .gitkeep
└── slides
└── multer-work-schema.jpg
/lesson-1/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-1/README.md:
--------------------------------------------------------------------------------
1 | [Мотивационная картинка](./slides/motivation-picture.png)
2 |
3 | [Причины изучать Node.js](./slides/reasons-learn-nodejs.jpg)
4 |
5 | [Как V8 обрабатывает JS-код](./slides/JS-V8-work.jpg)
6 |
7 | [Как V8 обрабатывает JS-код, которого нет в документации JS](./slides/JS-V8-setTimeout-work.jpg)
8 |
9 | [Структура Node.js](./slides/Nodejs-structure.jpg)
10 |
11 | [Проблемы при добавлении библиотек на чистом JS](./slides/add-vanilla-js-library-problems.jpg)
12 |
13 | [Структура NPM](./slides/npm-structure.jpg)
14 |
15 | [Последовательность шагов при создании проекта](./slides/project-create-steps.jpg)
16 |
--------------------------------------------------------------------------------
/lesson-1/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
15 |
16 |
21 |
22 |
--------------------------------------------------------------------------------
/lesson-1/node start/index.js:
--------------------------------------------------------------------------------
1 | const date = new Date();
2 |
3 | // console.log(date.getFullYear());
4 | console.log("Welcome to Hell!");
--------------------------------------------------------------------------------
/lesson-1/node-CommonJS-module/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-1/node-CommonJS-module/date/getCurrentMonth.js:
--------------------------------------------------------------------------------
1 | const getCurrentMonth = ()=> {
2 | const now = new Date();
3 | return now.getMonth() + 1;
4 | }
5 |
6 | module.exports = getCurrentMonth;
7 |
8 |
--------------------------------------------------------------------------------
/lesson-1/node-CommonJS-module/date/index.js:
--------------------------------------------------------------------------------
1 | const getCurrentMonth = require("./getCurrentMonth");
2 | const isLeapYear = require("./isLeapYear");
3 |
4 | module.exports = {
5 | getCurrentMonth,
6 | isLeapYear
7 | }
8 |
9 |
10 |
--------------------------------------------------------------------------------
/lesson-1/node-CommonJS-module/date/isLeapYear.js:
--------------------------------------------------------------------------------
1 | const isLeapYear = (year) => {
2 |
3 | }
4 |
5 | module.exports = isLeapYear;
--------------------------------------------------------------------------------
/lesson-1/node-CommonJS-module/index.js:
--------------------------------------------------------------------------------
1 | // CommonJS
2 | // const nodemon = require("nodemon");
3 |
4 | // const users = require("./users");
5 | // console.log(users);
6 |
7 | // const {admins} = require("./users");
8 | // console.log(admins);
9 |
10 | // const {getCurrentMonth} = require("./date");
11 | const currentMonth = require("./date").getCurrentMonth();
12 | // const currentMonth = getCurrentMonth();
13 | console.log(`Сейчас ${currentMonth} месяц`);
14 |
15 | // const user = new require("./user");
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/lesson-1/node-CommonJS-module/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-CommonJS-module",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node index",
9 | "start:dev": "nodemon index"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lesson-1/node-CommonJS-module/users.js:
--------------------------------------------------------------------------------
1 | // const now = new Date();
2 | // console.log(now);
3 |
4 | const admins = ["Alex", "Andrey", "VAsiliy"];
5 |
6 | const clients = ["Anna", "Alina", "Tamara"];
7 |
8 | const users = {
9 | admins,
10 | clients
11 | };
12 |
13 | module.exports = users;
14 |
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-mjs/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-mjs/index.mjs:
--------------------------------------------------------------------------------
1 |
2 | import users from "./users.mjs";
3 | console.log(users);
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-mjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-CommonJS-module",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node index.mjs",
9 | "start:dev": "nodemon index.mjs"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-mjs/users.mjs:
--------------------------------------------------------------------------------
1 | // const now = new Date();
2 | // console.log(now);
3 |
4 | const admins = ["Alex", "Andrey", "VAsiliy"];
5 |
6 | const clients = ["Anna", "Alina", "Tamara"];
7 |
8 | const users = {
9 | admins,
10 | clients
11 | };
12 |
13 | export default users;
14 |
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-type/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-type/index.js:
--------------------------------------------------------------------------------
1 | import users from "./users.js";
2 | console.log(users);
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-type/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-CommonJS-module",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "start": "node index",
10 | "start:dev": "nodemon index"
11 | },
12 | "keywords": [],
13 | "author": "",
14 | "license": "ISC",
15 | "devDependencies": {
16 | "nodemon": "^2.0.12"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-type/users.js:
--------------------------------------------------------------------------------
1 | // const now = new Date();
2 | // console.log(now);
3 |
4 | const admins = ["Alex", "Andrey", "VAsiliy"];
5 |
6 | const clients = ["Anna", "Alina", "Tamara"];
7 |
8 | const users = {
9 | admins,
10 | clients
11 | };
12 |
13 | export default users;
14 |
--------------------------------------------------------------------------------
/lesson-1/npm-example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/lesson-1/npm-example/index.js:
--------------------------------------------------------------------------------
1 | console.log("Nodemon example")
--------------------------------------------------------------------------------
/lesson-1/npm-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "npm-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node index",
9 | "start:dev": "nodemon index"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.14"
16 | },
17 | "dependencies": {
18 | "cors": "^2.8.5",
19 | "express": "^4.17.1",
20 | "mongoose": "^6.0.12"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lesson-1/slides/JS-V8-setTimeout-work.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-1/slides/JS-V8-setTimeout-work.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/JS-V8-work.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-1/slides/JS-V8-work.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/Nodejs-structure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-1/slides/Nodejs-structure.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/add-vanilla-js-library-problems.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-1/slides/add-vanilla-js-library-problems.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/motivation-picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-1/slides/motivation-picture.png
--------------------------------------------------------------------------------
/lesson-1/slides/npm-structure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-1/slides/npm-structure.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/project-create-steps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-1/slides/project-create-steps.jpg
--------------------------------------------------------------------------------
/lesson-10/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/lesson-10/slides/QA-work.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/slides/QA-work.jpg
--------------------------------------------------------------------------------
/lesson-10/slides/Test-driven-development-ru.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/slides/Test-driven-development-ru.png
--------------------------------------------------------------------------------
/lesson-10/slides/developing-with-test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/slides/developing-with-test.jpg
--------------------------------------------------------------------------------
/lesson-10/slides/piramida.drawio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/slides/piramida.drawio.png
--------------------------------------------------------------------------------
/lesson-10/slides/test-first-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/slides/test-first-schema.jpg
--------------------------------------------------------------------------------
/lesson-10/slides/test-instruments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/slides/test-instruments.png
--------------------------------------------------------------------------------
/lesson-10/slides/test-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/slides/test-schema.jpg
--------------------------------------------------------------------------------
/lesson-10/test-function-example/app.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/test-function-example/app.js
--------------------------------------------------------------------------------
/lesson-10/test-function-example/controllers/products/getAll.js:
--------------------------------------------------------------------------------
1 | const products = [
2 | {
3 | id: "1",
4 | name: "iPhone X",
5 | price: 17000
6 | }
7 | ];
8 |
9 | const getAll = async(req, res)=> {
10 | res.json(products)
11 | }
12 |
13 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-10/test-function-example/controllers/products/getAll.test.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const request = require("supertest");
3 |
4 | const getAll = require("./getAll");
5 |
6 | const app = express();
7 |
8 | app.get("/api/products", getAll);
9 |
10 | describe("test getAll controller", ()=> {
11 | let server;
12 | beforeAll(()=> server = app.listen(3000));
13 | afterAll(()=> server.close());
14 |
15 | test("getAll return products array", async()=> {
16 | const response = await request(app).get("/api/products");
17 | expect(response.status).toBe(200);
18 | expect(Array.isArray(response.body)).toBe(true);
19 | const [product] = response.body;
20 | expect(typeof product.id).toBe("string");
21 | expect(typeof product.name).toBe("string");
22 | expect(typeof product.price).toBe("number");
23 | });
24 | })
--------------------------------------------------------------------------------
/lesson-10/test-function-example/controllers/products/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-10/test-function-example/controllers/products/index.js
--------------------------------------------------------------------------------
/lesson-10/test-function-example/funcs/index.js:
--------------------------------------------------------------------------------
1 | const isLeapYear = require("./isLeapYear");
2 |
3 | module.exports = {
4 | isLeapYear
5 | }
--------------------------------------------------------------------------------
/lesson-10/test-function-example/funcs/isLeapYear.js:
--------------------------------------------------------------------------------
1 | const isLeapYear = (year)=> {
2 | if(year === undefined){
3 | throw new Error('Year must be exist');
4 | }
5 |
6 | if(typeof year !== "number"){
7 | throw new Error('Year must be number')
8 | }
9 |
10 | if(!Number.isInteger(year)){
11 | throw new Error('Year must be integer');
12 | }
13 |
14 | if(year < 42){
15 | throw new Error('Year must me 42 or more');
16 | }
17 |
18 | const date = new Date(year, 2, 0);
19 | const days = date.getDate();
20 | return (days === 29);
21 | };
22 |
23 | module.exports = isLeapYear
--------------------------------------------------------------------------------
/lesson-10/test-function-example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
19 |
20 |
--------------------------------------------------------------------------------
/lesson-10/test-function-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-function-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "jest",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "jest": "^27.4.3",
16 | "nodemon": "^2.0.13"
17 | },
18 | "dependencies": {
19 | "express": "^4.17.1",
20 | "supertest": "^6.1.6"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=mongodb+srv://Bogdan:pBje6ZbFRATcsTq@cluster0.lhj89.mongodb.net/online_shop?retryWrites=true&w=majority
2 | SENDGRID_API_KEY=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
3 | SECRET_KEY=GHGSDFM23Tfgsfs3
4 | DB_USER=Bogdan
5 | DB_PASSWORD=pBje6ZbFRATcsTq
6 | DB_NAME=online_shop
--------------------------------------------------------------------------------
/lesson-11/auth-example/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/lesson-11/auth-example/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | node: true,
6 | },
7 | extends: ['standard'],
8 | parserOptions: {
9 | ecmaVersion: 12,
10 | },
11 | rules: {
12 | 'comma-dangle': 'off',
13 | 'space-before-function-paren': 'off',
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const logger = require('morgan')
3 | const cors = require('cors')
4 | require("dotenv").config();
5 |
6 | const authRouter = require("./routes/api/auth");
7 | const usersRouter = require("./routes/api/users");
8 | const productsRouter = require("./routes/api/products");
9 |
10 | const app = express()
11 |
12 | const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'
13 |
14 | app.use(logger(formatsLogger))
15 | app.use(cors())
16 | app.use(express.json())
17 |
18 | app.use("/api/auth", authRouter);
19 | app.use("/api/users", usersRouter);
20 | app.use('/api/products', productsRouter);
21 |
22 | app.use((req, res) => {
23 | res.status(404).json({ message: 'Not found' })
24 | })
25 |
26 | app.use((err, req, res, next) => {
27 | const {status = 500, message = "Server error"} = err;
28 | res.status(status).json({ message: err.message })
29 | })
30 |
31 | module.exports = app
32 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/bin/server.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const app = require('../app');
4 |
5 | const {DB_HOST, PORT = 3000} = process.env;
6 |
7 | mongoose.connect(DB_HOST)
8 | .then(()=> app.listen(PORT))
9 | .catch(error => {
10 | console.log(error.message);
11 | process.exit(1);
12 | })
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/auth/index.js:
--------------------------------------------------------------------------------
1 | const register = require("./register");
2 | const login = require("./login");
3 | const logout = require("./logout");
4 |
5 | module.exports = {
6 | register,
7 | login,
8 | logout
9 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/auth/login.js:
--------------------------------------------------------------------------------
1 | const {Unauthorized} = require("http-errors");
2 | const jwt = require("jsonwebtoken");
3 | // const bcrypt = require("bcryptjs");
4 |
5 | const {User} = require("../../models");
6 |
7 | const {SECRET_KEY} = process.env;
8 |
9 | const login = async(req, res)=> {
10 | const {email, password} = req.body;
11 | const user = await User.findOne({email});
12 | if(!user || !user.verify || !user.comparePassword(password)){
13 | throw new Unauthorized("Email is wrong or not verify, or password is wrong");
14 | }
15 |
16 | const payload = {
17 | id: user._id
18 | };
19 | const token = jwt.sign(payload, SECRET_KEY, {expiresIn: "1h"});
20 | await User.findByIdAndUpdate(user._id, {token});
21 | res.json({
22 | status: "success",
23 | code: 200,
24 | data: {
25 | token
26 | }
27 | })
28 | }
29 |
30 | module.exports = login;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/auth/logout.js:
--------------------------------------------------------------------------------
1 | const {User} = require("../../models");
2 |
3 | const logout = async(req, res)=> {
4 | const {_id} = req.user;
5 | await User.findByIdAndUpdate(_id, {token: null});
6 | res.status(204).json();
7 | }
8 |
9 | module.exports = logout;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/auth/register.js:
--------------------------------------------------------------------------------
1 | const {Conflict} = require("http-errors");
2 | const {nanoid} = require("nanoid");
3 |
4 | const {sendEmail} = require("../../helpers");
5 | const {User} = require("../../models");
6 |
7 | const register = async(req, res)=> {
8 | const {name, email, password} = req.body;
9 | const user = await User.findOne({email});
10 | if(user){
11 | throw new Conflict(`User with ${email} already exist`)
12 | }
13 | const verificationToken = nanoid();
14 | const newUser = new User({name, email, verificationToken});
15 |
16 | newUser.setPassword(password);
17 |
18 | await newUser.save();
19 | const mail = {
20 | to: email,
21 | subject: "Подтверждения email",
22 | html: `Подтвердить email`
23 | };
24 |
25 | await sendEmail(mail);
26 |
27 | res.status(201).json({
28 | status: "success",
29 | code: 201,
30 | data: {
31 | user: {
32 | email,
33 | name,
34 | verificationToken
35 | }
36 | }
37 | });
38 | }
39 |
40 | module.exports = register;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 | const auth = require("./auth");
3 | const users = require("./users");
4 |
5 | module.exports = {
6 | products,
7 | auth,
8 | users
9 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/products/add.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const add = async (req, res) => {
4 | const {_id} = req.user;
5 | const result = await Product.create({...req.body, owner: _id});
6 | res.status(201).json({
7 | status: "success",
8 | code: 201,
9 | data: {
10 | result
11 | }
12 | })
13 | }
14 |
15 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/products/getAll.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const getAll = async (req, res) => {
4 | const {_id} = req.user;
5 | const {page = 1, limit = 10} = req.query;
6 | const skip = (page - 1) * limit;
7 | const products = await Product.find({owner: _id}, "", {skip, limit: Number(limit)}).populate("owner", "_id name email");
8 |
9 | res.json({
10 | status: "success",
11 | code: 200,
12 | data: {
13 | result: products
14 | }
15 | });
16 | };
17 |
18 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/products/getById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const getById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findById(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 | const updateStatus = require("./updateStatus");
7 |
8 | module.exports = {
9 | getAll,
10 | getById,
11 | add,
12 | updateById,
13 | updateStatus,
14 | removeById
15 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/products/removeById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const removeById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndRemove(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | message: "product deleted",
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/products/updateById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndUpdate(id, req.body, {new: true});
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/products/updateStatus.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateStatus = async (req, res) => {
6 | const { id } = req.params;
7 | const {status} = req.body;
8 | const result = await Product.findByIdAndUpdate(id, {status}, {new: true});
9 | if (!result) {
10 | throw new NotFound(`Product with id=${id} not found`);
11 | }
12 | res.json({
13 | status: "success",
14 | code: 200,
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = updateStatus;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/users/getCurrent.js:
--------------------------------------------------------------------------------
1 | const {User} = require("../../models");
2 |
3 | const getCurrent = async(req, res)=> {
4 | const {name, email} = req.user;
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | user: {
10 | name,
11 | email
12 | }
13 |
14 | }
15 | })
16 | }
17 |
18 | module.exports = getCurrent;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/users/index.js:
--------------------------------------------------------------------------------
1 | const getCurrent = require("./getCurrent");
2 | const verifyEmail = require("./verifyEmail");
3 |
4 | module.exports = {
5 | getCurrent,
6 | verifyEmail
7 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/users/verifyEmail.js:
--------------------------------------------------------------------------------
1 | const {NotFound} = require("http-errors");
2 |
3 | const {User} = require("../../models");
4 |
5 | const verifyEmail = async(req, res)=> {
6 | const {verificationToken} = req.params;
7 | const user = await User.findOne({verificationToken});
8 | if(!user){
9 | throw NotFound();
10 | }
11 | await User.findByIdAndUpdate(user._id, {verify: true, verificationToken: null});
12 |
13 | res.json({
14 | message: "Verify success"
15 | })
16 | }
17 |
18 | module.exports = verifyEmail;
--------------------------------------------------------------------------------
/lesson-11/auth-example/env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | DB_USER=
3 | DB_PASSWORD=
4 | DB_NAME=
--------------------------------------------------------------------------------
/lesson-11/auth-example/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendEmail = require("./sendEmail");
2 |
3 | module.exports = {
4 | sendEmail
5 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/helpers/sendEmail.js:
--------------------------------------------------------------------------------
1 | const sgMail = require("@sendgrid/mail");
2 | require("dotenv").config();
3 |
4 | const {SENDGRID_API_KEY} = process.env;
5 |
6 | sgMail.setApiKey(SENDGRID_API_KEY);
7 |
8 | const sendEmail = async(data)=> {
9 | const email = {...data, from: "bogdan.lyamzin.d@gmail.com"};
10 | try {
11 | await sgMail.send(email);
12 | return true;
13 | } catch (error) {
14 | throw error;
15 | }
16 | }
17 |
18 | module.exports = sendEmail;
19 |
20 |
21 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/middlewares/ctrlWrapper.js:
--------------------------------------------------------------------------------
1 | const ctrlWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | } catch (error) {
6 | next(error);
7 | }
8 | }
9 | }
10 |
11 | module.exports = ctrlWrapper;
--------------------------------------------------------------------------------
/lesson-11/auth-example/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const ctrlWrapper = require("./ctrlWrapper");
3 | const auth = require("./auth");
4 |
5 | module.exports = {
6 | validation,
7 | ctrlWrapper,
8 | auth
9 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema)=> {
2 | return (req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | error.status = 400;
6 | next(error);
7 | }
8 | next()
9 | }
10 | }
11 |
12 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-11/auth-example/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 | const {User} = require("./user");
3 |
4 | module.exports = {
5 | Product,
6 | User
7 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["node_modules", "model/contacts.json"]
3 | }
4 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "cross-env NODE_ENV=production node ./bin/server.js",
7 | "start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
8 | "lint": "eslint **/*.js",
9 | "lint:fix": "eslint --fix **/*.js"
10 | },
11 | "dependencies": {
12 | "bcryptjs": "^2.4.3",
13 | "cors": "2.8.5",
14 | "cross-env": "7.0.3",
15 | "dotenv": "^10.0.0",
16 | "express": "4.17.1",
17 | "http-errors": "^1.8.1",
18 | "joi": "^17.4.2",
19 | "jsonwebtoken": "^8.5.1",
20 | "mongoose": "^6.0.13",
21 | "morgan": "1.10.0",
22 | "nanoid": "^3.1.30",
23 | "uuid": "^8.3.2"
24 | },
25 | "devDependencies": {
26 | "eslint": "^7.19.0",
27 | "eslint-config-standard": "^16.0.2",
28 | "eslint-plugin-import": "^2.22.1",
29 | "eslint-plugin-node": "^11.1.0",
30 | "eslint-plugin-promise": "^4.2.1",
31 | "nodemon": "2.0.7"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/readme.md:
--------------------------------------------------------------------------------
1 | ## GoIT Node.js Course Template Homework
2 |
3 | Выполните форк этого репозитория для выполнения домашних заданий (2-6)
4 | Форк создаст репозиторий на вашем http://github.com
5 |
6 | Добавьте ментора в коллаборацию
7 |
8 | Для каждой домашней работы создавайте свою ветку.
9 |
10 | - hw02
11 | - hw03
12 | - hw04
13 | - hw05
14 | - hw06
15 |
16 | Каждая новая ветка для дз должна делаться с master
17 |
18 | После того как вы закончили выполнять домашнее задание в своей ветке, необходимо сделать пулл-реквест (PR). Потом добавить ментора для ревью кода. Только после того как ментор заапрувит PR, вы можете выполнить мердж ветки с домашним заданием в мастер.
19 |
20 | Внимательно читайте комментарии ментора. Исправьте замечания и сделайте коммит в ветке с домашним заданием. Изменения подтянуться в PR автоматически после того как вы отправите коммит с исправлениями на github
21 | После исправления снова добавьте ментора на ревью кода.
22 |
23 | - При сдаче домашней работы есть ссылка на PR
24 | - JS-код чистый и понятный, для форматирования используется Prettier
25 |
26 | ### Команды:
27 |
28 | - `npm start` — старт сервера в режиме production
29 | - `npm run start:dev` — старт сервера в режиме разработки (development)
30 | - `npm run lint` — запустить выполнение проверки кода с eslint, необходимо выполнять перед каждым PR и исправлять все ошибки линтера
31 | - `npm lint:fix` — та же проверка линтера, но с автоматическими исправлениями простых ошибок
32 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/routes/api/auth.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, validation, ctrlWrapper} = require("../../middlewares");
4 | const {auth: ctrl} = require("../../controllers");
5 | const {joiRegisterSchema, joiLoginSchema} = require("../../models/user");
6 |
7 | const router = express.Router();
8 |
9 | router.post("/register", validation(joiRegisterSchema), ctrlWrapper(ctrl.register));
10 | // router.post("/signup")
11 | router.post("/login", validation(joiLoginSchema), ctrlWrapper(ctrl.login));
12 | // router.post("/signin")
13 | router.get("/logout", auth, ctrlWrapper(ctrl.logout));
14 | // router.get("/signout")
15 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-11/auth-example/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, validation, ctrlWrapper} = require("../../middlewares");
4 | const {joiSchema, statusJoiSchema} = require("../../models/product");
5 | const {products: ctrl} = require("../../controllers")
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", auth, ctrlWrapper(ctrl.getAll));
10 |
11 | router.get("/:id", ctrlWrapper(ctrl.getById));
12 |
13 | router.post("/", auth, validation(joiSchema), ctrlWrapper(ctrl.add));
14 |
15 | router.put("/:id", validation(joiSchema), ctrlWrapper(ctrl.updateById));
16 |
17 | router.patch("/:id/status", validation(statusJoiSchema), ctrlWrapper(ctrl.updateStatus));
18 |
19 | router.delete("/:id", ctrlWrapper(ctrl.removeById));
20 |
21 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-11/auth-example/routes/api/users.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, ctrlWrapper} = require("../../middlewares");
4 | const {users: ctrl} = require("../../controllers");
5 |
6 | const router = express.Router();
7 |
8 | router.get("/current", auth, ctrlWrapper(ctrl.getCurrent));
9 |
10 | router.get("/verify/:verificationToken", ctrlWrapper(ctrl.verifyEmail));
11 |
12 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-11/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/lesson-11/nodemailer/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-11/nodemailer/app.js:
--------------------------------------------------------------------------------
1 | const nodemailer = require("nodemailer");
2 | require("dotenv").config();
3 |
4 | const {META_PASSWORD} = process.env;
5 |
6 | const nodemailerConfig = {
7 | host: "smtp.meta.ua",
8 | port: 465, // 25, 465 и 2255
9 | secure: true,
10 | auth: {
11 | user: "bogdan.lyamzin.d@meta.ua",
12 | pass: META_PASSWORD
13 | }
14 | };
15 |
16 | const transporter = nodemailer.createTransport(nodemailerConfig);
17 |
18 | const email = {
19 | to: "hiyowop403@kingsready.com",
20 | from: "bogdan.lyamzin.d@meta.ua",
21 | subject: "Новая заявка с сайта",
22 | html: "С сайта пришла новая заявка
"
23 | };
24 |
25 | transporter.sendMail(email)
26 | .then(()=> console.log("Email send success"))
27 | .catch(error => console.log(error.message))
--------------------------------------------------------------------------------
/lesson-11/nodemailer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nodemailer",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.13"
16 | },
17 | "dependencies": {
18 | "dotenv": "^10.0.0",
19 | "nodemailer": "^6.7.2"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lesson-11/sendgrid/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-11/sendgrid/app.js:
--------------------------------------------------------------------------------
1 | const sgMail = require("@sendgrid/mail");
2 | require("dotenv").config();
3 |
4 | const {SENDGRID_API_KEY} = process.env;
5 |
6 | sgMail.setApiKey(SENDGRID_API_KEY);
7 |
8 | const email = {
9 | to: "hiyowop403@kingsready.com",
10 | from: "bogdan.lyamzin.d@gmail.com",
11 | subject: "Новая заявка с сайта",
12 | html: "С сайта пришла новая заявка
"
13 | };
14 |
15 | sgMail.send(email)
16 | .then(()=> console.log("Email send success"))
17 | .catch(error => console.log(error.message))
18 |
--------------------------------------------------------------------------------
/lesson-11/sendgrid/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendEmail = require("./sendEmail");
2 |
3 | module.exports = {
4 | sendEmail
5 | }
--------------------------------------------------------------------------------
/lesson-11/sendgrid/helpers/sendEmail.js:
--------------------------------------------------------------------------------
1 | const sgMail = require("@sendgrid/mail");
2 | require("dotenv").config();
3 |
4 | const {SENDGRID_API_KEY} = process.env;
5 |
6 | sgMail.setApiKey(SENDGRID_API_KEY);
7 |
8 | const sendEmail = async(data)=> {
9 | const email = {...data, from: "bogdan.lyamzin.d@gmail.com"};
10 | try {
11 | await sgMail.send(email);
12 | return true;
13 | } catch (error) {
14 | throw error;
15 | }
16 | }
17 |
18 | module.exports = sendEmail;
19 |
20 |
21 |
--------------------------------------------------------------------------------
/lesson-11/sendgrid/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sendgrid",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.13"
16 | },
17 | "dependencies": {
18 | "@sendgrid/mail": "^7.6.0",
19 | "dotenv": "^10.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lesson-11/slides/mailing-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-11/slides/mailing-schema.jpg
--------------------------------------------------------------------------------
/lesson-11/slides/nodemailer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-11/slides/nodemailer.jpg
--------------------------------------------------------------------------------
/lesson-11/slides/sendgrid-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-11/slides/sendgrid-schema.jpg
--------------------------------------------------------------------------------
/lesson-12/README.md:
--------------------------------------------------------------------------------
1 | [Где применяются веб-сокеты](./slides/websocket-projects.jpg)
2 |
3 | [Разница между веб-сокетами и HTTP](./slides/different-between-websockets-and-http.jpg)
4 |
5 | [Основные нюансы вет-сокет протокола](./slides/websocket-main-features.jpg)
6 |
7 | [Схема взаимодействия клиент-сервер у веб-сокетов](./slides/web-socket-client-server-schema.jpg)
8 |
9 | [Принцип работы с каждым отдельным клиентом у веб-сокетов](./slides/web-socket-personal-client-object.jpg)
--------------------------------------------------------------------------------
/lesson-12/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-12/slides/different-between-websockets-and-http.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-12/slides/different-between-websockets-and-http.jpg
--------------------------------------------------------------------------------
/lesson-12/slides/web-socket-client-server-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-12/slides/web-socket-client-server-schema.jpg
--------------------------------------------------------------------------------
/lesson-12/slides/web-socket-personal-client-object.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-12/slides/web-socket-personal-client-object.jpg
--------------------------------------------------------------------------------
/lesson-12/slides/websocket-main-features.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-12/slides/websocket-main-features.jpg
--------------------------------------------------------------------------------
/lesson-12/slides/websocket-projects.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-12/slides/websocket-projects.jpg
--------------------------------------------------------------------------------
/lesson-12/web-socket-chat-example/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | package-lock.json
4 | yarn.lock
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-12/web-socket-chat-example/app.js:
--------------------------------------------------------------------------------
1 | const ws = new require("ws");
2 |
3 | const wsServer = new ws.Server({port: 5000});
4 |
5 | const users = [];
6 |
7 | wsServer.on("connection", (newUser)=>{
8 | users.push(newUser);
9 |
10 | newUser.on("message", (data)=> {
11 | const message = JSON.parse(data);
12 | users.forEach(user => {
13 | if(user !== newUser){
14 | user.send(JSON.stringify(message));
15 | }
16 | })
17 | })
18 | })
--------------------------------------------------------------------------------
/lesson-12/web-socket-chat-example/frontend/style.css:
--------------------------------------------------------------------------------
1 | .chat {
2 | width: 242px;
3 | margin-bottom: 15px;
4 | border: 1px solid;
5 | }
6 |
7 | .chat p {
8 | margin: 10px 5px 25px;
9 | }
10 |
11 | .enter-chat-message {
12 | font-size: 18px;
13 | font-weight: bold;
14 | font-family: Arial, Helvetica, sans-serif;
15 | padding: 5px;
16 | border-radius: 5px;
17 | display: inline-block;
18 | }
19 |
20 | .you-chat-message {
21 | font-size: 16px;
22 | font-family: Arial, Helvetica, sans-serif;
23 | background-color: lightgray;
24 | padding: 5px;
25 | border-radius: 5px;
26 | display: inline-block;
27 | }
28 |
29 | .user-chat-message {
30 | font-size: 16px;
31 | font-family: Arial, Helvetica, sans-serif;
32 | text-align: right;
33 | background-color: lightskyblue;
34 | padding: 5px;
35 | border-radius: 5px;
36 | display: inline-block;
37 | }
--------------------------------------------------------------------------------
/lesson-12/web-socket-chat-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web-socket-chat-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.9"
16 | },
17 | "dependencies": {
18 | "ws": "^8.3.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-12/websocket-basic-example/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | package-lock.json
4 | yarn.lock
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-12/websocket-basic-example/app.js:
--------------------------------------------------------------------------------
1 | const ws = new require("ws");
2 |
3 | const wsServer = new ws.Server({port: 5000});
4 |
5 | const clients = [];
6 |
7 | wsServer.on("connection", (newClient)=> {
8 | clients.push(newClient)
9 | // console.log("Новое подключение с фронтенда")
10 | // setTimeout(()=> {
11 | // newClient.send("Добро пожаловать на наш сервер!")
12 | // }, 3000)
13 | clients.forEach(client => {
14 | if(client !== newClient){
15 | client.send("К нам присоединился новый пользователь")
16 | }
17 | })
18 | })
19 |
20 |
21 |
--------------------------------------------------------------------------------
/lesson-12/websocket-basic-example/frontend.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Title
7 |
8 |
9 |
10 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/lesson-12/websocket-basic-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "websocket-basic-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.8"
16 | },
17 | "dependencies": {
18 | "ws": "^8.3.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-2/README.md:
--------------------------------------------------------------------------------
1 | [Где используется работа с файлами в Node.js](./slides/work-with-files-examples.png)
2 |
--------------------------------------------------------------------------------
/lesson-2/commander-example/.gitignore:
--------------------------------------------------------------------------------
1 | package-lock.json
2 | yarn.lock
3 | node_modules/
--------------------------------------------------------------------------------
/lesson-2/commander-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "commander-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "nodemon": "^2.0.12"
14 | },
15 | "dependencies": {
16 | "commander": "^8.2.0",
17 | "uuid": "^8.3.2"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/add.js:
--------------------------------------------------------------------------------
1 | const {v4} = require("uuid");
2 |
3 | const updateProducts = require("./updateProducts");
4 | const getAll = require("./getAll");
5 |
6 | const add = async(data)=> {
7 | const products = await getAll();
8 | const newProduct = {...data, id: v4()};
9 | products.push(newProduct);
10 | await updateProducts(products);
11 | return newProduct;
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/filePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const filePath = path.join(__dirname, "products.json");
4 |
5 | module.exports = filePath;
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/getAll.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const getAll = async()=> {
6 | const data = await fs.readFile(filePath);
7 | const products = JSON.parse(data);
8 | return products;
9 | }
10 |
11 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/getById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 |
3 | const getById = async(id)=> {
4 | const products = await getAll();
5 | const result = products.find(item => item.id === id);
6 | if(!result){
7 | return null;
8 | }
9 | return result;
10 | }
11 |
12 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 |
7 | module.exports = {
8 | getAll,
9 | getById,
10 | add,
11 | updateById,
12 | removeById
13 | }
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/products.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "48bd1cd8-72ca-42cc-8457-156bb8c30873",
4 | "name": "cheese",
5 | "price": 2.5,
6 | "location": "Refrigerated foods"
7 | },
8 | {
9 | "id": "61c0169c-e693-4a20-af3e-2e55fdc34f79",
10 | "name": "Crisps",
11 | "price": 4,
12 | "location": "the Snack isle"
13 | },
14 | {
15 | "id": "2c9c3d67-07b3-4ee1-a59f-67d54427d3c3",
16 | "name": "Pizza",
17 | "price": 4,
18 | "location": "Refrigerated foods"
19 | },
20 | {
21 | "id": "2386a63f-140a-494c-b4e5-b23a219bbac0",
22 | "name": "Chocolate",
23 | "price": 1.5,
24 | "location": "the Snack isle"
25 | },
26 | {
27 | "id": "8263b539-c546-4a64-866d-97d58e42c585",
28 | "name": "Self-raising flour",
29 | "price": 1.5,
30 | "location": "Home baking"
31 | },
32 | {
33 | "id": "767580d5-f509-4f45-98f9-28e74ec4af66",
34 | "name": "Ground almonds",
35 | "price": 5,
36 | "location": "Home baking"
37 | }
38 | ]
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/removeById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const removeById = async(id)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | // const [removeProduct] = products.splice(idx, 1);
11 | // await updateProducts(products);
12 | // return removeProduct
13 | const newProducts = products.filter((_, index) => index !== idx);
14 | await updateProducts(newProducts);
15 | return products[idx];
16 | }
17 |
18 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/updateById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const updateById = async(id, data)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | products[idx] = {...data, id};
11 | await updateProducts(products);
12 | return products[idx];
13 | }
14 |
15 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-2/commander-example/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const updateProducts = async(products)=> {
6 | await fs.writeFile(filePath, JSON.stringify(products));
7 | }
8 |
9 | module.exports = updateProducts;
--------------------------------------------------------------------------------
/lesson-2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
15 |
16 |
21 |
22 |
--------------------------------------------------------------------------------
/lesson-2/process.argv-example/.gitignore:
--------------------------------------------------------------------------------
1 | package-lock.json
2 | yarn.lock
3 | node_modules/
--------------------------------------------------------------------------------
/lesson-2/process.argv-example/app.js:
--------------------------------------------------------------------------------
1 | const actionIndex = process.argv.indexOf("--action");
2 |
3 | if(actionIndex !== -1){
4 |
5 | }
--------------------------------------------------------------------------------
/lesson-2/process.argv-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "process.argv-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "nodemon": "^2.0.12"
14 | },
15 | "dependencies": {
16 | "uuid": "^8.3.2"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lesson-2/slides/work-with-files-examples.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-2/slides/work-with-files-examples.jpg
--------------------------------------------------------------------------------
/lesson-2/work-with-files/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-2/work-with-files/app.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | // const fs = require("fs").promises;
3 |
4 | const fileOperation = async(filePath, action = "read", data = "") => {
5 | switch(action){
6 | case "read":
7 | const text = await fs.readFile(filePath, "utf-8");
8 | console.log(text);
9 | break;
10 | case "add":
11 | await fs.appendFile(filePath, data);
12 | break;
13 | case "replace":
14 | await fs.writeFile(filePath, data);
15 | break;
16 | default:
17 | console.log("Unknown action")
18 | }
19 | }
20 |
21 | // fileOperation("files/file.txt");
22 | // fileOperation("files/file.txt", "add", "\nНе плюйся - никто не носит золота во рту");
23 | fileOperation("files/file.txt", "replace", "Не плюйся - никто не носит золота во рту");
24 |
25 | // fs.readFile("files/file.txt", "utf-8")
26 | // .then(data => {
27 | // console.log(data);
28 | // // const text = data.toString();
29 | // // console.log(text);
30 | // })
31 | // .catch(error => console.log(error.message))
32 |
33 |
--------------------------------------------------------------------------------
/lesson-2/work-with-files/files/file.txt:
--------------------------------------------------------------------------------
1 |
2 | Не плюйся - никто не носит золота во рту
--------------------------------------------------------------------------------
/lesson-2/work-with-files/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "work-with-files",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "work-with-json-files",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | },
17 | "dependencies": {
18 | "uuid": "^8.3.2"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/add.js:
--------------------------------------------------------------------------------
1 | const {v4} = require("uuid");
2 |
3 | const updateProducts = require("./updateProducts");
4 | const getAll = require("./getAll");
5 |
6 | const add = async(data)=> {
7 | const products = await getAll();
8 | const newProduct = {...data, id: v4()};
9 | products.push(newProduct);
10 | await updateProducts(products);
11 | return newProduct;
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/filePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const filePath = path.join(__dirname, "products.json");
4 |
5 | module.exports = filePath;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/getAll.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const getAll = async()=> {
6 | const data = await fs.readFile(filePath);
7 | const products = JSON.parse(data);
8 | return products;
9 | }
10 |
11 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/getById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 |
3 | const getById = async(id)=> {
4 | const products = await getAll();
5 | const result = products.find(item => item.id === id);
6 | if(!result){
7 | return null;
8 | }
9 | return result;
10 | }
11 |
12 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 |
7 | module.exports = {
8 | getAll,
9 | getById,
10 | add,
11 | updateById,
12 | removeById
13 | }
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/products.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "48bd1cd8-72ca-42cc-8457-156bb8c30873",
4 | "name": "cheese",
5 | "price": 2.5,
6 | "location": "Refrigerated foods"
7 | },
8 | {
9 | "id": "61c0169c-e693-4a20-af3e-2e55fdc34f79",
10 | "name": "Crisps",
11 | "price": 4,
12 | "location": "the Snack isle"
13 | },
14 | {
15 | "id": "2c9c3d67-07b3-4ee1-a59f-67d54427d3c3",
16 | "name": "Pizza",
17 | "price": 4,
18 | "location": "Refrigerated foods"
19 | },
20 | {
21 | "id": "2386a63f-140a-494c-b4e5-b23a219bbac0",
22 | "name": "Chocolate",
23 | "price": 1.5,
24 | "location": "the Snack isle"
25 | },
26 | {
27 | "id": "8263b539-c546-4a64-866d-97d58e42c585",
28 | "name": "Self-raising flour",
29 | "price": 1.5,
30 | "location": "Home baking"
31 | },
32 | {
33 | "id": "767580d5-f509-4f45-98f9-28e74ec4af66",
34 | "name": "Ground almonds",
35 | "price": 5,
36 | "location": "Home baking"
37 | }
38 | ]
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/removeById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const removeById = async(id)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | // const [removeProduct] = products.splice(idx, 1);
11 | // await updateProducts(products);
12 | // return removeProduct
13 | const newProducts = products.filter((_, index) => index !== idx);
14 | await updateProducts(newProducts);
15 | return products[idx];
16 | }
17 |
18 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/updateById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const updateById = async(id, data)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | products[idx] = {...data, id};
11 | await updateProducts(products);
12 | return products[idx];
13 | }
14 |
15 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const updateProducts = async(products)=> {
6 | await fs.writeFile(filePath, JSON.stringify(products));
7 | }
8 |
9 | module.exports = updateProducts;
--------------------------------------------------------------------------------
/lesson-2/yargs-example/.gitignore:
--------------------------------------------------------------------------------
1 | package-lock.json
2 | yarn.lock
3 | node_modules/
--------------------------------------------------------------------------------
/lesson-2/yargs-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "yargs-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "nodemon": "^2.0.12"
14 | },
15 | "dependencies": {
16 | "uuid": "^8.3.2",
17 | "yargs": "^17.1.1"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/add.js:
--------------------------------------------------------------------------------
1 | const {v4} = require("uuid");
2 |
3 | const updateProducts = require("./updateProducts");
4 | const getAll = require("./getAll");
5 |
6 | const add = async(data)=> {
7 | const products = await getAll();
8 | const newProduct = {...data, id: v4()};
9 | products.push(newProduct);
10 | await updateProducts(products);
11 | return newProduct;
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/filePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const filePath = path.join(__dirname, "products.json");
4 |
5 | module.exports = filePath;
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/getAll.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const getAll = async()=> {
6 | const data = await fs.readFile(filePath);
7 | const products = JSON.parse(data);
8 | return products;
9 | }
10 |
11 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/getById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 |
3 | const getById = async(id)=> {
4 | const products = await getAll();
5 | const result = products.find(item => item.id === id);
6 | if(!result){
7 | return null;
8 | }
9 | return result;
10 | }
11 |
12 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 |
7 | module.exports = {
8 | getAll,
9 | getById,
10 | add,
11 | updateById,
12 | removeById
13 | }
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/products.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "48bd1cd8-72ca-42cc-8457-156bb8c30873",
4 | "name": "cheese",
5 | "price": 2.5,
6 | "location": "Refrigerated foods"
7 | },
8 | {
9 | "id": "61c0169c-e693-4a20-af3e-2e55fdc34f79",
10 | "name": "Crisps",
11 | "price": 4,
12 | "location": "the Snack isle"
13 | },
14 | {
15 | "id": "2c9c3d67-07b3-4ee1-a59f-67d54427d3c3",
16 | "name": "Pizza",
17 | "price": 4,
18 | "location": "Refrigerated foods"
19 | },
20 | {
21 | "id": "2386a63f-140a-494c-b4e5-b23a219bbac0",
22 | "name": "Chocolate",
23 | "price": 1.5,
24 | "location": "the Snack isle"
25 | },
26 | {
27 | "id": "8263b539-c546-4a64-866d-97d58e42c585",
28 | "name": "Self-raising flour",
29 | "price": 1.5,
30 | "location": "Home baking"
31 | },
32 | {
33 | "id": "767580d5-f509-4f45-98f9-28e74ec4af66",
34 | "name": "Ground almonds",
35 | "price": 5,
36 | "location": "Home baking"
37 | }
38 | ]
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/removeById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const removeById = async(id)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | // const [removeProduct] = products.splice(idx, 1);
11 | // await updateProducts(products);
12 | // return removeProduct
13 | const newProducts = products.filter((_, index) => index !== idx);
14 | await updateProducts(newProducts);
15 | return products[idx];
16 | }
17 |
18 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/updateById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const updateById = async(id, data)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | products[idx] = {...data, id};
11 | await updateProducts(products);
12 | return products[idx];
13 | }
14 |
15 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-2/yargs-example/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const updateProducts = async(products)=> {
6 | await fs.writeFile(filePath, JSON.stringify(products));
7 | }
8 |
9 | module.exports = updateProducts;
--------------------------------------------------------------------------------
/lesson-3/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | package-lock.json
4 | yarn.lock
5 | .env
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-3/README.md:
--------------------------------------------------------------------------------
1 | [Схема взаимодействия клиента и сервера](./slides/Client-Server-schema.jpg)
2 |
3 | [Как работают middleware в express](./slides/middleware-work-schema.jpg)
4 |
5 | [Как работают middleware в express](./slides/middleware-work-schema.jpg)
6 |
7 | [Более подробно - как работают middleware в express](./slides/middleware-work-schema-details.jpg)
8 |
9 | [Middleware в express как оглавление записной книжки](./slides/middleware-work-schema-details-2.jpg)
10 |
11 | [Middleware в express как набор обязательных действий на ресепшен](./slides/middleware-work-schema-details-3.jpg)
12 |
13 | [Что такое CORS - кросс-доменные запросы](./slides/what-is-it-cors.jpg)
14 |
15 | [Проблемы с CORS при разработки одновремено фронтенда и бекенда](./slides/fullstack-developer-cors-problem.jpg)
16 |
17 | [Проблемы с CORS когда бекенд задеплоен на удаленный сервер](./slides/fullstack-developer-cors-problem-2.jpg)
--------------------------------------------------------------------------------
/lesson-3/express-example-1/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | package-lock.json
4 | yarn.lock
5 | .env
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-3/express-example-1/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const app = express();
4 |
5 | // Если прийдет GET запрос на адрес /contacts, выполнить эту функцию
6 | app.get("/contacts", (request, response)=> {
7 | // console.log(request.url);
8 | // console.log(request.method);
9 | // console.log(request.headers);
10 | response.send("Contacts page
")
11 | });
12 |
13 | app.get("/contact", (request, response)=> {
14 | response.send("Contact page
")
15 | })
16 |
17 | app.get("/", (request, response)=> {
18 | response.send("Home page
")
19 | })
20 |
21 | app.listen(3000, ()=> console.log("Server running"));
--------------------------------------------------------------------------------
/lesson-3/express-example-1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-example-1",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | },
17 | "dependencies": {
18 | "express": "^4.17.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-3/express-example-2/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | package-lock.json
4 | yarn.lock
5 | .env
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-3/express-example-2/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const products = require("./products");
4 |
5 | const app = express();
6 |
7 | // app.set("json spaces", 18);
8 |
9 | app.get("/products", (req, res)=> {
10 | // res.json(null);
11 | // res.send(null);
12 | // res.json({
13 | // status: "success",
14 | // code: 200,
15 | // data: {
16 | // result: products
17 | // }
18 | // });
19 | // res.json(products);
20 | // res.send(products);
21 | // res.render("products", {name: "iPhone"} )
22 | });
23 |
24 | app.listen(3000);
25 |
26 |
--------------------------------------------------------------------------------
/lesson-3/express-example-2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-example-2",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | },
17 | "dependencies": {
18 | "express": "^4.17.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-3/express-example-2/products.js:
--------------------------------------------------------------------------------
1 | const products = [
2 | {
3 | _id: "34ggffg",
4 | name: "iPhone X",
5 | price: 34000
6 | },
7 | {
8 | _id: "dffgsdgdg",
9 | name: "GeForce RTX 3090",
10 | price: 90000
11 | }
12 | ];
13 |
14 | module.exports = products;
--------------------------------------------------------------------------------
/lesson-3/express-example-2/views/products.ejs:
--------------------------------------------------------------------------------
1 | <% name %>
--------------------------------------------------------------------------------
/lesson-3/express-example-3/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | package-lock.json
4 | yarn.lock
5 | .env
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-3/express-example-3/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const fs = require("fs/promises");
3 | const moment = require("moment");
4 | const cors = require("cors");
5 |
6 | const products = require("./products");
7 |
8 | const app = express();
9 |
10 | app.use(cors());
11 |
12 | // app.use(async(req, res, next)=> {
13 | // const {method, url} = req;
14 | // const date = moment().format("DD-MM-YYYY_hh:mm:ss");
15 | // await fs.appendFile("server.log", `\n${method} ${url} ${date}`);
16 | // next();
17 | // })
18 |
19 | // app.use((req, res, next)=> {
20 | // console.log("First middleware");
21 | // next();
22 | // });
23 |
24 | // app.use((req, res, next)=> {
25 | // console.log("Second middleware");
26 | // next();
27 | // })
28 |
29 | app.get("/products", (req, res)=> {
30 | res.json(products);
31 | })
32 |
33 | app.listen(3000);
--------------------------------------------------------------------------------
/lesson-3/express-example-3/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
17 |
18 |
--------------------------------------------------------------------------------
/lesson-3/express-example-3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-example-3",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | },
17 | "dependencies": {
18 | "cors": "^2.8.5",
19 | "express": "^4.17.1",
20 | "moment": "^2.29.1"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lesson-3/express-example-3/products.js:
--------------------------------------------------------------------------------
1 | const products = [
2 | {
3 | _id: "34ggffg",
4 | name: "iPhone X",
5 | price: 34000
6 | },
7 | {
8 | _id: "dffgsdgdg",
9 | name: "GeForce RTX 3090",
10 | price: 90000
11 | }
12 | ];
13 |
14 | module.exports = products;
--------------------------------------------------------------------------------
/lesson-3/express-example-3/server.log:
--------------------------------------------------------------------------------
1 | GET /products 21.09.2021_20:32:55
2 |
3 | GET /products 15-11-2021_08:24:23
4 | GET /orders 15-11-2021_08:24:37
--------------------------------------------------------------------------------
/lesson-3/express-example-4/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | package-lock.json
4 | yarn.lock
5 | .env
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-3/express-example-4/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const cors = require("cors");
3 |
4 | const productsRouter = require("./routes/api/products");
5 |
6 | const app = express();
7 |
8 | app.use(cors());
9 | app.use(express.json());
10 |
11 | app.use("/api/products", productsRouter);
12 |
13 | app.listen(3000);
--------------------------------------------------------------------------------
/lesson-3/express-example-4/data/products.js:
--------------------------------------------------------------------------------
1 | const products = [
2 | {
3 | _id: "34ggffg",
4 | name: "iPhone X",
5 | price: 34000
6 | },
7 | {
8 | _id: "dffgsdgdg",
9 | name: "GeForce RTX 3090",
10 | price: 90000
11 | }
12 | ];
13 |
14 | module.exports = products;
--------------------------------------------------------------------------------
/lesson-3/express-example-4/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-example-4",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | },
17 | "dependencies": {
18 | "cors": "^2.8.5",
19 | "express": "^4.17.1",
20 | "uuid": "^8.3.2"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lesson-3/express-example-4/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const {v4} = require("uuid");
3 |
4 | const products = require("../../data/products");
5 |
6 | const router = express.Router();
7 | /*
8 | 1. Получить все товары.
9 | 2. Получить один товар по id.
10 | 3. Добавить товар.
11 | 4. Обновить товар по id.
12 | 5. Удалить товар по id.
13 | */
14 | // GET /api/products
15 | router.get("/", (req, res)=> {
16 | res.json({
17 | status: "success",
18 | code: 200,
19 | data: {
20 | result: products
21 | }
22 | })
23 | });
24 |
25 | router.get("/:id", (req, res)=> {
26 | const {id} = req.params;
27 | const result = products.find(item => item._id === id);
28 | if(!result){
29 | res.status(404).json({
30 | status: "error",
31 | code: 404,
32 | message: `Product with id=${id} not found`
33 | })
34 | }
35 | res.json({
36 | status: "success",
37 | code: 200,
38 | data: {
39 | result
40 | }
41 | })
42 | })
43 | // POST /api/products
44 | router.post("/", (req, res)=> {
45 | const newProduct = {...req.body, id: v4()};
46 | products.push(newProduct);
47 | res.status(201).json({
48 | status: "success",
49 | code: 201,
50 | data: {
51 | result: newProduct
52 | }
53 | });
54 | });
55 |
56 |
57 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-3/http-server-example/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vscode
3 | package-lock.json
4 | yarn.lock
5 | .env
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-3/http-server-example/app.js:
--------------------------------------------------------------------------------
1 | const http = require("http");
2 | // request - объект, описывающий весь запрос
3 | // response - объект, описывающий весь ответ
4 |
5 | const server = http.createServer((request, response)=>{
6 | const {url} = request;
7 | if(url === "/"){
8 | response.write("Home page
");
9 | } else if(url === "/contacts") {
10 | response.write("Contacts page
");
11 | } else {
12 | response.write("Not found
");
13 | }
14 | response.end();
15 | })
16 |
17 | // const server = http.createServer((request, response)=>{
18 | // // console.log(request.url);
19 | // // console.log(request.headers["user-agent"]);
20 | // // console.log(request.method);
21 |
22 | // response.write("Добро пожаловать на наш сайт!
");
23 | // response.end();
24 | // });
25 |
26 | server.listen(3000, ()=> {
27 | console.log("Сервер запущен!");
28 | });
--------------------------------------------------------------------------------
/lesson-3/http-server-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "http-server-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "nodemon": "^2.0.7"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lesson-3/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/lesson-3/slides/Client-Server-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/Client-Server-schema.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/REST-API/CRUD.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/REST-API/CRUD.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/REST-API/HTTP-methods.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/REST-API/HTTP-methods.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/REST-API/REST-API-additional-rules.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/REST-API/REST-API-additional-rules.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/REST-API/REST-API-basic-rules.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/REST-API/REST-API-basic-rules.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/REST-API/Server-response-code.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/REST-API/Server-response-code.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/REST-API/old-routes-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/REST-API/old-routes-example.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/fullstack-developer-cors-problem-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/fullstack-developer-cors-problem-2.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/fullstack-developer-cors-problem.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/fullstack-developer-cors-problem.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/middleware-work-schema-details-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/middleware-work-schema-details-2.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/middleware-work-schema-details-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/middleware-work-schema-details-3.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/middleware-work-schema-details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/middleware-work-schema-details.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/middleware-work-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/middleware-work-schema.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/what-is-it-cors.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-3/slides/what-is-it-cors.jpg
--------------------------------------------------------------------------------
/lesson-4/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | node: true,
6 | },
7 | extends: ['standard'],
8 | parserOptions: {
9 | ecmaVersion: 12,
10 | },
11 | rules: {
12 | 'comma-dangle': 'off',
13 | 'space-before-function-paren': 'off',
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const logger = require('morgan')
3 | const cors = require('cors')
4 |
5 | const productsRouter = require("./routes/api/products");
6 |
7 | const app = express()
8 |
9 | const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'
10 |
11 | app.use(logger(formatsLogger))
12 | app.use(cors())
13 | app.use(express.json())
14 |
15 | app.use('/api/products', productsRouter)
16 |
17 | app.use((req, res) => {
18 | res.status(404).json({ message: 'Not found' })
19 | })
20 |
21 | app.use((err, req, res, next) => {
22 | const {status = 500, message = "Server error"} = err;
23 | res.status(status).json({ message: err.message })
24 | })
25 |
26 | module.exports = app
27 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/bin/server.js:
--------------------------------------------------------------------------------
1 | const app = require('../app')
2 |
3 | const {PORT = 3000} = process.env;
4 |
5 | app.listen(PORT, () => {
6 | console.log(`Server running. Use our API on port: ${PORT}`)
7 | })
8 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 |
3 | module.exports = {
4 | products
5 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/controllers/products/add.js:
--------------------------------------------------------------------------------
1 | const productsOperations = require("../../model/products");
2 |
3 | const add = async (req, res) => {
4 | const result = await productsOperations.add(req.body);
5 | res.status(201).json({
6 | status: "success",
7 | code: 201,
8 | data: {
9 | result
10 | }
11 | })
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/controllers/products/getAll.js:
--------------------------------------------------------------------------------
1 | const productsOperations = require("../../model/products");
2 |
3 | const getAll = async (req, res) => {
4 | const products = await productsOperations.getAll();
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | result: products
10 | }
11 | });
12 | };
13 |
14 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/controllers/products/getById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const productsOperations = require("../../model/products");
4 |
5 | const getById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await productsOperations.getById(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/controllers/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 |
7 | module.exports = {
8 | getAll,
9 | getById,
10 | add,
11 | updateById,
12 | removeById
13 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/controllers/products/removeById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const productsOperations = require("../../model/products");
4 |
5 | const removeById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await productsOperations.removeById(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | message: "product deleted",
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/controllers/products/updateById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const productsOperations = require("../../model/products")
4 |
5 | const updateById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await productsOperations.updateById(id, req.body);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/middlewares/ctrlWrapper.js:
--------------------------------------------------------------------------------
1 | const ctrlWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | } catch (error) {
6 | next(error);
7 | }
8 | }
9 | }
10 |
11 | module.exports = ctrlWrapper;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const ctrlWrapper = require("./ctrlWrapper");
3 |
4 | module.exports = {
5 | validation,
6 | ctrlWrapper
7 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema)=> {
2 | return (req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | error.status = 400;
6 | next(error);
7 | }
8 | next()
9 | }
10 | }
11 |
12 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/add.js:
--------------------------------------------------------------------------------
1 | const {v4} = require("uuid");
2 |
3 | const updateProducts = require("./updateProducts");
4 | const getAll = require("./getAll");
5 |
6 | const add = async(data)=> {
7 | const products = await getAll();
8 | const newProduct = {...data, id: v4()};
9 | products.push(newProduct);
10 | await updateProducts(products);
11 | return newProduct;
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/filePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const filePath = path.join(__dirname, "products.json");
4 |
5 | module.exports = filePath;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/getAll.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const getAll = async()=> {
6 | const data = await fs.readFile(filePath);
7 | const products = JSON.parse(data);
8 | return products;
9 | }
10 |
11 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/getById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 |
3 | const getById = async(id)=> {
4 | const products = await getAll();
5 | const result = products.find(item => item.id === id);
6 | if(!result){
7 | return null;
8 | }
9 | return result;
10 | }
11 |
12 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 |
7 | module.exports = {
8 | getAll,
9 | getById,
10 | add,
11 | updateById,
12 | removeById
13 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/products.json:
--------------------------------------------------------------------------------
1 | [{"id":"48bd1cd8-72ca-42cc-8457-156bb8c30873","name":"cheese","price":2.5,"location":"Refrigerated foods"},{"id":"61c0169c-e693-4a20-af3e-2e55fdc34f79","name":"Crisps","price":4,"location":"the Snack isle"},{"id":"2c9c3d67-07b3-4ee1-a59f-67d54427d3c3","name":"Pizza","price":4,"location":"Refrigerated foods"},{"id":"2386a63f-140a-494c-b4e5-b23a219bbac0","name":"Chocolate","price":1.5,"location":"the Snack isle"},{"id":"8263b539-c546-4a64-866d-97d58e42c585","name":"Self-raising flour","price":1.5,"location":"Home baking"}]
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/removeById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const removeById = async(id)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | // const [removeProduct] = products.splice(idx, 1);
11 | // await updateProducts(products);
12 | // return removeProduct
13 | const newProducts = products.filter((_, index) => index !== idx);
14 | await updateProducts(newProducts);
15 | return products[idx];
16 | }
17 |
18 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/updateById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const updateById = async(id, data)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | products[idx] = {...data, id};
11 | await updateProducts(products);
12 | return products[idx];
13 | }
14 |
15 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const updateProducts = async(products)=> {
6 | await fs.writeFile(filePath, JSON.stringify(products));
7 | }
8 |
9 | module.exports = updateProducts;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["node_modules", "model/contacts.json"]
3 | }
4 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "cross-env NODE_ENV=production node ./bin/server.js",
7 | "start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
8 | "lint": "eslint **/*.js",
9 | "lint:fix": "eslint --fix **/*.js"
10 | },
11 | "dependencies": {
12 | "cors": "2.8.5",
13 | "cross-env": "7.0.3",
14 | "express": "4.17.1",
15 | "http-errors": "^1.8.1",
16 | "joi": "^17.4.2",
17 | "morgan": "1.10.0",
18 | "uuid": "^8.3.2"
19 | },
20 | "devDependencies": {
21 | "eslint": "^7.19.0",
22 | "eslint-config-standard": "^16.0.2",
23 | "eslint-plugin-import": "^2.22.1",
24 | "eslint-plugin-node": "^11.1.0",
25 | "eslint-plugin-promise": "^4.2.1",
26 | "nodemon": "2.0.7"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {validation, ctrlWrapper} = require("../../middlewares");
4 | const {productSchema} = require("../../schemas");
5 | const {products: ctrl} = require("../../controllers")
6 |
7 | const validateMiddleware = validation(productSchema);
8 | /*
9 | validateMiddleware = (req, res, next)=> {
10 | const {error} = productSchema.validate(req.body);
11 | if(error){
12 | error.status = 400;
13 | next(error);
14 | }
15 | next()
16 | }
17 | */
18 | const router = express.Router();
19 |
20 | router.get("/", ctrlWrapper(ctrl.getAll));
21 |
22 | router.get("/:id", ctrlWrapper(ctrl.getById));
23 |
24 | router.post("/", validateMiddleware, ctrlWrapper(ctrl.add));
25 |
26 | router.put("/:id", validation(productSchema), ctrlWrapper(ctrl.updateById));
27 |
28 | router.delete("/:id", ctrlWrapper(ctrl.removeById))
29 |
30 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/schemas/index.js:
--------------------------------------------------------------------------------
1 | const productSchema = require("./product");
2 |
3 | module.exports = {
4 | productSchema
5 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/schemas/product.js:
--------------------------------------------------------------------------------
1 | const Joi = require("joi");
2 |
3 | const productSchema = Joi.object({
4 | name: Joi.string().required(),
5 | price: Joi.number().min(0.01).required(),
6 | location: Joi.string().required(),
7 | });
8 |
9 | module.exports = productSchema
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | node: true,
6 | },
7 | extends: ['standard'],
8 | parserOptions: {
9 | ecmaVersion: 12,
10 | },
11 | rules: {
12 | 'comma-dangle': 'off',
13 | 'space-before-function-paren': 'off',
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const logger = require('morgan')
3 | const cors = require('cors')
4 |
5 | const productsRouter = require("./routes/api/products");
6 |
7 | const app = express()
8 |
9 | const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'
10 |
11 | app.use(logger(formatsLogger))
12 | app.use(cors())
13 | app.use(express.json())
14 |
15 | app.use('/api/products', productsRouter)
16 |
17 | app.use((req, res) => {
18 | res.status(404).json({ message: 'Not found' })
19 | })
20 |
21 | app.use((err, req, res, next) => {
22 | const {status = 500, message = "Server error"} = err;
23 | res.status(status).json({ message: err.message })
24 | })
25 |
26 | module.exports = app
27 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/bin/server.js:
--------------------------------------------------------------------------------
1 | const app = require('../app')
2 |
3 | const {PORT = 3000} = process.env;
4 |
5 | app.listen(PORT, () => {
6 | console.log(`Server running. Use our API on port: ${PORT}`)
7 | })
8 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/add.js:
--------------------------------------------------------------------------------
1 | const {v4} = require("uuid");
2 |
3 | const updateProducts = require("./updateProducts");
4 | const getAll = require("./getAll");
5 |
6 | const add = async(data)=> {
7 | const products = await getAll();
8 | const newProduct = {...data, id: v4()};
9 | products.push(newProduct);
10 | await updateProducts(products);
11 | return newProduct;
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/filePath.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | const filePath = path.join(__dirname, "products.json");
4 |
5 | module.exports = filePath;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/getAll.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const getAll = async()=> {
6 | const data = await fs.readFile(filePath);
7 | const products = JSON.parse(data);
8 | return products;
9 | }
10 |
11 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/getById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 |
3 | const getById = async(id)=> {
4 | const products = await getAll();
5 | const result = products.find(item => item.id === id);
6 | if(!result){
7 | return null;
8 | }
9 | return result;
10 | }
11 |
12 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 |
7 | module.exports = {
8 | getAll,
9 | getById,
10 | add,
11 | updateById,
12 | removeById
13 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/products.json:
--------------------------------------------------------------------------------
1 | [{"id":"48bd1cd8-72ca-42cc-8457-156bb8c30873","name":"cheese","price":2.5,"location":"Refrigerated foods"},{"id":"61c0169c-e693-4a20-af3e-2e55fdc34f79","name":"Crisps","price":4,"location":"the Snack isle"},{"id":"2c9c3d67-07b3-4ee1-a59f-67d54427d3c3","name":"Pizza","price":4,"location":"Refrigerated foods"},{"id":"2386a63f-140a-494c-b4e5-b23a219bbac0","name":"Chocolate","price":1.5,"location":"the Snack isle"},{"id":"8263b539-c546-4a64-866d-97d58e42c585","name":"Self-raising flour","price":1.5,"location":"Home baking"}]
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/removeById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const removeById = async(id)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | // const [removeProduct] = products.splice(idx, 1);
11 | // await updateProducts(products);
12 | // return removeProduct
13 | const newProducts = products.filter((_, index) => index !== idx);
14 | await updateProducts(newProducts);
15 | return products[idx];
16 | }
17 |
18 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/updateById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const updateProducts = require("./updateProducts");
3 |
4 | const updateById = async(id, data)=> {
5 | const products = await getAll();
6 | const idx = products.findIndex(item => item.id === id);
7 | if(idx === -1){
8 | return null;
9 | }
10 | products[idx] = {...data, id};
11 | await updateProducts(products);
12 | return products[idx];
13 | }
14 |
15 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 |
3 | const filePath = require("./filePath");
4 |
5 | const updateProducts = async(products)=> {
6 | await fs.writeFile(filePath, JSON.stringify(products));
7 | }
8 |
9 | module.exports = updateProducts;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["node_modules", "model/contacts.json"]
3 | }
4 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "cross-env NODE_ENV=production node ./bin/server.js",
7 | "start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
8 | "lint": "eslint **/*.js",
9 | "lint:fix": "eslint --fix **/*.js"
10 | },
11 | "dependencies": {
12 | "cors": "2.8.5",
13 | "cross-env": "7.0.3",
14 | "express": "4.17.1",
15 | "http-errors": "^1.8.1",
16 | "joi": "^17.4.2",
17 | "morgan": "1.10.0",
18 | "uuid": "^8.3.2"
19 | },
20 | "devDependencies": {
21 | "eslint": "^7.19.0",
22 | "eslint-config-standard": "^16.0.2",
23 | "eslint-plugin-import": "^2.22.1",
24 | "eslint-plugin-node": "^11.1.0",
25 | "eslint-plugin-promise": "^4.2.1",
26 | "nodemon": "2.0.7"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/.env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | dB_USER=
3 | DB_PASSWORD=
4 | DB_NAME=
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | config.js
3 | package-lock.json
4 | yarn.lock
5 | yarn.log
6 | yarn.error
7 | node_modules/
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/app.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const express = require("express");
3 | const cors = require("cors");
4 | require("dotenv").config();
5 |
6 | const productsRouter = require("./routes/api/products")
7 |
8 | const app = express();
9 |
10 | app.use(cors());
11 | app.use(express.json());
12 |
13 | app.use("/api/products", productsRouter);
14 |
15 | const {DB_HOST, PORT = 3000} = process.env;
16 |
17 | mongoose.connect(DB_HOST)
18 | .then(()=> app.listen(PORT))
19 | .catch(error => {
20 | console.log(error.message);
21 | process.exit(1);
22 | })
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 |
3 | module.exports = {
4 | products
5 | }
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/controllers/products/add.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const add = async(req, res)=> {
4 | const result = await Product.create(req.body);
5 | res.status(201).json({
6 | status: "success",
7 | code: 201,
8 | data: {
9 | result
10 | }
11 | })
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/controllers/products/getAll.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const getAll = async(req, res)=> {
4 | const result = await Product.find({});
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | result
10 | }
11 | })
12 | }
13 |
14 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/controllers/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const add = require("./add");
3 |
4 | module.exports = {
5 | getAll,
6 | add
7 | }
8 |
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/middlewares/ctrlWrapper.js:
--------------------------------------------------------------------------------
1 | const ctrlWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | } catch (error) {
6 | next(error);
7 | }
8 | }
9 | }
10 |
11 | module.exports = ctrlWrapper;
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const ctrlWrapper = require("./ctrlWrapper");
3 |
4 | module.exports = {
5 | validation,
6 | ctrlWrapper
7 | }
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema)=> {
2 | return (req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | error.status = 400;
6 | next(error);
7 | }
8 | next()
9 | }
10 | }
11 |
12 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/models/index.js:
--------------------------------------------------------------------------------
1 | const Product = require("./product");
2 |
3 | module.exports = {
4 | Product
5 | }
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/models/product.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 |
3 | const productSchema = Schema({
4 | name: String,
5 | price: Number,
6 | location: String
7 | });
8 |
9 | const Product = model("product", productSchema);
10 | // categories => category
11 | // mice => mouse
12 |
13 | module.exports = Product;
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mongodb-project",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.13"
16 | },
17 | "dependencies": {
18 | "cors": "^2.8.5",
19 | "dotenv": "^10.0.0",
20 | "express": "^4.17.1",
21 | "mongoose": "^6.0.13"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {ctrlWrapper} = require("../../middlewares");
4 | const {products: ctrl} = require("../../controllers");
5 |
6 | const router = express.Router();
7 |
8 | router.get("/", ctrlWrapper(ctrl.getAll));
9 |
10 | router.post("/", ctrlWrapper(ctrl.add))
11 |
12 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-5/process-env-example/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | node_modules/
--------------------------------------------------------------------------------
/lesson-5/process-env-example/app.js:
--------------------------------------------------------------------------------
1 | console.log(process.env.DB_HOST);
--------------------------------------------------------------------------------
/lesson-5/process-env-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "process-env-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.13"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lesson-5/products.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "cheese",
4 | "price": 2.5,
5 | "location": "Refrigerated foods"
6 | },
7 | {
8 | "name": "Crisps",
9 | "price": 4,
10 | "location": "the Snack isle"
11 | },
12 | {
13 | "name": "Pizza",
14 | "price": 4,
15 | "location": "Refrigerated foods"
16 | },
17 | {
18 | "name": "Chocolate",
19 | "price": 1.5,
20 | "location": "the Snack isle"
21 | },
22 | {
23 | "name": "Self-raising flour",
24 | "price": 1.5,
25 | "location": "Home baking"
26 | },
27 | {
28 | "name": "Ground almonds",
29 | "price": 5,
30 | "location": "Home baking"
31 | }
32 | ]
--------------------------------------------------------------------------------
/lesson-5/readme.md:
--------------------------------------------------------------------------------
1 | [Какие бывают варианты размещения сайта на хостинге](./slides/deploy-variants.jpg)
2 |
3 | [Как разместить сайт на одном сервере](./slides/variants-deploy-all-in-one.jpg)
4 |
5 | [Структура бекенда](./slides/backend-structure.jpg)
6 |
7 | [Какие типы баз данных бывают](./slides/database-types.jpg)
8 |
9 | [Почему noSQL базы называают документоориентированными](./slides/documents-database-schema.jpg)
10 |
11 | [Какие типы баз данных бывают](./slides/database-types.jpg)
12 |
13 | [Почему нужно использовать удаленную базу данных](./slides/remote-database.jpg)
14 |
15 | [Как работает пакет dotenv](./slides/dotenv-work-schema.jpg)
16 |
17 | [Как работает бекенд с Google таблицами](./slides/woork-with-google-sheets.jpg)
18 |
19 | [Пример структуры 'схема-модель-коллекция' в жизни](./slides/schema-model-example.jpg)
20 |
21 | [Схема-Модель-коллекцция в MongoDB](./slides/schema-model-collection.jpg)
22 |
23 |
24 |
--------------------------------------------------------------------------------
/lesson-5/slides/backend-structure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-5/slides/backend-structure.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/database-types.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-5/slides/database-types.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/documents-database-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-5/slides/documents-database-schema.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/dotenv-work-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-5/slides/dotenv-work-schema.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/mongodb-database-structure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-5/slides/mongodb-database-structure.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/remote-database.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-5/slides/remote-database.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/schema-model-collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-5/slides/schema-model-collection.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/schema-model-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-5/slides/schema-model-example.jpg
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=mongodb+srv://Bogdan:pBje6ZbFRATcsTq@cluster0.lhj89.mongodb.net/online_shop?retryWrites=true&w=majority
2 | DB_USER=Bogdan
3 | DB_PASSWORD=pBje6ZbFRATcsTq
4 | DB_NAME=online_shop
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | node: true,
6 | },
7 | extends: ['standard'],
8 | parserOptions: {
9 | ecmaVersion: 12,
10 | },
11 | rules: {
12 | 'comma-dangle': 'off',
13 | 'space-before-function-paren': 'off',
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const logger = require('morgan')
3 | const cors = require('cors')
4 | require("dotenv").config();
5 |
6 | const productsRouter = require("./routes/api/products");
7 |
8 | const app = express()
9 |
10 | const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'
11 |
12 | app.use(logger(formatsLogger))
13 | app.use(cors())
14 | app.use(express.json())
15 |
16 | app.use('/api/products', productsRouter)
17 |
18 | app.use((req, res) => {
19 | res.status(404).json({ message: 'Not found' })
20 | })
21 |
22 | app.use((err, req, res, next) => {
23 | const {status = 500, message = "Server error"} = err;
24 | res.status(status).json({ message: err.message })
25 | })
26 |
27 | module.exports = app
28 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/bin/server.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const app = require('../app');
4 |
5 | const {DB_HOST, PORT = 3000} = process.env;
6 |
7 | mongoose.connect(DB_HOST)
8 | .then(()=> app.listen(PORT))
9 | .catch(error => {
10 | console.log(error.message);
11 | process.exit(1);
12 | })
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 |
3 | module.exports = {
4 | products
5 | }
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/controllers/products/add.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const add = async (req, res) => {
4 | const result = await Product.create(req.body);
5 | res.status(201).json({
6 | status: "success",
7 | code: 201,
8 | data: {
9 | result
10 | }
11 | })
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/controllers/products/getAll.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const getAll = async (req, res) => {
4 | const products = await Product.find({});
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | result: products
10 | }
11 | });
12 | };
13 |
14 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/controllers/products/getById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const getById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findById(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/controllers/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 | const updateStatus = require("./updateStatus");
7 |
8 | module.exports = {
9 | getAll,
10 | getById,
11 | add,
12 | updateById,
13 | updateStatus,
14 | removeById
15 | }
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/controllers/products/removeById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const removeById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndRemove(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | message: "product deleted",
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/controllers/products/updateById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndUpdate(id, req.body, {new: true});
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/controllers/products/updateStatus.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateStatus = async (req, res) => {
6 | const { id } = req.params;
7 | const {status} = req.body;
8 | const result = await Product.findByIdAndUpdate(id, {status}, {new: true});
9 | if (!result) {
10 | throw new NotFound(`Product with id=${id} not found`);
11 | }
12 | res.json({
13 | status: "success",
14 | code: 200,
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = updateStatus;
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | DB_USER=
3 | DB_PASSWORD=
4 | DB_NAME=
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/middlewares/ctrlWrapper.js:
--------------------------------------------------------------------------------
1 | const ctrlWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | } catch (error) {
6 | next(error);
7 | }
8 | }
9 | }
10 |
11 | module.exports = ctrlWrapper;
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const ctrlWrapper = require("./ctrlWrapper");
3 |
4 | module.exports = {
5 | validation,
6 | ctrlWrapper
7 | }
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema)=> {
2 | return (req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | error.status = 400;
6 | next(error);
7 | }
8 | next()
9 | }
10 | }
11 |
12 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 |
3 | module.exports = {
4 | Product
5 | }
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/models/product.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 |
4 | const codeRegexp = /^[0-9]{9}$/;
5 |
6 | const productSchema = Schema({
7 | name: {
8 | type: String,
9 | required: true,
10 | // minlength: 2,
11 | // maxlength: 50
12 | },
13 | price: {
14 | type: Number,
15 | required: [true, "price must be exist"],
16 | min: 0.01
17 | },
18 | active: {
19 | type: Boolean,
20 | default: true
21 | },
22 | status: {
23 | type: String,
24 | enum: ["basic", "sale", "stock"],
25 | default: "basic"
26 | },
27 | code: {
28 | type: String,
29 | required: true,
30 | unique: true,
31 | match: codeRegexp
32 | }
33 | }, {versionKey: false, timestamps: true});
34 |
35 | const joiSchema = Joi.object({
36 | name: Joi.string().required(),
37 | price: Joi.number().min(0.01).required(),
38 | active: Joi.bool(),
39 | status: Joi.string().valid("basic", "sale", "stock"),
40 | code: Joi.string().pattern(codeRegexp)
41 | });
42 |
43 | const statusJoiSchema = Joi.object({
44 | status: Joi.string().valid("basic", "sale", "stock").required()
45 | })
46 |
47 | const Product = model("product", productSchema);
48 |
49 | module.exports = {
50 | Product,
51 | joiSchema,
52 | statusJoiSchema
53 | }
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["node_modules", "model/contacts.json"]
3 | }
4 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "cross-env NODE_ENV=production node ./bin/server.js",
7 | "start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
8 | "lint": "eslint **/*.js",
9 | "lint:fix": "eslint --fix **/*.js"
10 | },
11 | "dependencies": {
12 | "cors": "2.8.5",
13 | "cross-env": "7.0.3",
14 | "dotenv": "^10.0.0",
15 | "express": "4.17.1",
16 | "http-errors": "^1.8.1",
17 | "joi": "^17.4.2",
18 | "mongoose": "^6.0.13",
19 | "morgan": "1.10.0",
20 | "uuid": "^8.3.2"
21 | },
22 | "devDependencies": {
23 | "eslint": "^7.19.0",
24 | "eslint-config-standard": "^16.0.2",
25 | "eslint-plugin-import": "^2.22.1",
26 | "eslint-plugin-node": "^11.1.0",
27 | "eslint-plugin-promise": "^4.2.1",
28 | "nodemon": "2.0.7"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {validation, ctrlWrapper} = require("../../middlewares");
4 | const {joiSchema, statusJoiSchema} = require("../../models/product");
5 | const {products: ctrl} = require("../../controllers")
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", ctrlWrapper(ctrl.getAll));
10 |
11 | router.get("/:id", ctrlWrapper(ctrl.getById));
12 |
13 | router.post("/", validation(joiSchema), ctrlWrapper(ctrl.add));
14 |
15 | router.put("/:id", validation(joiSchema), ctrlWrapper(ctrl.updateById));
16 |
17 | router.patch("/:id/status", validation(statusJoiSchema), ctrlWrapper(ctrl.updateStatus));
18 |
19 | router.delete("/:id", ctrlWrapper(ctrl.removeById));
20 |
21 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-7/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vscode/
3 | node_modules/
--------------------------------------------------------------------------------
/lesson-7/README.md:
--------------------------------------------------------------------------------
1 | [Как HTTP-протокол общается с бекендом](./slides/HTTP-common-schema.jpg)
2 | [Когда ответ на HTTP-запрос должен быть персонализированным](./slides/HTTP-personal-request-schema.jpg)
3 | [Как сделать ответ на HTTP-запрос персонализированным и не логинится при каждом запросе](./slides/frontend-backend-requests-with-token.jpg)
4 | [Разница между регистрацией, аутентификацией и авторизацией](./slides/register-auth-steps.jpg)
5 | [Этапы создания модуля регистрации-аутентфикации-авторизации](./slides/reigster-auth-create-steps.jpg)
6 | [Разница между хэшем и шифрованием](./slides/hash-schema.jpg)
7 | [Работа с переменными окружения на локальном хосте и на удаленном сервере](./slides/process.env-and-deploy.jpg)
8 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=mongodb+srv://Bogdan:pBje6ZbFRATcsTq@cluster0.lhj89.mongodb.net/online_shop?retryWrites=true&w=majority
2 | SECRET_KEY=GHGSDFM23Tfgsfs3
3 | DB_USER=Bogdan
4 | DB_PASSWORD=pBje6ZbFRATcsTq
5 | DB_NAME=online_shop
--------------------------------------------------------------------------------
/lesson-7/auth-example/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/lesson-7/auth-example/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | node: true,
6 | },
7 | extends: ['standard'],
8 | parserOptions: {
9 | ecmaVersion: 12,
10 | },
11 | rules: {
12 | 'comma-dangle': 'off',
13 | 'space-before-function-paren': 'off',
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const logger = require('morgan')
3 | const cors = require('cors')
4 | require("dotenv").config();
5 |
6 | const authRouter = require("./routes/api/auth");
7 | const productsRouter = require("./routes/api/products");
8 |
9 | const app = express()
10 |
11 | const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'
12 |
13 | app.use(logger(formatsLogger))
14 | app.use(cors())
15 | app.use(express.json())
16 |
17 | app.use("/api/auth", authRouter);
18 | app.use('/api/products', productsRouter);
19 |
20 | app.use((req, res) => {
21 | res.status(404).json({ message: 'Not found' })
22 | })
23 |
24 | app.use((err, req, res, next) => {
25 | const {status = 500, message = "Server error"} = err;
26 | res.status(status).json({ message: err.message })
27 | })
28 |
29 | module.exports = app
30 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/bin/server.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const app = require('../app');
4 |
5 | const {DB_HOST, PORT = 3000} = process.env;
6 |
7 | mongoose.connect(DB_HOST)
8 | .then(()=> app.listen(PORT))
9 | .catch(error => {
10 | console.log(error.message);
11 | process.exit(1);
12 | })
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/auth/index.js:
--------------------------------------------------------------------------------
1 | const register = require("./register");
2 | const login = require("./login");
3 |
4 | module.exports = {
5 | register,
6 | login
7 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/auth/login.js:
--------------------------------------------------------------------------------
1 | const {Unauthorized} = require("http-errors");
2 | const jwt = require("jsonwebtoken");
3 | // const bcrypt = require("bcryptjs");
4 |
5 | const {User} = require("../../models");
6 |
7 | const {SECRET_KEY} = process.env;
8 |
9 | const login = async(req, res)=> {
10 | const {email, password} = req.body;
11 | const user = await User.findOne({email});
12 | if(!user || !user.comparePassword(password)){
13 | throw new Unauthorized("Email or password is wrong");
14 | }
15 | // const passCompare = bcrypt.compareSync(password, user.password);
16 | // if(!user || !passCompare){
17 | // throw new Unauthorized("Email or password is wrong");
18 | // }
19 | // if(!user){
20 | // throw new Unauthorized(`Email ${email} not found`);
21 | // }
22 | // const passCompare = bcrypt.compareSync(password, user.password);
23 | // if(!passCompare){
24 | // throw new Unauthorized("Password wrong");
25 | // }
26 | const payload = {
27 | id: user._id
28 | };
29 | const token = jwt.sign(payload, SECRET_KEY, {expiresIn: "1h"});
30 | res.json({
31 | status: "success",
32 | code: 200,
33 | data: {
34 | token
35 | }
36 | })
37 | }
38 |
39 | module.exports = login;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/auth/register.js:
--------------------------------------------------------------------------------
1 | const {Conflict} = require("http-errors");
2 | // const bcrypt = require("bcryptjs");
3 |
4 | const {User} = require("../../models");
5 |
6 | const register = async(req, res)=> {
7 | const {name, email, password} = req.body;
8 | const user = await User.findOne({email});
9 | if(user){
10 | throw new Conflict(`User with ${email} already exist`)
11 | }
12 | const newUser = new User({name, email});
13 | /*
14 | newUser = {
15 | name,
16 | email,
17 | setPassword(password){
18 | this.password = bcrypt.hashSync(password, bcrypt.genSaltSync(10))
19 | }
20 | }
21 | */
22 | newUser.setPassword(password);
23 | /*
24 | newUser = {
25 | name,
26 | email,
27 | password,
28 | setPassword(password){
29 | this.passord = bcrypt.hashSync(password, bcrypt.genSaltSync(10))
30 | }
31 | }
32 | */
33 | newUser.save();
34 | // const hashPassword = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
35 | // const result = await User.create({name, email, password: hashPassword});
36 | res.status(201).json({
37 | status: "success",
38 | code: 201,
39 | data: {
40 | user: {
41 | email,
42 | name
43 | }
44 | }
45 | });
46 | }
47 |
48 | module.exports = register;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 | const auth = require("./auth");
3 |
4 | module.exports = {
5 | products,
6 | auth
7 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/products/add.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const add = async (req, res) => {
4 | const result = await Product.create(req.body);
5 | res.status(201).json({
6 | status: "success",
7 | code: 201,
8 | data: {
9 | result
10 | }
11 | })
12 | }
13 |
14 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/products/getAll.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const getAll = async (req, res) => {
4 | const products = await Product.find({});
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | result: products
10 | }
11 | });
12 | };
13 |
14 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/products/getById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const getById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findById(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 | const updateStatus = require("./updateStatus");
7 |
8 | module.exports = {
9 | getAll,
10 | getById,
11 | add,
12 | updateById,
13 | updateStatus,
14 | removeById
15 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/products/removeById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const removeById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndRemove(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | message: "product deleted",
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/products/updateById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndUpdate(id, req.body, {new: true});
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/products/updateStatus.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateStatus = async (req, res) => {
6 | const { id } = req.params;
7 | const {status} = req.body;
8 | const result = await Product.findByIdAndUpdate(id, {status}, {new: true});
9 | if (!result) {
10 | throw new NotFound(`Product with id=${id} not found`);
11 | }
12 | res.json({
13 | status: "success",
14 | code: 200,
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = updateStatus;
--------------------------------------------------------------------------------
/lesson-7/auth-example/env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | DB_USER=
3 | DB_PASSWORD=
4 | DB_NAME=
--------------------------------------------------------------------------------
/lesson-7/auth-example/middlewares/ctrlWrapper.js:
--------------------------------------------------------------------------------
1 | const ctrlWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | } catch (error) {
6 | next(error);
7 | }
8 | }
9 | }
10 |
11 | module.exports = ctrlWrapper;
--------------------------------------------------------------------------------
/lesson-7/auth-example/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const ctrlWrapper = require("./ctrlWrapper");
3 |
4 | module.exports = {
5 | validation,
6 | ctrlWrapper
7 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema)=> {
2 | return (req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | error.status = 400;
6 | next(error);
7 | }
8 | next()
9 | }
10 | }
11 |
12 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-7/auth-example/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 | const {User} = require("./user");
3 |
4 | module.exports = {
5 | Product,
6 | User
7 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/models/product.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 |
4 | const codeRegexp = /^[0-9]{9}$/;
5 |
6 | const productSchema = Schema({
7 | name: {
8 | type: String,
9 | required: true,
10 | // minlength: 2,
11 | // maxlength: 50
12 | },
13 | price: {
14 | type: Number,
15 | required: [true, "price must be exist"],
16 | min: 0.01
17 | },
18 | active: {
19 | type: Boolean,
20 | default: true
21 | },
22 | status: {
23 | type: String,
24 | enum: ["basic", "sale", "stock"],
25 | default: "basic"
26 | },
27 | code: {
28 | type: String,
29 | required: true,
30 | unique: true,
31 | match: codeRegexp
32 | }
33 | }, {versionKey: false, timestamps: true});
34 |
35 | const joiSchema = Joi.object({
36 | name: Joi.string().required(),
37 | price: Joi.number().min(0.01).required(),
38 | active: Joi.bool(),
39 | status: Joi.string().valid("basic", "sale", "stock"),
40 | code: Joi.string().pattern(codeRegexp)
41 | });
42 |
43 | const statusJoiSchema = Joi.object({
44 | status: Joi.string().valid("basic", "sale", "stock").required()
45 | })
46 |
47 | const Product = model("product", productSchema);
48 |
49 | module.exports = {
50 | Product,
51 | joiSchema,
52 | statusJoiSchema
53 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/models/user.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 | const bcrypt = require("bcryptjs");
4 |
5 | const userSchema = Schema({
6 | name: {
7 | type: String,
8 | required: true
9 | },
10 | email: {
11 | type: String,
12 | required: true,
13 | unique: true
14 | },
15 | password: {
16 | type: String,
17 | required: true,
18 | minlength: 6
19 | }
20 | }, {versionKey: false, timestamps: true});
21 |
22 | userSchema.methods.setPassword = function(password){
23 | this.password = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
24 | }
25 |
26 | userSchema.methods.comparePassword = function(password){
27 | return bcrypt.compareSync(password, this.password);
28 | }
29 |
30 | const joiRegisterSchema = Joi.object({
31 | name: Joi.string().required(),
32 | email: Joi.string().required(),
33 | password: Joi.string().min(6).required()
34 | })
35 |
36 | const joiLoginSchema = Joi.object({
37 | email: Joi.string().required(),
38 | password: Joi.string().min(6).required()
39 | })
40 |
41 |
42 | const User = model("user", userSchema);
43 |
44 | module.exports = {
45 | User,
46 | joiRegisterSchema,
47 | joiLoginSchema
48 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["node_modules", "model/contacts.json"]
3 | }
4 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "cross-env NODE_ENV=production node ./bin/server.js",
7 | "start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
8 | "lint": "eslint **/*.js",
9 | "lint:fix": "eslint --fix **/*.js"
10 | },
11 | "dependencies": {
12 | "bcryptjs": "^2.4.3",
13 | "cors": "2.8.5",
14 | "cross-env": "7.0.3",
15 | "dotenv": "^10.0.0",
16 | "express": "4.17.1",
17 | "http-errors": "^1.8.1",
18 | "joi": "^17.4.2",
19 | "jsonwebtoken": "^8.5.1",
20 | "mongoose": "^6.0.13",
21 | "morgan": "1.10.0",
22 | "uuid": "^8.3.2"
23 | },
24 | "devDependencies": {
25 | "eslint": "^7.19.0",
26 | "eslint-config-standard": "^16.0.2",
27 | "eslint-plugin-import": "^2.22.1",
28 | "eslint-plugin-node": "^11.1.0",
29 | "eslint-plugin-promise": "^4.2.1",
30 | "nodemon": "2.0.7"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/readme.md:
--------------------------------------------------------------------------------
1 | ## GoIT Node.js Course Template Homework
2 |
3 | Выполните форк этого репозитория для выполнения домашних заданий (2-6)
4 | Форк создаст репозиторий на вашем http://github.com
5 |
6 | Добавьте ментора в коллаборацию
7 |
8 | Для каждой домашней работы создавайте свою ветку.
9 |
10 | - hw02
11 | - hw03
12 | - hw04
13 | - hw05
14 | - hw06
15 |
16 | Каждая новая ветка для дз должна делаться с master
17 |
18 | После того как вы закончили выполнять домашнее задание в своей ветке, необходимо сделать пулл-реквест (PR). Потом добавить ментора для ревью кода. Только после того как ментор заапрувит PR, вы можете выполнить мердж ветки с домашним заданием в мастер.
19 |
20 | Внимательно читайте комментарии ментора. Исправьте замечания и сделайте коммит в ветке с домашним заданием. Изменения подтянуться в PR автоматически после того как вы отправите коммит с исправлениями на github
21 | После исправления снова добавьте ментора на ревью кода.
22 |
23 | - При сдаче домашней работы есть ссылка на PR
24 | - JS-код чистый и понятный, для форматирования используется Prettier
25 |
26 | ### Команды:
27 |
28 | - `npm start` — старт сервера в режиме production
29 | - `npm run start:dev` — старт сервера в режиме разработки (development)
30 | - `npm run lint` — запустить выполнение проверки кода с eslint, необходимо выполнять перед каждым PR и исправлять все ошибки линтера
31 | - `npm lint:fix` — та же проверка линтера, но с автоматическими исправлениями простых ошибок
32 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/routes/api/auth.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {validation, ctrlWrapper} = require("../../middlewares");
4 | const {auth: ctrl} = require("../../controllers");
5 | const {joiRegisterSchema, joiLoginSchema} = require("../../models/user");
6 |
7 | const router = express.Router();
8 |
9 | router.post("/register", validation(joiRegisterSchema), ctrlWrapper(ctrl.register));
10 | // router.post("/signup")
11 | router.post("/login", validation(joiLoginSchema), ctrlWrapper(ctrl.login));
12 | // router.post("/signin")
13 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-7/auth-example/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {validation, ctrlWrapper} = require("../../middlewares");
4 | const {joiSchema, statusJoiSchema} = require("../../models/product");
5 | const {products: ctrl} = require("../../controllers")
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", ctrlWrapper(ctrl.getAll));
10 |
11 | router.get("/:id", ctrlWrapper(ctrl.getById));
12 |
13 | router.post("/", validation(joiSchema), ctrlWrapper(ctrl.add));
14 |
15 | router.put("/:id", validation(joiSchema), ctrlWrapper(ctrl.updateById));
16 |
17 | router.patch("/:id/status", validation(statusJoiSchema), ctrlWrapper(ctrl.updateStatus));
18 |
19 | router.delete("/:id", ctrlWrapper(ctrl.removeById));
20 |
21 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-7/hash-example/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-7/hash-example/app.js:
--------------------------------------------------------------------------------
1 | const bcrypt = require("bcryptjs");
2 |
3 | const password = "password";
4 |
5 | // console.log(bcrypt.genSaltSync(10));
6 | const hashPassword = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
7 | // console.log(hashPassword);
8 |
9 | const result1 = bcrypt.compareSync(password, hashPassword);
10 | console.log(result1);
11 |
12 | const result2 = bcrypt.compareSync("passwort", hashPassword);
13 | console.log(result2);
14 |
15 |
--------------------------------------------------------------------------------
/lesson-7/hash-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hash-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.13"
16 | },
17 | "dependencies": {
18 | "bcryptjs": "^2.4.3"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-7/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-7/jsonwebtoken-example/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-7/jsonwebtoken-example/app.js:
--------------------------------------------------------------------------------
1 | const jwt = require("jsonwebtoken");
2 |
3 | const SECRET_KEY = "2refaasdfhgsdg313fd";
4 |
5 | const payload = {
6 | id: "61a52562a6476e7590d7d5f6"
7 | }
8 |
9 | const token = jwt.sign(payload, SECRET_KEY, {expiresIn: "1h"});
10 | // console.log(token);
11 |
12 | const decodeToken = jwt.decode(token);
13 | // console.log(decodeToken)
14 |
15 | try {
16 | // const result = jwt.verify(token, SECRET_KEY);
17 | // console.log(result);
18 | const result2 = jwt.verify(`${token}22`, SECRET_KEY);
19 | } catch (error) {
20 | console.log(error.message);
21 | }
--------------------------------------------------------------------------------
/lesson-7/jsonwebtoken-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jsonwebtoken-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.12"
16 | },
17 | "dependencies": {
18 | "jsonwebtoken": "^8.5.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-7/slides/HTTP-common-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/HTTP-common-schema.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/HTTP-personal-request-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/HTTP-personal-request-schema.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/JWT-token-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/JWT-token-schema.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/frontend-backend-requests-with-token.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/frontend-backend-requests-with-token.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/hash-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/hash-schema.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/jwt-token-real-life-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/jwt-token-real-life-example.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/logout-examples.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/logout-examples.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/process.env-and-deploy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/process.env-and-deploy.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/register-auth-steps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/register-auth-steps.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/reigster-auth-create-steps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-7/slides/reigster-auth-create-steps.jpg
--------------------------------------------------------------------------------
/lesson-8/auth-example/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=mongodb+srv://Bogdan:pBje6ZbFRATcsTq@cluster0.lhj89.mongodb.net/online_shop?retryWrites=true&w=majority
2 | SECRET_KEY=GHGSDFM23Tfgsfs3
3 | DB_USER=Bogdan
4 | DB_PASSWORD=pBje6ZbFRATcsTq
5 | DB_NAME=online_shop
--------------------------------------------------------------------------------
/lesson-8/auth-example/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/lesson-8/auth-example/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | node: true,
6 | },
7 | extends: ['standard'],
8 | parserOptions: {
9 | ecmaVersion: 12,
10 | },
11 | rules: {
12 | 'comma-dangle': 'off',
13 | 'space-before-function-paren': 'off',
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const logger = require('morgan')
3 | const cors = require('cors')
4 | require("dotenv").config();
5 |
6 | const authRouter = require("./routes/api/auth");
7 | const usersRouter = require("./routes/api/users");
8 | const productsRouter = require("./routes/api/products");
9 |
10 | const app = express()
11 |
12 | const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'
13 |
14 | app.use(logger(formatsLogger))
15 | app.use(cors())
16 | app.use(express.json())
17 |
18 | app.use("/api/auth", authRouter);
19 | app.use("/api/users", usersRouter);
20 | app.use('/api/products', productsRouter);
21 |
22 | app.use((req, res) => {
23 | res.status(404).json({ message: 'Not found' })
24 | })
25 |
26 | app.use((err, req, res, next) => {
27 | const {status = 500, message = "Server error"} = err;
28 | res.status(status).json({ message: err.message })
29 | })
30 |
31 | module.exports = app
32 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/bin/server.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const app = require('../app');
4 |
5 | const {DB_HOST, PORT = 3000} = process.env;
6 |
7 | mongoose.connect(DB_HOST)
8 | .then(()=> app.listen(PORT))
9 | .catch(error => {
10 | console.log(error.message);
11 | process.exit(1);
12 | })
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/auth/index.js:
--------------------------------------------------------------------------------
1 | const register = require("./register");
2 | const login = require("./login");
3 | const logout = require("./logout");
4 |
5 | module.exports = {
6 | register,
7 | login,
8 | logout
9 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/auth/login.js:
--------------------------------------------------------------------------------
1 | const {Unauthorized} = require("http-errors");
2 | const jwt = require("jsonwebtoken");
3 | // const bcrypt = require("bcryptjs");
4 |
5 | const {User} = require("../../models");
6 |
7 | const {SECRET_KEY} = process.env;
8 |
9 | const login = async(req, res)=> {
10 | const {email, password} = req.body;
11 | const user = await User.findOne({email});
12 | if(!user || !user.comparePassword(password)){
13 | throw new Unauthorized("Email or password is wrong");
14 | }
15 | // const passCompare = bcrypt.compareSync(password, user.password);
16 | // if(!user || !passCompare){
17 | // throw new Unauthorized("Email or password is wrong");
18 | // }
19 | // if(!user){
20 | // throw new Unauthorized(`Email ${email} not found`);
21 | // }
22 | // const passCompare = bcrypt.compareSync(password, user.password);
23 | // if(!passCompare){
24 | // throw new Unauthorized("Password wrong");
25 | // }
26 | const payload = {
27 | id: user._id
28 | };
29 | const token = jwt.sign(payload, SECRET_KEY, {expiresIn: "1h"});
30 | await User.findByIdAndUpdate(user._id, {token});
31 | res.json({
32 | status: "success",
33 | code: 200,
34 | data: {
35 | token
36 | }
37 | })
38 | }
39 |
40 | module.exports = login;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/auth/logout.js:
--------------------------------------------------------------------------------
1 | const {User} = require("../../models");
2 |
3 | const logout = async(req, res)=> {
4 | const {_id} = req.user;
5 | await User.findByIdAndUpdate(_id, {token: null});
6 | res.status(204).json();
7 | }
8 |
9 | module.exports = logout;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/auth/register.js:
--------------------------------------------------------------------------------
1 | const {Conflict} = require("http-errors");
2 | // const bcrypt = require("bcryptjs");
3 |
4 | const {User} = require("../../models");
5 |
6 | const register = async(req, res)=> {
7 | const {name, email, password} = req.body;
8 | const user = await User.findOne({email});
9 | if(user){
10 | throw new Conflict(`User with ${email} already exist`)
11 | }
12 | const newUser = new User({name, email});
13 | /*
14 | newUser = {
15 | name,
16 | email,
17 | setPassword(password){
18 | this.password = bcrypt.hashSync(password, bcrypt.genSaltSync(10))
19 | }
20 | }
21 | */
22 | newUser.setPassword(password);
23 | /*
24 | newUser = {
25 | name,
26 | email,
27 | password,
28 | setPassword(password){
29 | this.passord = bcrypt.hashSync(password, bcrypt.genSaltSync(10))
30 | }
31 | }
32 | */
33 | newUser.save();
34 | // const hashPassword = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
35 | // const result = await User.create({name, email, password: hashPassword});
36 | res.status(201).json({
37 | status: "success",
38 | code: 201,
39 | data: {
40 | user: {
41 | email,
42 | name
43 | }
44 | }
45 | });
46 | }
47 |
48 | module.exports = register;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 | const auth = require("./auth");
3 | const users = require("./users");
4 |
5 | module.exports = {
6 | products,
7 | auth,
8 | users
9 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/products/add.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const add = async (req, res) => {
4 | const {_id} = req.user;
5 | const result = await Product.create({...req.body, owner: _id});
6 | res.status(201).json({
7 | status: "success",
8 | code: 201,
9 | data: {
10 | result
11 | }
12 | })
13 | }
14 |
15 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/products/getAll.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const getAll = async (req, res) => {
4 | const {_id} = req.user;
5 | const {page = 1, limit = 10} = req.query;
6 | const skip = (page - 1) * limit;
7 | const products = await Product.find({owner: _id}, "", {skip, limit: Number(limit)}).populate("owner", "_id name email");
8 |
9 | res.json({
10 | status: "success",
11 | code: 200,
12 | data: {
13 | result: products
14 | }
15 | });
16 | };
17 |
18 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/products/getById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const getById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findById(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 | const updateStatus = require("./updateStatus");
7 |
8 | module.exports = {
9 | getAll,
10 | getById,
11 | add,
12 | updateById,
13 | updateStatus,
14 | removeById
15 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/products/removeById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const removeById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndRemove(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | message: "product deleted",
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/products/updateById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndUpdate(id, req.body, {new: true});
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/products/updateStatus.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateStatus = async (req, res) => {
6 | const { id } = req.params;
7 | const {status} = req.body;
8 | const result = await Product.findByIdAndUpdate(id, {status}, {new: true});
9 | if (!result) {
10 | throw new NotFound(`Product with id=${id} not found`);
11 | }
12 | res.json({
13 | status: "success",
14 | code: 200,
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = updateStatus;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/users/getCurrent.js:
--------------------------------------------------------------------------------
1 | const {User} = require("../../models");
2 |
3 | const getCurrent = async(req, res)=> {
4 | const {name, email} = req.user;
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | user: {
10 | name,
11 | email
12 | }
13 |
14 | }
15 | })
16 | }
17 |
18 | module.exports = getCurrent;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/users/index.js:
--------------------------------------------------------------------------------
1 | const getCurrent = require("./getCurrent");
2 |
3 | module.exports = {
4 | getCurrent
5 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | DB_USER=
3 | DB_PASSWORD=
4 | DB_NAME=
--------------------------------------------------------------------------------
/lesson-8/auth-example/middlewares/ctrlWrapper.js:
--------------------------------------------------------------------------------
1 | const ctrlWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | } catch (error) {
6 | next(error);
7 | }
8 | }
9 | }
10 |
11 | module.exports = ctrlWrapper;
--------------------------------------------------------------------------------
/lesson-8/auth-example/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const ctrlWrapper = require("./ctrlWrapper");
3 | const auth = require("./auth");
4 |
5 | module.exports = {
6 | validation,
7 | ctrlWrapper,
8 | auth
9 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema)=> {
2 | return (req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | error.status = 400;
6 | next(error);
7 | }
8 | next()
9 | }
10 | }
11 |
12 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-8/auth-example/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 | const {User} = require("./user");
3 |
4 | module.exports = {
5 | Product,
6 | User
7 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/models/user.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 | const bcrypt = require("bcryptjs");
4 |
5 | const userSchema = Schema({
6 | name: {
7 | type: String,
8 | required: true
9 | },
10 | email: {
11 | type: String,
12 | required: true,
13 | unique: true
14 | },
15 | password: {
16 | type: String,
17 | required: true,
18 | minlength: 6
19 | },
20 | token: {
21 | type: String,
22 | default: null
23 | }
24 | }, {versionKey: false, timestamps: true});
25 |
26 | userSchema.methods.setPassword = function(password){
27 | this.password = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
28 | }
29 |
30 | userSchema.methods.comparePassword = function(password){
31 | return bcrypt.compareSync(password, this.password);
32 | }
33 |
34 | const joiRegisterSchema = Joi.object({
35 | name: Joi.string().required(),
36 | email: Joi.string().required(),
37 | password: Joi.string().min(6).required()
38 | })
39 |
40 | const joiLoginSchema = Joi.object({
41 | email: Joi.string().required(),
42 | password: Joi.string().min(6).required()
43 | })
44 |
45 |
46 | const User = model("user", userSchema);
47 |
48 | module.exports = {
49 | User,
50 | joiRegisterSchema,
51 | joiLoginSchema
52 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["node_modules", "model/contacts.json"]
3 | }
4 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "cross-env NODE_ENV=production node ./bin/server.js",
7 | "start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
8 | "lint": "eslint **/*.js",
9 | "lint:fix": "eslint --fix **/*.js"
10 | },
11 | "dependencies": {
12 | "bcryptjs": "^2.4.3",
13 | "cors": "2.8.5",
14 | "cross-env": "7.0.3",
15 | "dotenv": "^10.0.0",
16 | "express": "4.17.1",
17 | "http-errors": "^1.8.1",
18 | "joi": "^17.4.2",
19 | "jsonwebtoken": "^8.5.1",
20 | "mongoose": "^6.0.13",
21 | "morgan": "1.10.0",
22 | "uuid": "^8.3.2"
23 | },
24 | "devDependencies": {
25 | "eslint": "^7.19.0",
26 | "eslint-config-standard": "^16.0.2",
27 | "eslint-plugin-import": "^2.22.1",
28 | "eslint-plugin-node": "^11.1.0",
29 | "eslint-plugin-promise": "^4.2.1",
30 | "nodemon": "2.0.7"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/readme.md:
--------------------------------------------------------------------------------
1 | ## GoIT Node.js Course Template Homework
2 |
3 | Выполните форк этого репозитория для выполнения домашних заданий (2-6)
4 | Форк создаст репозиторий на вашем http://github.com
5 |
6 | Добавьте ментора в коллаборацию
7 |
8 | Для каждой домашней работы создавайте свою ветку.
9 |
10 | - hw02
11 | - hw03
12 | - hw04
13 | - hw05
14 | - hw06
15 |
16 | Каждая новая ветка для дз должна делаться с master
17 |
18 | После того как вы закончили выполнять домашнее задание в своей ветке, необходимо сделать пулл-реквест (PR). Потом добавить ментора для ревью кода. Только после того как ментор заапрувит PR, вы можете выполнить мердж ветки с домашним заданием в мастер.
19 |
20 | Внимательно читайте комментарии ментора. Исправьте замечания и сделайте коммит в ветке с домашним заданием. Изменения подтянуться в PR автоматически после того как вы отправите коммит с исправлениями на github
21 | После исправления снова добавьте ментора на ревью кода.
22 |
23 | - При сдаче домашней работы есть ссылка на PR
24 | - JS-код чистый и понятный, для форматирования используется Prettier
25 |
26 | ### Команды:
27 |
28 | - `npm start` — старт сервера в режиме production
29 | - `npm run start:dev` — старт сервера в режиме разработки (development)
30 | - `npm run lint` — запустить выполнение проверки кода с eslint, необходимо выполнять перед каждым PR и исправлять все ошибки линтера
31 | - `npm lint:fix` — та же проверка линтера, но с автоматическими исправлениями простых ошибок
32 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/routes/api/auth.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, validation, ctrlWrapper} = require("../../middlewares");
4 | const {auth: ctrl} = require("../../controllers");
5 | const {joiRegisterSchema, joiLoginSchema} = require("../../models/user");
6 |
7 | const router = express.Router();
8 |
9 | router.post("/register", validation(joiRegisterSchema), ctrlWrapper(ctrl.register));
10 | // router.post("/signup")
11 | router.post("/login", validation(joiLoginSchema), ctrlWrapper(ctrl.login));
12 | // router.post("/signin")
13 | router.get("/logout", auth, ctrlWrapper(ctrl.logout));
14 | // router.get("/signout")
15 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-8/auth-example/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, validation, ctrlWrapper} = require("../../middlewares");
4 | const {joiSchema, statusJoiSchema} = require("../../models/product");
5 | const {products: ctrl} = require("../../controllers")
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", auth, ctrlWrapper(ctrl.getAll));
10 |
11 | router.get("/:id", ctrlWrapper(ctrl.getById));
12 |
13 | router.post("/", auth, validation(joiSchema), ctrlWrapper(ctrl.add));
14 |
15 | router.put("/:id", validation(joiSchema), ctrlWrapper(ctrl.updateById));
16 |
17 | router.patch("/:id/status", validation(statusJoiSchema), ctrlWrapper(ctrl.updateStatus));
18 |
19 | router.delete("/:id", ctrlWrapper(ctrl.removeById));
20 |
21 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-8/auth-example/routes/api/users.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, ctrlWrapper} = require("../../middlewares");
4 | const {users: ctrl} = require("../../controllers");
5 |
6 | const router = express.Router();
7 |
8 | router.get("/current", auth, ctrlWrapper(ctrl.getCurrent));
9 |
10 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-8/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-8/slides/HTTP-common-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/HTTP-common-schema.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/HTTP-personal-request-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/HTTP-personal-request-schema.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/JWT-token-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/JWT-token-schema.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/frontend-backend-requests-with-token.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/frontend-backend-requests-with-token.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/hash-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/hash-schema.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/jwt-token-real-life-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/jwt-token-real-life-example.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/logout-examples.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/logout-examples.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/process.env-and-deploy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/process.env-and-deploy.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/register-auth-steps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/register-auth-steps.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/reigster-auth-create-steps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-8/slides/reigster-auth-create-steps.jpg
--------------------------------------------------------------------------------
/lesson-9/2085-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-9/2085-1.png
--------------------------------------------------------------------------------
/lesson-9/auth-example/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=mongodb+srv://Bogdan:pBje6ZbFRATcsTq@cluster0.lhj89.mongodb.net/online_shop?retryWrites=true&w=majority
2 | SECRET_KEY=GHGSDFM23Tfgsfs3
3 | DB_USER=Bogdan
4 | DB_PASSWORD=pBje6ZbFRATcsTq
5 | DB_NAME=online_shop
--------------------------------------------------------------------------------
/lesson-9/auth-example/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/lesson-9/auth-example/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | node: true,
6 | },
7 | extends: ['standard'],
8 | parserOptions: {
9 | ecmaVersion: 12,
10 | },
11 | rules: {
12 | 'comma-dangle': 'off',
13 | 'space-before-function-paren': 'off',
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/lesson-9/auth-example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/lesson-9/auth-example/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const logger = require('morgan')
3 | const cors = require('cors')
4 | require("dotenv").config();
5 |
6 | const authRouter = require("./routes/api/auth");
7 | const usersRouter = require("./routes/api/users");
8 | const productsRouter = require("./routes/api/products");
9 |
10 | const app = express()
11 |
12 | const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short'
13 |
14 | app.use(logger(formatsLogger))
15 | app.use(cors())
16 | app.use(express.json())
17 | app.use(express.static("public"))
18 |
19 | app.use("/api/auth", authRouter);
20 | app.use("/api/users", usersRouter);
21 | app.use('/api/products', productsRouter);
22 |
23 | app.use((req, res) => {
24 | res.status(404).json({ message: 'Not found' })
25 | })
26 |
27 | app.use((err, req, res, next) => {
28 | const {status = 500, message = "Server error"} = err;
29 | res.status(status).json({ message: err.message })
30 | })
31 |
32 | module.exports = app
33 |
--------------------------------------------------------------------------------
/lesson-9/auth-example/bin/server.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const app = require('../app');
4 |
5 | const {DB_HOST, PORT = 3000} = process.env;
6 |
7 | mongoose.connect(DB_HOST)
8 | .then(()=> app.listen(PORT))
9 | .catch(error => {
10 | console.log(error.message);
11 | process.exit(1);
12 | })
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/auth/index.js:
--------------------------------------------------------------------------------
1 | const register = require("./register");
2 | const login = require("./login");
3 | const logout = require("./logout");
4 |
5 | module.exports = {
6 | register,
7 | login,
8 | logout
9 | }
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/auth/login.js:
--------------------------------------------------------------------------------
1 | const {Unauthorized} = require("http-errors");
2 | const jwt = require("jsonwebtoken");
3 | // const bcrypt = require("bcryptjs");
4 |
5 | const {User} = require("../../models");
6 |
7 | const {SECRET_KEY} = process.env;
8 |
9 | const login = async(req, res)=> {
10 | const {email, password} = req.body;
11 | const user = await User.findOne({email});
12 | if(!user || !user.comparePassword(password)){
13 | throw new Unauthorized("Email or password is wrong");
14 | }
15 | // const passCompare = bcrypt.compareSync(password, user.password);
16 | // if(!user || !passCompare){
17 | // throw new Unauthorized("Email or password is wrong");
18 | // }
19 | // if(!user){
20 | // throw new Unauthorized(`Email ${email} not found`);
21 | // }
22 | // const passCompare = bcrypt.compareSync(password, user.password);
23 | // if(!passCompare){
24 | // throw new Unauthorized("Password wrong");
25 | // }
26 | const payload = {
27 | id: user._id
28 | };
29 | const token = jwt.sign(payload, SECRET_KEY, {expiresIn: "1h"});
30 | await User.findByIdAndUpdate(user._id, {token});
31 | res.json({
32 | status: "success",
33 | code: 200,
34 | data: {
35 | token
36 | }
37 | })
38 | }
39 |
40 | module.exports = login;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/auth/logout.js:
--------------------------------------------------------------------------------
1 | const {User} = require("../../models");
2 |
3 | const logout = async(req, res)=> {
4 | const {_id} = req.user;
5 | await User.findByIdAndUpdate(_id, {token: null});
6 | res.status(204).json();
7 | }
8 |
9 | module.exports = logout;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/auth/register.js:
--------------------------------------------------------------------------------
1 | const {Conflict} = require("http-errors");
2 | const gravatar = require("gravatar");
3 |
4 | const {User} = require("../../models");
5 |
6 | const register = async(req, res)=> {
7 | const {name, email, password} = req.body;
8 | const user = await User.findOne({email});
9 | if(user){
10 | throw new Conflict(`User with ${email} already exist`)
11 | }
12 | const avatarURL = gravatar.url(email);
13 | const newUser = new User({name, email, avatarURL});
14 |
15 | newUser.setPassword(password);
16 |
17 | newUser.save();
18 |
19 | res.status(201).json({
20 | status: "success",
21 | code: 201,
22 | data: {
23 | user: {
24 | name,
25 | email,
26 | avatarURL
27 | }
28 | }
29 | });
30 | }
31 |
32 | module.exports = register;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 | const auth = require("./auth");
3 | const users = require("./users");
4 |
5 | module.exports = {
6 | products,
7 | auth,
8 | users
9 | }
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/products/add.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const add = async (req, res) => {
4 | const {_id} = req.user;
5 | const result = await Product.create({...req.body, owner: _id});
6 | res.status(201).json({
7 | status: "success",
8 | code: 201,
9 | data: {
10 | result
11 | }
12 | })
13 | }
14 |
15 | module.exports = add;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/products/getAll.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("../../models");
2 |
3 | const getAll = async (req, res) => {
4 | const {_id} = req.user;
5 | const {page = 1, limit = 10} = req.query;
6 | const skip = (page - 1) * limit;
7 | const products = await Product.find({owner: _id}, "", {skip, limit: Number(limit)}).populate("owner", "_id name email");
8 |
9 | res.json({
10 | status: "success",
11 | code: 200,
12 | data: {
13 | result: products
14 | }
15 | });
16 | };
17 |
18 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/products/getById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const getById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findById(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/products/index.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 | const getById = require("./getById");
3 | const add = require("./add");
4 | const updateById = require("./updateById");
5 | const removeById = require("./removeById");
6 | const updateStatus = require("./updateStatus");
7 |
8 | module.exports = {
9 | getAll,
10 | getById,
11 | add,
12 | updateById,
13 | updateStatus,
14 | removeById
15 | }
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/products/removeById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const removeById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndRemove(id);
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | message: "product deleted",
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/products/updateById.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateById = async (req, res) => {
6 | const { id } = req.params;
7 | const result = await Product.findByIdAndUpdate(id, req.body, {new: true});
8 | if (!result) {
9 | throw new NotFound(`Product with id=${id} not found`);
10 | }
11 | res.json({
12 | status: "success",
13 | code: 200,
14 | data: {
15 | result
16 | }
17 | })
18 | }
19 |
20 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/products/updateStatus.js:
--------------------------------------------------------------------------------
1 | const { NotFound } = require("http-errors");
2 |
3 | const {Product} = require("../../models");
4 |
5 | const updateStatus = async (req, res) => {
6 | const { id } = req.params;
7 | const {status} = req.body;
8 | const result = await Product.findByIdAndUpdate(id, {status}, {new: true});
9 | if (!result) {
10 | throw new NotFound(`Product with id=${id} not found`);
11 | }
12 | res.json({
13 | status: "success",
14 | code: 200,
15 | data: {
16 | result
17 | }
18 | })
19 | }
20 |
21 | module.exports = updateStatus;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/users/getCurrent.js:
--------------------------------------------------------------------------------
1 | const {User} = require("../../models");
2 |
3 | const getCurrent = async(req, res)=> {
4 | const {name, email} = req.user;
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | user: {
10 | name,
11 | email
12 | }
13 |
14 | }
15 | })
16 | }
17 |
18 | module.exports = getCurrent;
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/users/index.js:
--------------------------------------------------------------------------------
1 | const getCurrent = require("./getCurrent");
2 | const updateAvatar = require("./updateAvatar");
3 |
4 | module.exports = {
5 | getCurrent,
6 | updateAvatar
7 | }
--------------------------------------------------------------------------------
/lesson-9/auth-example/controllers/users/updateAvatar.js:
--------------------------------------------------------------------------------
1 | const {User} = require("../../models");
2 | const path = require("path");
3 | const fs = require("fs/promises");
4 |
5 | const avatarsDir = path.join(__dirname, "../../", "public", "avatars");
6 |
7 | const updateAvatar = async(req, res)=> {
8 | const {path: tempUpload, originalname} = req.file;
9 | const {_id: id} = req.user;
10 | const imageName = `${id}_${originalname}`;
11 | try {
12 | const resultUpload = path.join(avatarsDir, imageName);
13 | await fs.rename(tempUpload, resultUpload);
14 | const avatarURL = path.join("public", "avatars", imageName);
15 | await User.findByIdAndUpdate(req.user._id, {avatarURL});
16 | res.json({avatarURL});
17 | } catch (error) {
18 | await fs.unlink(tempUpload);
19 | throw error;
20 | }
21 | };
22 |
23 | module.exports = updateAvatar;
--------------------------------------------------------------------------------
/lesson-9/auth-example/env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | DB_USER=
3 | DB_PASSWORD=
4 | DB_NAME=
--------------------------------------------------------------------------------
/lesson-9/auth-example/middlewares/ctrlWrapper.js:
--------------------------------------------------------------------------------
1 | const ctrlWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | } catch (error) {
6 | next(error);
7 | }
8 | }
9 | }
10 |
11 | module.exports = ctrlWrapper;
--------------------------------------------------------------------------------
/lesson-9/auth-example/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const ctrlWrapper = require("./ctrlWrapper");
3 | const auth = require("./auth");
4 | const upload = require("./upload");
5 |
6 | module.exports = {
7 | validation,
8 | ctrlWrapper,
9 | auth,
10 | upload
11 | }
--------------------------------------------------------------------------------
/lesson-9/auth-example/middlewares/upload.js:
--------------------------------------------------------------------------------
1 | const multer = require("multer");
2 | const path = require("path");
3 |
4 | const tempDir = path.join(__dirname, "../", "temp");
5 |
6 | const multerConfig = multer.diskStorage({
7 | destination: (req, file, cb)=> {
8 | cb(null, tempDir)
9 | },
10 | filename: (req, file, cb)=> {
11 | cb(null, file.originalname)
12 | },
13 | limits: {
14 | fileSize: 2048
15 | }
16 | })
17 |
18 | const upload = multer({
19 | storage: multerConfig
20 | })
21 |
22 | module.exports = upload;
--------------------------------------------------------------------------------
/lesson-9/auth-example/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema)=> {
2 | return (req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | error.status = 400;
6 | next(error);
7 | }
8 | next()
9 | }
10 | }
11 |
12 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-9/auth-example/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 | const {User} = require("./user");
3 |
4 | module.exports = {
5 | Product,
6 | User
7 | }
--------------------------------------------------------------------------------
/lesson-9/auth-example/models/user.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 | const bcrypt = require("bcryptjs");
4 |
5 | const userSchema = Schema({
6 | name: {
7 | type: String,
8 | required: true
9 | },
10 | email: {
11 | type: String,
12 | required: true,
13 | unique: true
14 | },
15 | password: {
16 | type: String,
17 | required: true,
18 | minlength: 6
19 | },
20 | token: {
21 | type: String,
22 | default: null
23 | },
24 | avatarURL: {
25 | type: String,
26 | required: true
27 | }
28 | }, {versionKey: false, timestamps: true});
29 |
30 | userSchema.methods.setPassword = function(password){
31 | this.password = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
32 | }
33 |
34 | userSchema.methods.comparePassword = function(password){
35 | return bcrypt.compareSync(password, this.password);
36 | }
37 |
38 | const joiRegisterSchema = Joi.object({
39 | name: Joi.string().required(),
40 | email: Joi.string().required(),
41 | password: Joi.string().min(6).required()
42 | })
43 |
44 | const joiLoginSchema = Joi.object({
45 | email: Joi.string().required(),
46 | password: Joi.string().min(6).required()
47 | })
48 |
49 |
50 | const User = model("user", userSchema);
51 |
52 | module.exports = {
53 | User,
54 | joiRegisterSchema,
55 | joiLoginSchema
56 | }
--------------------------------------------------------------------------------
/lesson-9/auth-example/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["node_modules", "model/contacts.json"]
3 | }
4 |
--------------------------------------------------------------------------------
/lesson-9/auth-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "cross-env NODE_ENV=production node ./bin/server.js",
7 | "start:dev": "cross-env NODE_ENV=development nodemon ./bin/server.js",
8 | "lint": "eslint **/*.js",
9 | "lint:fix": "eslint --fix **/*.js"
10 | },
11 | "dependencies": {
12 | "bcryptjs": "^2.4.3",
13 | "cors": "2.8.5",
14 | "cross-env": "7.0.3",
15 | "dotenv": "^10.0.0",
16 | "express": "4.17.1",
17 | "gravatar": "^1.8.2",
18 | "http-errors": "^1.8.1",
19 | "joi": "^17.4.2",
20 | "jsonwebtoken": "^8.5.1",
21 | "mongoose": "^6.0.13",
22 | "morgan": "1.10.0",
23 | "multer": "^1.4.4",
24 | "uuid": "^8.3.2"
25 | },
26 | "devDependencies": {
27 | "eslint": "^7.19.0",
28 | "eslint-config-standard": "^16.0.2",
29 | "eslint-plugin-import": "^2.22.1",
30 | "eslint-plugin-node": "^11.1.0",
31 | "eslint-plugin-promise": "^4.2.1",
32 | "nodemon": "2.0.7"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lesson-9/auth-example/public/avatars/61afac845d2f14829dd3b79a_2085-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-9/auth-example/public/avatars/61afac845d2f14829dd3b79a_2085-1.png
--------------------------------------------------------------------------------
/lesson-9/auth-example/readme.md:
--------------------------------------------------------------------------------
1 | ## GoIT Node.js Course Template Homework
2 |
3 | Выполните форк этого репозитория для выполнения домашних заданий (2-6)
4 | Форк создаст репозиторий на вашем http://github.com
5 |
6 | Добавьте ментора в коллаборацию
7 |
8 | Для каждой домашней работы создавайте свою ветку.
9 |
10 | - hw02
11 | - hw03
12 | - hw04
13 | - hw05
14 | - hw06
15 |
16 | Каждая новая ветка для дз должна делаться с master
17 |
18 | После того как вы закончили выполнять домашнее задание в своей ветке, необходимо сделать пулл-реквест (PR). Потом добавить ментора для ревью кода. Только после того как ментор заапрувит PR, вы можете выполнить мердж ветки с домашним заданием в мастер.
19 |
20 | Внимательно читайте комментарии ментора. Исправьте замечания и сделайте коммит в ветке с домашним заданием. Изменения подтянуться в PR автоматически после того как вы отправите коммит с исправлениями на github
21 | После исправления снова добавьте ментора на ревью кода.
22 |
23 | - При сдаче домашней работы есть ссылка на PR
24 | - JS-код чистый и понятный, для форматирования используется Prettier
25 |
26 | ### Команды:
27 |
28 | - `npm start` — старт сервера в режиме production
29 | - `npm run start:dev` — старт сервера в режиме разработки (development)
30 | - `npm run lint` — запустить выполнение проверки кода с eslint, необходимо выполнять перед каждым PR и исправлять все ошибки линтера
31 | - `npm lint:fix` — та же проверка линтера, но с автоматическими исправлениями простых ошибок
32 |
--------------------------------------------------------------------------------
/lesson-9/auth-example/routes/api/auth.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, validation, ctrlWrapper} = require("../../middlewares");
4 | const {auth: ctrl} = require("../../controllers");
5 | const {joiRegisterSchema, joiLoginSchema} = require("../../models/user");
6 |
7 | const router = express.Router();
8 |
9 | router.post("/register", validation(joiRegisterSchema), ctrlWrapper(ctrl.register));
10 | // router.post("/signup")
11 | router.post("/login", validation(joiLoginSchema), ctrlWrapper(ctrl.login));
12 | // router.post("/signin")
13 | router.get("/logout", auth, ctrlWrapper(ctrl.logout));
14 | // router.get("/signout")
15 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-9/auth-example/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, validation, ctrlWrapper} = require("../../middlewares");
4 | const {joiSchema, statusJoiSchema} = require("../../models/product");
5 | const {products: ctrl} = require("../../controllers")
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", auth, ctrlWrapper(ctrl.getAll));
10 |
11 | router.get("/:id", ctrlWrapper(ctrl.getById));
12 |
13 | router.post("/", auth, validation(joiSchema), ctrlWrapper(ctrl.add));
14 |
15 | router.put("/:id", validation(joiSchema), ctrlWrapper(ctrl.updateById));
16 |
17 | router.patch("/:id/status", validation(statusJoiSchema), ctrlWrapper(ctrl.updateStatus));
18 |
19 | router.delete("/:id", ctrlWrapper(ctrl.removeById));
20 |
21 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-9/auth-example/routes/api/users.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {auth, upload, ctrlWrapper} = require("../../middlewares");
4 | const {users: ctrl} = require("../../controllers");
5 |
6 | const router = express.Router();
7 |
8 | router.get("/current", auth, ctrlWrapper(ctrl.getCurrent));
9 | router.patch("/avatars", auth, upload.single("avatar"), ctrlWrapper(ctrl.updateAvatar));
10 |
11 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-9/auth-example/temp/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-9/auth-example/temp/.gitkeep
--------------------------------------------------------------------------------
/lesson-9/multer-example/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vscode/
3 | node_modules/
--------------------------------------------------------------------------------
/lesson-9/multer-example/frontend.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
25 |
26 |
--------------------------------------------------------------------------------
/lesson-9/multer-example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
14 |
23 |
24 |
--------------------------------------------------------------------------------
/lesson-9/multer-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multer-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node app",
9 | "start:dev": "nodemon app"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "nodemon": "^2.0.13"
16 | },
17 | "dependencies": {
18 | "cors": "^2.8.5",
19 | "express": "^4.17.1",
20 | "multer": "^1.4.4",
21 | "uuid": "^8.3.2"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lesson-9/multer-example/public/products/2085-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-9/multer-example/public/products/2085-1.png
--------------------------------------------------------------------------------
/lesson-9/multer-example/temp/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-9/multer-example/temp/.gitkeep
--------------------------------------------------------------------------------
/lesson-9/slides/multer-work-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/33-nodejs/eb9e1a04903e3f65ec35db4c4f18c59e2b8229f4/lesson-9/slides/multer-work-schema.jpg
--------------------------------------------------------------------------------