├── README.md
├── assets
└── course-logo.png
├── cross-check
├── auth-jwt.md
├── ciphering-cli-tool.md
├── docker-basics.md
├── logging-error-handling.md
├── nestjs.md
├── postgresql-typeorm.md
├── rest-service.md
├── simple-crud-api.md
├── testing.md
└── typescript-basics.md
└── descriptions
├── auth-jwt.md
├── ciphering-cli-tool.md
├── docker-basics.md
├── logging-error-handling.md
├── nestjs.md
├── postgresql-typeorm.md
├── rest-service.md
├── simple-crud-api.md
├── testing.md
└── typescript-basics.md
/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to the Rolling Scopes School Node.js course!
2 |
3 | 
4 |
5 | **N.B!**. Tasks for which the field *"Execute in"* written "template" should be implemented using the template, others - in the student's private repository.
6 |
7 | ---
8 |
9 | ## Tasks
10 |
11 | ### Task 1. Ciphering CLI tool
12 |
13 | * Execute in: **private repository**
14 | * [Description](./descriptions/ciphering-cli-tool.md)
15 | * [Cross-check criteria](./cross-check/ciphering-cli-tool.md)
16 |
17 | ### Task 2. Testing
18 |
19 | * Execute in: **private repository (from 1st task)**
20 | * [Description](./descriptions/testing.md)
21 | * [Cross-check criteria](./cross-check/testing.md)
22 |
23 | ### Task 3. Simple CRUD API
24 |
25 | * Execute in: **private repository**
26 | * [Description](./descriptions/simple-crud-api.md)
27 | * [Cross-check criteria](./cross-check/simple-crud-api.md)
28 |
29 | ### Task 4. REST Service
30 |
31 | * Execute in: **template**
32 | * [Description](./descriptions/rest-service.md)
33 | * [Cross-check criteria](./cross-check/rest-service.md)
34 |
35 | ### Task 5. Typescript basics
36 |
37 | * Execute in: **template**
38 | * [Description](./descriptions/typescript-basics.md)
39 | * [Cross-check criteria](./cross-check/typescript-basics.md)
40 |
41 | ### Task 6. Logging & Error Handling
42 |
43 | * Execute in: **template**
44 | * [Description](./descriptions/logging-error-handling.md)
45 | * [Cross-check criteria](./cross-check/logging-error-handling.md)
46 |
47 | ### Task 7. Docker basics
48 |
49 | * Execute in: **template**
50 | * [Description](./descriptions/docker-basics.md)
51 | * [Cross-check criteria](./cross-check/docker-basics.md)
52 |
53 | ### Task 8. PostgreSQL & Typeorm
54 |
55 | * Execute in: **template**
56 | * [Description](./descriptions/postgresql-typeorm.md)
57 | * [Cross-check criteria](./cross-check/postgresql-typeorm.md)
58 |
59 | ### Task 9. Authentication & JWT
60 |
61 | * Execute in: **template**
62 | * [Description](./descriptions/auth-jwt.md)
63 | * [Cross-check criteria](./cross-check/auth-jwt.md)
64 |
65 | ### Task 10. Nest.js
66 |
67 | * Execute in: **template**
68 | * [Description](./descriptions/nestjs.md)
69 | * [Cross-check criteria](./cross-check/nestjs.md)
--------------------------------------------------------------------------------
/assets/course-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rolling-scopes-school/basic-nodejs-course/1d0b40fd76b30a13b23d649266d77693ab5bb062/assets/course-logo.png
--------------------------------------------------------------------------------
/cross-check/auth-jwt.md:
--------------------------------------------------------------------------------
1 | # Authentication & JWT
2 |
3 | ## NB! Для успешного прохождения тестов обязательно наличие в БД юзера с логином - **admin**, паролем - **admin**.
4 |
5 | ## Базовая реализация
6 |
7 | 1. Пароли пользователей сохраняются в базу в виде хэша с использованием `bcrypt` (либо аналогичного пакета, например, `bcryptjs`). **плюс 20 баллов**.
8 | 2. Добавлен роут `/login`, связанная с ним логика разделена между контроллером и соответствующим сервисом. В случае отсутствия юзера в БД, возвращается **403** (`Forbidden`) HTTP статус. **плюс 20 баллов**.
9 | 3. `JWT` токен содержит `userId` и `login`, секретный ключ хранится в `.env` **плюс 20 баллов**.
10 | 4. Доступ ко всем роутам, за исключением `/login`, `/doc` и `/`, требует аутентификации **плюс 20 баллов**.
11 | 5. Проверка на наличие токена в реквесте реализована в отдельном модуле **на уровне приложения**. В случае если токен не валидный, или отсутствует, возвращается **401** (`Unauthorized`) HTTP статус. **плюс 20 баллов**.
12 |
13 | ## Штрафы:
14 | * Наличие изменений в тестах либо в workflow **минус 100 баллов**
15 | * Внесение изменений в репозиторий после дедлайна не считая коммиты, вносящие изменения только в `Readme.md` **минус 30% от максимального балла за задание (для этого задания 30 баллов)**
16 | * За **каждую** ошибку линтера при запуске `npm run lint` на основе **локального конфига** **минус 20 баллов** (именно `errors`, не `warnings`)
17 | * За **каждую** ошибку компилятора **минус 20 баллов**
18 | * Все тесты `npm run test:auth` должны проходить успешно, каждый не пройденный тест **минус 20 баллов**.
19 | * Имеется явно указанный тип `any` **минус 20 баллов** за каждое использование
20 | * За отсутствие отдельной ветки для разработки **минус 20 баллов**
21 | * За отсутствие `Pull Request` **минус 20 баллов**
22 | * За неполную информацию в описании `Pull Request` (отсутствует либо некорректен один из 3 обязательных пунктов) **минус 10 баллов**
23 | * Меньше 3 коммитов в ветке разработки, не считая коммиты, вносящие изменения только в `Readme.md` — **минус 20 баллов**
--------------------------------------------------------------------------------
/cross-check/ciphering-cli-tool.md:
--------------------------------------------------------------------------------
1 | # Ciphering CLI Tool
2 |
3 | **Базовая реализация**
4 |
5 | 1. В `README.md` должно быть описано, как можно запустить программу из командной строки, описаны аргументы, которые можно передать приложению **плюс 10 баллов**.
6 | 2. Если переданы все аргументы и они корректны, приложение читает из файла и записывает в файл преобразованный текст, при этом предыдущие записи не удаляются **плюс 20 баллов**
7 | 3. Приложение работает в соответствии с описанными в задании примерами **плюс 30 баллов**
8 | 4. Если аргументы `input` и/или `output` ведут к несуществующему файлу либо директории,приложение передает соответствующее сообщение в `process.stderr` и прoцесс завершается с кодом, отличным от 0 **плюс 10 баллов**
9 | 5. Если любой из аргументов дублируется, приложение передает соответствующее сообщение в `process.stderr` и прoцесс завершается с кодом, отличным от 0 **плюс 10 баллов**
10 | 6. Если `config` невалиден или отсутствует, приложение передает соответствующее сообщение в `process.stderr` и прoцесс завершается с кодом, отличным от 0 **плюс 20 баллов**.
11 | Объем валидации `config`:
12 | * проверяется, что `config` имеет формат `{XY(-)}n`
13 | * проверяется, что `X` соответствует одному из шифров
14 | * проверяется, что для ROT-8 и Цезаря присутствует элемент `Y`
15 | * проверяется, что для Атбаш отсутствует элемент `Y`
16 | * проверяется, что `Y` — это 1 или 0
17 | 7. Если не передан аргумент с путем до файла на чтение, то чтение осуществляется из `process.stdin` **плюс 10 баллов**
18 | 8. Если не передан аргумент с путем до файла на запись, то вывод осуществляется в `process.stdout` **плюс 10 баллов**
19 | 9. Шифруются/дешифруются только латинские буквы, регистр сохраняется, остальные символы не изменяются **плюс 20 баллов**
20 | 10. Если текст вводится из консоли, то программа не должна завершаться после выполнения шифровки/дешифровки введенного текста, т.е. должна быть возможность ввести еще текст **плюс 10 баллов**
21 | 11. Кодовая база не находится в одном файле, а разделена на файлы в соответствии с выполняемыми задачами (например - функция, преобразующая строку, в отдельном файле, код, создающий transform стрим, в отдельном файле, функция для парсинга и валидации аргументов в отдельном файле и т.п.) **плюс 10 баллов**
22 |
23 | **Продвинутая реализация**
24 | 1. Чтение реализовано при помощи кастомного стрима (класс, отнаследованный от Readable) **плюс 10 баллов**
25 | 2. Запись реализована при помощи кастомного стрима (класс, отнаследованный от Writable) **плюс 10 баллов**
26 | 3. Для передачи сообщения в `process.stderr` используются `пользовательские ошибки` и их обработка **плюс 10 баллов**
27 |
28 | Штрафы:
29 | * Наличие коммитов после дедлайна (за исключением коммитов, изменяющих исключительно `Readme.md` либо вспомогательные файлы (`.gitignore`, `.prettierrc.json` и т.д.) **минус 30% от максимального балла за задание (для этого задания 57 баллов)**
30 | * Использование любых сторонних пакетов, библиотек, фреймворков (за исключением `nodemon`, `prettier` и его плагинов, `eslint` и его плагинов) **минус 150 баллов**
31 | * Запись, чтение, трансформация текста осуществляются без использования потоков (streams) **минус 150 баллов**
32 | * При изменении порядка аргументов происходит ошибка либо изменяется результат выполнения кода **минус 30 баллов**
33 |
34 | N.B. `console.error` пишет ошибку в `process.stderr`. В VS Code, если запустить приложение в режиме [дебага](https://code.visualstudio.com/docs/editor/debugging), можно увидеть в панели output, что цвет сообщений, выводимых в `process.stdout` и `process.stderr` отличаются.
35 |
--------------------------------------------------------------------------------
/cross-check/docker-basics.md:
--------------------------------------------------------------------------------
1 | # Docker basics
2 |
3 | ## Базовая реализация:
4 | * Наличие в `Readme.md` секции с инструкцией как запустить приложение **плюс 20 баллов**
5 | * Используется `user-defined bridge` **плюс 30 баллов**
6 | * При возникновении ошибки контейнер должен перезапускается автоматически **плюс 30 баллов**
7 | * Логи и файлы базы данных хранятся в `volumes`, а не в контейнере **плюс 30 баллов**
8 |
9 | ## Продвинутая реализация
10 | * Итоговый docker-образ с приложением имеет размер меньше 300 мб **плюс 20 баллов**
11 |
12 | ## Штрафы:
13 | * Внесение изменений в репозиторий после дедлайна не считая коммиты, вносящие изменения только в `Readme.md` **минус 30% от максимального балла за задание (для этого задания 39 баллов)**
14 | * За отсутствие отдельной ветки для разработки **минус 20 баллов**
15 | * За отсутствие `Pull Request` **минус 20 баллов**
16 | * За неполную информацию в описании `Pull Request` **минус 10 баллов**
17 | * Используется `default bridge network` **минус 20 баллов**
18 | * Конфигурация приложения жестко прописана в` docker-compose.yml` и `Dockerfile` **минус 20 баллов**
19 | * При изменении файлов в папке `src` приложение не перезапускается **минус 20 баллов**
20 | * Должен использоваться специфичный образ. (Например `postgres` и `node`, а не `ubuntu` с установкой `node` или `postgres`) **минус 20 баллов** в случае, если не используется.
21 | * `Postgress image` не указана как зависимость для node `image` **минус 20 баллов**
--------------------------------------------------------------------------------
/cross-check/logging-error-handling.md:
--------------------------------------------------------------------------------
1 | # Logging & Error Handling
2 |
3 | ## Базовая реализация
4 |
5 | 1. Логирование (как минимум `url`, `query parameters`, `body`) для всех запросов к серверу, а также кода ответа (`status code`)**плюс 20 баллов**
6 | 2. Добавлена централизованная обработка всех ошибок, которая включает отправку респонса с соответствующим кодом http статуса и их логирование **плюс 20 баллов**
7 | 3. Добавлены обработка и логирование ошибок на событие `uncaughtException` **плюс 10 баллов**
8 | 4. Добавлены обработка и логирование ошибок на событие `unhandledRejection` **плюс 10 баллов**
9 | 5. Процесс логирования осуществляется единственным модулем (т.е. код, осуществляющий логирование, находится в одном модуле, при этом этот модуль может **использоваться** внутри других модулей) **плюс 20 баллов**
10 |
11 | ## Продвинутая реализация
12 | 1. Логи записываются в файл **плюс 20 баллов**
13 | 2. Логи ошибок записываются в отдельный файл (либо только в него, либо в дополнение к записи в общий файл) **плюс 10 баллов**
14 | 3. Добавить переменную окружения для указания уровня логирования и соотвутствующий функционал **плюс 20 баллов**
15 | При указании уровня логирования будут регистрироваться записи этого уровня и всех уровней с более высоким приоритетом. Например, указав уровень 2, вы соберете в лог все сообщения уровней 0, 1 и 2. **Пример** уровней логирования:
16 | * `0`: `error` (ошибка)
17 | * `1`: `warn` (предупреждение)
18 | * `2`: `info` (информация)
19 | * `3`: `debug` (отладочное сообщение)
20 | * `4`: `all` (все сообщения)
21 |
22 | ## Штрафы
23 | * Наличие изменений в тестах либо в workflow **минус 100 баллов**
24 | * Внесение изменений в репозиторий после дедлайна не считая коммиты, вносящие изменения только в `Readme.md` и вспомогательные файлы **минус 30% от максимального балла за задание (для этого задания 39 баллов)**
25 | * За каждый непрошедший тест **минус 10 баллов**
26 | * За **каждую** ошибку линтера при запуске `npm run lint` на основе **локального конфига**, равно как и за ошибки компиляции на основе локального tsconfig **минус 10 баллов** (именно `errors`, не `warnings`)
27 | * Имеется явно указанный тип `any` **минус 20 баллов** за каждое использование
28 | * За отсутствие отдельной ветки для разработки **минус 20 баллов**
29 | * За отсутствие `Pull Request` **минус 20 баллов**
30 | * За неполную информацию в описании `Pull Request` (отсутствует либо некорректен один из 3 обязательных пунктов) **минус 20 баллов**
31 | * Меньше 3 коммитов в ветке разработки, не считая коммиты, вносящие изменения только в `Readme.md`, либо другие вспомогательные файлы — **минус 20 баллов**
32 |
33 | **Подсказки:**
34 | - _(3 пункт)_ Для проверки пропишите `throw Error('Oops!')` ПОСЛЕ `process.on('uncaughtException', () => {...})`. Например, в случае с Express:
35 | ```ts
36 | // Express initialization
37 | const app = express().use(...);
38 |
39 | // Exceptions catcher
40 | process.on('uncaughtException'...);
41 |
42 | // PUT IT HERE
43 | throw Error('Oops!');
44 |
45 | module.exports = app;
46 | ```
47 | _Как результат_: вывод в консоли отловленной ошибки
48 |
49 | - _(4 пункт)_ Для проверки пропишите `Promise.reject(Error('Oops!'))` ВНЕ инициализации express и ПОСЛЕ `process.on('unhandledRejection', () => {...})`. Например, в случае с Express:
50 | ```ts
51 | // Express initialization
52 | const app = express().use(...);
53 |
54 | // Exceptions catcher
55 | process.on('unhandledRejection'...);
56 |
57 | // PUT IT HERE
58 | Promise.reject(Error('Oops!'));
59 |
60 | module.exports = app;
61 | ```
62 | _Как результат_: вывод в консоли отловленной ошибки
63 |
--------------------------------------------------------------------------------
/cross-check/nestjs.md:
--------------------------------------------------------------------------------
1 | # NestJS
2 |
3 | Приложение на Nest.js должно работать аналогично ранее созданному.
4 | В файле `Readme.md` должна быть таблица со сравнением производительности `Nestjs express` vs `Nestjs fastify`
5 |
6 | ## Новый функционал
7 | 1. Соответствующий POST-запрос на эндпоинт `/file` позволяет загрузить файл и сохранить его на сервере с приложением **плюс 30 баллов**
8 | 2. GET-запрос на эндпоинт `/file/:filename` позволяет получить загруженный на сервер файл **плюс 30 баллов**
9 | 3. Приходящие со стороны клиента DTO валидируются с использованием `ValidationPipeline` **плюс 30 баллов**
10 |
11 | ## Особенности реализации
12 | 1. `Guards` должны использоваться для работы с авторизацией/аутентификацией **плюс 30 баллов**
13 | 2. В приложении должны использоваться модули для разбиения структуры приложения на различные части (`User`, `Board`, `Task`, `File`) **плюс 30 баллов**
14 | 3. `Exception filters` должны использоваться для обработки исключений в приложении **плюс 30 баллов**
15 | 4. Для работы с базой данных должна использоваться ORM, совместимая с Nest.js (`@nestjs/typeorm`, Prisma, и т.д.) **плюс 30 баллов**
16 | 5. Для логирования должен использоваться встроенный `Logger` или кастомная имплементация **плюс 30 баллов**
17 | 6. Все внешние зависимости для модулей/классов должны предоставляться с помощью механизма `dependency injection` **плюс 30 баллов**
18 | 7. В зависисимости от переменной окружения `USE_FASTIFY` `Nest.js` должен использовать или `express` или `fastify` **плюс 30 баллов**
19 | 8. Необходимо сравнить производительность `Nest.js` с использованием `express` и `fastify` (можно использовать для этих целей [artillery](https://artillery.io/)) **плюс 30 баллов**
20 |
21 | ## Штрафы:
22 | * Наличие изменений в тестах либо в workflow **минус 200 баллов**
23 | * Внесение изменений в репозиторий после дедлайна не считая коммиты, вносящие изменения только в `Readme.md` и другую документацию) **минус 30% от максимального балла за задание (для этого задания 99 баллов)**
24 | * За отсутствие отдельной ветки для разработки **минус 20 баллов**
25 | * За отсутствие `Pull Request` **минус 20 баллов**
26 | * За неполную информацию в описании `Pull Request` (отсутствует либо некорректен один из 3 обязательных пунктов) **минус 10 баллов**
27 | * За **каждую** ошибку линтера при запуске `npm run lint` на основе **локального конфига** **минус 10 баллов** (именно `errors`, не `warnings`)
28 | * За каждый непроходящий тест npm run test:auth **минус 20 баллов**
29 | * Меньше 3 коммитов (не считая коммиты, вносящие изменения только в `Readme.md` и другую документацию) — **минус 20 баллов**
30 |
31 | ## Подсказки
32 | * Для проведения load testing берем один модуль нашего приложения и тестриуем все CRUD методы нашего ресурса (какой ресурс вы будете тестировать вы можете выбрать сами). Если для тестируемого эндпоинта необходима авторизация, то необходимо получить токен заранее и передвать его с каждым запросом.
33 |
34 | Вот пример репорта, полученного с помощью `vegeta`, который вы должны прикрепить в ваш `Readme.md` (инструмент для load tesing может использоваться любой)
35 |
36 | # Express
37 | | | | |
38 | |--------------|----------------------------------|--------------------------------------------------------------------------|
39 | | Requests | [total, rate, throughput] | 65584, 6558.34, 6558.26 |
40 | | Duration | [total, attack, wait] | 10s, 10s, 130.149µs |
41 | | Latencies | [min, mean, 50, 90, 95, 99, max] | 122.225µs, 151.803µs, 147.911µs, 160.265µs, 164.189µs, 194.74µs, 3.094ms |
42 | | Success | [ratio] | 100.00% |
43 | | Status Codes | [code:count] | 200:65584 |
44 |
45 | # Fastify
46 | | | | |
47 | |--------------|----------------------------------|----------------------------------------------------------------------|
48 | | Requests | [total, rate, throughput] | 118489, 11848.94, 11848.84 |
49 | | Duration | [total, attack, wait] | 10s, 10s, 80.298µs |
50 | | Latencies | [min, mean, 50, 90, 95, 99, max] | 63.858µs, 83.763µs, 81.544µs, 88.909µs, 92.922µs, 136.839µs, 8.852ms |
51 | | Success | [ratio] | 100.00% |
52 | | Status Codes | [code:count] | 200:118489 |
53 |
--------------------------------------------------------------------------------
/cross-check/postgresql-typeorm.md:
--------------------------------------------------------------------------------
1 | # PostgreSQL & Typeorm
2 |
3 | ## Базовая реализация
4 | 1. В качестве источника данных для `users` используется **PostgreSQL** база данных, работа с которой происходит при помощи `typeorm` **плюс 40 баллов**
5 | 2. В качестве источника данных для `tasks` используется **PostgreSQL** база данных, работа с которой происходит при помощи `typeorm` **плюс 40 баллов**
6 | 3. В качестве источника данных для `boards` используется **PostgreSQL** база данных, работа с которой происходит при помощи `typeorm` **плюс 40 баллов**
7 |
8 | ## Продвинутая реализация
9 | 1. Для создания таблиц с сущностями используются миграции **плюс 50 баллов**
10 | 2. Переменные, используемые для подключения к базе данных, хранятся в `.env` **плюс 10 баллов**
11 | 3. Для установления отношений между сущностями используются соответствующие [декораторы](https://typeorm.io/#/relations) `typeorm` **плюс 10 баллов**
12 | 4. Для проверки задания не требуется локальная установка **PostgreSQL**, подключение осуществляется к базе данных, работающей в `docker` контейнере (на основе созданной в предыдущем задании) **плюс 30 баллов**
13 |
14 | ## Штрафы
15 | * Наличие изменений в тестах либо в workflow **минус 150 баллов**
16 | * Внесение изменений в репозиторий после дедлайна не считая коммиты, вносящие изменения только в `Readme.md` **минус 30% от максимального балла за задание (для этого задания 66 баллов)**
17 | * За **каждую** ошибку линтера при запуске `npm run lint` на основе **локального конфига** **минус 20 баллов** (именно `errors`, не `warnings`)
18 | * За **каждую** ошибку компилятора **минус 20 баллов**
19 | * За каждый непроходящий тест при запуске `npm run test` **минус 20 баллов**
20 | * Имеются явно указанный тип `any` **минус 20 баллов** за каждое использование
21 | * За отсутствие отдельной ветки для разработки **минус 20 баллов**
22 | * За отсутствие `Pull Request` **минус 20 баллов**
23 | * За неполную информацию в описании `Pull Request` (отсутствует либо некорректен один из 3 обязательных пунктов) **минус 10 баллов**
24 | * Меньше 3 коммитов в ветке разработки, не считая коммиты, вносящие изменения только в `Readme.md` **минус 20 баллов**
--------------------------------------------------------------------------------
/cross-check/rest-service.md:
--------------------------------------------------------------------------------
1 | # REST service
2 |
3 | Проверку тестов следует проводить в [Node.js 16 LTS версии](https://nodejs.org/en/).
4 | Максимальная оценка за задание **300 баллов**
5 | Минимальная оценка за таску **не может быть меньше 0**.
6 |
7 | # Базовая реализация
8 | 1. Каждый успешный тест при выполнении скрипта `npm run test` **плюс 10 баллов**.
9 | 2. Код приложения, работающий с сущностью `user` разделен по модулям в соответствии с его назначением (к примеру: работа с запросом и ответом в `*.router.js`, бизнес-логика в `*.service.js`, работа с хранилищем данных в `*.repository.js` и т.п.) **плюс 10 баллов**
10 | 4. Аналогично пункту 2 для `boards` **плюс 10 баллов**
11 | 5. Аналогично пункту 2 для `tasks` **плюс 10 баллов**
12 |
13 | # Продвинутая реализация
14 | 1. REST сервис построен на базе фреймворка/библиотеки, отличной от Express и Nest.js, либо на чистом Node.js **плюс 100 баллов**
15 |
16 | ## Штрафы:
17 | * Наличие изменений в тестах либо в workflow **минус 150 баллов**
18 | * Полная ссылка на репозиторий с решением отличается от `https://github.com/%your-gihub-id%/nodejs2021Q4-service` **минус 100 баллов**
19 | * Внесение изменений в репозиторий после дедлайна не считая коммиты, вносящие изменения только в `Readme.md` и другую документацию) **минус 30% от максимального балла за задание (для этого задания 90 баллов)**
20 | * За отсутствие отдельной ветки для разработки **минус 20 баллов**
21 | * За отсутствие `Pull Request` **минус 20 баллов**
22 | * За неполную информацию в описании `Pull Request` (отсутствует либо некорректен один из 3 обязательных пунктов) **минус 20 баллов**
23 | * За **каждую** ошибку линтера при запуске `npm run lint` на основе **локального конфига** (именно `errors`, не `warnings`) **минус 5 баллов**
24 | * Меньше 3 коммитов (не считая коммиты, вносящие изменения только в `Readme.md` и другие вспомогательные файлы) — **минус 20 баллов**
25 |
26 | ## Подсказки:
27 |
28 | > ### **Как увидеть различия для папок `test` и `.github` между текущей веткой и веткой master из темплейта**
29 | > Помимо несовпадения, отображаемого в workflow во время пулл реквеста (`MD5 check`), есть следующий способ:
30 | > 1. Открыть глобальный `.gitconfig`:
31 | > `git config --global -e`
32 | > 2. Добавить в глобальный `.gitconfig` следующие строки. Если вы не используете VSCode замените `code` на соответстующую вашей IDE команду (или путь к выполняемому файлу).
33 | > ```
34 | > [diff]
35 | > tool = vscode
36 | > [difftool "vscode"]
37 | > cmd = code --wait --diff $LOCAL $REMOTE
38 | > ```
39 | > 3. Добавить в качестве дополнительного удаленного репозитория темплейт
40 | > ```bash
41 | > git remote add template https://github.com/rolling-scopes-school/nodejs-course-template.git
42 | > ```
43 | > 4. Создать локальную копию ветки master из темплейта
44 | > `git fetch template master:template-master`
45 | > 5. Запустить сравнение для текущей ветки с веткой master темплейта для тестов
46 | > `git difftool <название текущей ветки> template-master test/`
47 | > 5. Запустить сравнение для текущей ветки с веткой master темплейта для workflow
48 | > `git difftool <название текущей ветки> template-master .github/`
--------------------------------------------------------------------------------
/cross-check/simple-crud-api.md:
--------------------------------------------------------------------------------
1 | # In-memory CRUD API
2 |
3 | ## Базовая реализация
4 |
5 | 1. В репозитории с приложением имеется файл `Readme.md`, содержащий подробные инструкции по установке, запуску и использованию приложения **плюс 10 баллов**
6 | 2. Сервер возвращает соответствующие ответы на запросы:
7 | * **GET** `/person`:
8 | * Сервер возвращает статус код 200 и все записи **плюс 6 баллов**
9 | * **GET** `/person/{personId}`:
10 | * Сервер возвращает статус код 200 и запись с `id === personId`, если такая запись есть **плюс 10 баллов**
11 | * Сервер возвращает статус код 400 и соответствующее сообщение, если `personId` невалиден (не `uuid`) **плюс 6 баллов**
12 | * Сервер возвращает статус код 404 и соответствующее сообщение, если запись с `id === personId` не найдена **плюс 6 баллов**
13 | * **POST** `/person`
14 | * Сервер возвращает статус код 201 и свежесозданную запись **плюс 10 баллов**
15 | * Сервер возвращает статус код 400 и соответствующее сообщение, если тело запроса не содержит обязательных полей **плюс 6 баллов**
16 | * **PUT** `/person/{personId}`
17 | * Сервер возвращает статус код 200 и обновленную запись **плюс 10 баллов**
18 | * Сервер возвращает статус код 400 и соответствующее сообщение, если `personId` невалиден (не `uuid`) **плюс 6 баллов**
19 | * Сервер возвращает статус код 404 и соответствующее сообщение, если запись с `id === personId` не найдена **плюс 6 баллов**
20 | * **DELETE** `/person/{personId}`
21 | * Сервер возвращает статус код 204 если запись найдена и удалена **плюс 10 баллов**
22 | * Сервер возвращает статус код 400 и соответствующее сообщение, если `personId` невалиден (не `uuid`) **плюс 6 баллов**
23 | * Сервер возвращает статус код 404 и соответствующее сообщение, если запись с `id === personId` не найдена **плюс 6 баллов**
24 |
25 | ## Продвинутая реализация:
26 | * Ошибки, возникающие при обработке запроса на `/person` корректно обрабатываются и в случае их возникновения API возвращает статус код 500 с соответствующим сообщением **плюс 10 баллов**
27 | * Запросы на несуществующие ресурсы (например, `/some/non/existing/resource`) корректно обрабатываются (возвращается human friendly сообщение и 404 статус код) **плюс 6 баллов**
28 | * Приложение запускается в development-режиме при помощи `nodemon` (имеется `npm` скрипт `start:dev`, который запускает отслеживание изменений в файлах приложения) **плюс 6 баллов**
29 | * Приложение запускается в production-режиме при помощи `webpack` (имеется `npm` скрипт `start:prod`, который запускает процесс сборки webpack и после этого запускает файл с билдом) **плюс 6 баллов**
30 | * Значение `PORT` хранится в `.env` файле **плюс 6 баллов**
31 |
32 | ## Hacker scope
33 | * Имеются E2E тесты, покрывающие логику приложения (не меньше 3 различных сценариев) **плюс 30 баллов**
34 | Пример сценария:
35 | 1. GET-запросом получаем все объекты (ожидается пустой массив)
36 | 2. POST-запросом создается новый объект (ожидается ответ, содержащий свежесозданный объект)
37 | 3. GET-запросом пытаемся получить созданный объект по его `id` (ожидается созданный объект)
38 | 4. PUT-запросом пытаемся обновить созданный объект (ожидается ответ, содержащий обновленный объект с тем же `id`)
39 | 5. DELETE-запросом удаляем созданный объект по `id` (ожидается подтверждение успешного удаления)
40 | 6. GET-запросом пытаемся получить удаленный объект по `id` (ожидается ответ, что такого объекта нет)
41 |
42 | ## Штрафы
43 | * Полная ссылка на репозиторий с решением отличается от `https://github.com/%your-github-id%/simple-crud-api` **минус 100 баллов**
44 | * Использование любых пакетов, библиотек, фреймворков кроме `nodemon`, `dotenv`, `cross-env`, `eslint` и его плагинов, `webpack` и его плагинов, `uuid`, а также библиотек, используемых для тестирования **минус 130 баллов**
45 | * Имеются коммиты после дедлайна, за исключением коммитов, изменяющих исключительно `Readme.md` либо вспомогательные файлы (`.gitignore`, `.prettierrc.json` и т.д.) **минус 30% от максимального балла за задание (минус 49 баллов)**
46 | * Отсутствует PR либо его описание некорректно (отсутствуют либо некорректен любой из 3 обязательных пунктов) **минус 20 баллов**
47 | * Отсутствует отдельная ветка для разработки **минус 20 баллов**
48 | * Меньше 3 коммитов в ветке разработки, не считая коммиты, вносящие изменения только в `Readme.md` либо вспомогательные файлы (`.gitignore`, `.prettierrc.json` и т.д.) **минус 20 баллов**
49 |
50 |
--------------------------------------------------------------------------------
/cross-check/testing.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | ## Баллы за реализацию
4 |
5 | 1. По **плюс 2 балла** за каждый юнит-тест (не более **20 баллов** в сумме, баллы начисляются не более чем за 3 теста на каждую отдельную функцию/компонент).
6 | 2. Покрытие не менее 70% **плюс 20 баллов** (покрытие по **строкам**, вычисляется при помощи `jest --coverage`)
7 | 3. В тестах задействованы все сценарии из описания **плюс 20 баллов**
8 | 4. Для тестирования используются mock-объекты **плюс 20 баллов**
9 |
10 | ## Продвинутая реализация
11 |
12 | 1. Покрытие не менее 85% **плюс 20 баллов** (покрытие по **бранчам** вычисляется при помощи `jest --coverage`)
13 |
14 | ## Штрафы
15 |
16 | * Не используется Jest **минус 80 баллов**
17 | * Имеются коммиты после дедлайна, за исключением коммитов, изменяющих исключительно в `Readme.md` либо вспомогательные файлы (`.gitignore`, `.prettierrc.json` и т.д.) **минус 30% от максимального балла за задание (-30 баллов)**
18 | * Отсутствует PR либо его описание некорректно (отсутствуют либо некорректен любой из 3 обязательных пунктов) **минус 20 баллов**
19 | * Отсутствует отдельная ветка для разработки **минус 20 баллов**
20 | * Меньше 3 коммитов в ветке разработки, не считая коммиты, вносящие изменения только в `Readme.md` либо вспомогательные файлы (`.gitignore`, `.prettierrc.json` и т.д.) — **минус 20 баллов**
21 |
--------------------------------------------------------------------------------
/cross-check/typescript-basics.md:
--------------------------------------------------------------------------------
1 | # Typescript basics
2 |
3 | ## Оценка миграции (максимум **260 баллов**)
4 |
5 | - За каждый успешно пройденный тест **плюс 10 баллов** (максимум **170 баллов**)
6 | - В проекте настроен ESLint и имеется правило `no-explicit-any` **плюс 20 баллов**
7 | - В проекте имеется `tsconfig` и в нем `noImplicitAny: true` **плюс 20 баллов**
8 | - В проекте имеется `tsconfig` и в нем включена опция [strict](https://www.typescriptlang.org/tsconfig#strict) и при этом strict-related опции не перезаписаны в `false` **плюс 50 баллов**
9 |
10 | ## Оценка TSDoc (максимум **70 баллов**)
11 |
12 | ### Баллы за описание функций при помощи TSDoc
13 |
14 | Расчет количества баллов осуществляется по формуле
15 | X = ( (k1 + k2 + ... + kn) / n) * 70
16 | Где **X** - количество баллов, округленное до целого числа вверх
17 | **n** - общее количество пользовательских функций
18 | **k** - коэффициент выполнения TSDoc-описания для каждой пользовательской функции, где:
19 | * k = 0, если TSDoc-описание полностью неправильное или отсутствует
20 | * k = 0.5, если TSDoc-описание содержит ошибки в части типов или фактического описания работы функции (без учета орфографических, пунктуационных ошибок)
21 | * k = 1, если TSDoc-описание корректно
22 |
23 |
24 | Штрафы:
25 | * Наличие изменений в тестах либо в workflow **минус 150 баллов**
26 | * Внесение изменений в репозиторий после дедлайна не считая коммиты, вносящие изменения только в `Readme.md` и вспомогательные файлы **минус 30% от максимального балла за задание (для этого задания 99 баллов)**
27 | * Не все файлы с кодом в папке src имеют расширение `.ts` **минус 50 баллов**
28 | * За **каждую** ошибку линтера при запуске `npm run lint` на основе **локального конфига** **минус 10 баллов** (именно `errors`, не `warnings`)
29 | * Имеется явно указанный тип `any`, **минус 20 баллов** за каждое использование
30 | * За отсутствие отдельной ветки для разработки **минус 20 баллов**
31 | * За отсутствие `Pull Request` **минус 20 баллов**
32 | * За неполную информацию в описании `Pull Request` (отсутствует либо некорректен один из 3 обязательных пунктов) **минус 20 баллов**
33 | * Меньше 3 коммитов в ветке разработки, не считая коммиты, вносящие изменения только в `Readme.md`, либо другие вспомогательные файлы — **минус 20 баллов**
34 |
35 | Примеры TSDoc-описаний
36 |
37 | Корректное описание
38 | ```ts
39 | /**
40 | * Returns the sum of a and b
41 | * @param a first term number
42 | * @param b second term number
43 | * @returns Sum of a and b number
44 | */
45 | const sum = (a: number, b: number): number => a + b;
46 | ```
47 |
48 | Частично корректное описание (отсутствует описание одного из входных параметров)
49 | ```ts
50 | /**
51 | * Returns the sum of a and b
52 | * @param a first term number
53 | * @returns Sum of a and b number
54 | */
55 | const sum = (a: number, b: number): number => a + b;
56 | ```
57 |
58 | Некорректное описание (неправильные описание функции и возвращаемого значения, отсутствует описание одного из входных параметров)
59 | ```ts
60 | /**
61 | * Returns the square root from a
62 | * @param a first term number
63 | * @returns string "OK" or "NOT_FOUND"
64 | */
65 | const sum = (a: number, b: number): number => a + b;
66 | ```
67 |
68 | ## Подсказки:
69 |
70 | > ### **Как увидеть различия для папок `test` и `.github` между текущей веткой и веткой master из темплейта**
71 | > Помимо несовпадения, отображаемого в workflow во время пулл реквеста (`MD5 check`), есть следующий способ:
72 | > 1. Открыть глобальный `.gitconfig`:
73 | > `git config --global -e`
74 | > 2. Добавить в глобальный `.gitconfig` следующие строки. Если вы не используете VSCode замените `code` на соответстующую вашей IDE команду (или путь к выполняемому файлу).
75 | > ```
76 | > [diff]
77 | > tool = vscode
78 | > [difftool "vscode"]
79 | > cmd = code --wait --diff $LOCAL $REMOTE
80 | > ```
81 | > 3. Добавить в качестве дополнительного удаленного репозитория темплейт
82 | > ```bash
83 | > git remote add template https://github.com/rolling-scopes-school/nodejs-course-template.git
84 | > ```
85 | > 4. Создать локальную копию ветки master из темплейта
86 | > `git fetch template master:template-master`
87 | > 5. Запустить сравнение для текущей ветки с веткой master темплейта для тестов
88 | > `git difftool <название текущей ветки> template-master test/`
89 | > 5. Запустить сравнение для текущей ветки с веткой master темплейта для workflow
90 | > `git difftool <название текущей ветки> template-master .github/`
91 |
--------------------------------------------------------------------------------
/descriptions/auth-jwt.md:
--------------------------------------------------------------------------------
1 | # Authentication and JWT
2 |
3 | 1. `POST /users` should accept `password` field and before save replace it with **hash** (use [bcrypt package](https://www.npmjs.com/package/bcrypt) or its equivalent like `bcryptjs`).
4 | 2. Implement `POST /login` method which accepts **JSON** with `login` and `password` and returns **JWT** token in response body: `{ token: }` (use [jsonwebtoken package](https://www.npmjs.com/package/jsonwebtoken)).
5 | 3. **JWT** token should contain `userId` and `login` in a **payload**.
6 | 4. Secret that used for signing the token should be stored in `.env` file.
7 | 5. For all client requests the **JWT** token should be added in HTTP `Authorization` header to all requests that requires authentication. HTTP authentication must follow `Bearer` scheme, e.g.:
8 | ```
9 | Authorization: Bearer
10 | ```
11 | 6. Proxy all the requests (except `/login`) and check that HTTP `Authorization` header has the correct value of **JWT** token.
12 | 7. In case of the HTTP `Authorization` header in the request is absent or invalid or doesn’t follow `Bearer` scheme, further router method execution should be stopped and lead to response with HTTP **401** code (Unauthorized error) and the corresponding error message.
13 | 8. **Add admin user to DB** on service start with `login = admin` and `password = admin`.
14 |
15 | ### `bcrypt` installation issues:
16 |
17 | #### If you see an error that starts with:
18 |
19 | ```console
20 | gyp ERR! stack Error: "pre" versions of node cannot be installed, use the --nodedir flag instead
21 | ```
22 | Please check [compatibility between Node.JS and Bcrypt versions](https://www.npmjs.com/package/bcrypt#version-compatibility).
23 |
24 | #### If you face an error like this:
25 |
26 | ```console
27 | node-pre-gyp ERR! Tried to download(404): https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.2/bcrypt_lib-v1.0.2-node-v48-linux-x64.tar.gz
28 | ```
29 |
30 | Make sure you have the appropriate dependencies installed and configured for your platform. You can find installation instructions for the dependencies for some common platforms in [this page](https://github.com/kelektiv/node.bcrypt.js/wiki/Installation-Instructions).
--------------------------------------------------------------------------------
/descriptions/ciphering-cli-tool.md:
--------------------------------------------------------------------------------
1 | # Ciphering CLI Tool
2 |
3 | ## Implement CLI tool that will encode and decode a text by 3 substitution ciphers:
4 | * [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher)
5 | * [Atbash cipher](https://en.wikipedia.org/wiki/Atbash)
6 | * [ROT-8 as variation of ROT-13](https://en.wikipedia.org/wiki/ROT13)
7 |
8 | CLI tool should accept 3 options (short alias and full name):
9 |
10 | 1. **-c, --config**: config for ciphers
11 | Config is a string with pattern `{XY(-)}n`, where:
12 | * `X` is a cipher mark:
13 | * `C` is for Caesar cipher (with shift 1)
14 | * `A` is for Atbash cipher
15 | * `R` is for ROT-8 cipher
16 | * `Y` is flag of encoding or decoding (mandatory for Caesar cipher and ROT-8 cipher and should not be passed Atbash cipher)
17 | * `1` is for encoding
18 | * `0` is for decoding
19 | 2. **-i, --input**: a path to input file
20 | 3. **-o, --output**: a path to output file
21 |
22 | For example, config `"C1-C1-R0-A"` means "encode by Caesar cipher => encode by Caesar cipher => decode by ROT-8 => use Atbash"
23 |
24 | ## Details:
25 |
26 | 1. The task must be solved using only **pure Node.js**. Any libraries and packages (except `nodemon`, `prettier` and its plugins, `eslint` and its plugins) **are prohibited**.
27 | 2. `Config` option is required and should be validated. In case of invalid confing **human-friendly** error should be printed in `stderr` and the process should exit with non-zero status code.
28 | 3. If any option is duplicated (i.e. `bash $ node my_ciphering_cli -c C1-C1-A-R0 -c C0`) then **human-friendly** error should be printed in `stderr` and the process should exit with non-zero status code.
29 | 4. If the input file option is missed - use `stdin` as an input source.
30 | 5. If the output file option is missed - use `stdout` as an output destination.
31 | 6. If the input and/or output file is given but doesn't exist or you can't access it (e.g. because of permissions or it's a directory) - **human-friendly** error should be printed in `stderr` and the process should exit with non-zero status code.
32 | 7. If passed params are fine the output (file or `stdout`) should contain transformed content of input (file or `stdin`).
33 | 8. For encoding/decoding **use only the English alphabet**, all other characters should be kept untouched.
34 | 9. Using `streams` for reading, writing and transformation of text **is mandatory**.
35 | 10. Each cipher is implemented in the form of a **transform stream**.
36 | 11. Streams are piped inside each other according to `config` (you can use `.pipe` streams instances method or `pipeline`)
37 |
38 | **Usage example:**
39 |
40 | ```bash
41 | $ node my_ciphering_cli -c "C1-C1-R0-A" -i "./input.txt" -o "./output.txt"
42 | ```
43 |
44 | > input.txt
45 | > `This is secret. Message about "_" symbol!`
46 |
47 | > output.txt
48 | > `Myxn xn nbdobm. Tbnnfzb ferlm "_" nhteru!`
49 |
50 | ```bash
51 | $ node my_ciphering_cli -c "C1-C0-A-R1-R0-A-R0-R0-C1-A" -i "./input.txt" -o "./output.txt"
52 | ```
53 |
54 | > input.txt
55 | > `This is secret. Message about "_" symbol!`
56 |
57 | > output.txt
58 | > `Vhgw gw wkmxkv. Ckwwoik onauv "_" wqcnad!`
59 |
60 | ```bash
61 | $ node my_ciphering_cli -c "A-A-A-R1-R0-R0-R0-C1-C1-A" -i "./input.txt" -o "./output.txt"
62 | ```
63 |
64 | > input.txt
65 | > `This is secret. Message about "_" symbol!`
66 |
67 | > output.txt
68 | > `Hvwg wg gsqfsh. Asggous opcih "_" gmapcz!`
69 |
70 | ```bash
71 | $ node my_ciphering_cli -c "C1-R1-C0-C0-A-R0-R1-R1-A-C1" -i "./input.txt" -o "./output.txt"
72 | ```
73 |
74 | > input.txt
75 | > `This is secret. Message about "_" symbol!`
76 |
77 | > output.txt
78 | > `This is secret. Message about "_" symbol!`
79 |
--------------------------------------------------------------------------------
/descriptions/docker-basics.md:
--------------------------------------------------------------------------------
1 | # Docker basics
2 |
3 | ## Prerequisites
4 |
5 | 1. Install [Docker](https://docs.docker.com/engine/install/)
6 | 2. Create `Docker Hub` account [Docker Hub](https://hub.docker.com/)
7 |
8 | **Details:**
9 |
10 | 1. Create `.dockerignore` file and list all files that should be ignored by `Docker`
11 | 2. Create `Dockerfile` that will be used for building image of `PostgreSQL` database
12 | 3. Create `Dockerfile` that will be used for building image of your aplication
13 | 4. Create `docker-compose.yml` file that will be used for running multi-container application (your application and `PostgreSQL` database). Specify custom network that will be used for communication between application and database containers
14 | 6. Build images and scan it for security vulnerabilities
15 | 7. Push built images to your private repository on `Docker Hub`
16 |
--------------------------------------------------------------------------------
/descriptions/logging-error-handling.md:
--------------------------------------------------------------------------------
1 | # Logging & Error Handling
2 |
3 | Add logging functionality to already existing REST service.
4 |
5 | 1. Add logger which will log incoming requests to service (at least `url`, `query parameters`, `body`) and response `status code`.
6 | 2. Add logger which will log all unhandled `errors` and return a standard message with HTTP code `500` (Internal Server Error).
7 | 3. Add listener and logging to `uncaughtException`.
8 | 4. Add listener and logging to `unhandledRejection`.
9 | 5. Writing to `process.stdout` or to a file both can be used for logging. Any third-party logging library can also be used for this purpose.
10 | 6. Create multiple logging levels and store logging level in environment variable.
--------------------------------------------------------------------------------
/descriptions/nestjs.md:
--------------------------------------------------------------------------------
1 | # NestJS
2 |
3 | Your task is to migrate your application to `Nest.js`
4 |
5 | Main application functionality remain unchanged. Besides that, you should implement additional functionalities:
6 | * file uploading functionality (`POST /file`)
7 | * file streaming functionality (`GET /file/:filename`)
8 | * validation of DTO (using Nest.js validation pipelines)
9 | * In `Readme.md` should be table `with Nest.js express` vs `Nest.js fastify` performance comparison.
10 |
--------------------------------------------------------------------------------
/descriptions/postgresql-typeorm.md:
--------------------------------------------------------------------------------
1 | # PostgreSQL & Typeorm
2 |
3 | 1. Use **PostgreSQL** database to store **REST** service data (`Users`, `Boards`, `Tasks`)
4 | 2. Use [Typeorm](https://typeorm.io/#/) to store and update data
5 | 3. The information on DB connection should be stored in `.env` file
6 | 4. **PostgeSQL** database should run inside of the `docker` container
7 |
--------------------------------------------------------------------------------
/descriptions/rest-service.md:
--------------------------------------------------------------------------------
1 | # REST service
2 |
3 | Let's try to create a competitor for [Trello](https://trello.com/)!
4 |
5 | NB! You must create new repository from [template](https://github.com/rolling-scopes-school/nodejs-course-template/) for this task. Its name must be `nodejs2021Q4-service` i.e. full link to the repository must be `https://github.com/%your-gihub-id%/nodejs2021Q4-service`.
6 |
7 | **Create an application, the application should operate with the following resources:**
8 |
9 | - `User` (with attributes):
10 | ```javascript
11 | { id, name, login, password }
12 | ```
13 | - `Board` (set of `columns`):
14 | ```javascript
15 | { id, title, columns }
16 | ```
17 | - `Column` (set of tasks):
18 | ```javascript
19 | { id, title, order }
20 | ```
21 | - `Task`:
22 | ```javascript
23 | {
24 | id,
25 | title,
26 | order,
27 | description,
28 | userId, //assignee
29 | boardId,
30 | columnId
31 | }
32 | ```
33 |
34 | **Details:**
35 |
36 | 1. For `User`, `Board` and `Task` REST endpoints with separate router paths should be created
37 | * `User` (`/users` route)
38 | * `GET /users` - get all users (remove password from response)
39 | * `GET /users/:userId` - get the user by id (ex. “/users/123”) (remove password from response)
40 | * `POST /users` - create user
41 | * `PUT /users/:userId` - update user
42 | * `DELETE /users/:userId` - delete user
43 | * `Board` (`/boards` route)
44 | * `GET /boards` - get all boards
45 | * `GET /boards/:boardId` - get the board by id
46 | * `POST /boards` - create board
47 | * `PUT /boards/:boardId` - update board
48 | * `DELETE /boards/:boardId` - delete board
49 | * `Task` (`boards/:boardId/tasks` route)
50 | * `GET boards/:boardId/tasks` - get all tasks
51 | * `GET boards/:boardId/tasks/:taskId` - get the task by id
52 | * `POST boards/:boardId/tasks` - create task
53 | * `PUT boards/:boardId/tasks/:taskId` - update task
54 | * `DELETE boards/:boardId/tasks/:taskId` - delete task
55 |
56 | 2. When somebody `DELETEs` `Board`, all its `Tasks` should be deleted as well.
57 |
58 | 3. When somebody `DELETEs` `User`, all `Tasks` where `User` is assignee should be updated to put `userId = null`.
59 |
60 | 4. For now, these endpoints should operate only with **in-memory** (hardcoded) data, in the next tasks we will use a DB for it. You may organize your modules with the consideration that the data source will be changed soon.
61 |
62 | 5. An `application/json` format should be used for request and response body.
63 |
64 | 6. Do not put everything in one file - use a separate file for application creation (bootstrapping), for controllers (routers) and code related to business logic. Also split files to different modules depends on a domain (user-related, board-related, etc...).
65 |
66 | 7. To run the service `npm start` command should be used.
67 |
68 | 8. Service should listen on PORT `4000`.
69 |
70 | 9. You can try to refactor template using framework that differs from Express.js and Nest.js
71 |
72 | **Hints**
73 |
74 | * To generate all entities `id`s use [uuid](https://www.npmjs.com/package/uuid) package or [Node.js analogue](https://nodejs.org/dist/latest-v16.x/docs/api/crypto.html#cryptorandomuuidoptions).
--------------------------------------------------------------------------------
/descriptions/simple-crud-api.md:
--------------------------------------------------------------------------------
1 | # Simple CRUD API
2 |
3 | Your task is to implement simple CRUD API using in-memory database underneath.
4 | NB! You must create new repository for this task. Its name must be `simple-crud-api` i.e. full link to the repository must be `https://github.com/%your-gihub-id%/simple-crud-api`.
5 |
6 | ## Details:
7 |
8 | 1. The task must be solved using only **pure Node.js**. Any libraries and packages (except `nodemon`, `eslint` and its plugins, `prettier` and its plugins, `uuid`, `webpack` and its plugins, testing tools, `dotenv`, `cross-env`) **are prohibited**.
9 | 2. API path `/person`:
10 | * **GET** `/person` or `/person/${personId}` should return all persons or person with corresponding `personId`
11 | * **POST** `/person` is used to create record about new person and store it in database
12 | * **PUT** `/person/${personId}` is used to update record about existing person
13 | * **DELETE** `/person/${personId}` is used to delete record about existing person from database
14 | 3. Persons are stored as `objects` that have following properties:
15 | * `id` — unique identifier (`string`, `uuid`) generated on server side
16 | * `name` — person's name (`string`, **required**)
17 | * `age` — person's age (`number`, **required**)
18 | * `hobbies` — person's hobbies (`array` of `strings` or empty `array`, **required**)
19 | 4. Requests to non-existing endpoints (e.g. `/some-non/existing/resource`) should be handled.
20 | 5. Internal server errors should be handled and processed correctly.
21 | 6. Value of port on which application is running should be stored in `.env` file.
22 | 7. There should be 2 modes of running application: **development** and **production**
23 | 8. There could be some tests for API.
24 |
25 |
--------------------------------------------------------------------------------
/descriptions/testing.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | Write tests for Ciphering machine CLI from 1st task.
4 | For writing tests [Jest](https://jestjs.io/) testing framework should be used.
5 |
6 | You can write simple unit tests on single functions (e.g. ciphering function, arguments parsing function, config validation function, etc.), mock some modules, test CLI using [child processes](https://nodejs.org/dist/latest-v14.x/docs/api/child_process.html) and so on.
7 |
8 | ## Scenarios
9 |
10 | ### Error scenarios
11 | 1) Input: User passes the same cli argument twice; Result: Error message is shown;
12 | e.g. input: `node my_caesar_cli -c C1-C1-A-R0 -c C0` result: `Error: You provided -c argument more than once`;
13 | 2) Input: User doesn't pass -c or --config argument; Result: Error message is shown;
14 | 3) Input: User passes -i argument with path that doesn't exist or with no read access; Result: Error message is shown;
15 | 4) Input: User passes -o argument with path to directory that doesn't exist or with no read access; Result: Error message is shown;
16 | 5) Input: User passes incorrent symbols in argument for --config; Result: Error message is shown;
17 |
18 | ### Success scenarios
19 | 1) Input: User passes correct sequence of symbols as argument for --config that matches regular expression; Result: test passed
20 | 2) Take cipher usage scenarios from [first task description](https://github.com/AlreadyBored/basic-nodejs-course/blob/review-2021Q4/descriptions/caesar-cipher-cli-tool.md) usage examples.
--------------------------------------------------------------------------------
/descriptions/typescript-basics.md:
--------------------------------------------------------------------------------
1 | # Typescript basics
2 |
3 | Your task is to migrate your project from Javascript to Typescript
4 |
5 | * All code files in `src` folder must have `.ts` extension
6 | * There shouldn't be errors of TS compiler and linter
7 | * `eslintrc` and `tsconfig` should be used in the project
8 | * Type `any` is not permitted
9 | * Migration to **Typescript** should not break application functionality
10 | * You can also add [TSDoc](https://www.npmjs.com/package/@microsoft/tsdoc) annotations that contain short functionality description as well as description of its arguments (type, description) and its returned value (if applicable)
11 |
--------------------------------------------------------------------------------