├── .gitignore
├── lesson-1
├── .gitignore
├── README.md
├── index.html
├── node start
│ ├── index.js
│ └── server
│ │ └── bin.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
│ ├── motivation-picture.png
│ ├── npm-structure.jpg
│ ├── project-create-steps.jpg
│ └── reasons-learn-nodejs.jpg
├── lesson-10
├── index.html
├── pagination-mongoose
│ ├── .env
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ │ └── server.js
│ ├── controllers
│ │ ├── index.js
│ │ └── products.js
│ ├── helpers
│ │ ├── index.js
│ │ └── sendSuccessRes.js
│ ├── middlewares
│ │ ├── controllerWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── index.js
│ │ └── product.js
│ ├── nodemon.json
│ ├── package.json
│ ├── readme.md
│ └── routes
│ │ └── api
│ │ └── products.js
├── 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
│ ├── funcs
│ ├── index.js
│ ├── isLeapYear.js
│ └── isLearYear.test.js
│ ├── index.html
│ └── package.json
├── lesson-11
├── auth-example
│ ├── .env.example
│ ├── .gitignore
│ ├── app.js
│ ├── controllers
│ │ ├── auth
│ │ │ ├── index.js
│ │ │ ├── login.js
│ │ │ ├── logout.js
│ │ │ ├── register.js
│ │ │ └── verify.js
│ │ ├── index.js
│ │ └── orders
│ │ │ ├── add.js
│ │ │ ├── getAll.js
│ │ │ ├── getAllByUser.js
│ │ │ └── index.js
│ ├── helpers
│ │ ├── index.js
│ │ ├── sendEmail.js
│ │ └── sendSuccessRes.js
│ ├── middlewares
│ │ ├── authenticate.js
│ │ ├── controllerWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── index.js
│ │ ├── order.js
│ │ └── user.js
│ ├── package.json
│ └── routes
│ │ └── api
│ │ ├── auth.js
│ │ └── orders.js
├── index.html
├── nodemailer-meta-ua
│ ├── .gitignore
│ ├── app.js
│ ├── helpers
│ │ └── sendEmail.js
│ └── package.json
├── nodemailer
│ ├── .gitignore
│ ├── app.js
│ ├── helpers
│ │ └── sendEmail.js
│ └── package.json
├── sendgrid
│ ├── .gitignore
│ ├── app.js
│ ├── helpers
│ │ └── sendEmail.js
│ └── package.json
└── slides
│ ├── mailing-schema.jpg
│ ├── nodemailer.jpg
│ └── sendgrid-schema.jpg
├── lesson-12
├── README.md
├── index.html
├── mongodb-project
│ ├── .env.example
│ ├── .gitignore
│ ├── app.js
│ ├── controllers
│ │ ├── index.js
│ │ └── products.js
│ ├── helpers
│ │ ├── index.js
│ │ └── sendSuccessReq.js
│ ├── middlewares
│ │ ├── controllerWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── category.js
│ │ ├── index.js
│ │ └── product.js
│ ├── package.json
│ └── routes
│ │ └── api
│ │ └── products.js
├── 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-13
├── index.html
├── mongodb-project
│ ├── .env.example
│ ├── .gitignore
│ ├── Dockerfile
│ ├── app.js
│ ├── controllers
│ │ ├── index.js
│ │ └── products.js
│ ├── helpers
│ │ ├── index.js
│ │ └── sendSuccessReq.js
│ ├── middlewares
│ │ ├── controllerWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── category.js
│ │ ├── index.js
│ │ └── product.js
│ ├── package.json
│ └── routes
│ │ └── api
│ │ └── products.js
├── php-project
│ ├── Dockerfile
│ └── index.php
└── slides
│ ├── 05efe6379b.jpg
│ ├── 09bf934cc1.jpg
│ ├── 0aac227e26.jpg
│ ├── 1e8868fd69.jpg
│ ├── 206360c857.jpg
│ ├── 35e71d29de.jpg
│ ├── 505114e755.jpg
│ ├── 6423d760db.jpg
│ ├── 7155b6b76d.jpg
│ ├── 76a678f8e7.jpg
│ ├── 83fc82807e.jpg
│ ├── 9b35bf3889.jpg
│ ├── a7cc498c22.jpg
│ ├── b78636dee9.jpg
│ ├── ca8261d313.jpg
│ └── daf8a4de74.jpg
├── lesson-2
├── README.md
├── file-reader
│ ├── .gitignore
│ ├── files
│ │ └── read.txt
│ ├── index.js
│ ├── package.json
│ └── promise-index.js
├── slides
│ └── work-with-files-examples.jpg
├── work-with-files
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── work-with-json-files-example-2
│ ├── .gitignore
│ ├── app.js
│ ├── package.json
│ └── products
│ │ ├── add.js
│ │ ├── getAll.js
│ │ ├── getById.js
│ │ ├── index.js
│ │ ├── products.json
│ │ ├── removeById.js
│ │ ├── updateById.js
│ │ └── updateProducts.js
└── work-with-json-files
│ ├── .gitignore
│ ├── app.js
│ ├── package.json
│ └── products
│ ├── add.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
├── express-example-3
│ ├── .gitignore
│ ├── app.js
│ ├── index.html
│ ├── package.json
│ ├── products.js
│ └── server.log
├── http-server-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── index.html
└── slides
│ ├── Client-Server-schema.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
├── README.md
├── index.html
├── joi-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── nodejs-homework-template-master-2
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ │ └── server.js
│ ├── controllers
│ │ ├── index.js
│ │ └── products.js
│ ├── helpers
│ │ ├── index.js
│ │ └── sendSuccessRes.js
│ ├── middlewares
│ │ ├── controllerWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── model
│ │ └── products
│ │ │ ├── add.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
│ │ │ ├── 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
└── slides
│ ├── CRUD.jpg
│ ├── Client-Server-schema.jpg
│ ├── HTTP-methods.jpg
│ ├── REST-API-additional-rules.jpg
│ ├── REST-API-basic-rules.jpg
│ ├── Server-response-code.jpg
│ ├── middleware-work-schema-details-2.jpg
│ ├── middleware-work-schema-details-3.jpg
│ ├── middleware-work-schema-details.jpg
│ ├── middleware-work-schema.jpg
│ ├── old-routes-example.jpg
│ └── what-is-it-cors.jpg
├── lesson-5
├── index.html
├── mongodb-project
│ ├── .gitignore
│ ├── app.js
│ ├── models
│ │ ├── category.js
│ │ └── index.js
│ └── package.json
├── process-env-example
│ ├── .gitignore
│ ├── app.js
│ └── package.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
├── index.html
├── mongodb-project
│ ├── .gitignore
│ ├── app.js
│ ├── models
│ │ ├── category.js
│ │ └── index.js
│ └── package.json
├── nodejs-homework-template-master
│ ├── .env
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── app.js
│ ├── bin
│ │ └── server.js
│ ├── controllers
│ │ ├── index.js
│ │ └── products.js
│ ├── helpers
│ │ ├── index.js
│ │ └── sendSuccessRes.js
│ ├── middlewares
│ │ ├── controllerWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── index.js
│ │ └── product.js
│ ├── nodemon.json
│ ├── package.json
│ ├── readme.md
│ └── routes
│ │ └── api
│ │ └── products.js
└── slides
│ ├── schema-model-collection.jpg
│ └── schema-model-example.jpg
├── lesson-7
├── .gitignore
├── README.md
├── auth-example
│ ├── .env.example
│ ├── .gitignore
│ ├── app.js
│ ├── controllers
│ │ ├── auth
│ │ │ ├── index.js
│ │ │ ├── login.js
│ │ │ ├── logout.js
│ │ │ └── register.js
│ │ └── index.js
│ ├── helpers
│ │ ├── index.js
│ │ └── sendSuccessRes.js
│ ├── models
│ │ ├── index.js
│ │ └── user.js
│ ├── package.json
│ └── routes
│ │ └── api
│ │ └── auth.js
├── hash-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
├── index.html
└── slides
│ ├── HTTP-common-schema.jpg
│ ├── HTTP-personal-request-schema.jpg
│ ├── frontend-backend-requests-with-token.jpg
│ ├── hash-schema.jpg
│ ├── jwt-token-real-life-example.jpg
│ ├── process.env-and-deploy.jpg
│ ├── register-auth-steps.jpg
│ └── reigster-auth-create-steps.jpg
├── lesson-8
├── .gitignore
├── README.md
├── auth-example
│ ├── .env.example
│ ├── .gitignore
│ ├── app.js
│ ├── controllers
│ │ ├── auth
│ │ │ ├── index.js
│ │ │ ├── login.js
│ │ │ ├── logout.js
│ │ │ └── register.js
│ │ ├── index.js
│ │ └── orders
│ │ │ ├── add.js
│ │ │ ├── getAll.js
│ │ │ ├── getAllByUser.js
│ │ │ └── index.js
│ ├── helpers
│ │ ├── index.js
│ │ └── sendSuccessRes.js
│ ├── middlewares
│ │ ├── authenticate.js
│ │ ├── controllerWrapper.js
│ │ ├── index.js
│ │ └── validation.js
│ ├── models
│ │ ├── index.js
│ │ ├── order.js
│ │ └── user.js
│ ├── package.json
│ └── routes
│ │ └── api
│ │ ├── auth.js
│ │ └── orders.js
├── index.html
├── jsonwebtoken-example
│ ├── .gitignore
│ ├── app.js
│ └── package.json
└── slides
│ ├── JWT-token-schema.jpg
│ ├── hash-schema.jpg
│ └── logout-examples.jpg
└── lesson-9
├── README.md
├── index.html
├── multer-example-2
├── .env
├── .gitignore
├── app.js
├── controllers
│ ├── index.js
│ └── products.js
├── index.html
├── middlewares
│ ├── controllerWrapper.js
│ ├── index.js
│ └── upload.js
├── models
│ ├── index.js
│ └── product.js
├── package.json
└── routes
│ └── api
│ └── products.js
├── multer-example
├── .gitignore
├── app.js
├── frontend.html
├── index.html
├── package.json
├── public
│ └── products
│ │ └── 2085-1.png
└── temp
│ └── .gitkeep
└── slides
└── multer-work-schema.jpg
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/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 | [Структура NPM](./slides/npm-structure.jpg)
12 |
13 | [Последовательность шагов при создании проекта](./slides/project-create-steps.jpg)
14 |
--------------------------------------------------------------------------------
/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 start/server/bin.js:
--------------------------------------------------------------------------------
1 | console.log("Вложенный файл");
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | // const nodemon = require("nodemon");
2 | // const users = require("./users");
3 |
4 | // console.log(users);
5 |
6 | // const obj = require("./users");
7 |
8 | // console.log(obj);
9 |
10 | // const {clients} = require("./users");
11 |
12 | // console.log(clients);
13 |
14 | // const dateFunctions = require("./date");
15 | // const {getCurrentMonth} = require("./date");
16 | // const getCurrentMonth = require("./date/getCurrentMonth")
17 |
18 | // const {getCurrentMonth} = require("./date");
19 |
20 | // console.log(`Текущий месяц - ${getCurrentMonth()}`)
21 |
22 | const currentMonth = require("./date/getCurrentMonth")();
23 |
24 | console.log(`Текущий месяц - ${currentMonth}`);
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/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 | import users from "./users.mjs";
2 | import {clients} from "./users.mjs";
3 |
4 | console.log(users);
5 | console.log(clients);
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-mjs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-module-es6-mjs",
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-module-es6-mjs/users.mjs:
--------------------------------------------------------------------------------
1 | // const now = new Date();
2 | // console.log(now);
3 |
4 | export const admins = ["Alex", "Andrey", "VAsiliy"];
5 |
6 | export 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 |
3 | console.log(users);
4 |
5 |
6 |
--------------------------------------------------------------------------------
/lesson-1/node-module-es6-type/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-module-es6-type",
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 | export const admins = ["Alex", "Andrey", "VAsiliy"];
2 |
3 | export const clients = ["Anna", "Alina", "Tamara"];
4 |
5 | const users = {
6 | admins,
7 | clients
8 | };
9 |
10 | export default users;
11 |
--------------------------------------------------------------------------------
/lesson-1/npm-example/.gitignore:
--------------------------------------------------------------------------------
1 | package-lock.json
2 | node_modules/
--------------------------------------------------------------------------------
/lesson-1/npm-example/index.js:
--------------------------------------------------------------------------------
1 | console.log("Welcome, friends!");
--------------------------------------------------------------------------------
/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 | "dependencies": {
15 | "cors": "^2.8.5",
16 | "dotenv": "^10.0.0",
17 | "express": "^4.17.1",
18 | "mongoose": "^6.0.5",
19 | "nodemailer": "^6.6.3",
20 | "slick-slider": "^1.8.2"
21 | },
22 | "devDependencies": {
23 | "nodemon": "^2.0.12",
24 | "webpack": "^5.52.0"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lesson-1/slides/JS-V8-setTimeout-work.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-1/slides/JS-V8-setTimeout-work.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/JS-V8-work.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-1/slides/JS-V8-work.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/Nodejs-structure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-1/slides/Nodejs-structure.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/motivation-picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-1/slides/motivation-picture.png
--------------------------------------------------------------------------------
/lesson-1/slides/npm-structure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-1/slides/npm-structure.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/project-create-steps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-1/slides/project-create-steps.jpg
--------------------------------------------------------------------------------
/lesson-1/slides/reasons-learn-nodejs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-1/slides/reasons-learn-nodejs.jpg
--------------------------------------------------------------------------------
/lesson-10/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
14 |
24 |
25 |
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=mongodb+srv://Bogdan:pBje6ZbFRATcsTq@cluster0.fbkoo.mongodb.net/online_shop?retryWrites=true&w=majority
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/.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-10/pagination-mongoose/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .vcode
3 | node_modules/
4 |
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/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 | // api/product
18 | app.use((req, res) => {
19 | res.status(404).json({
20 | status: "error",
21 | message: 'Not found'
22 | })
23 | })
24 |
25 | app.use((err, req, res, next) => {
26 | const {status = 500, message = "Server error"} = err;
27 | res.status(status).json({ message })
28 | });
29 |
30 | module.exports = app
31 |
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/bin/server.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | require("dotenv").config();
3 |
4 | const app = require('../app');
5 |
6 | const {DB_HOST, PORT = 3000} = process.env;
7 |
8 | mongoose.connect(DB_HOST, {
9 | useNewUrlParser: true,
10 | useUnifiedTopology: true
11 | })
12 | .then(()=> app.listen(PORT))
13 | .catch(error => {
14 | console.log(error.message);
15 | process.exit(1);
16 | })
17 |
18 |
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 |
3 | module.exports = {
4 | products
5 | }
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = require("./sendSuccessRes");
2 |
3 | module.exports = {
4 | sendSuccessRes
5 | }
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/helpers/sendSuccessRes.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = (res, data, status = 200)=> {
2 | res.status(status).json({
3 | status: "success",
4 | code: status,
5 | data
6 | });
7 | }
8 |
9 | module.exports = sendSuccessRes
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/middlewares/controllerWrapper.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = (ctrl) => {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | }
6 | catch(error){
7 | next(error);
8 | }
9 | }
10 | };
11 |
12 | module.exports = controllerWrapper
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = require("./controllerWrapper");
2 | const validation = require("./validation");
3 |
4 | module.exports = {
5 | controllerWrapper,
6 | validation
7 | }
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema) => {
2 | return async(req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | res.status(400).json({
6 | status: "error",
7 | code: 400,
8 | message: error.message
9 | });
10 | return;
11 | }
12 | next();
13 | }
14 | };
15 |
16 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 |
3 | module.exports = {
4 | Product
5 | }
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/models/product.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 |
4 | const codeRegexp = /^[0-9]{9}$/; // newRegexp("^[0-9]{9}$")
5 |
6 | const productSchema = Schema({
7 | name: {
8 | type: String,
9 | required: [true, "Название товара обязательно"]
10 | },
11 | price: {
12 | type: Number,
13 | required: [true, "Цена товара обязательно"],
14 | min: 0.01
15 | },
16 | code: {
17 | type: String,
18 | unique: true,
19 | match: codeRegexp
20 | },
21 | active: {
22 | type: Boolean,
23 | default: true
24 | }
25 | }, {versionKey: false, timestamps: true});
26 |
27 | const joiSchema = Joi.object({
28 | name: Joi.string().required(),
29 | price:Joi.number().min(0.01).required(),
30 | code: Joi.string().pattern(codeRegexp).required(),
31 | active: Joi.boolean()
32 | });
33 |
34 | const updateActiveJoiSchema = Joi.object({
35 | active: Joi.boolean().required()
36 | });
37 |
38 | const Product = model("product", productSchema);
39 |
40 | module.exports = {
41 | joiSchema,
42 | updateActiveJoiSchema,
43 | Product
44 | };
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": ["node_modules", "model/contacts.json"]
3 | }
4 |
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template-2",
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.0",
17 | "joi": "^17.4.2",
18 | "mongoose": "^6.0.7",
19 | "morgan": "1.10.0"
20 | },
21 | "devDependencies": {
22 | "eslint": "^7.19.0",
23 | "eslint-config-standard": "^16.0.2",
24 | "eslint-plugin-import": "^2.22.1",
25 | "eslint-plugin-node": "^11.1.0",
26 | "eslint-plugin-promise": "^4.2.1",
27 | "nodemon": "2.0.7"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lesson-10/pagination-mongoose/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-10/pagination-mongoose/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {joiSchema, updateActiveJoiSchema} = require("../../models/product");
4 | const {controllerWrapper, validation} = require("../../middlewares");
5 | const {products: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | /*
10 | 1. Получить все товары.
11 | 2. Получить один товар по id.
12 | 3. Добавить товар.
13 | 4. Обновить товар по id.
14 | 5. Удалить товар по id.
15 | */
16 |
17 | router.get("/", controllerWrapper(ctrl.getAll));
18 |
19 | router.get("/:id", controllerWrapper(ctrl.getById));
20 |
21 | router.post("/", validation(joiSchema), controllerWrapper(ctrl.add));
22 |
23 | router.put("/:id", validation(joiSchema), controllerWrapper(ctrl.updateById));
24 |
25 | router.patch("/:id/active", validation(updateActiveJoiSchema), controllerWrapper(ctrl.updateActive));
26 |
27 | router.patch("/:id/code", validation(updateActiveJoiSchema), controllerWrapper(ctrl.updateCode));
28 |
29 | router.delete("/:id", controllerWrapper(ctrl.removeById));
30 |
31 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-10/slides/QA-work.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-10/slides/QA-work.jpg
--------------------------------------------------------------------------------
/lesson-10/slides/Test-driven-development-ru.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-10/slides/Test-driven-development-ru.png
--------------------------------------------------------------------------------
/lesson-10/slides/developing-with-test.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-10/slides/developing-with-test.jpg
--------------------------------------------------------------------------------
/lesson-10/slides/piramida.drawio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-10/slides/piramida.drawio.png
--------------------------------------------------------------------------------
/lesson-10/slides/test-first-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-10/slides/test-first-schema.jpg
--------------------------------------------------------------------------------
/lesson-10/slides/test-instruments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-10/slides/test-instruments.png
--------------------------------------------------------------------------------
/lesson-10/slides/test-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-10/slides/test-schema.jpg
--------------------------------------------------------------------------------
/lesson-10/test-function-example/app.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-10/test-function-example/app.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('Год должен быть обязательно указан');
4 | }
5 | if(typeof year !== "number"){
6 | throw new Error('Год должен быть number');
7 | }
8 | if(year < 42){
9 | throw new Error('Год не может быть меньше 42');
10 | }
11 | if(!Number.isInteger(year)){
12 | throw new Error('Год должен быть целым числом');
13 | }
14 | const date = new Date(year, 2, 0);
15 | const days = date.getDate();
16 |
17 | return (days === 29);
18 | };
19 |
20 | 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.2.4",
16 | "nodemon": "^2.0.13"
17 | },
18 | "dependencies": {}
19 | }
20 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/.env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | SECRET_KEY=
--------------------------------------------------------------------------------
/lesson-11/auth-example/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-11/auth-example/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const cors = require("cors");
3 | const mongoose = require("mongoose");
4 | require("dotenv").config();
5 |
6 | const authRouter = require("./routes/api/auth");
7 | const ordersRouter = require("./routes/api/orders");
8 |
9 | const app = express();
10 |
11 | app.use(cors());
12 | app.use(express.json());
13 |
14 | app.use("/api/auth", authRouter);
15 | app.use("/api/orders", ordersRouter);
16 |
17 | app.use((req, res)=>{
18 | res.status(404).json({
19 | status: "error",
20 | code: 404,
21 | message: "Not Found"
22 | })
23 | });
24 |
25 | app.use((error, req, res, next)=>{
26 | const {status = 500, message = "Server error"} = error;
27 | res.status(status).json({
28 | status: "error",
29 | code: status,
30 | message
31 | })
32 | });
33 |
34 | const {DB_HOST, PORT = 3000} = process.env;
35 | // const {DB_USER, DB_USER_PASS, DB_NAME} = process.env;
36 | // const DB_HOST = `mongodb+srv://${DB_USER}:${DB_USER_PASS}@cluster0.fbkoo.mongodb.net/${DB_NAME}?retryWrites=true&w=majority`
37 |
38 | mongoose.connect(DB_HOST, {
39 | useNewUrlParser: true,
40 | useUnifiedTopology: true
41 | }).then(()=> app.listen(PORT))
42 | .catch(error => {
43 | console.log(error.message);
44 | process.exit(1);
45 | });
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/auth/index.js:
--------------------------------------------------------------------------------
1 | const register = require("./register");
2 | const verify = require("./verify");
3 | const login = require("./login");
4 | const logout = require("./logout");
5 |
6 | module.exports = {
7 | register,
8 | verify,
9 | login,
10 | logout
11 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/auth/login.js:
--------------------------------------------------------------------------------
1 | const {BadRequest} = require("http-errors");
2 | const jwt = require("jsonwebtoken");
3 |
4 | const {User} = require("../../models");
5 |
6 | const {SECRET_KEY} = process.env;
7 |
8 | const login = async(req, res)=>{
9 | const {email, password} = req.body;
10 | const user = await User.findOne({email}, "_id email password verify");
11 | if(!user || !user.comparePassword(password)){
12 | throw new BadRequest("Invalid email, password");
13 | }
14 |
15 | if(!user.verify){
16 | throw new BadRequest("Email not verify");
17 | }
18 |
19 | const {_id} = user;
20 | const payload = {
21 | _id
22 | }
23 | const token = jwt.sign(payload, SECRET_KEY);
24 |
25 | await User.findByIdAndUpdate(_id, {token});
26 | res.json({
27 | status: "success",
28 | code: 200,
29 | data: {
30 | token
31 | }
32 | })
33 | };
34 |
35 | 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.json({
7 | status: "success",
8 | code: 200,
9 | message: "Success logout"
10 | });
11 | };
12 |
13 | 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 {User} = require("../../models");
5 |
6 | const {sendEmail}= require("../../helpers");
7 |
8 | const register = async(req, res)=>{
9 | const {email, password} = req.body;
10 | const user = await User.findOne({email});
11 | if(user){
12 | throw new Conflict("Already register");
13 | }
14 | const verifyToken = nanoid();
15 | const newUser = new User({
16 | email,
17 | verifyToken
18 | });
19 | newUser.setPassword(password);
20 | await newUser.save();
21 |
22 | const data = {
23 | to: email,
24 | subject: "Подтверждения регистрации на сайте",
25 | html: `
26 | Подтвердить почту
27 | `
28 | }
29 |
30 | await sendEmail(data);
31 | res.status(201).json({
32 | status: "success",
33 | code: 201,
34 | message: "Success register",
35 | data: {
36 | verifyToken
37 | }
38 | });
39 | };
40 |
41 | module.exports = register;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/auth/verify.js:
--------------------------------------------------------------------------------
1 | const {NotFound} = require("http-errors");
2 |
3 | const {User} = require("../../models");
4 |
5 | const verify = async(req, res)=> {
6 | const {verifyToken} = req.params;
7 | const user = await User.findOne({verifyToken});
8 | if(!user){
9 | throw new NotFound("Verify error");
10 | }
11 | await User.findByIdAndUpdate(user._id, {verifyToken: null, verify: true});
12 | res.json({
13 | status: "success",
14 | code: 200,
15 | message: "Email verify success"
16 | })
17 | };
18 |
19 | module.exports = verify;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/index.js:
--------------------------------------------------------------------------------
1 | const auth = require("./auth");
2 | const orders = require("./orders");
3 |
4 | module.exports = {
5 | auth,
6 | orders
7 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/orders/add.js:
--------------------------------------------------------------------------------
1 | const {Order} = require("../../models");
2 |
3 | const add = async(req, res)=> {
4 | const newOrder = {...req.body, owner: req.user._id};
5 | const result = await Order.create(newOrder);
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/orders/getAll.js:
--------------------------------------------------------------------------------
1 | const {Order} = require("../../models");
2 |
3 | const getAll = async(req, res)=>{
4 | const result = await Order.find({}, "_id content owner");
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | result
10 | }
11 | })
12 | };
13 |
14 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/orders/getAllByUser.js:
--------------------------------------------------------------------------------
1 | const {Order} = require("../../models");
2 |
3 | const getAllByUser = async(req, res)=>{
4 | const {_id} = req.user;
5 | const result = await Order.find({owner: _id}, "_id content owner");
6 | res.json({
7 | status: "success",
8 | code: 200,
9 | data: {
10 | result
11 | }
12 | })
13 | };
14 |
15 | module.exports = getAllByUser;
--------------------------------------------------------------------------------
/lesson-11/auth-example/controllers/orders/index.js:
--------------------------------------------------------------------------------
1 | const add = require("./add");
2 | const getAllByUser = require("./getAllByUser");
3 | const getAll = require("./getAll");
4 |
5 | module.exports = {
6 | add,
7 | getAllByUser,
8 | getAll
9 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = require("./sendSuccessRes");
2 | const sendEmail = require("./sendEmail");
3 |
4 | module.exports = {
5 | sendSuccessRes,
6 | sendEmail
7 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/helpers/sendEmail.js:
--------------------------------------------------------------------------------
1 | const nodemailer = require("nodemailer");
2 |
3 | const {EMAIL_PASSWORD} = process.env;
4 |
5 | const nodemailerConfig = {
6 | host: "mail.adm.tools",
7 | port: 465,
8 | secure: true,
9 | auth: {
10 | user: "info@ntonyartist.com",
11 | pass: EMAIL_PASSWORD
12 | }
13 | };
14 |
15 | const transporter = nodemailer.createTransport(nodemailerConfig);
16 |
17 | const sendEmail = async(data)=> {
18 | const email = {
19 | ...data,
20 | from: "info@ntonyartist.com",
21 | }
22 | await transporter.sendMail(email);
23 | };
24 |
25 | module.exports = sendEmail;
26 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/helpers/sendSuccessRes.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = (res, data, status = 200)=> {
2 | res.status(status).json({
3 | status: "success",
4 | code: status,
5 | data
6 | });
7 | }
8 |
9 | module.exports = sendSuccessRes
--------------------------------------------------------------------------------
/lesson-11/auth-example/middlewares/authenticate.js:
--------------------------------------------------------------------------------
1 | const jwt = require("jsonwebtoken");
2 |
3 | const {User} = require("../models");
4 |
5 | const {SECRET_KEY} = process.env;
6 |
7 | const authenticate = async(req, res, next) => {
8 | const {authorization} = req.headers;
9 | if(!authorization){
10 | res.status(401).json({
11 | status: "error",
12 | code: 401,
13 | message: "Not authorized"
14 | });
15 | return;
16 | }
17 |
18 | const [bearer, token] = authorization.split(" ");
19 | if(bearer !== "Bearer"){
20 | res.status(401).json({
21 | status: "error",
22 | code: 401,
23 | message: "Not authorized"
24 | });
25 | return;
26 | }
27 |
28 | try {
29 | const {_id} = jwt.verify(token, SECRET_KEY);
30 | const user = await User.findById(_id);
31 | if(!user.token){
32 | res.status(401).json({
33 | status: "error",
34 | code: 401,
35 | message: "Not authorized"
36 | });
37 | return;
38 | }
39 | req.user = user;
40 | next();
41 | }
42 | catch (error) {
43 | res.status(401).json({
44 | status: "error",
45 | code: 401,
46 | message: "Not authorized"
47 | });
48 | return;
49 | }
50 | };
51 |
52 | module.exports = authenticate;
--------------------------------------------------------------------------------
/lesson-11/auth-example/middlewares/controllerWrapper.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = (ctrl) => {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | }
6 | catch(error){
7 | next(error);
8 | }
9 | }
10 | };
11 |
12 | module.exports = controllerWrapper
--------------------------------------------------------------------------------
/lesson-11/auth-example/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = require("./controllerWrapper");
2 | const validation = require("./validation");
3 | const authenticate = require("./authenticate");
4 |
5 | module.exports = {
6 | controllerWrapper,
7 | validation,
8 | authenticate
9 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema) => {
2 | return async(req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | res.status(400).json({
6 | status: "error",
7 | code: 400,
8 | message: error.message
9 | });
10 | return;
11 | }
12 | next();
13 | }
14 | };
15 |
16 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-11/auth-example/models/index.js:
--------------------------------------------------------------------------------
1 | const {User} = require("./user");
2 | const {Order} = require("./order");
3 |
4 | module.exports = {
5 | User,
6 | Order
7 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/models/order.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 |
4 | const orderSchema = Schema({
5 | content: {
6 | type: String,
7 | required: true
8 | },
9 | owner: {
10 | type: Schema.Types.ObjectId,
11 | ref: "user"
12 | }
13 | }, {versionKey: false, timestamps: true});
14 |
15 | const joiSchema = Joi.object({
16 | content: Joi.string().required()
17 | });
18 |
19 | const Order = model("order", orderSchema);
20 |
21 | module.exports = {
22 | Order,
23 | joiSchema
24 | }
--------------------------------------------------------------------------------
/lesson-11/auth-example/models/user.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 | const bcrypt = require("bcryptjs");
4 | const jwt = require("jsonwebtoken");
5 |
6 | const userSchema = Schema({
7 | email: {
8 | type: String,
9 | required: true,
10 | unique: true
11 | },
12 | password: {
13 | type: String,
14 | required: true,
15 | minlength: 6
16 | },
17 | token: {
18 | type: String,
19 | default: null
20 | },
21 | verify: {
22 | type: Boolean,
23 | default: false,
24 | },
25 | verifyToken: {
26 | type: String,
27 | required: [true, 'Verify token is required'],
28 | },
29 | }, {versionKey: false, timestamps: true});
30 |
31 | userSchema.methods.setPassword = function(password){
32 | this.password = bcrypt.hashSync(password, bcrypt.genSaltSync(10))
33 | }
34 |
35 | userSchema.methods.comparePassword = function(password){
36 | return bcrypt.compareSync(password, this.password);
37 | }
38 |
39 | const {SECRET_KEY} = process.env;
40 |
41 | userSchema.methods.createToken = function(){
42 | const payload = {
43 | _id: this._id
44 | };
45 | return jwt.sign(payload, SECRET_KEY)
46 | }
47 |
48 | const joiSchema = Joi.object({
49 | email: Joi.string().required(),
50 | password: Joi.string().min(6).required()
51 | });
52 |
53 | const User = model("user", userSchema);
54 |
55 | module.exports = {
56 | User,
57 | joiSchema
58 | }
59 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auth-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 | "cors": "^2.8.5",
20 | "dotenv": "^10.0.0",
21 | "express": "^4.17.1",
22 | "http-errors": "^1.8.0",
23 | "joi": "^17.4.2",
24 | "jsonwebtoken": "^8.5.1",
25 | "mongoose": "^6.0.8",
26 | "nanoid": "^3.1.29",
27 | "nodemailer": "^6.7.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lesson-11/auth-example/routes/api/auth.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {joiSchema} = require("../../models/user");
4 | const {controllerWrapper, validation, authenticate} = require("../../middlewares");
5 | const {auth: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | // api/auth/register
10 | router.post("/register", validation(joiSchema), controllerWrapper(ctrl.register));
11 | // router.post("/signup")
12 |
13 | router.get("/verify/:verifyToken", controllerWrapper(ctrl.verify));
14 |
15 | router.post("/login", validation(joiSchema), controllerWrapper(ctrl.login));
16 | // router.post("/signin")
17 |
18 | router.get("/logout", authenticate, controllerWrapper(ctrl.logout));
19 | // router.get("/signuot")
20 |
21 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-11/auth-example/routes/api/orders.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {joiSchema} = require("../../models/order");
4 | const {controllerWrapper, validation, authenticate} = require("../../middlewares");
5 | const {orders: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", authenticate, controllerWrapper(ctrl.getAllByUser));
10 |
11 | router.get("/all", controllerWrapper(ctrl.getAll));
12 |
13 | router.post("/", authenticate, validation(joiSchema), controllerWrapper(ctrl.add));
14 |
15 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-11/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-11/nodemailer-meta-ua/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-11/nodemailer-meta-ua/app.js:
--------------------------------------------------------------------------------
1 | const nodemailer = require("nodemailer");
2 | require("dotenv").config();
3 |
4 | const {EMAIL_PASSWORD} = process.env;
5 |
6 | const nodemailerConfig = {
7 | host: "smtp.meta.ua",
8 | port: 465,
9 | secure: true,
10 | auth: {
11 | user: "bogdan.lyamzin.d@meta.ua",
12 | pass: EMAIL_PASSWORD
13 | }
14 | };
15 |
16 | const transporter = nodemailer.createTransport(nodemailerConfig);
17 |
18 | const email = {
19 | to: "bogdan.lyamzin.d@gmail.com",
20 | from: "bogdan.lyamzin.d@meta.ua",
21 | subject: "Новая заявка с сайта",
22 | html: `Email клиента: bogdan.lyamzin.d@gmail.com
23 | Телефон клиента: 8-067 555-55-55
`
24 | };
25 |
26 | transporter.sendMail(email)
27 | .then(()=> console.log("Email success send"))
28 | .catch(error => console.log(error.message))
--------------------------------------------------------------------------------
/lesson-11/nodemailer-meta-ua/helpers/sendEmail.js:
--------------------------------------------------------------------------------
1 | const nodemailer = require("nodemailer");
2 |
3 | const {EMAIL_PASSWORD} = process.env;
4 |
5 | const nodemailerConfig = {
6 | host: "smtp.meta.ua",
7 | port: 465,
8 | secure: true,
9 | auth: {
10 | user: "bogdan.lyamzin.d@meta.ua",
11 | pass: EMAIL_PASSWORD
12 | }
13 | };
14 |
15 | const transporter = nodemailer.createTransport(nodemailerConfig);
16 |
17 | const sendEmail = async(data)=> {
18 | const email = {
19 | ...data,
20 | from: "bogdan.lyamzin.d@meta.ua",
21 | }
22 | await transporter.sendMail(email);
23 | };
24 |
25 | module.exports = sendEmail;
26 |
--------------------------------------------------------------------------------
/lesson-11/nodemailer-meta-ua/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.6.5"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/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 {EMAIL_PASSWORD} = process.env;
5 |
6 | const nodemailerConfig = {
7 | host: "mail.adm.tools",
8 | port: 465,
9 | secure: true,
10 | auth: {
11 | user: "info@ntonyartist.com",
12 | pass: EMAIL_PASSWORD
13 | }
14 | };
15 |
16 | const transporter = nodemailer.createTransport(nodemailerConfig);
17 |
18 | const email = {
19 | to: "bogdan.lyamzin.d@gmail.com",
20 | from: "info@ntonyartist.com",
21 | subject: "Новая заявка с сайта",
22 | html: `Email клиента: bogdan.lyamzin.d@gmail.com
23 | Телефон клиента: 8-067 555-55-55
`
24 | };
25 |
26 | transporter.sendMail(email)
27 | .then(()=> console.log("Email success send"))
28 | .catch(error => console.log(error.message))
--------------------------------------------------------------------------------
/lesson-11/nodemailer/helpers/sendEmail.js:
--------------------------------------------------------------------------------
1 | const nodemailer = require("nodemailer");
2 |
3 | const {EMAIL_PASSWORD} = process.env;
4 |
5 | const nodemailerConfig = {
6 | host: "mail.adm.tools",
7 | port: 465,
8 | secure: true,
9 | auth: {
10 | user: "info@ntonyartist.com",
11 | pass: EMAIL_PASSWORD
12 | }
13 | };
14 |
15 | const transporter = nodemailer.createTransport(nodemailerConfig);
16 |
17 | const sendEmail = async(data)=> {
18 | const email = {
19 | ...data,
20 | from: "bogdan.lyamzin.d@meta.ua",
21 | }
22 | await transporter.sendMail(email);
23 | };
24 |
25 | module.exports = sendEmail;
26 |
--------------------------------------------------------------------------------
/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.6.5"
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_KEY} = process.env;
5 |
6 | sgMail.setApiKey(SENDGRID_KEY);
7 |
8 | const email = {
9 | to: "tokkagudru@vusra.com",
10 | from: "bogdan.lyamzin.d@gmail.com",
11 | subject: "Новая заявка с сайта",
12 | html: `Email клиента: bogdan.lyamzin.d@gmail.com
13 | Телефон клиента: 8-067 555-55-55
`
14 | };
15 |
16 | sgMail.send(email)
17 | .then(()=> console.log("Email success send"))
18 | .catch(error => console.log(error.message))
--------------------------------------------------------------------------------
/lesson-11/sendgrid/helpers/sendEmail.js:
--------------------------------------------------------------------------------
1 | const sgMail = require("@sendgrid/mail");
2 | require("dotenv").config();
3 |
4 | const {SENDGRID_KEY} = process.env;
5 |
6 | sgMail.setApiKey(SENDGRID_KEY);
7 |
8 | const sendEmail = async(data)=> {
9 | const email = {...data, from: "bogdan.lyamzin.d@gmail.com"}
10 | await sgMail.send(email);
11 | };
12 |
13 | module.exports = sendEmail;
14 |
15 |
--------------------------------------------------------------------------------
/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.4.7",
19 | "dotenv": "^10.0.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lesson-11/slides/mailing-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-11/slides/mailing-schema.jpg
--------------------------------------------------------------------------------
/lesson-11/slides/nodemailer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-11/slides/nodemailer.jpg
--------------------------------------------------------------------------------
/lesson-11/slides/sendgrid-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/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/mongodb-project/.env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | yarn.log
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-12/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 | app.use((_, res)=>{
16 | res.status(404).json({
17 | status: "error",
18 | code: 404,
19 | message: "Not found"
20 | });
21 | });
22 |
23 | app.use((error, _, res, __)=> {
24 | const {status = 500, message = "Server error"} = error;
25 | res.status(status).json({
26 | status: "error",
27 | code: status,
28 | message
29 | })
30 | });
31 |
32 | const {DB_HOST, PORT = 3000} = process.env;
33 |
34 | mongoose.connect(DB_HOST, {
35 | useNewUrlParser: true,
36 | useUnifiedTopology: true
37 | }).then(()=>{
38 | app.listen(PORT);
39 | })
40 | .catch(error => {
41 | console.log(error.message);
42 | process.exit(1);
43 | });
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 |
3 | module.exports = {
4 | products
5 | }
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendSuccessReq = require("./sendSuccessReq");
2 |
3 | module.exports = {
4 | sendSuccessReq
5 | }
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/helpers/sendSuccessReq.js:
--------------------------------------------------------------------------------
1 | const sendSuccessReq = (res, data, status = 200) => {
2 | res.status(status).json({
3 | status: "success",
4 | code: status,
5 | data
6 | });
7 | };
8 |
9 | module.exports = sendSuccessReq;
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/middlewares/controllerWrapper.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | }
6 | catch (error) {
7 | next(error);
8 | }
9 | }
10 | }
11 |
12 | module.exports = controllerWrapper;
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const controllerWrapper = require("./controllerWrapper");
3 |
4 | module.exports = {
5 | validation,
6 | controllerWrapper
7 | }
--------------------------------------------------------------------------------
/lesson-12/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 | return res.status(400).json({
6 | status: "error",
7 | code: 400,
8 | message: error.message
9 | });
10 | }
11 | next();
12 | }
13 | };
14 |
15 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/models/category.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-12/mongodb-project/models/category.js
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 |
3 | module.exports = {
4 | Product
5 | }
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/models/product.js:
--------------------------------------------------------------------------------
1 | const Joi = require("joi");
2 | const {Schema, model} = require("mongoose");
3 |
4 | const codeRegexp = /^[0-9]{5}$/;
5 |
6 | const productSchema = Schema({
7 | name: {
8 | type: String,
9 | required: [true, "Имя товара обязательно"]
10 | },
11 | description: {
12 | type: String,
13 | required: [true, "Описание товара обязательно"],
14 | minlength: 2
15 | },
16 | price: {
17 | type: Number,
18 | required: [true, "Цена товара обязательна"],
19 | min: 0.01
20 | },
21 | isActive: {
22 | type: Boolean,
23 | default: true
24 | },
25 | // status: stock, priceLow, basic
26 | status: {
27 | type: String,
28 | enum: ["stock", "priceLow", "basic"],
29 | default: "basic"
30 | },
31 | code: {
32 | type: String,
33 | match: [codeRegexp, "Код - это строка из 5 чисел"],
34 | required: [true, "Код должен быть обязательно указан"],
35 | unique: true
36 | }
37 | }, {versionKey: false, timestamps: true});
38 |
39 | const joiSchema = Joi.object({
40 | name: Joi.string().required(),
41 | description: Joi.string().required(),
42 | price: Joi.number().min(0.01).required(),
43 | isActive: Joi.boolean(),
44 | status: Joi.string(),
45 | code: Joi.string().pattern(codeRegexp)
46 | });
47 |
48 | const Product = model("product", productSchema);
49 |
50 | module.exports = {Product, joiSchema};
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mongodb-project-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 | "cors": "^2.8.5",
19 | "dotenv": "^10.0.0",
20 | "express": "^4.17.1",
21 | "http-errors": "^1.8.0",
22 | "joi": "^17.4.2",
23 | "mongoose": "^6.0.6"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lesson-12/mongodb-project/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {validation, controllerWrapper} = require("../../middlewares");
4 | const {joiSchema} = require("../../models/product");
5 | const {products: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", controllerWrapper(ctrl.getAll));
10 |
11 | router.get("/:id", controllerWrapper(ctrl.getById));
12 |
13 | router.post("/", validation(joiSchema), controllerWrapper(ctrl.add));
14 |
15 | router.put("/:id", validation(joiSchema), controllerWrapper(ctrl.updateById));
16 |
17 | router.patch("/:id", controllerWrapper(ctrl.updateStatus));
18 |
19 | router.delete("/:id", controllerWrapper(ctrl.removeById));
20 |
21 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-12/slides/different-between-websockets-and-http.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-12/slides/different-between-websockets-and-http.jpg
--------------------------------------------------------------------------------
/lesson-12/slides/web-socket-client-server-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-12/slides/web-socket-client-server-schema.jpg
--------------------------------------------------------------------------------
/lesson-12/slides/web-socket-personal-client-object.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-12/slides/web-socket-personal-client-object.jpg
--------------------------------------------------------------------------------
/lesson-12/slides/websocket-main-features.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-12/slides/websocket-main-features.jpg
--------------------------------------------------------------------------------
/lesson-12/slides/websocket-projects.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/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", (message)=> {
11 | users.forEach(user => {
12 | if(user !== newUser){
13 | user.send(message);
14 | }
15 | });
16 | })
17 | });
--------------------------------------------------------------------------------
/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": "^7.5.1"
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 | newClient.send("Добро пожаловать в компанию!");
10 |
11 | newClient.on("message", (message)=> {
12 | console.log(message);
13 | });
14 |
15 | clients.forEach(client => {
16 | if(client !== newClient){
17 | client.send("У нас новый член команды")
18 | }
19 | });
20 | // console.log("Новое подключение с фронтенда")
21 | });
--------------------------------------------------------------------------------
/lesson-12/websocket-basic-example/frontend.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
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": "^7.5.1"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-13/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/.env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | yarn.log
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node
2 |
3 | WORKDIR /app
4 |
5 | COPY . .
6 |
7 | RUN npm install
8 |
9 | EXPOSE 3000
10 |
11 | CMD ["node", "app"]
12 |
13 |
--------------------------------------------------------------------------------
/lesson-13/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 | app.use((_, res)=>{
16 | res.status(404).json({
17 | status: "error",
18 | code: 404,
19 | message: "Not found"
20 | });
21 | });
22 |
23 | app.use((error, _, res, __)=> {
24 | const {status = 500, message = "Server error"} = error;
25 | res.status(status).json({
26 | status: "error",
27 | code: status,
28 | message
29 | })
30 | });
31 |
32 | const {DB_HOST, PORT = 3000} = process.env;
33 |
34 | mongoose.connect(DB_HOST, {
35 | useNewUrlParser: true,
36 | useUnifiedTopology: true
37 | }).then(()=>{
38 | app.listen(PORT);
39 | })
40 | .catch(error => {
41 | console.log(error.message);
42 | process.exit(1);
43 | });
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 |
3 | module.exports = {
4 | products
5 | }
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendSuccessReq = require("./sendSuccessReq");
2 |
3 | module.exports = {
4 | sendSuccessReq
5 | }
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/helpers/sendSuccessReq.js:
--------------------------------------------------------------------------------
1 | const sendSuccessReq = (res, data, status = 200) => {
2 | res.status(status).json({
3 | status: "success",
4 | code: status,
5 | data
6 | });
7 | };
8 |
9 | module.exports = sendSuccessReq;
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/middlewares/controllerWrapper.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | }
6 | catch (error) {
7 | next(error);
8 | }
9 | }
10 | }
11 |
12 | module.exports = controllerWrapper;
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const validation = require("./validation");
2 | const controllerWrapper = require("./controllerWrapper");
3 |
4 | module.exports = {
5 | validation,
6 | controllerWrapper
7 | }
--------------------------------------------------------------------------------
/lesson-13/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 | return res.status(400).json({
6 | status: "error",
7 | code: 400,
8 | message: error.message
9 | });
10 | }
11 | next();
12 | }
13 | };
14 |
15 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/models/category.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/mongodb-project/models/category.js
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 |
3 | module.exports = {
4 | Product
5 | }
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/models/product.js:
--------------------------------------------------------------------------------
1 | const Joi = require("joi");
2 | const {Schema, model} = require("mongoose");
3 |
4 | const codeRegexp = /^[0-9]{5}$/;
5 |
6 | const productSchema = Schema({
7 | name: {
8 | type: String,
9 | required: [true, "Имя товара обязательно"]
10 | },
11 | description: {
12 | type: String,
13 | required: [true, "Описание товара обязательно"],
14 | minlength: 2
15 | },
16 | price: {
17 | type: Number,
18 | required: [true, "Цена товара обязательна"],
19 | min: 0.01
20 | },
21 | isActive: {
22 | type: Boolean,
23 | default: true
24 | },
25 | // status: stock, priceLow, basic
26 | status: {
27 | type: String,
28 | enum: ["stock", "priceLow", "basic"],
29 | default: "basic"
30 | },
31 | code: {
32 | type: String,
33 | match: [codeRegexp, "Код - это строка из 5 чисел"],
34 | required: [true, "Код должен быть обязательно указан"],
35 | unique: true
36 | }
37 | }, {versionKey: false, timestamps: true});
38 |
39 | const joiSchema = Joi.object({
40 | name: Joi.string().required(),
41 | description: Joi.string().required(),
42 | price: Joi.number().min(0.01).required(),
43 | isActive: Joi.boolean(),
44 | status: Joi.string(),
45 | code: Joi.string().pattern(codeRegexp)
46 | });
47 |
48 | const Product = model("product", productSchema);
49 |
50 | module.exports = {Product, joiSchema};
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mongodb-project-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 | "cors": "^2.8.5",
19 | "dotenv": "^10.0.0",
20 | "express": "^4.17.1",
21 | "http-errors": "^1.8.0",
22 | "joi": "^17.4.2",
23 | "mongoose": "^6.0.6"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lesson-13/mongodb-project/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {validation, controllerWrapper} = require("../../middlewares");
4 | const {joiSchema} = require("../../models/product");
5 | const {products: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", controllerWrapper(ctrl.getAll));
10 |
11 | router.get("/:id", controllerWrapper(ctrl.getById));
12 |
13 | router.post("/", validation(joiSchema), controllerWrapper(ctrl.add));
14 |
15 | router.put("/:id", validation(joiSchema), controllerWrapper(ctrl.updateById));
16 |
17 | router.patch("/:id", controllerWrapper(ctrl.updateStatus));
18 |
19 | router.delete("/:id", controllerWrapper(ctrl.removeById));
20 |
21 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-13/php-project/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php
2 |
3 | WORKDIR /app
4 |
5 | COPY . .
6 |
7 | CMD ["php", "index.php"]
--------------------------------------------------------------------------------
/lesson-13/php-project/index.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lesson-13/slides/05efe6379b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/05efe6379b.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/09bf934cc1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/09bf934cc1.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/0aac227e26.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/0aac227e26.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/1e8868fd69.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/1e8868fd69.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/206360c857.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/206360c857.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/35e71d29de.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/35e71d29de.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/505114e755.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/505114e755.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/6423d760db.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/6423d760db.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/7155b6b76d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/7155b6b76d.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/76a678f8e7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/76a678f8e7.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/83fc82807e.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/83fc82807e.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/9b35bf3889.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/9b35bf3889.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/a7cc498c22.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/a7cc498c22.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/b78636dee9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/b78636dee9.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/ca8261d313.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/ca8261d313.jpg
--------------------------------------------------------------------------------
/lesson-13/slides/daf8a4de74.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-13/slides/daf8a4de74.jpg
--------------------------------------------------------------------------------
/lesson-2/README.md:
--------------------------------------------------------------------------------
1 | [Где используется работа с файлами в Node.js](./slides/work-with-files-examples.png)
2 |
--------------------------------------------------------------------------------
/lesson-2/file-reader/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-2/file-reader/files/read.txt:
--------------------------------------------------------------------------------
1 | Мишка очень любит мед.
--------------------------------------------------------------------------------
/lesson-2/file-reader/index.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 |
3 | fs.readFile("files/read.txt", "utf-8", (error, data)=>{
4 | if(error){
5 | throw error;
6 | }
7 | console.log(data);
8 | // const text = data.toString();
9 | // console.log(text);
10 | // console.log(error);
11 | // console.log(data);
12 | });
--------------------------------------------------------------------------------
/lesson-2/file-reader/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "file-reader",
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-2/file-reader/promise-index.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | // const fs = require("fs").promises;
3 |
4 | // (async()=>{
5 | // try {
6 | // const data = await fs.readFile("files/read.txt", "utf-8");
7 | // console.log(data);
8 | // }
9 | // catch(error){
10 | // console.log(error);
11 | // }
12 | // })();
13 |
14 | const readFile = async(filePath) => {
15 | try {
16 | const data = await fs.readFile(filePath, "utf-8");
17 | return data;
18 | }
19 | catch(error){
20 | throw error;
21 | }
22 | };
23 |
24 | readFile("files/read.txt")
25 | .then(data => console.log(data))
26 | .catch(error => console.log(error));
27 |
28 | // fs.readFile("files/read.txt", "utf-8")
29 | // .then(data => console.log(data))
30 | // .catch(error => console.log(error));
--------------------------------------------------------------------------------
/lesson-2/slides/work-with-files-examples.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/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 |
3 | const fileOperation = async(filePath, type = "read", data = "") => {
4 | switch(type){
5 | case "read":
6 | return await fs.readFile(filePath, "utf-8");
7 | case "add":
8 | await fs.appendFile(filePath, data);
9 | return await fs.readFile(filePath, "utf-8");
10 | case "rewrite":
11 | await fs.writeFile(filePath, data);
12 | return await fs.readFile(filePath, "utf-8");
13 | case "remove":
14 | return await fs.unlink(filePath);
15 | default:
16 | return "Unknown command";
17 | }
18 | };
19 |
20 | // fileOperation("file.txt")
21 | // .then(data => console.log(data))
22 | // .catch(error => console.log(error));
23 |
24 | // fileOperation("file.txt", "add", "\nНичего я не говорил")
25 | // .then(data => console.log(data))
26 | // .catch(error => console.log(error));
27 |
28 | fileOperation("file.txt", "rewrite", "Ничего я не говорил")
29 | .then(data => console.log(data))
30 | .catch(error => console.log(error));
31 |
32 | // fileOperation("file.txt", "remove")
33 | // .then(_ => console.log("Success remove"))
34 | // .catch(error => console.log(error));
35 |
36 |
--------------------------------------------------------------------------------
/lesson-2/work-with-files/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "work-with-files",
3 | "version": "1.0.0",
4 | "main": "app.js",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1",
7 | "start": "node app",
8 | "start:dev": "nodemon app"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "nodemon": "^2.0.12"
15 | },
16 | "description": ""
17 | }
18 |
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "work-with-json-files",
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 | "uuid": "^8.3.2"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/products/add.js:
--------------------------------------------------------------------------------
1 | const {v4} = require("uuid");
2 |
3 | const updateProducts = require("./updateProducts");
4 | const getAll = require("./getAll");
5 |
6 |
7 |
8 | module.exports = add;
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/products/getAll.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-2/work-with-json-files-example-2/products/getAll.js
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/products/getById.js:
--------------------------------------------------------------------------------
1 | const getAll = require("./getAll");
2 |
3 |
4 |
5 | module.exports = getById;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/products/index.js:
--------------------------------------------------------------------------------
1 | const {v4} = require("uuid");
2 | const fs = require("fs/promises");
3 | const path = require("path");
4 |
5 | const products = require("./products.json");
6 |
7 | const filePath = path.join(__dirname, "products.json");
8 |
9 | const updateProducts = async(newProducts) => {
10 | await fs.writeFile(filePath, JSON.stringify(newProducts));
11 | };
12 |
13 | const getAll = async() => products;
14 |
15 | const getById = async(id) => {
16 | const product = products.find(item => item.id === id);
17 | if(!product) {
18 | return null;
19 | }
20 | return product;
21 | }
22 |
23 | const add = async(data) => {
24 | const newProduct = {...data, id: v4()};
25 | products.push(newProduct);
26 | await updateProducts(products);
27 | return newProduct;
28 | }
29 |
30 | const updateById = async(id, data) => {
31 | const idx = products.findIndex(item => item.id === id);
32 | if(idx === -1){
33 | return null;
34 | }
35 | const updateProduct = {...products[idx], ...data};
36 | products[idx] = updateProduct;
37 | await updateProducts(products);
38 | return updateProduct;
39 | };
40 |
41 |
42 | module.exports = {
43 | getAll,
44 | getById,
45 | add,
46 | updateById,
47 | removeById
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/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": 4,
36 | "location": "Home baking"
37 | }
38 | ]
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/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 newProducts = products.filter(item => item.id !== id);
11 | products.splice(idx, 1);
12 | await updateProducts(products);
13 | // await updateProducts(newProducts);
14 | return "Success remove"
15 | }
16 |
17 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/products/updateById.js:
--------------------------------------------------------------------------------
1 | const updateProducts = require("./updateProducts");
2 | const getAll = require("./getAll");
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 | const updateProduct = {...products[idx], ...data};
11 | products[idx] = updateProduct;
12 | await updateProducts(products);
13 | return updateProduct;
14 | };
15 |
16 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files-example-2/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | const path = require("path");
3 |
4 |
5 |
6 | module.exports = updateProducts;
--------------------------------------------------------------------------------
/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": "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 | "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 | // const newProducts = [...products, newProduct];
11 | await updateProducts(products);
12 | // await updateProducts(newProducts);
13 | return newProduct;
14 | }
15 |
16 | module.exports = add;
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/getAll.js:
--------------------------------------------------------------------------------
1 | const products = require("./products.json");
2 | /*
3 | const data = fs.readFileSync("./products.json");
4 | const products = JSON.parse(data);
5 | */
6 | const getAll = async() => products;
7 |
8 | 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 product = products.find(item => item.id === id);
6 | if(!product) {
7 | return null;
8 | }
9 | return product;
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 | }
14 |
15 |
--------------------------------------------------------------------------------
/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": 4,
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 newProducts = products.filter(item => item.id !== id);
11 | products.splice(idx, 1);
12 | await updateProducts(products);
13 | // await updateProducts(newProducts);
14 | return "Success remove"
15 | }
16 |
17 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/updateById.js:
--------------------------------------------------------------------------------
1 | const updateProducts = require("./updateProducts");
2 | const getAll = require("./getAll");
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 | const updateProduct = {...products[idx], ...data};
11 | products[idx] = updateProduct;
12 | await updateProducts(products);
13 | return updateProduct;
14 | };
15 |
16 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-2/work-with-json-files/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | const path = require("path");
3 |
4 | const filePath = path.join(__dirname, "products.json");
5 |
6 | const updateProducts = async(newProducts) => {
7 | await fs.writeFile(filePath, JSON.stringify(newProducts));
8 | };
9 |
10 | 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 | app.get("/", (request, response)=>{
6 | response.send("Главная страница
");
7 | });
8 |
9 | app.get("/contacts", (request, response)=>{
10 | response.send("Наши контакты
");
11 | });
12 |
13 | app.get("/about-us", (request, response)=> {
14 | console.log(request.url);
15 | console.log(request.method);
16 | console.log(request.headers);
17 | response.send("О нас
");
18 | });
19 |
20 | app.listen(3000);
21 |
22 |
--------------------------------------------------------------------------------
/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("space", 8);
8 | // app.set("json replacer", " ");
9 |
10 | app.get("/products", (req, res) => {
11 | res.json({
12 | status: "success",
13 | data: {
14 | result: products
15 | }
16 | });
17 | // res.json(null);
18 | // res.send(null);
19 | });
20 |
21 | app.post("/products", (req, res)=> {
22 | res.send({
23 | message: "товар успешно добавлен"
24 | });
25 | });
26 |
27 | app.listen(3000);
--------------------------------------------------------------------------------
/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-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 | // 15.09.2021_21:03:54 GET /products
13 | // 15.09.2021_21:04:05 POST /products
14 |
15 | // app.use(async (req, res, next)=> {
16 | // const {url, method} = req;
17 | // const now = moment().format("DD.MM.YYYY_hh:mm:ss");
18 | // const data = `\n${now} ${method} ${url}`;
19 | // await fs.appendFile("server.log", data);
20 | // next();
21 | // });
22 |
23 | // app.use((req, res, next)=> {
24 | // console.log("First middleware");
25 | // next();
26 | // });
27 |
28 | // app.use((req, res)=> {
29 | // console.log("Second middleware");
30 | // next();
31 | // });
32 |
33 | app.get("/products", (req, res)=> {
34 | res.json(products);
35 | });
36 |
37 | app.post("/products", (req, res)=> {
38 | res.json({
39 | message: "Товар успешно добавлен"
40 | })
41 | });
42 |
43 | // app.use((req, res, next)=> {
44 | // console.log("Last middleware");
45 | // });
46 |
47 |
48 |
49 | 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 | 15.09.2021_09:16:34 GET /products
2 | 15.09.2021_09:16:52 POST /products
--------------------------------------------------------------------------------
/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 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-3/slides/Client-Server-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-3/slides/Client-Server-schema.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/fullstack-developer-cors-problem-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-3/slides/fullstack-developer-cors-problem-2.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/fullstack-developer-cors-problem.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-3/slides/fullstack-developer-cors-problem.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/middleware-work-schema-details-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-3/slides/middleware-work-schema-details-2.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/middleware-work-schema-details-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-3/slides/middleware-work-schema-details-3.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/middleware-work-schema-details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-3/slides/middleware-work-schema-details.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/middleware-work-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-3/slides/middleware-work-schema.jpg
--------------------------------------------------------------------------------
/lesson-3/slides/what-is-it-cors.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-3/slides/what-is-it-cors.jpg
--------------------------------------------------------------------------------
/lesson-4/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-4/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-4/joi-example/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode/
2 | .idea/
3 | package-lock.json
4 | yarn.lock
5 | yarn.error
6 | node_modules/
--------------------------------------------------------------------------------
/lesson-4/joi-example/app.js:
--------------------------------------------------------------------------------
1 | const Joi = require("joi");
2 |
3 | const productJoiSchema = Joi.object({
4 | name: Joi.string().min(1).required(),
5 | price: Joi.number().min(0.01).required(),
6 | location: Joi.string().min(1).required(),
7 | });
8 |
9 | const product = {
10 | "name": "iPhone X",
11 | "price": 17000,
12 | // "location": "Apple store"
13 | };
14 |
15 | const {error} = productJoiSchema.validate(product);
16 | if(error){
17 | console.log(error.message)
18 | }
19 |
--------------------------------------------------------------------------------
/lesson-4/joi-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "joi-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.12"
16 | },
17 | "dependencies": {
18 | "joi": "^17.4.2"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/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 | // api/product
18 | app.use((req, res) => {
19 | res.status(404).json({
20 | status: "error",
21 | message: 'Not found'
22 | })
23 | })
24 |
25 | app.use((err, req, res, next) => {
26 | const {status = 500, message = "Server error"} = err;
27 | res.status(status).json({ message })
28 | });
29 |
30 | module.exports = app
31 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/bin/server.js:
--------------------------------------------------------------------------------
1 | const app = require('../app')
2 | // console.log(process.env);
3 | // const PORT = process.env.PORT || 3000
4 | const {PORT = 3000} = process.env;
5 |
6 | app.listen(PORT, () => {
7 | console.log(`Server running. Use our API on port: ${PORT}`)
8 | })
9 |
--------------------------------------------------------------------------------
/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.js:
--------------------------------------------------------------------------------
1 | const {NotFound} = require("http-errors");
2 |
3 | const {sendSuccessRes} = require("../helpers");
4 | const productsOperations = require("../model/products");
5 |
6 | const getAll = async(req, res)=> {
7 | const result = await productsOperations.getAll();
8 | sendSuccessRes(res, {result});
9 | // res.json({
10 | // status: "success",
11 | // code: 200,
12 | // data: {
13 | // result: products
14 | // }
15 | // });
16 | };
17 |
18 | const getById = async(req, res)=> {
19 | const {id} = req.params;
20 | const result = await productsOperations.getById(id);
21 | if(!result){
22 | throw new NotFound(`Product with id=${id} not found`);
23 | }
24 | sendSuccessRes(res, {result});
25 | }
26 |
27 | const add = async(req, res)=>{
28 | const result = await productsOperations.add(req.body);
29 | sendSuccessRes(res, {result}, 201);
30 | }
31 |
32 | const updateById = async(req, res)=> {
33 | const {id} = req.params;
34 | const result = await productsOperations.updateById(id, req.body);
35 | if(!result){
36 | throw new NotFound(`Product with id=${id} not found`);
37 | }
38 | sendSuccessRes(res, {result});
39 | }
40 |
41 | const removeById = async(req, res, next)=>{
42 | const {id} = req.params;
43 | const result = await productsOperations.removeById(id);
44 | if(!result){
45 | throw new NotFound(`Product with id=${id} not found`);
46 | }
47 | sendSuccessRes(res, {message: "Success delete"});
48 | };
49 |
50 | module.exports = {
51 | getAll,
52 | getById,
53 | add,
54 | updateById,
55 | removeById
56 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = require("./sendSuccessRes");
2 |
3 | module.exports = {
4 | sendSuccessRes
5 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/helpers/sendSuccessRes.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = (res, data, status = 200)=> {
2 | res.status(status).json({
3 | status: "success",
4 | code: status,
5 | data
6 | });
7 | }
8 |
9 | module.exports = sendSuccessRes
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/middlewares/controllerWrapper.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = (ctrl) => {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | }
6 | catch(error){
7 | next(error);
8 | }
9 | }
10 | };
11 |
12 | module.exports = controllerWrapper
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = require("./controllerWrapper");
2 | const validation = require("./validation");
3 |
4 | module.exports = {
5 | controllerWrapper,
6 | validation
7 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema) => {
2 | return async(req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | res.status(400).json({
6 | status: "error",
7 | code: 400,
8 | message: error.message
9 | });
10 | return;
11 | }
12 | next();
13 | }
14 | };
15 |
16 | 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 | // const newProducts = [...products, newProduct];
11 | await updateProducts(products);
12 | // await updateProducts(newProducts);
13 | return newProduct;
14 | }
15 |
16 | module.exports = add;
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/getAll.js:
--------------------------------------------------------------------------------
1 | const products = require("./products.json");
2 | /*
3 | const data = fs.readFileSync("./products.json");
4 | const products = JSON.parse(data);
5 | */
6 | const getAll = async() => products;
7 |
8 | 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 product = products.find(item => item.id === id);
6 | if(!product) {
7 | return null;
8 | }
9 | return product;
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 | }
14 |
15 |
--------------------------------------------------------------------------------
/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"},{"id":"767580d5-f509-4f45-98f9-28e74ec4af66","name":"Ground almonds","price":4,"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 newProducts = products.filter(item => item.id !== id);
11 | products.splice(idx, 1);
12 | await updateProducts(products);
13 | // await updateProducts(newProducts);
14 | return "Success remove"
15 | }
16 |
17 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/updateById.js:
--------------------------------------------------------------------------------
1 | const updateProducts = require("./updateProducts");
2 | const getAll = require("./getAll");
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 | const updateProduct = {...products[idx], ...data};
11 | products[idx] = updateProduct;
12 | await updateProducts(products);
13 | return updateProduct;
14 | };
15 |
16 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master-2/model/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | const path = require("path");
3 |
4 | const filePath = path.join(__dirname, "products.json");
5 |
6 | const updateProducts = async(newProducts) => {
7 | await fs.writeFile(filePath, JSON.stringify(newProducts));
8 | };
9 |
10 | 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-2",
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.0",
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/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-4/nodejs-homework-template-master-2/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {productSchema} = require("../../schemas");
4 | const {controllerWrapper, validation} = require("../../middlewares");
5 | const {products: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | /*
10 | 1. Получить все товары.
11 | 2. Получить один товар по id.
12 | 3. Добавить товар.
13 | 4. Обновить товар по id.
14 | 5. Удалить товар по id.
15 | */
16 |
17 | router.get("/", controllerWrapper(ctrl.getAll));
18 |
19 | router.get("/:id", controllerWrapper(ctrl.getById));
20 |
21 | router.post("/", validation(productSchema), controllerWrapper(ctrl.add));
22 |
23 | router.put("/:id", validation(productSchema), controllerWrapper(ctrl.updateById));
24 |
25 | router.delete("/:id", controllerWrapper(ctrl.removeById));
26 |
27 | 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().min(1).required(),
5 | price: Joi.number().min(0.01).required(),
6 | location: Joi.string().min(1).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 | // api/product
18 | app.use((req, res) => {
19 | res.status(404).json({
20 | status: "error",
21 | message: 'Not found'
22 | })
23 | })
24 |
25 | app.use((err, req, res, next) => {
26 | const {status = 500, message = "Server error"} = err;
27 | res.status(status).json({ message })
28 | });
29 |
30 | module.exports = app
31 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/bin/server.js:
--------------------------------------------------------------------------------
1 | const app = require('../app')
2 | // console.log(process.env);
3 | // const PORT = process.env.PORT || 3000
4 | const {PORT = 3000} = process.env;
5 |
6 | app.listen(PORT, () => {
7 | console.log(`Server running. Use our API on port: ${PORT}`)
8 | })
9 |
--------------------------------------------------------------------------------
/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 | // const newProducts = [...products, newProduct];
11 | await updateProducts(products);
12 | // await updateProducts(newProducts);
13 | return newProduct;
14 | }
15 |
16 | module.exports = add;
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/getAll.js:
--------------------------------------------------------------------------------
1 | const products = require("./products.json");
2 | /*
3 | const data = fs.readFileSync("./products.json");
4 | const products = JSON.parse(data);
5 | */
6 | const getAll = async() => products;
7 |
8 | 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 product = products.find(item => item.id === id);
6 | if(!product) {
7 | return null;
8 | }
9 | return product;
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 | }
14 |
15 |
--------------------------------------------------------------------------------
/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"},{"id":"767580d5-f509-4f45-98f9-28e74ec4af66","name":"Ground almonds","price":4,"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 newProducts = products.filter(item => item.id !== id);
11 | products.splice(idx, 1);
12 | await updateProducts(products);
13 | // await updateProducts(newProducts);
14 | return "Success remove"
15 | }
16 |
17 | module.exports = removeById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/updateById.js:
--------------------------------------------------------------------------------
1 | const updateProducts = require("./updateProducts");
2 | const getAll = require("./getAll");
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 | const updateProduct = {...products[idx], ...data};
11 | products[idx] = updateProduct;
12 | await updateProducts(products);
13 | return updateProduct;
14 | };
15 |
16 | module.exports = updateById;
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/model/products/updateProducts.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs/promises");
2 | const path = require("path");
3 |
4 | const filePath = path.join(__dirname, "products.json");
5 |
6 | const updateProducts = async(newProducts) => {
7 | await fs.writeFile(filePath, JSON.stringify(newProducts));
8 | };
9 |
10 | 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 | "joi": "^17.4.2",
16 | "morgan": "1.10.0",
17 | "uuid": "^8.3.2"
18 | },
19 | "devDependencies": {
20 | "eslint": "^7.19.0",
21 | "eslint-config-standard": "^16.0.2",
22 | "eslint-plugin-import": "^2.22.1",
23 | "eslint-plugin-node": "^11.1.0",
24 | "eslint-plugin-promise": "^4.2.1",
25 | "nodemon": "2.0.7"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/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-4/nodejs-homework-template-master/schemas/index.js:
--------------------------------------------------------------------------------
1 | const productSchema = require("./product");
2 |
3 | module.exports = {
4 | productSchema
5 | }
--------------------------------------------------------------------------------
/lesson-4/nodejs-homework-template-master/schemas/product.js:
--------------------------------------------------------------------------------
1 | const Joi = require("joi");
2 |
3 | const productSchema = Joi.object({
4 | name: Joi.string().min(1).required(),
5 | price: Joi.number().min(0.01).required(),
6 | location: Joi.string().min(1).required(),
7 | });
8 |
9 | module.exports = productSchema;
--------------------------------------------------------------------------------
/lesson-4/slides/CRUD.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/CRUD.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/Client-Server-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/Client-Server-schema.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/HTTP-methods.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/HTTP-methods.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/REST-API-additional-rules.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/REST-API-additional-rules.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/REST-API-basic-rules.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/REST-API-basic-rules.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/Server-response-code.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/Server-response-code.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/middleware-work-schema-details-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/middleware-work-schema-details-2.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/middleware-work-schema-details-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/middleware-work-schema-details-3.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/middleware-work-schema-details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/middleware-work-schema-details.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/middleware-work-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/middleware-work-schema.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/old-routes-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/old-routes-example.jpg
--------------------------------------------------------------------------------
/lesson-4/slides/what-is-it-cors.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-4/slides/what-is-it-cors.jpg
--------------------------------------------------------------------------------
/lesson-5/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
38 |
44 |
45 |
48 |
49 |
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | yarn.log
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/app.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | require("dotenv").config();
3 |
4 | const {Category} = require("./models");
5 |
6 | const {DB_HOST} = process.env;
7 |
8 | const newCategory = {
9 | name: "tablets",
10 | description: "Самый широкий выбор планшетов!",
11 | image: "./category.jpg"
12 | };
13 |
14 | mongoose.connect(DB_HOST, {
15 | useNewUrlParser: true,
16 | useUnifiedTopology: true
17 | })
18 | .then(async()=> {
19 | try {
20 | const result = await Category.create(newCategory);
21 | console.log(result);
22 | } catch (error) {
23 | console.log(error.message)
24 | }
25 | // Category.create(newCategory, (error, data)=>{
26 | // console.log(error);
27 | // console.log(data);
28 | // });
29 | // console.log("Database connect success");
30 | })
31 | .catch(error => {
32 | console.log(error.message);
33 | })
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/models/category.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 |
3 | const categorySchema = Schema({
4 | name: String,
5 | description: String
6 | });
7 |
8 | const Category = model("category", categorySchema);
9 |
10 | module.exports = Category;
11 |
--------------------------------------------------------------------------------
/lesson-5/mongodb-project/models/index.js:
--------------------------------------------------------------------------------
1 | const Category = require("./category");
2 |
3 | module.exports = {
4 | Category
5 | }
--------------------------------------------------------------------------------
/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.12"
16 | },
17 | "dependencies": {
18 | "cors": "^2.8.5",
19 | "dotenv": "^10.0.0",
20 | "express": "^4.17.1",
21 | "mongoose": "^6.0.7"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lesson-5/process-env-example/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | node_modules/
--------------------------------------------------------------------------------
/lesson-5/process-env-example/app.js:
--------------------------------------------------------------------------------
1 | const dotenv = require("dotenv");
2 | dotenv.config();
3 | console.log(process.env.DB_HOST);
--------------------------------------------------------------------------------
/lesson-5/process-env-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "dotenv": "^10.0.0"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/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/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-5/slides/backend-structure.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/database-types.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-5/slides/database-types.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/documents-database-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-5/slides/documents-database-schema.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/dotenv-work-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-5/slides/dotenv-work-schema.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/mongodb-database-structure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-5/slides/mongodb-database-structure.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/remote-database.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-5/slides/remote-database.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/schema-model-collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-5/slides/schema-model-collection.jpg
--------------------------------------------------------------------------------
/lesson-5/slides/schema-model-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-5/slides/schema-model-example.jpg
--------------------------------------------------------------------------------
/lesson-6/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
38 |
44 |
45 |
48 |
49 |
--------------------------------------------------------------------------------
/lesson-6/mongodb-project/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | yarn.log
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-6/mongodb-project/app.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | require("dotenv").config();
3 |
4 | const {DB_HOST} = process.env;
5 |
6 | mongoose.connect(DB_HOST, {
7 | useNewUrlParser: true,
8 | useUnifiedTopology: true
9 | })
10 | .then(()=> {
11 |
12 | })
13 | .catch(error => {
14 | console.log(error.message);
15 | })
--------------------------------------------------------------------------------
/lesson-6/mongodb-project/models/category.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 |
3 | const categorySchema = Schema({
4 | name: String,
5 | description: String
6 | });
7 |
8 | const Category = model("category", categorySchema);
9 |
10 | module.exports = Category;
11 |
--------------------------------------------------------------------------------
/lesson-6/mongodb-project/models/index.js:
--------------------------------------------------------------------------------
1 | const Category = require("./category");
2 |
3 | module.exports = {
4 | Category
5 | }
--------------------------------------------------------------------------------
/lesson-6/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.12"
16 | },
17 | "dependencies": {
18 | "cors": "^2.8.5",
19 | "dotenv": "^10.0.0",
20 | "express": "^4.17.1",
21 | "mongoose": "^6.0.7"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=mongodb+srv://Bogdan:pBje6ZbFRATcsTq@cluster0.fbkoo.mongodb.net/online_shop?retryWrites=true&w=majority
--------------------------------------------------------------------------------
/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 |
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 | // api/product
18 | app.use((req, res) => {
19 | res.status(404).json({
20 | status: "error",
21 | message: 'Not found'
22 | })
23 | })
24 |
25 | app.use((err, req, res, next) => {
26 | const {status = 500, message = "Server error"} = err;
27 | res.status(status).json({ message })
28 | });
29 |
30 | module.exports = app
31 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/bin/server.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | require("dotenv").config();
3 |
4 | const app = require('../app');
5 |
6 | const {DB_HOST, PORT = 3000} = process.env;
7 |
8 | mongoose.connect(DB_HOST, {
9 | useNewUrlParser: true,
10 | useUnifiedTopology: true
11 | })
12 | .then(()=> app.listen(PORT))
13 | .catch(error => {
14 | console.log(error.message);
15 | process.exit(1);
16 | })
17 |
18 |
--------------------------------------------------------------------------------
/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/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = require("./sendSuccessRes");
2 |
3 | module.exports = {
4 | sendSuccessRes
5 | }
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/helpers/sendSuccessRes.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = (res, data, status = 200)=> {
2 | res.status(status).json({
3 | status: "success",
4 | code: status,
5 | data
6 | });
7 | }
8 |
9 | module.exports = sendSuccessRes
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/middlewares/controllerWrapper.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = (ctrl) => {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | }
6 | catch(error){
7 | next(error);
8 | }
9 | }
10 | };
11 |
12 | module.exports = controllerWrapper
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = require("./controllerWrapper");
2 | const validation = require("./validation");
3 |
4 | module.exports = {
5 | controllerWrapper,
6 | validation
7 | }
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema) => {
2 | return async(req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | res.status(400).json({
6 | status: "error",
7 | code: 400,
8 | message: error.message
9 | });
10 | return;
11 | }
12 | next();
13 | }
14 | };
15 |
16 | 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}$/; // newRegexp("^[0-9]{9}$")
5 |
6 | const productSchema = Schema({
7 | name: {
8 | type: String,
9 | required: [true, "Название товара обязательно"]
10 | },
11 | price: {
12 | type: Number,
13 | required: [true, "Цена товара обязательно"],
14 | min: 0.01
15 | },
16 | code: {
17 | type: String,
18 | unique: true,
19 | match: codeRegexp
20 | },
21 | active: {
22 | type: Boolean,
23 | default: true
24 | }
25 | }, {versionKey: false, timestamps: true});
26 |
27 | const joiSchema = Joi.object({
28 | name: Joi.string().required(),
29 | price:Joi.number().min(0.01).required(),
30 | code: Joi.string().pattern(codeRegexp).required(),
31 | active: Joi.boolean()
32 | });
33 |
34 | const updateActiveJoiSchema = Joi.object({
35 | active: Joi.boolean().required()
36 | });
37 |
38 | const Product = model("product", productSchema);
39 |
40 | module.exports = {
41 | joiSchema,
42 | updateActiveJoiSchema,
43 | Product
44 | };
--------------------------------------------------------------------------------
/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-2",
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.0",
17 | "joi": "^17.4.2",
18 | "mongoose": "^6.0.7",
19 | "morgan": "1.10.0"
20 | },
21 | "devDependencies": {
22 | "eslint": "^7.19.0",
23 | "eslint-config-standard": "^16.0.2",
24 | "eslint-plugin-import": "^2.22.1",
25 | "eslint-plugin-node": "^11.1.0",
26 | "eslint-plugin-promise": "^4.2.1",
27 | "nodemon": "2.0.7"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lesson-6/nodejs-homework-template-master/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-6/nodejs-homework-template-master/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {joiSchema, updateActiveJoiSchema} = require("../../models/product");
4 | const {controllerWrapper, validation} = require("../../middlewares");
5 | const {products: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | /*
10 | 1. Получить все товары.
11 | 2. Получить один товар по id.
12 | 3. Добавить товар.
13 | 4. Обновить товар по id.
14 | 5. Удалить товар по id.
15 | */
16 |
17 | router.get("/", controllerWrapper(ctrl.getAll));
18 |
19 | router.get("/:id", controllerWrapper(ctrl.getById));
20 |
21 | router.post("/", validation(joiSchema), controllerWrapper(ctrl.add));
22 |
23 | router.put("/:id", validation(joiSchema), controllerWrapper(ctrl.updateById));
24 |
25 | router.patch("/:id/active", validation(updateActiveJoiSchema), controllerWrapper(ctrl.updateActive));
26 |
27 | router.patch("/:id/code", validation(updateActiveJoiSchema), controllerWrapper(ctrl.updateCode));
28 |
29 | router.delete("/:id", controllerWrapper(ctrl.removeById));
30 |
31 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-6/slides/schema-model-collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-6/slides/schema-model-collection.jpg
--------------------------------------------------------------------------------
/lesson-6/slides/schema-model-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-6/slides/schema-model-example.jpg
--------------------------------------------------------------------------------
/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.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | SECRET_KEY=
--------------------------------------------------------------------------------
/lesson-7/auth-example/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-7/auth-example/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const cors = require("cors");
3 | const mongoose = require("mongoose");
4 | require("dotenv").config();
5 |
6 | const authRouter = require("./routes/api/auth");
7 |
8 | const app = express();
9 |
10 | app.use(cors());
11 | app.use(express.json());
12 |
13 | app.use("/api/auth", authRouter);
14 |
15 | app.use((req, res)=>{
16 | res.status(404).json({
17 | status: "error",
18 | code: 404,
19 | message: "Not Found"
20 | })
21 | });
22 |
23 | app.use((error, req, res, next)=>{
24 | const {status = 500, message = "Server error"} = error;
25 | res.status(status).json({
26 | status: "error",
27 | code: status,
28 | message
29 | })
30 | });
31 |
32 | const {DB_HOST, PORT = 3000} = process.env;
33 | // const {DB_USER, DB_USER_PASS, DB_NAME} = process.env;
34 | // const DB_HOST = `mongodb+srv://${DB_USER}:${DB_USER_PASS}@cluster0.fbkoo.mongodb.net/${DB_NAME}?retryWrites=true&w=majority`
35 |
36 | mongoose.connect(DB_HOST, {
37 | useNewUrlParser: true,
38 | useUnifiedTopology: true
39 | }).then(()=> app.listen(PORT))
40 | .catch(error => {
41 | console.log(error.message);
42 | process.exit(1);
43 | });
--------------------------------------------------------------------------------
/lesson-7/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-7/auth-example/controllers/auth/login.js:
--------------------------------------------------------------------------------
1 | const {BadRequest, NotFound} = require("http-errors");
2 | const bcrypt = require("bcryptjs");
3 |
4 | const {User} = require("../../models");
5 |
6 | const login = async(req, res)=>{
7 | const {email, password} = req.body;
8 | const user = await User.findOne({email}, "_id email password");
9 | if(!user || !user.comparePassword(password)){
10 | throw new BadRequest("Invalid email or password");
11 | }
12 | // if(!user){
13 | // throw new NotFound(`Email ${email} not found`);
14 | // // res.status(404).json({
15 | // // status: "error",
16 | // // code: 404,
17 | // // message: `Email ${email} not found`
18 | // // });
19 | // // return;
20 | // }
21 | // if(!user.comparePassword(password)){
22 | // throw new BadRequest("Invalid password");
23 | // }
24 | // if(!bcrypt.compareSync(password, user.password)){
25 | // throw new BadRequest("Invalid password");
26 | // // res.status(400).json({
27 | // // status: "error",
28 | // // code: 400,
29 | // // message: "Invalid password"
30 | // // });
31 | // // return;
32 | // }
33 | const token = "ghsdfsdfsfg.hsgfdhdghdh.dfgdhdhsdsasa";
34 | res.json({
35 | status: "success",
36 | code: 200,
37 | data: {
38 | token
39 | }
40 | })
41 | };
42 |
43 | module.exports = login;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/auth/logout.js:
--------------------------------------------------------------------------------
1 | const {User} = require("../../models");
2 |
3 | const logout = async(req, res)=>{
4 |
5 | };
6 |
7 | module.exports = logout;
--------------------------------------------------------------------------------
/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 {email, password} = req.body;
8 | const user = await User.findOne({email});
9 | if(user){
10 | throw new Conflict("Already register");
11 | // res.status(409).json({
12 | // status: "error",
13 | // code: 409,
14 | // message: "Already register"
15 | // });
16 | // return;
17 | }
18 | const newUser = new User({email});
19 | // newUser = {email}
20 | newUser.setPassword(password);
21 | // newUser = {email, password}
22 | await newUser.save();
23 | // const hashPassword = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
24 | // const newUser = {email, password: hashPassword};
25 | // await User.create(newUser);
26 | res.status(201).json({
27 | status: "success",
28 | code: 201,
29 | message: "Success register"
30 | })
31 | };
32 |
33 | module.exports = register;
--------------------------------------------------------------------------------
/lesson-7/auth-example/controllers/index.js:
--------------------------------------------------------------------------------
1 | const auth = require("./auth");
2 |
3 | module.exports = {
4 | auth
5 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = require("./sendSuccessRes");
2 |
3 | module.exports = {
4 | sendSuccessRes
5 | }
--------------------------------------------------------------------------------
/lesson-7/auth-example/helpers/sendSuccessRes.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = (res, data, status = 200)=> {
2 | res.status(status).json({
3 | status: "success",
4 | code: status,
5 | data
6 | });
7 | }
8 |
9 | module.exports = sendSuccessRes
--------------------------------------------------------------------------------
/lesson-7/auth-example/models/index.js:
--------------------------------------------------------------------------------
1 | const {User} = require("./user");
2 |
3 | module.exports = {
4 | User
5 | }
--------------------------------------------------------------------------------
/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 | email: {
7 | type: String,
8 | required: true,
9 | unique: true
10 | },
11 | password: {
12 | type: String,
13 | required: true,
14 | minlength: 6
15 | }
16 | }, {versionKey: false, timestamps: true});
17 |
18 | userSchema.methods.setPassword = function(password){
19 | this.password = bcrypt.hashSync(password, bcrypt.genSaltSync(10))
20 | }
21 |
22 | userSchema.methods.comparePassword = function(password){
23 | return bcrypt.compareSync(password, this.password);
24 | }
25 |
26 | const joiSchema = Joi.object({
27 | email: Joi.string().required(),
28 | password: Joi.string().min(6).required()
29 | });
30 |
31 | const User = model("user", userSchema);
32 |
33 | module.exports = {
34 | User,
35 | joiSchema
36 | }
37 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auth-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 | "cors": "^2.8.5",
20 | "dotenv": "^10.0.0",
21 | "express": "^4.17.1",
22 | "http-errors": "^1.8.0",
23 | "joi": "^17.4.2",
24 | "mongoose": "^6.0.8"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lesson-7/auth-example/routes/api/auth.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {joiSchema} = require("../../models/user");
4 | const {controllerWrapper, validation} = require("../../middlewares");
5 | const {auth: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | /*
10 | 1. Регистраця нового нового пользователя.
11 | 2. Аутентификациия (логин) зарегистрированного пользователя.
12 | 3. Авторизация аутентифицированного (зашедшего на сайт) пользователя.
13 | 4. Выход (Logout).
14 | */
15 | // api/auth/register
16 | router.post("/register", validation(joiSchema), controllerWrapper(ctrl.register));
17 | // router.post("/signup")
18 |
19 | router.post("/login", validation(joiSchema), controllerWrapper(ctrl.login));
20 | // router.post("/signin")
21 |
22 | router.get("/logout", controllerWrapper(ctrl.logout));
23 | // router.get("/signuot")
24 |
25 | 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 | const hashPassword = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
6 | // console.log(hashPassword);
7 |
8 | const compareResult = bcrypt.compareSync(password, hashPassword);
9 | // console.log(compareResult);
10 |
11 | const compareResult2 = bcrypt.compareSync("password2", hashPassword);
12 | console.log(compareResult2);
--------------------------------------------------------------------------------
/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/slides/HTTP-common-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-7/slides/HTTP-common-schema.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/HTTP-personal-request-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-7/slides/HTTP-personal-request-schema.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/frontend-backend-requests-with-token.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-7/slides/frontend-backend-requests-with-token.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/hash-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-7/slides/hash-schema.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/jwt-token-real-life-example.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-7/slides/jwt-token-real-life-example.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/process.env-and-deploy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-7/slides/process.env-and-deploy.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/register-auth-steps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-7/slides/register-auth-steps.jpg
--------------------------------------------------------------------------------
/lesson-7/slides/reigster-auth-create-steps.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-7/slides/reigster-auth-create-steps.jpg
--------------------------------------------------------------------------------
/lesson-8/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vscode/
3 | node_modules/
--------------------------------------------------------------------------------
/lesson-8/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-8/auth-example/.env.example:
--------------------------------------------------------------------------------
1 | DB_HOST=
2 | SECRET_KEY=
--------------------------------------------------------------------------------
/lesson-8/auth-example/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-8/auth-example/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const cors = require("cors");
3 | const mongoose = require("mongoose");
4 | require("dotenv").config();
5 |
6 | const authRouter = require("./routes/api/auth");
7 | const ordersRouter = require("./routes/api/orders");
8 |
9 | const app = express();
10 |
11 | app.use(cors());
12 | app.use(express.json());
13 |
14 | app.use("/api/auth", authRouter);
15 | app.use("/api/orders", ordersRouter);
16 |
17 | app.use((req, res)=>{
18 | res.status(404).json({
19 | status: "error",
20 | code: 404,
21 | message: "Not Found"
22 | })
23 | });
24 |
25 | app.use((error, req, res, next)=>{
26 | const {status = 500, message = "Server error"} = error;
27 | res.status(status).json({
28 | status: "error",
29 | code: status,
30 | message
31 | })
32 | });
33 |
34 | const {DB_HOST, PORT = 3000} = process.env;
35 | // const {DB_USER, DB_USER_PASS, DB_NAME} = process.env;
36 | // const DB_HOST = `mongodb+srv://${DB_USER}:${DB_USER_PASS}@cluster0.fbkoo.mongodb.net/${DB_NAME}?retryWrites=true&w=majority`
37 |
38 | mongoose.connect(DB_HOST, {
39 | useNewUrlParser: true,
40 | useUnifiedTopology: true
41 | }).then(()=> app.listen(PORT))
42 | .catch(error => {
43 | console.log(error.message);
44 | process.exit(1);
45 | });
--------------------------------------------------------------------------------
/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 {BadRequest} = require("http-errors");
2 | const bcrypt = require("bcryptjs");
3 | const jwt = require("jsonwebtoken");
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}, "_id email password");
12 | if(!user || !user.comparePassword(password)){
13 | throw new BadRequest("Invalid email or password");
14 | }
15 | // if(!user){
16 | // throw new NotFound(`Email ${email} not found`);
17 | // // res.status(404).json({
18 | // // status: "error",
19 | // // code: 404,
20 | // // message: `Email ${email} not found`
21 | // // });
22 | // // return;
23 | // }
24 | // if(!user.comparePassword(password)){
25 | // throw new BadRequest("Invalid password");
26 | // }
27 | // if(!bcrypt.compareSync(password, user.password)){
28 | // throw new BadRequest("Invalid password");
29 | // // res.status(400).json({
30 | // // status: "error",
31 | // // code: 400,
32 | // // message: "Invalid password"
33 | // // });
34 | // // return;
35 | // }
36 | const {_id} = user;
37 | const payload = {
38 | _id
39 | }
40 | const token = jwt.sign(payload, SECRET_KEY);
41 | // const token = user.createToken();
42 | await User.findByIdAndUpdate(_id, {token});
43 | res.json({
44 | status: "success",
45 | code: 200,
46 | data: {
47 | token
48 | }
49 | })
50 | };
51 |
52 | 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.json({
7 | status: "success",
8 | code: 200,
9 | message: "Success logout"
10 | });
11 | };
12 |
13 | 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 {email, password} = req.body;
8 | const user = await User.findOne({email});
9 | if(user){
10 | throw new Conflict("Already register");
11 | // res.status(409).json({
12 | // status: "error",
13 | // code: 409,
14 | // message: "Already register"
15 | // });
16 | // return;
17 | }
18 | const newUser = new User({email});
19 | // newUser = {email}
20 | newUser.setPassword(password);
21 | // newUser = {email, password}
22 | await newUser.save();
23 | // const hashPassword = bcrypt.hashSync(password, bcrypt.genSaltSync(10));
24 | // const newUser = {email, password: hashPassword};
25 | // await User.create(newUser);
26 | res.status(201).json({
27 | status: "success",
28 | code: 201,
29 | message: "Success register"
30 | });
31 | };
32 |
33 | module.exports = register;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/index.js:
--------------------------------------------------------------------------------
1 | const auth = require("./auth");
2 | const orders = require("./orders");
3 |
4 | module.exports = {
5 | auth,
6 | orders
7 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/orders/add.js:
--------------------------------------------------------------------------------
1 | const {Order} = require("../../models");
2 |
3 | const add = async(req, res)=> {
4 | const newOrder = {...req.body, owner: req.user._id};
5 | const result = await Order.create(newOrder);
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/orders/getAll.js:
--------------------------------------------------------------------------------
1 | const {Order} = require("../../models");
2 |
3 | const getAll = async(req, res)=>{
4 | const result = await Order.find({}, "_id content owner");
5 | res.json({
6 | status: "success",
7 | code: 200,
8 | data: {
9 | result
10 | }
11 | })
12 | };
13 |
14 | module.exports = getAll;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/orders/getAllByUser.js:
--------------------------------------------------------------------------------
1 | const {Order} = require("../../models");
2 |
3 | const getAllByUser = async(req, res)=>{
4 | const {_id} = req.user;
5 | const result = await Order.find({owner: _id}, "_id content owner");
6 | res.json({
7 | status: "success",
8 | code: 200,
9 | data: {
10 | result
11 | }
12 | })
13 | };
14 |
15 | module.exports = getAllByUser;
--------------------------------------------------------------------------------
/lesson-8/auth-example/controllers/orders/index.js:
--------------------------------------------------------------------------------
1 | const add = require("./add");
2 | const getAllByUser = require("./getAllByUser");
3 | const getAll = require("./getAll");
4 |
5 | module.exports = {
6 | add,
7 | getAllByUser,
8 | getAll
9 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/helpers/index.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = require("./sendSuccessRes");
2 |
3 | module.exports = {
4 | sendSuccessRes
5 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/helpers/sendSuccessRes.js:
--------------------------------------------------------------------------------
1 | const sendSuccessRes = (res, data, status = 200)=> {
2 | res.status(status).json({
3 | status: "success",
4 | code: status,
5 | data
6 | });
7 | }
8 |
9 | module.exports = sendSuccessRes
--------------------------------------------------------------------------------
/lesson-8/auth-example/middlewares/authenticate.js:
--------------------------------------------------------------------------------
1 | const jwt = require("jsonwebtoken");
2 |
3 | const {User} = require("../models");
4 |
5 | const {SECRET_KEY} = process.env;
6 |
7 | const authenticate = async(req, res, next) => {
8 | const {authorization} = req.headers;
9 | if(!authorization){
10 | res.status(401).json({
11 | status: "error",
12 | code: 401,
13 | message: "Not authorized"
14 | });
15 | return;
16 | }
17 |
18 | const [bearer, token] = authorization.split(" ");
19 | if(bearer !== "Bearer"){
20 | res.status(401).json({
21 | status: "error",
22 | code: 401,
23 | message: "Not authorized"
24 | });
25 | return;
26 | }
27 |
28 | try {
29 | const {_id} = jwt.verify(token, SECRET_KEY);
30 | const user = await User.findById(_id);
31 | if(!user.token){
32 | res.status(401).json({
33 | status: "error",
34 | code: 401,
35 | message: "Not authorized"
36 | });
37 | return;
38 | }
39 | req.user = user;
40 | next();
41 | }
42 | catch (error) {
43 | res.status(401).json({
44 | status: "error",
45 | code: 401,
46 | message: "Not authorized"
47 | });
48 | return;
49 | }
50 | };
51 |
52 | module.exports = authenticate;
--------------------------------------------------------------------------------
/lesson-8/auth-example/middlewares/controllerWrapper.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = (ctrl) => {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | }
6 | catch(error){
7 | next(error);
8 | }
9 | }
10 | };
11 |
12 | module.exports = controllerWrapper
--------------------------------------------------------------------------------
/lesson-8/auth-example/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = require("./controllerWrapper");
2 | const validation = require("./validation");
3 | const authenticate = require("./authenticate");
4 |
5 | module.exports = {
6 | controllerWrapper,
7 | validation,
8 | authenticate
9 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/middlewares/validation.js:
--------------------------------------------------------------------------------
1 | const validation = (schema) => {
2 | return async(req, res, next)=> {
3 | const {error} = schema.validate(req.body);
4 | if(error){
5 | res.status(400).json({
6 | status: "error",
7 | code: 400,
8 | message: error.message
9 | });
10 | return;
11 | }
12 | next();
13 | }
14 | };
15 |
16 | module.exports = validation;
--------------------------------------------------------------------------------
/lesson-8/auth-example/models/index.js:
--------------------------------------------------------------------------------
1 | const {User} = require("./user");
2 | const {Order} = require("./order");
3 |
4 | module.exports = {
5 | User,
6 | Order
7 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/models/order.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 |
4 | const orderSchema = Schema({
5 | content: {
6 | type: String,
7 | required: true
8 | },
9 | owner: {
10 | type: Schema.Types.ObjectId,
11 | ref: "user"
12 | }
13 | }, {versionKey: false, timestamps: true});
14 |
15 | const joiSchema = Joi.object({
16 | content: Joi.string().required()
17 | });
18 |
19 | const Order = model("order", orderSchema);
20 |
21 | module.exports = {
22 | Order,
23 | joiSchema
24 | }
--------------------------------------------------------------------------------
/lesson-8/auth-example/models/user.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 | const Joi = require("joi");
3 | const bcrypt = require("bcryptjs");
4 | const jwt = require("jsonwebtoken");
5 |
6 | const userSchema = Schema({
7 | email: {
8 | type: String,
9 | required: true,
10 | unique: true
11 | },
12 | password: {
13 | type: String,
14 | required: true,
15 | minlength: 6
16 | },
17 | token: {
18 | type: String,
19 | default: null
20 | }
21 | }, {versionKey: false, timestamps: true});
22 |
23 | userSchema.methods.setPassword = function(password){
24 | this.password = bcrypt.hashSync(password, bcrypt.genSaltSync(10))
25 | }
26 |
27 | userSchema.methods.comparePassword = function(password){
28 | return bcrypt.compareSync(password, this.password);
29 | }
30 |
31 | const {SECRET_KEY} = process.env;
32 |
33 | userSchema.methods.createToken = function(){
34 | const payload = {
35 | _id: this._id
36 | };
37 | return jwt.sign(payload, SECRET_KEY)
38 | }
39 |
40 | const joiSchema = Joi.object({
41 | email: Joi.string().required(),
42 | password: Joi.string().min(6).required()
43 | });
44 |
45 | const User = model("user", userSchema);
46 |
47 | module.exports = {
48 | User,
49 | joiSchema
50 | }
51 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auth-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 | "cors": "^2.8.5",
20 | "dotenv": "^10.0.0",
21 | "express": "^4.17.1",
22 | "http-errors": "^1.8.0",
23 | "joi": "^17.4.2",
24 | "jsonwebtoken": "^8.5.1",
25 | "mongoose": "^6.0.8"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lesson-8/auth-example/routes/api/auth.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {joiSchema} = require("../../models/user");
4 | const {controllerWrapper, validation, authenticate} = require("../../middlewares");
5 | const {auth: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | /*
10 | 1. Регистраця нового нового пользователя.
11 | 2. Аутентификациия (логин) зарегистрированного пользователя.
12 | 3. Авторизация аутентифицированного (зашедшего на сайт) пользователя.
13 | 4. Выход (Logout).
14 | */
15 | // api/auth/register
16 | router.post("/register", validation(joiSchema), controllerWrapper(ctrl.register));
17 | // router.post("/signup")
18 |
19 | router.post("/login", validation(joiSchema), controllerWrapper(ctrl.login));
20 | // router.post("/signin")
21 |
22 | router.get("/logout", authenticate, controllerWrapper(ctrl.logout));
23 | // router.get("/signuot")
24 |
25 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-8/auth-example/routes/api/orders.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {joiSchema} = require("../../models/order");
4 | const {controllerWrapper, validation, authenticate} = require("../../middlewares");
5 | const {orders: ctrl} = require("../../controllers");
6 |
7 | const router = express.Router();
8 |
9 | router.get("/", authenticate, controllerWrapper(ctrl.getAllByUser));
10 |
11 | router.get("/all", controllerWrapper(ctrl.getAll));
12 |
13 | router.post("/", authenticate, validation(joiSchema), controllerWrapper(ctrl.add));
14 |
15 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-8/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lesson-8/jsonwebtoken-example/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | package-lock.json
3 | yarn.lock
4 | .yarn.error
5 | node_modules/
--------------------------------------------------------------------------------
/lesson-8/jsonwebtoken-example/app.js:
--------------------------------------------------------------------------------
1 | const jwt = require("jsonwebtoken");
2 |
3 | const SECRET_KEY = "fhgsdffhsd";
4 |
5 | const payload = {
6 | _id: "6154b0ae55bcd821faba0fe9"
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 verifyToken = jwt.verify(`${token}e`, SECRET_KEY);
17 | console.log(verifyToken);
18 | } catch (error) {
19 | console.log(error.message);
20 | }
21 |
--------------------------------------------------------------------------------
/lesson-8/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-8/slides/JWT-token-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-8/slides/JWT-token-schema.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/hash-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-8/slides/hash-schema.jpg
--------------------------------------------------------------------------------
/lesson-8/slides/logout-examples.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-8/slides/logout-examples.jpg
--------------------------------------------------------------------------------
/lesson-9/README.md:
--------------------------------------------------------------------------------
1 | [Схема работы библиотеки passport](./slides/passport-work-schema.jpg)
2 |
3 | [Схема работы библиотеки multer](./slides/multer-work-schema.jpg)
--------------------------------------------------------------------------------
/lesson-9/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
14 |
24 |
25 |
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/.env:
--------------------------------------------------------------------------------
1 | DB_HOST=mongodb+srv://Bogdan:pBje6ZbFRATcsTq@cluster0.ubani.mongodb.net/online_shop?retryWrites=true&w=majority
2 | SECRET_KEY=ghsdfdfhdsdfsdgsgsdfd
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vscode/
3 | node_modules/
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const cors = require("cors");
3 | const mongoose = require("mongoose");
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 | app.use(express.static("public"));
13 |
14 | app.use("/api/products", productsRouter);
15 |
16 | const {DB_HOST, PORT = 3000} = process.env;
17 |
18 | mongoose.connect(DB_HOST).then(()=> app.listen(PORT))
19 | .catch(error => {
20 | console.log(error.message);
21 | process.exit(1);
22 | });
23 |
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/controllers/index.js:
--------------------------------------------------------------------------------
1 | const products = require("./products");
2 |
3 | module.exports = {
4 | products
5 | }
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/controllers/products.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | const fs = require("fs/promises");
3 |
4 | const {Product} = require("../models");
5 |
6 | const productsDir = path.join( __dirname, "../", "public/products");
7 |
8 | const add = async(req, res)=>{
9 | const {path: tempStorage, originalname} = req.file;
10 | try {
11 | const newProduct = {
12 | name: req.body.name,
13 | photo: "/public/products/default.png"
14 | };
15 | const result = await Product.create(newProduct);
16 | const [extention] = originalname.split(".").reverse();
17 | const newFileName = `product_main-image_${result._id}.${extention}`;
18 | const resultStorage = path.join(productsDir, newFileName);
19 | await fs.rename(tempStorage, resultStorage);
20 | const photo = path.join("/products", newFileName);
21 | const product = await Product.findByIdAndUpdate(result._id, {photo}, {new: true});
22 | res.status(201).json({
23 | result: product
24 | });
25 | } catch (error) {
26 | await fs.unlink(tempStorage);
27 | throw error;
28 | }
29 | };
30 |
31 | const getAll = async(req, res)=>{
32 | const result = await Product.find({});
33 | res.json(
34 | result
35 | )
36 | };
37 |
38 | module.exports = {
39 | add,
40 | getAll
41 | }
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
14 |
34 |
35 |
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/middlewares/controllerWrapper.js:
--------------------------------------------------------------------------------
1 | const controllerWrapper = (ctrl)=> {
2 | return async(req, res, next)=> {
3 | try {
4 | await ctrl(req, res, next);
5 | }
6 | catch (error) {
7 | next(error);
8 | }
9 | }
10 | }
11 |
12 | module.exports = controllerWrapper;
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/middlewares/index.js:
--------------------------------------------------------------------------------
1 | const upload = require("./upload");
2 | const controllerWrapper = require("./controllerWrapper");
3 |
4 | module.exports = {
5 | upload,
6 | controllerWrapper
7 | };
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/middlewares/upload.js:
--------------------------------------------------------------------------------
1 | const multer = require("multer");
2 | const path = require("path");
3 |
4 | const tempDir = path.join(__dirname, "../", "temp");
5 |
6 | const multerSetting = 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: 2058
15 | }
16 | });
17 |
18 | const upload = multer({
19 | storage: multerSetting
20 | });
21 |
22 | module.exports = upload;
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/models/index.js:
--------------------------------------------------------------------------------
1 | const {Product} = require("./product");
2 |
3 | module.exports = {
4 | Product
5 | }
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/models/product.js:
--------------------------------------------------------------------------------
1 | const {Schema, model} = require("mongoose");
2 |
3 | const productSchema = Schema({
4 | name: {
5 | type: String,
6 | required: true
7 | },
8 | photo: {
9 | type: String,
10 | required: true
11 | }
12 | }, {versionKey: false, timestamps: true});
13 |
14 | const Product = model("product", productSchema);
15 |
16 | module.exports = {
17 | Product
18 | }
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multer-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.13"
16 | },
17 | "dependencies": {
18 | "cors": "^2.8.5",
19 | "dotenv": "^10.0.0",
20 | "express": "^4.17.1",
21 | "mongoose": "^6.0.8",
22 | "multer": "^1.4.3"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lesson-9/multer-example-2/routes/api/products.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 |
3 | const {upload, controllerWrapper} = require("../../middlewares");
4 | const {products: ctrl} = require("../../controllers");
5 |
6 | const router = express.Router();
7 |
8 | router.post("/", upload.single("photo"), controllerWrapper(ctrl.add));
9 |
10 | router.get("/", controllerWrapper(ctrl.getAll));
11 |
12 | module.exports = router;
--------------------------------------------------------------------------------
/lesson-9/multer-example/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vscode/
3 | node_modules/
--------------------------------------------------------------------------------
/lesson-9/multer-example/app.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const cors = require("cors");
3 | const multer = require("multer");
4 | const path = require("path");
5 | const {v4} = require("uuid");
6 | const fs = require("fs/promises");
7 |
8 | const tempDir = path.join(__dirname, "temp");
9 | const uploadDir = path.join(__dirname, "public");
10 |
11 | const uploadConfig = multer.diskStorage({
12 | destination: (req, file, cb)=>{
13 | cb(null, tempDir);
14 | },
15 | filename: (req, file, cb)=> {
16 | cb(null, file.originalname);
17 | },
18 | limits: {
19 | fileSize: 2048
20 | }
21 | });
22 |
23 | const uploadMiddleware = multer({
24 | storage: uploadConfig
25 | });
26 |
27 | const app = express();
28 |
29 | app.use(cors());
30 | app.use(express.json());
31 | app.use(express.static("public"));
32 |
33 | const products = [];
34 |
35 | app.post("/api/products", uploadMiddleware.single("image"), async(req, res)=> {
36 | const {originalname, path: tempName} = req.file;
37 | const fileName = path.join(uploadDir, "products", originalname);
38 | try {
39 | await fs.rename(tempName, fileName);
40 | const image = path.join("/products", originalname);
41 | const newProduct = {...req.body, id: v4(), image};
42 | products.push(newProduct);
43 | res.status(201).json({
44 | status: "success",
45 | code: 201,
46 | data: {
47 | result: newProduct
48 | }
49 | });
50 | } catch (error) {
51 | await fs.unlink(tempName);
52 | }
53 |
54 | });
55 |
56 | app.get("/api/products", async(req, res)=> {
57 | res.json(products)
58 | })
59 |
60 | app.listen(3000);
61 |
62 |
63 |
--------------------------------------------------------------------------------
/lesson-9/multer-example/frontend.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
24 |
25 |
--------------------------------------------------------------------------------
/lesson-9/multer-example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/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.3",
21 | "uuid": "^8.3.2"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lesson-9/multer-example/public/products/2085-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-9/multer-example/public/products/2085-1.png
--------------------------------------------------------------------------------
/lesson-9/multer-example/temp/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-9/multer-example/temp/.gitkeep
--------------------------------------------------------------------------------
/lesson-9/slides/multer-work-schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BogdanLyamzin/30-nodejs/670d182261478f59518e45914861b981376ea91a/lesson-9/slides/multer-work-schema.jpg
--------------------------------------------------------------------------------