├── .gitignore ├── LICENSE ├── README.md └── assignments ├── authentication ├── assignment.md └── score.md ├── basic-testing ├── assignment.md └── score.md ├── battleship ├── assignment.md └── score.md ├── containerization-database-orm ├── assignment.md └── score.md ├── containerization ├── assignment.md └── score.md ├── crud-api ├── assignment.md └── score.md ├── database-orm ├── assignment.md └── score.md ├── file-manager ├── assignment.md ├── ls-example.JPG └── score.md ├── graphql-service ├── assignment.md └── score.md ├── logging-error-authentication-authorization ├── assignment.md └── score.md ├── logging-error-handling ├── assignment.md └── score.md ├── nodejs-basics ├── assignment.md ├── cross-check-manual.md └── score.md ├── remote-control ├── assignment.md └── score.md └── rest-service ├── assignment.md └── score.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .dcignore -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Maksim Shylau 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Course program (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/README.md) 2 | 3 | # Node.js Assignments 4 | 5 | ## Node.js basics 6 | - [Assignment](assignments/nodejs-basics/assignment.md) 7 | - [Scoring](assignments/nodejs-basics/score.md) 8 | - [Cross-Check manual](assignments/nodejs-basics/cross-check-manual.md) 9 | 10 | ## File Manager 11 | - [Assignment](assignments/file-manager/assignment.md) 12 | - [Scoring](assignments/file-manager/score.md) 13 | 14 | ## Basic Testing 15 | - [Assignment](assignments/basic-testing/assignment.md) 16 | - [Scoring](assignments/basic-testing/score.md) 17 | 18 | ## Simple CRUD API 19 | - [Assignment](assignments/crud-api/assignment.md) 20 | - [Scoring](assignments/crud-api/score.md) 21 | 22 | ## Battleship backend 23 | - [Assignment](assignments/battleship/assignment.md) 24 | - [Scoring](assignments/battleship/score.md) 25 | 26 | ## GraphQL service 27 | - [Assignment](assignments/graphql-service/assignment.md) 28 | - [Scoring](assignments/graphql-service/score.md) 29 | 30 | ## REST Service: Basic 31 | - [Assignment](assignments/rest-service/assignment.md) 32 | - [Scoring](assignments/rest-service/score.md) 33 | 34 | ## REST service: Database & ORM 35 | - [Assignment](assignments/database-orm/assignment.md) 36 | - [Scoring](assignments/database-orm/score.md) 37 | 38 | ## REST service: Logging & Error handling 39 | - [Assignment](assignments/logging-error-handling/assignment.md) 40 | - [Scoring](assignments/logging-error-handling/score.md) 41 | 42 | ## REST service: Authentication & Authorization 43 | - [Assignment](assignments/authentication/assignment.md) 44 | - [Scoring](assignments/authentication/score.md) 45 | 46 | ## REST service: Containerization 47 | - [Assignment](assignments/containerization/assignment.md) 48 | - [Scoring](assignments/containerization/score.md) 49 | -------------------------------------------------------------------------------- /assignments/authentication/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/authentication-jwt/README.md) 2 | 3 | # Authentication and Authorization 4 | 5 | ## Description 6 | 7 | Your task is to implement Authentication and Authorization with JWT (Access and Refresh tokens) 8 | - User can **signup** new account with personal login & password 9 | – User can **login** with personal login & password, server returns response with Access token and Refresh token (Refresh token is in advanced scope). 10 | - **Refresh** token helps to get new pair Access/Refresh tokens (optional) 11 | – User now should use valid Access token to access resources 12 | – When the Access token is expired, user can't use it anymore 13 | - Refresh token helps to get new pair Access/Refresh tokens (optional) 14 | 15 | ## Technical requirements 16 | 17 | - Task should be implemented on Typescript 18 | - Use 22.x.x version (22.14.0 or upper) of Node.js 19 | 20 | ## Implementation details 21 | 22 | 1. Endpoints 23 | * `Signup` (`auth/signup` route) 24 | * `POST auth/signup` - send `login` and `password` to create a new `user` 25 | - Server should answer with `status code` **201** and corresponding message if dto is valid 26 | - Server should answer with `status code` **400** and corresponding message if dto is invalid (no `login` or `password`, or they are not a `strings`) 27 | * `Login` (`auth/login` route) 28 | * `POST auth/login` - send `login` and `password` to get Access token and Refresh token (optionally) 29 | - Server should answer with `status code` **200** and tokens if dto is valid 30 | - Server should answer with `status code` **400** and corresponding message if dto is invalid (no `login` or `password`, or they are not a `strings`) 31 | - Server should answer with `status code` **403** and corresponding message if authentication failed (no user with such `login`, `password` doesn't match actual one, etc.) 32 | * `Refresh` (`auth/refresh` route) 33 | * `POST auth/refresh` - send refresh token in body as `{ refreshToken }` to get new pair of Access token and Refresh token 34 | - Server should answer with `status code` **200** and tokens in body if dto is valid 35 | - Server should answer with `status code` **401** and corresponding message if dto is invalid (no `refreshToken` in body) 36 | - Server should answer with `status code` **403** and corresponding message if authentication failed (Refresh token is invalid or expired) 37 | 38 | 2. Once **POST** `/auth/signup` accepts `password` property, it is replaced with **hash** (for example, you can use [bcrypt package](https://www.npmjs.com/package/bcrypt) or its equivalent like `bcryptjs`) for password encryption, no raw passwords should be in database (NB! Password should remain hashed after any operation with service). 39 | 40 | 3. **JWT** Access token should contain `userId` and `login` in a **payload** and has expiration time (expiration time of Refresh token should be longer, than Access token). 41 | 42 | 4. The **JWT** Access token should be added in HTTP `Authorization` header to all requests that requires authentication. Proxy all the requests (except `auth/signup`, `auth/login`, `/doc`, `/`) and check that HTTP `Authorization` header has the correct value of **JWT** Access token. 43 | HTTP authentication must follow `Bearer` scheme: 44 | ``` 45 | Authorization: Bearer 46 | ``` 47 | 5. In case of the HTTP `Authorization` header in the request is absent or invalid or doesn’t follow `Bearer` scheme or Access token has expired, further router method execution should be stopped and lead to response with HTTP **401** code and the corresponding error message. 48 | 49 | 6. Secrets used for signing the tokens should be stored in `.env` file. 50 | 51 | ### `bcrypt` installation issues: 52 | 53 | #### If you see an error that starts with: 54 | 55 | ```console 56 | gyp ERR! stack Error: "pre" versions of node cannot be installed, use the --nodedir flag instead 57 | ``` 58 | Please check [compatibility between Node.JS and Bcrypt versions](https://www.npmjs.com/package/bcrypt#version-compatibility). 59 | 60 | #### If you face an error like this: 61 | 62 | ```console 63 | 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 64 | ``` 65 | 66 | 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). 67 | -------------------------------------------------------------------------------- /assignments/authentication/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: Authentication & Authorization 2 | 3 | ## Basic Scope 4 | 5 | - **+30** Route `/auth/signup` implemented correctly, related logic is divided between controller and corresponding service 6 | - **+30** Route `/auth/login` has been implemented, related logic is divided between controller and corresponding service 7 | - **+10** `User` `password` saved into database as hash 8 | - **+20** Access Token is implemented,`JWT` payload contains `userId` and `login`, secret key is saved in `.env`. 9 | - **+40** Authentication is required for the access to all routes except `/auth/signup`, `/auth/login`, `/doc` and `/`. 10 | - **+10** Separate module is implemented **within application scope** to check that all requests to all routes except mentioned above contain required JWT token 11 | 12 | ## Advanced Scope 13 | 14 | - **+30** Route `/auth/refresh` implemented correctly, related logic is divided between controller and corresponding service 15 | 16 | ## Forfeits 17 | 18 | - **-10** for each failing test with `npm run test:auth` (this forfeit applied once if coincides with same forfeit in different assignments in case there are multiple assignments in task) 19 | - **-30% of max task score** Commits after deadline, except commits that affect only Readme.md, .gitignore, etc.(this forfeit applied once if coincides with same forfeit in different assignments in case there are multiple assignments in task) 20 | - **-20** Missing PR or its description is incorrect 21 | - **-20** No separate development branch 22 | - **-20** Less than 3 commits in the development branch, not taking into account commits, making changes only in `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) -------------------------------------------------------------------------------- /assignments/basic-testing/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/testing/README.md) 2 | 3 | # Assignment: Basic testing 4 | 5 | ## Description 6 | 7 | Your task is to write unit tests using [Jest](https://jestjs.io) API. 8 | 9 | Fork [this repository](https://github.com/AlreadyBored/basic-testing) 10 | 11 | Assignment contains several nested folders inside `src`. Your task is to write unit tests inside test cases 12 | 13 | ## Technical requirements 14 | 15 | Follow instructions in repository's `Readme.md` -------------------------------------------------------------------------------- /assignments/basic-testing/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: Basic testing 2 | 3 | ## Check 4 | For check simplification you have pre-implemented npm-scripts in `package.json` 5 | 6 | ## Basic Scope 7 | 8 | For each implemented test-case: 9 | - **+6** if test case is implemented correctly 10 | - **+3** if test case is implemented incorrectly 11 | - **0** if test case is not implemented 12 | 13 | Test case is considered to be correctly implemented if: 14 | - Actually tests what's described in its title 15 | 16 | Bad: 17 | ```ts 18 | test('should return null if one of arguments is negative number', () => { 19 | const result = sumPositiveNumbers(2, 3); 20 | expect(result).toBe(5); 21 | }); 22 | ``` 23 | Good: 24 | ```ts 25 | test('should return null if one of arguments is negative number', () => { 26 | const result = sumPositiveNumbers(1, -1); 27 | expect(result).toBeNull(); 28 | }); 29 | ``` 30 | - Doesn't break in case if we break functionality that is being tested 31 | ```ts 32 | // isEven.ts 33 | 34 | export const isEven = (num: number) => { 35 | return num % 2 === 0 ? 'Yes' : 'No'; 36 | }; 37 | ``` 38 | Good: 39 | ```ts 40 | test('should return "Yes" for even numbers', () => { 41 | const result = isEven(8); 42 | expect(result).toBe('Yes'); 43 | }); 44 | ``` 45 | Bad: 46 | ```ts 47 | test('should return "Yes" for even numbers', () => { 48 | const result = isEven(8); 49 | expect(typeof result).toBe('string'); 50 | }); 51 | ``` 52 | - Stable (multiple runs produce same test result) 53 | - Isolated (don't rely on external data/don't perform external API calls) 54 | 55 | ## Forfeits 56 | 57 | - **-5** for each linter warning 58 | - **-10** for each linter/TS compiler error 59 | - **-30% of total task score** Commits after deadline (except commits that affect only Readme.md, .gitignore, etc.) 60 | -------------------------------------------------------------------------------- /assignments/battleship/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/websocket/README.md) 2 | 3 | # Assignment: Websocket battleship server 4 | 5 | ## Description 6 | 7 | Your task is to implement battleship game backend using websocket. 8 | 9 | Player interface for your battleship backend is [here](https://github.com/rolling-scopes-school/websockets-ui). You should clone or copy this repository and write the code there. 10 | 11 | The backend should be able to do the following: 12 | - Start websocket server 13 | - Handle websocket connection 14 | - Handle player requests 15 | - Handle room requests 16 | - Handle ships requests 17 | - Handle game requests 18 | - Create single play bot (optional) 19 | 20 | ## Technical requirements 21 | 22 | - Task can be implemented on Javascript or Typescript 23 | - Use 22.x.x version (22.14.0 or upper) of Node.js 24 | - Only [ws](https://www.npmjs.com/package/ws), `cross-env`, `typescript`, `tsx`, `ts-node`, `ts-node-dev`, `nodemon`, `dotenv`, `eslint` and its plugins, `webpack` and its plugins, `prettier`, `@types/*` and testing tools (for example, Jest, Mocha, AVA, Jasmine, Cypress, Storybook, Puppeteer) are allowed 25 | - The program is started by npm script `start` in following way: 26 | - All requests and responses must be sent as JSON string 27 | 28 | ```bash 29 | npm run start 30 | ``` 31 | 32 | - After starting the program displays websocket parameters 33 | - After program work finished the program should end websocket work correctly 34 | - After each received command program should display the command and result 35 | 36 | ## The backend should have 3 types of response: 37 | 1. personal response 38 | - reg - player registration/login 39 | 2. response for the game room 40 | - create_game - game id and player id (unique id for user in this game) 41 | - start_game - informationa about game and player's ships positions 42 | - turn - who is shooting now 43 | - attack - coordinates of shot and status 44 | - finish - id of the winner 45 | 3. response for all 46 | - update_room - list of rooms and players in rooms 47 | - update_winners - send score table to players 48 | 49 | ## Game description 50 | 1. We should have inmemory DB with player data (login and password) storage 51 | 2. Player can create game room or connect to the game room after login 52 | 3. Player room data (players, game board, ships positions) storages in the server 53 | 3. Game starts after 2 players are connected to the room and sent ships positions to the server 54 | 4. Server sends move order 55 | 5. Players should shoot in their's turn 56 | 6. Server send back shot result 57 | 7. If player hits or kills the ship, player should make one more shoot 58 | 8. Player wins if he have killed all enemies ships 59 | 60 | ## List of websocket commands (requests/responses) and their syntax (<- - cmd from frontend, -> - answer): 61 | ### - data value should be a **json string** 62 | ### - id should be always 0 63 | - Player 64 | - Login or create player\ 65 | ```<-``` 66 | ```ts 67 | { 68 | type: "reg", 69 | data: 70 | { 71 | name: , 72 | password: , 73 | }, 74 | id: 0, 75 | } 76 | ``` 77 | ```->``` 78 | ```ts 79 | { 80 | type: "reg", 81 | data: 82 | { 83 | name: , 84 | index: , 85 | error: , 86 | errorText: , 87 | }, 88 | id: 0, 89 | } 90 | ``` 91 | - Update winners (for all after every winners table update)\ 92 | ```->``` 93 | ```ts 94 | { 95 | type: "update_winners", 96 | data: 97 | [ 98 | { 99 | name: , 100 | wins: , 101 | } 102 | ], 103 | id: 0, 104 | } 105 | ``` 106 | - Room 107 | - Create new room (create game room and add yourself there)\ 108 | ```<-``` 109 | ```ts 110 | { 111 | type: "create_room", 112 | data: "", 113 | id: 0, 114 | } 115 | ``` 116 | - Add user to room (add youself to somebodys room, then remove the room from available rooms list)\ 117 | ```<-``` 118 | ```ts 119 | { 120 | type: "add_user_to_room", 121 | data: 122 | { 123 | indexRoom: , 124 | }, 125 | id: 0, 126 | } 127 | ``` 128 | ```->``` 129 | ```ts 130 | { 131 | type: "create_game", //send for both players in the room, after they are connected to the room 132 | data: 133 | { 134 | idGame: , 135 | idPlayer: , /* generated by server id for player in the game session, not enemy (unique id for every player) */ 136 | }, 137 | id: 0, 138 | } 139 | ``` 140 | - Update room state (send rooms list, where only one player inside)\ 141 | ```->``` 142 | ```ts 143 | { 144 | type: "update_room", 145 | data: 146 | [ 147 | { 148 | roomId: , 149 | roomUsers: 150 | [ 151 | { 152 | name: , 153 | index: , 154 | } 155 | ], 156 | }, 157 | ], 158 | id: 0, 159 | } 160 | ``` 161 | - Ships 162 | - Add ships to the game board\ 163 | ```<-``` 164 | ```ts 165 | { 166 | type: "add_ships", 167 | data: 168 | { 169 | gameId: , 170 | ships: 171 | [ 172 | { 173 | position: { 174 | x: , 175 | y: , 176 | }, 177 | direction: , 178 | length: , 179 | type: "small"|"medium"|"large"|"huge", 180 | } 181 | ], 182 | indexPlayer: , /* id of the player in the current game session */ 183 | }, 184 | id: 0, 185 | } 186 | ``` 187 | - Start game (only after server receives both player's ships positions)\ 188 | ```->``` 189 | ```ts 190 | { 191 | type: "start_game", 192 | data: 193 | { 194 | ships: /* player's ships, not enemy's */ 195 | [ 196 | { 197 | position: { 198 | x: , 199 | y: , 200 | }, 201 | direction: , 202 | length: , 203 | type: "small"|"medium"|"large"|"huge", 204 | } 205 | ], 206 | currentPlayerIndex: , /* id of the player in the current game session, who have sent his ships */ 207 | }, 208 | id: 0, 209 | } 210 | ``` 211 | - Game 212 | - Attack\ 213 | ```<-``` 214 | ```ts 215 | { 216 | type: "attack", 217 | data: 218 | { 219 | gameId: , 220 | x: , 221 | y: , 222 | indexPlayer: , /* id of the player in the current game session */ 223 | }, 224 | id: 0, 225 | } 226 | ``` 227 | - Attack feedback (should be sent after every shot, miss and after kill sent miss for all cells around ship too)\ 228 | ```->``` 229 | ```ts 230 | { 231 | type: "attack", 232 | data: 233 | { 234 | position: 235 | { 236 | x: , 237 | y: , 238 | }, 239 | currentPlayer: , /* id of the player in the current game session */ 240 | status: "miss"|"killed"|"shot", 241 | }, 242 | id: 0, 243 | } 244 | ``` 245 | - Random attack\ 246 | ```<-``` 247 | ```ts 248 | { 249 | type: "randomAttack", 250 | data: 251 | { 252 | gameId: , 253 | indexPlayer: , /* id of the player in the current game session */ 254 | }, 255 | id: 0, 256 | } 257 | ``` 258 | - Info about player's turn (send after game start and every attack, miss or kill result)\ 259 | ```->``` 260 | ```ts 261 | { 262 | type: "turn", 263 | data: 264 | { 265 | currentPlayer: , /* id of the player in the current game session */ 266 | }, 267 | id: 0, 268 | } 269 | ``` 270 | - Finish game\ 271 | ```->``` 272 | ```ts 273 | { 274 | type: "finish", 275 | data: 276 | { 277 | winPlayer: , /* id of the player in the current game session */ 278 | }, 279 | id: 0, 280 | } 281 | ``` 282 | 283 | ## Websocket commands sequence 284 | ``` 285 | Player1 Server Player2 286 | reg --> 287 | <-- reg 288 | <-- update_room 289 | <-- update_winners 290 | create_room --> 291 | <-- update_room 292 | <-- reg 293 | reg --> 294 | <-- update_room --> 295 | <-- update_winners --> 296 | <-- add_user_to_room 297 | <-- update_room --> 298 | <-- create_game --> 299 | add_ships --> 300 | <-- add_ships 301 | <-- start_game --> 302 | <-- turn --> 303 | attack (miss) --> 304 | <-- attack --> 305 | <-- turn --> 306 | <-- randomAttack (shoot) 307 | <-- attack --> 308 | <-- turn --> 309 | <-- randomAttack (kill) - send state for all cells around killed ship 310 | <-- attack --> 311 | <-- turn --> 312 | <-- attack --> 313 | <-- turn --> 314 | <-- attack --> 315 | <-- turn --> 316 | <-- attack --> 317 | <-- turn --> 318 | ... 319 | <-- randomAttack (miss) 320 | <-- attack --> 321 | <-- turn --> 322 | attack (miss) --> 323 | <-- attack --> 324 | <-- turn --> 325 | ... 326 | <-- finish --> 327 | <-- update_winners --> 328 | ``` 329 | -------------------------------------------------------------------------------- /assignments/battleship/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: Websocket battleship server 2 | 3 | ## Basic Scope 4 | 5 | - Websocket 6 | - **+6** Implemented workable websocket server 7 | - **+6** Handle websocket clients connection/disconnection properly 8 | - **+10** Websocket server message handler implemented properly 9 | - **+10** Websocket server message sender implemented properly 10 | - User 11 | - **+5** Create user with password in temprorary database 12 | - **+5** User validation 13 | - Room 14 | - **+6** Create game room 15 | - **+6** Add user to game room 16 | - **+6** Start game 17 | - **+6** Finish game 18 | - **+8** Update room's game state 19 | - **+4** Update player's turn 20 | - **+8** Update players winner table 21 | - Ships 22 | - **+10** Locate ship to the game board 23 | - Game 24 | - **+8** Attack 25 | - **+4** Random attack 26 | 27 | ## Advanced Scope 28 | - **+30** Task implemented on Typescript 29 | - **+20** Codebase is separated (at least 4 modules) 30 | - **+30** Make bot for single play (optionally) 31 | 32 | ## Forfeits 33 | 34 | - **-95% of total task score** any external tools except `ws`, `cross-env`, `dotenv`, `tsx`, `typescript`, `ts-node`, `ts-node-dev`, `nodemon`, `eslint` and its plugins, `webpack` and its plugins, `prettier`, `@types/*` and testing tools (for example, Jest, Mocha, AVA, Jasmine, Cypress, Storybook, Puppeteer) 35 | - **-30% of total task score** Commits after deadline (except commits that affect only Readme.md, .gitignore, etc.) 36 | - **-10** Missing PR or its description is incorrect 37 | - **-10** No separate development branch 38 | - **-10** Less than 3 commits in the development branch, not including commits that make changes only to `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 39 | -------------------------------------------------------------------------------- /assignments/containerization-database-orm/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module 1 (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/containerization/README.md) 2 | 3 | # [Course program module 2 (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/database-orm/README.md) 4 | 5 | ## REST service: Containerization, Docker and Database & ORM 6 | 7 | ## Prerequisites 8 | 9 | 1. Install [Docker](https://docs.docker.com/engine/install/) 10 | 2. Create `Docker Hub` account [Docker Hub](https://hub.docker.com/) 11 | 12 | ## Technical requirements 13 | - Use 22.x.x version (22.14.0 or upper) of Node.js 14 | 15 | ## Description 16 | 17 | # 1) Containerization, Docker 18 | 19 | Your task is to build and run multi-container application using Docker. 20 | 21 | # 2) Database & ORM 22 | 23 | Your task is to implement PostgreSQL database as source of data for your application and TypeORM / Prisma to communicate with your database. 24 | 25 | 26 | ## Implementation details 27 | 28 | # 1) Containerization, Docker 29 | 30 | 1. Create `.dockerignore` file and list all files that should be ignored by `Docker`. 31 | 2. Create `Dockerfile` that will be used for building image of `PostgreSQL` database. 32 | 3. Create `Dockerfile` that will be used for building image of your application. 33 | 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. 34 | 6. Build images and scan it for security vulnerabilities. 35 | 7. Push built images to your personal or private repository on `Docker Hub`. 36 | 37 | # 2) Database (PostgreSQL) & ORM 38 | 39 | 1. Use **PostgreSQL** database to store **REST** service data (`Users`, `Albums`, `Tracks`, `Artists`, `Favorites`) 40 | 2. Use [TypeORM](https://typeorm.io/#/) or [Prisma](https://www.prisma.io/) with Nest.js to store and update data 41 | 3. The information on DB connection should be stored in `.env` file 42 | 4. **PostgreSQL** database should run inside of the `docker` container 43 | -------------------------------------------------------------------------------- /assignments/containerization-database-orm/score.md: -------------------------------------------------------------------------------- 1 | ## REST service: Containerization and Database (PostgreSQL) & ORM 2 | 3 | ## Basic Scope 4 | 5 | # 1) Containerization, Docker 6 | 7 | - **+20** `Readme.md` has instruction how to run application 8 | - **+30** `user-defined bridge` is created and configured 9 | - **+30** container auto restart after crash 10 | - **+20** application is restarting upon changes implemented into `src` folder 11 | - **+30** database files and logs to be stored in volumes instead of container 12 | 13 | # 2) Database (PostgreSQL) & ORM 14 | 15 | - **+20** `Users` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 16 | - **+20** `Artists` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 17 | - **+20** `Albums` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 18 | - **+20** `Tracks` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 19 | - **+20** `Favorites` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 20 | 21 | 22 | ## Advanced Scope 23 | 24 | # 1) Containerization, Docker 25 | 26 | - **+20** Final size of the Docker image with application is less than 500 MB 27 | - **+10** Implemented npm script for vulnerabilities scanning (free solution) 28 | - **+20** Your built image is pushed to DockerHub 29 | 30 | # 2) Database & ORM 31 | 32 | - **+30** Migrations are used to create database entities 33 | - **+10** Variables used for connection to database to be stored in `.env` 34 | - **+10** `typeorm` [decorators](https://typeorm.io/#/relations) or `prisma` relations create relations between entities 35 | - **+30** Local **PostgreSQL** installation is not required for task check, connection is implemented to database stored in `docker` container (on the basis of the previous task) 36 | 37 | ## Forfeits 38 | 39 | - **-20** In case specific image is not used (it is required to use images like `postgres` and `node`, but not `ubuntu` with installation of `node` or `postgres`) 40 | - **-20** Postgres container is not configured as dependency for application container 41 | - **-10** for each failing test with `npm run test` 42 | - **-20** `docker-compose.yml` contains hardcoded variables 43 | - **-30% of total task score** Commits after deadline, except commits that affect only Readme.md, .gitignore, etc. 44 | - **-40** No Pull Request created 45 | - **-20** PR description is incorrect 46 | - **-40** No separate development branch 47 | - **-20** Less than 3 commits in the development branch, not taking into account commits, making changes only in `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 48 | - **-10 points** for each error either on `npm run lint` on the basis of the **local config** or for compilation errors on the basis of the **local tsconfig** (`errors` not `warnings`). 49 | -------------------------------------------------------------------------------- /assignments/containerization/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/containerization/README.md) 2 | 3 | ## REST service: Containerization, Docker 4 | 5 | ## Description 6 | 7 | Your task is to build and run multi-container application using Docker. 8 | ## Prerequisites 9 | 10 | 1. Install [Docker](https://docs.docker.com/engine/install/) 11 | 2. Create `Docker Hub` account [Docker Hub](https://hub.docker.com/) 12 | 13 | ## Implementation details 14 | 15 | 1. Create `.dockerignore` file and list all files that should be ignored by `Docker`. 16 | 2. Create `Dockerfile` that will be used for building image of `PostgreSQL` database. 17 | 3. Create `Dockerfile` that will be used for building image of your application. 18 | 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. 19 | 6. Build images and scan it for security vulnerabilities. 20 | 7. Push built images to your personal or private repository on `Docker Hub`. 21 | -------------------------------------------------------------------------------- /assignments/containerization/score.md: -------------------------------------------------------------------------------- 1 | ## REST service: Containerization, Docker 2 | 3 | ## Basic Scope 4 | 5 | - **+20** `Readme.md` has instruction how to run application 6 | - **+30** `user-defined bridge` is created and configured 7 | - **+30** container auto restart after crash 8 | - **+20** application is restarting upon changes implemented into `src` folder 9 | - **+30** database files and logs to be stored in volumes instead of container 10 | 11 | ## Advanced Scope 12 | 13 | - **+20** Final size of the Docker image with application is less than 650 MB 14 | - **+10** Implemented npm script for vulnerabilities scanning (free solution) 15 | - **+20** Your built image is pushed to DockerHub 16 | 17 | ## Forfeits 18 | 19 | - **-20** In case specific image is not used (it is required to use images like `postgres` and `node`, but not `ubuntu` with installation of `node` or `postgres`) 20 | - **-20** Postgres container is not configured as dependency for application container 21 | - **-20** `docker-compose.yml` contains hardcoded variables 22 | - **-30% of total task score** Commits after deadline, except commits that affect only Readme.md, .gitignore, etc.(this forfeit applied once if coincides with same forfeit in different assignments in case there are multiple assignments in task) 23 | - **-20** Missing PR 24 | - **-10** PR description is incorrect 25 | - **-20** No separate development branch 26 | -------------------------------------------------------------------------------- /assignments/crud-api/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/crud-api/README.md) 2 | 3 | # Assignment: CRUD API 4 | 5 | ## Description 6 | 7 | Your task is to implement simple CRUD API using in-memory database underneath. 8 | 9 | ## Technical requirements 10 | 11 | - Task can be implemented on Javascript or Typescript 12 | - Only `nodemon`, `dotenv`, `cross-env`, `typescript`, `ts-node`, `ts-node-dev`, `eslint` and its plugins, `webpack-cli`, `webpack` and its plugins and loaders, `prettier`, `uuid`, `@types/*` as well as libraries used for testing are allowed 13 | - Use 22.x.x version (22.14.0 or upper) of Node.js 14 | - Prefer asynchronous API whenever possible 15 | 16 | ## Implementation details 17 | 18 | 1. Implemented endpoint `api/users`: 19 | - **GET** `api/users` is used to get all persons 20 | - Server should answer with `status code` **200** and all users records 21 | - **GET** `api/users/{userId}` 22 | - Server should answer with `status code` **200** and record with `id === userId` if it exists 23 | - Server should answer with `status code` **400** and corresponding message if `userId` is invalid (not `uuid`) 24 | - Server should answer with `status code` **404** and corresponding message if record with `id === userId` doesn't exist 25 | - **POST** `api/users` is used to create record about new user and store it in database 26 | - Server should answer with `status code` **201** and newly created record 27 | - Server should answer with `status code` **400** and corresponding message if request `body` does not contain **required** fields 28 | - **PUT** `api/users/{userId}` is used to update existing user 29 | - Server should answer with` status code` **200** and updated record 30 | - Server should answer with` status code` **400** and corresponding message if `userId` is invalid (not `uuid`) 31 | - Server should answer with` status code` **404** and corresponding message if record with `id === userId` doesn't exist 32 | - **DELETE** `api/users/{userId}` is used to delete existing user from database 33 | - Server should answer with `status code` **204** if the record is found and deleted 34 | - Server should answer with `status code` **400** and corresponding message if `userId` is invalid (not `uuid`) 35 | - Server should answer with `status code` **404** and corresponding message if record with `id === userId` doesn't exist 36 | 2. Users are stored as `objects` that have following properties: 37 | - `id` — unique identifier (`string`, `uuid`) generated on server side 38 | - `username` — user's name (`string`, **required**) 39 | - `age` — user's age (`number`, **required**) 40 | - `hobbies` — user's hobbies (`array` of `strings` or empty `array`, **required**) 41 | 3. Requests to non-existing endpoints (e.g. `some-non/existing/resource`) should be handled (server should answer with `status code` **404** and corresponding human-friendly message) 42 | 4. Errors on the server side that occur during the processing of a request should be handled and processed correctly (server should answer with `status code` **500** and corresponding human-friendly message) 43 | 5. Value of `port` on which application is running should be stored in `.env` file 44 | 6. There should be 2 modes of running application (**development** and **production**): 45 | - The application is run in development mode using `nodemon` or `ts-node-dev` (there is a `npm` script `start:dev`) 46 | - The application is run in production mode (there is a `npm` script `start:prod` that starts the build process and then runs the bundled file) 47 | 7. There could be some tests for API (not less than **3** scenarios). Example of test scenario: 48 | 1. Get all records with a `GET` `api/users` request (an empty array is expected) 49 | 2. A new object is created by a `POST` `api/users` request (a response containing newly created record is expected) 50 | 3. With a `GET` `api/users/{userId}` request, we try to get the created record by its `id` (the created record is expected) 51 | 4. We try to update the created record with a `PUT` `api/users/{userId}`request (a response is expected containing an updated object with the same `id`) 52 | 5. With a `DELETE` `api/users/{userId}` request, we delete the created object by `id` (confirmation of successful deletion is expected) 53 | 6. With a `GET` `api/users/{userId}` request, we are trying to get a deleted object by `id` (expected answer is that there is no such object) 54 | 8. There could be implemented horizontal scaling for application, there should be `npm` script `start:multi` that starts multiple instances of your application using the Node.js `Cluster` API (equal to the number of available parallelism - 1 on the host machine, each listening on port PORT + n) with a **load balancer** that distributes requests across them (using Round-robin algorithm). For example: available parallelism is 4, `PORT` is 4000. On run `npm run start:multi` it works following way 55 | - On `localhost:4000/api` load balancer is listening for requests 56 | - On `localhost:4001/api`, `localhost:4002/api`, `localhost:4003/api` workers are listening for requests from load balancer 57 | - When user sends request to `localhost:4000/api`, load balancer sends this request to `localhost:4001/api`, next user request is sent to `localhost:4002/api` and so on. 58 | - After sending request to `localhost:4003/api` load balancer starts from the first worker again (sends request to `localhost:4001/api`) 59 | - State of db should be consistent between different workers, for example: 60 | 1. First `POST` request addressed to `localhost:4001/api` creates user 61 | 2. Second `GET` request addressed to `localhost:4002/api` should return created user 62 | 3. Third `DELETE` request addressed to `localhost:4003/api` deletes created user 63 | 4. Fourth `GET` request addressed to `localhost:4001/api` should return **404** status code for created user 64 | -------------------------------------------------------------------------------- /assignments/crud-api/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: CRUD API 2 | 3 | ## Basic Scope 4 | 5 | - **+10** The repository with the application contains a `Readme.md` file containing detailed instructions for installing, running and using the application 6 | - **+10** **GET** `api/users` implemented properly 7 | - **+10** **GET** `api/users/{userId}` implemented properly 8 | - **+10** **POST** `api/users` implemented properly 9 | - **+10** **PUT** `api/users/{userId}` implemented properly 10 | - **+10** **DELETE** `api/users/{userId}` implemented properly 11 | - **+6** Users are stored in the form described in the technical requirements 12 | - **+6** Value of `port` on which application is running is stored in `.env` file 13 | 14 | ## Advanced Scope 15 | - **+30** Task implemented on Typescript 16 | - **+10** Processing of requests to non-existing endpoints implemented properly 17 | - **+10** Errors on the server side that occur during the processing of a request should be handled and processed properly 18 | - **+10** Development mode: `npm` script `start:dev` implemented properly 19 | - **+10** Production mode: `npm` script `start:prod` implemented properly 20 | 21 | ## Hacker Scope 22 | - **+30** There are tests for API (not less than **3** scenarios) 23 | - **+50** There is horizontal scaling for application with a **load balancer** 24 | 25 | ## Forfeits 26 | 27 | - **-95% of total task score** any external tools except `nodemon`, `dotenv`, `cross-env`, `typescript`, `ts-node`, `ts-node-dev`, `eslint` and its plugins, `webpack` and its plugins, `prettier` and it's plugins, `uuid`, `@types/*` as well as libraries used for testing 28 | - **-30% of total task score** Commits after deadline (except commits that affect only Readme.md, .gitignore, etc.) 29 | - **-20** Missing PR or its description is incorrect 30 | - **-20** No separate development branch 31 | - **-20** Less than 3 commits in the development branch, not including commits that make changes only to `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 32 | -------------------------------------------------------------------------------- /assignments/database-orm/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/database-orm/README.md) 2 | 3 | # REST service: PostgreSQL & ORM 4 | 5 | ## Description 6 | 7 | Your task is to implement PostgreSQL database as source of data for your application and TypeORM / Prisma to communicate with your database. 8 | 9 | 1. Use **PostgreSQL** database to store **REST** service data (`Users`, `Albums`, `Tracks`, `Artists`, `Favorites`) 10 | 2. Use [Typeorm](https://typeorm.io/#/) or [Prisma](https://www.prisma.io/) with Nest.js to store and update data 11 | 3. The information on DB connection should be stored in `.env` file 12 | 4. **PostgreSQL** database should run inside of the `docker` container 13 | -------------------------------------------------------------------------------- /assignments/database-orm/score.md: -------------------------------------------------------------------------------- 1 | # REST service: PostgreSQL & ORM 2 | 3 | ## Basic Scope 4 | 5 | - **+20** `Users` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 6 | - **+20** `Artists` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 7 | - **+20** `Albums` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 8 | - **+20** `Tracks` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 9 | - **+20** `Favorites` data is stored in **PostgreSQL** database and `typeorm` / `prisma` interacts with the database to manipulate data. 10 | 11 | ## Advanced Scope 12 | 13 | - **+30** Migrations are used to create database entities 14 | - **+10** Variables used for connection to database to be stored in `.env` 15 | - **+10** `typeorm` [decorators](https://typeorm.io/#/relations) or `prisma` relations create relations between entities 16 | - **+30** Local **PostgreSQL** installation is not required for task check, connection is implemented to database stored in `docker` container (on the basis of the previous task) 17 | 18 | 19 | ## Forfeits 20 | - **-10** for each failing test with `npm run test` (this forfeit applied once if coincides with same forfeit in different assignments in case there are multiple assignments in task) 21 | - **-30% of max task score** Commits after deadline, except commits that affect only Readme.md, .gitignore, etc.(this forfeit applied once if coincides with same forfeit in different assignments in case there are multiple assignments in task) 22 | - **-20** No separate development branch 23 | - **-20** No Pull Request 24 | - **-10** Pull Request description is incorrect 25 | - **-20** Less than 3 commits in the development branch, not including commits that make changes only to `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 26 | - **-10 points** for each lint error either on `npm run lint` on the basis of the **local config** or for compilation errors on the basis of the **local tsconfig** (`errors` not `warnings`). 27 | -------------------------------------------------------------------------------- /assignments/file-manager/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/nodejs-application/README.md) 2 | 3 | # Assignment: File Manager 4 | 5 | ## Description 6 | 7 | Your task is to implement File Manager using Node.js APIs. 8 | 9 | The file manager should be able to do the following: 10 | 11 | - Work using CLI 12 | - Perform basic file operations (copy, move, delete, rename, etc.) 13 | - Utilize Streams API 14 | - Get information about the host machine operating system 15 | - Perform hash calculations 16 | - Compress and decompress files 17 | 18 | ## Technical requirements 19 | 20 | - No external dependencies should be required 21 | - Use 22.x.x version (22.14.0 or upper) of Node.js 22 | - The program is started by npm-script `start` in following way: 23 | ```bash 24 | npm run start -- --username=your_username 25 | ``` 26 | - After starting the program displays the following text in the console (`Username` is equal to value that was passed on application start in `--username` CLI argument) 27 | `Welcome to the File Manager, Username!` 28 | - After program work finished (`ctrl + c` pressed or user sent `.exit` command into console) the program displays the following text in the console 29 | `Thank you for using File Manager, Username, goodbye!` 30 | - At the start of the program and after each end of input/operation current working directory should be printed in following way: 31 | `You are currently in path_to_working_directory` 32 | - Starting working directory is current user's home directory (for example, on Windows it's something like `system_drive/Users/Username`) 33 | - By default program should prompt user in console to print commands and wait for results 34 | - In case of unknown operation or invalid input (missing mandatory arguments, wrong data in arguments, etc.) `Invalid input` message should be shown and user should be able to enter another command 35 | - In case of error during execution of operation `Operation failed` message should be shown and user should be able to enter another command (e.g. attempt to perform an operation on a non-existent file or work on a non-existent path should result in the operation fail) 36 | - User can't go upper than root directory (e.g. on Windows it's current local drive root). If user tries to do so, current working directory doesn't change 37 | 38 | List of operations and their syntax: 39 | - Navigation & working directory (nwd) 40 | - Go upper from current directory (when you are in the root folder this operation shouldn't change working directory) 41 | ```bash 42 | up 43 | ``` 44 | - Go to dedicated folder from current directory (`path_to_directory` can be relative or absolute) 45 | ```bash 46 | cd path_to_directory 47 | ``` 48 | - Print in console list of all files and folders in current directory. List should contain: 49 | - list should contain files and folder names (for files - with extension) 50 | - folders and files are sorted in alphabetical order ascending, but list of folders goes first 51 | - type of directory content should be marked explicitly (e.g. as a corresponding column value) 52 | ```bash 53 | ls 54 | ``` 55 | Example of how `ls` command output may look like 56 | ![ls output example](./ls-example.JPG) 57 | - Basic operations with files 58 | - Read file and print it's content in console (should be done using Readable stream): 59 | ```bash 60 | cat path_to_file 61 | ``` 62 | - Create empty file in current working directory: 63 | ```bash 64 | add new_file_name 65 | ``` 66 | - Create new directory in current working directory: 67 | ```bash 68 | mkdir new_directory_name 69 | ``` 70 | - Rename file (content should remain unchanged): 71 | ```bash 72 | rn path_to_file new_filename 73 | ``` 74 | - Copy file (should be done using Readable and Writable streams): 75 | ```bash 76 | cp path_to_file path_to_new_directory 77 | ``` 78 | - Move file (same as copy but initial file is deleted, copying part should be done using Readable and Writable streams): 79 | ```bash 80 | mv path_to_file path_to_new_directory 81 | ``` 82 | - Delete file: 83 | ```bash 84 | rm path_to_file 85 | ``` 86 | - Operating system info (prints following information in console) 87 | - Get EOL (default system End-Of-Line) and print it to console 88 | ```bash 89 | os --EOL 90 | ``` 91 | - Get host machine CPUs info (overall amount of CPUS plus model and clock rate (in GHz) for each of them) and print it to console 92 | ```bash 93 | os --cpus 94 | ``` 95 | - Get home directory and print it to console 96 | ```bash 97 | os --homedir 98 | ``` 99 | - Get current *system user name* (Do not confuse with the username that is set when the application starts) and print it to console 100 | ```bash 101 | os --username 102 | ``` 103 | - Get CPU architecture for which Node.js binary has compiled and print it to console 104 | ```bash 105 | os --architecture 106 | ``` 107 | - Hash calculation 108 | - Calculate hash for file and print it into console 109 | ```bash 110 | hash path_to_file 111 | ``` 112 | - Compress and decompress operations 113 | - Compress file (using Brotli algorithm, should be done using Streams API) 114 | ```bash 115 | compress path_to_file path_to_destination 116 | ``` 117 | - Decompress file (using Brotli algorithm, should be done using Streams API) 118 | ```bash 119 | decompress path_to_file path_to_destination 120 | ``` 121 | NB! After decompressing of previously compressed file result should not differ with originally compressed file 122 | 123 | -------------------------------------------------------------------------------- /assignments/file-manager/ls-example.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlreadyBored/nodejs-assignments/2dafc2768732f33f1896a3f3d6b99cff71e2693f/assignments/file-manager/ls-example.JPG -------------------------------------------------------------------------------- /assignments/file-manager/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: File Manager 2 | ## Basic Scope 3 | - General 4 | - **+6** Application accepts username and prints proper message 5 | - **+10** Application exits if user pressed `ctrl+c` or sent `.exit` command and proper message is printed 6 | - Operations fail 7 | - **+20** Attempts to perform an operation on a non-existent file or work on a non-existent path result in the operation fail 8 | - **+10** Operation fail doesn't crash application 9 | - Navigation & working directory operations implemented properly 10 | - **+10** Go upper from current directory 11 | - **+10** Go to dedicated folder from current directory 12 | - **+20** List all files and folders in current directory 13 | - Basic operations with files implemented properly 14 | - **+10** Read file and print it's content in console 15 | - **+5** Create empty file 16 | - **+5** Create new directory 17 | - **+10** Rename file 18 | - **+10** Copy file 19 | - **+10** Move file 20 | - **+10** Delete file 21 | - Operating system info (prints following information in console) implemented properly 22 | - **+6** Get EOL (default system End-Of-Line) 23 | - **+10** Get host machine CPUs info (overall amount of CPUS plus model and clock rate (in GHz) for each of them) 24 | - **+6** Get home directory 25 | - **+6** Get current *system user name* (Do not confuse with the username that is set when the application starts) 26 | - **+6** Get CPU architecture for which Node.js binary has compiled 27 | - Hash calculation implemented properly 28 | - **+20** Calculate hash for file 29 | - Compress and decompress operations 30 | - **+20** Compress file (using Brotli algorithm) 31 | - **+20** Decompress file (using Brotli algorithm) 32 | 33 | ## Advanced Scope 34 | 35 | - **+30** All operations marked as to be implemented using certain streams should be performed using Streams API 36 | - **+20** No synchronous Node.js API with asynchronous analogues is used (e.g. not used `readFileSync` instead of `readFile`) 37 | - **+20** Codebase is written in ESM modules instead of CommonJS 38 | - **+20** Codebase is separated (at least 7 modules) 39 | 40 | ## Forfeits 41 | 42 | - **-95% of total task score** Any external tools/libraries are used 43 | - **-30% of total task score** Commits after deadline (except commits that affect only `Readme.md`, `.gitignore`, etc.) 44 | -------------------------------------------------------------------------------- /assignments/graphql-service/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/graphql/README.md) 2 | 3 | ## Assignment: Graphql 4 | 5 | ## Source repository 6 | Fork [this repository](https://github.com/nosbog/rsschool-nodejs-task-graphql) to start the task. 7 | 8 | ### Tasks: 9 | 10 | 1. Add logic to the graphql endpoint: ./src/routes/graphql. 11 | Constraints and logic for gql queries should be done based on restful implementation. 12 | As a result, you should get a gql schema like [this](https://github.com/nosbog/rsschool-nodejs-task-graphql/blob/main/schema.graphql). 13 | 1.1. npm run test-queries 14 | 1.2. npm run test-mutations 15 | 2. Limit the complexity of the graphql queries by their depth with [graphql-depth-limit](https://www.npmjs.com/package/graphql-depth-limit) package. 16 | Use value "5" for the package. 17 | 2.1. npm run test-rule 18 | 3. Solve `n+1` graphql problem with [dataloader](https://www.npmjs.com/package/dataloader). 19 | You can use only one "findMany" call per loader to consider this task completed. 20 | 3.1. npm run test-loader 21 | 3.2. npm run test-loader-prime 22 | When you query all users, you don't have to use the database again when you want to find subs. 23 | Pre-place users in the appropriate dataloader cache. 24 | To determine if a user is a sub you need to do the appropriate join ([include](https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#include)). 25 | But only do a join when you need it. You can use [graphql-parse-resolve-info](https://github.com/graphile/graphile-engine/tree/master/packages/graphql-parse-resolve-info) package to parse GraphQLResolveInfo to determine if subs are expected in the response. 26 | 27 | ### Info: 28 | 29 | It is forbidden to add new npm dependencies. 30 | You should only modify/add the code inside the folder ./src/routes/graphql. 31 | You should use [code-first](https://github.dev/graphql/graphql-js/blob/ffa18e9de0ae630d7e5f264f72c94d497c70016b/src/__tests__/starWarsSchema.ts) approach to create a gql server. 32 | Do not create files with the name "index.ts". This name is reserved for fastify plugins. 33 | You are responsible for using style configs that are in the repository. 34 | Make sure the important files have not been changed: npm run test-integrity. 35 | If the test was partially completed, then it is considered not completed. 36 | If the one test was not completed, then the subsequent ones are considered not completed. 37 | 38 | Steps to get started: 39 | 40 | 1. Install dependencies: npm ci 41 | 2. Create .env file (based on .env.example): ./.env 42 | 3. Create db file: ./prisma/database.db 43 | 4. Apply pending migrations: npx prisma migrate deploy 44 | 5. Seed db: npx prisma db seed 45 | 6. Start server: npm run start 46 | 47 | Useful things: 48 | 49 | - Database GUI: npx prisma studio 50 | - Reset database: npx prisma migrate reset (this command triggers db seeding) 51 | - To test an existing rest api (swagger): [::1]:8000/docs 52 | - For ease of test of graphql you can use [api platform](https://learning.postman.com/docs/sending-requests/graphql/graphql-overview/) that can fetch [introspection](https://graphql.org/learn/introspection/) 53 | -------------------------------------------------------------------------------- /assignments/graphql-service/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: Graphql 2 | 3 | ## Basic Scope 4 | - **+144** 1.1 npm run test-queries 5 | - **+90** 1.2 npm run test-mutations 6 | - **+18** 2.1 npm run test-rule 7 | - **+80** 3.1 npm run test-loader 8 | - **+28** 3.2 npm run test-loader-prime 9 | 10 | ## Info 11 | If the test was partially completed, then it is considered not completed. 12 | If the one test was not completed, then the subsequent ones are considered not completed. 13 | 14 | ## Forfeits 15 | - **-100% of max task score** Fails: npm run test-integrity 16 | - **-30% of max task score** Commits after deadline (except commits that affect only Readme.md, .gitignore, etc.) 17 | - **-20** No separate development branch 18 | - **-20** No Pull Request 19 | - **-10** Pull Request description is incorrect 20 | - **-20** Less than 3 commits in the development branch, not including commits that make changes only to `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 21 | -------------------------------------------------------------------------------- /assignments/logging-error-authentication-authorization/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module 1 (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/logging-error-handling/README.md) 2 | 3 | # [Course program module 2 (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/authentication-jwt/README.md) 4 | 5 | # REST service: Logging & Error Handling and Authentication and Authorization 6 | 7 | ## Description 8 | 9 | # 1) Logging & Error Handling. 10 | 11 | Your task is to implement logging functionality to the already existing REST service. 12 | 13 | # 2) Authentication and Authorization 14 | 15 | Your task is to implement Authentication and Authorization with JWT (Access and Refresh tokens). 16 | - User can **signup** new account with personal login & password 17 | – User can **login** with personal login & password, server returns response with Access token and Refresh token (Refresh token is in advanced scope). 18 | - **Refresh** token helps to get new pair Access/Refresh tokens (optional) 19 | – User now should use valid Access token to access resources 20 | – When the Access token is expired, user can't use it anymore 21 | 22 | 23 | ## Technical requirements 24 | 25 | - Only `@nestjs/common` and `@nestjs-core` Nest.js modules can be used for the logger and error handling feature assignment, other Nest.js modules are prohibited 26 | - Use 22.x.x version (22.14.0 or upper) of Node.js 27 | 28 | ## Implementation details 29 | 30 | # 1) Logging & Error Handling: 31 | 32 | 1. Implement custom `LoggingService` which will be used for logging and provided via `dependency injection` 33 | 2. Incoming requests to service (at least `url`, `query parameters`, `body`) and response with `status code` should be logged by `LoggingService`. 34 | 3. Implement custom `Exception Filter` and use it for handling errors during request processing. In case of unexpected error response with HTTP code `500` (Internal Server Error) and standard message should be sent 35 | 4. `LoggingService` should log all `errors` 36 | 5. Add listener and logging to `uncaughtException` event 37 | 6. Add listener and logging to `unhandledRejection` event 38 | 7. Writing to `process.stdout` or to a file both can be used for logging 39 | 8. There should be multiple logging levels and logging level should be stored in environment variable 40 | 9. Log file rotation should be setup with file size (kB) parameter. 41 | 42 | 43 | # 2) Authentication and Authorization 44 | 45 | 1. Endpoints 46 | * `Signup` (`auth/signup` route) 47 | * `POST auth/signup` - send `login` and `password` to create a new `user` 48 | - Server should answer with `status code` **201** and corresponding message if dto is valid 49 | - Server should answer with `status code` **400** and corresponding message if dto is invalid (no `login` or `password`, or they are not a `strings`) 50 | * `Login` (`auth/login` route) 51 | * `POST auth/login` - send `login` and `password` to get Access token and Refresh token (optionally) 52 | - Server should answer with `status code` **200** and tokens if dto is valid 53 | - Server should answer with `status code` **400** and corresponding message if dto is invalid (no `login` or `password`, or they are not a `strings`) 54 | - Server should answer with `status code` **403** and corresponding message if authentication failed (no user with such `login`, `password` doesn't match actual one, etc.) 55 | * `Refresh` (`auth/refresh` route) 56 | * `POST auth/refresh` - send refresh token in body as `{ refreshToken }` to get new pair of Access token and Refresh token 57 | - Server should answer with `status code` **200** and tokens in body if dto is valid 58 | - Server should answer with `status code` **401** and corresponding message if dto is invalid (no `refreshToken` in body) 59 | - Server should answer with `status code` **403** and corresponding message if authentication failed (Refresh token is invalid or expired) 60 | 61 | 62 | 2. Once **POST** `/auth/signup` accepts `password` property, it is replaced with **hash** (for example, you can use [bcrypt package](https://www.npmjs.com/package/bcrypt) or its equivalent like `bcryptjs`) for password encryption, no raw passwords should be in database (NB! Password should remain hashed after any operation with service). 63 | 64 | 3. **JWT** Access token should contain `userId` and `login` in a **payload** and has expiration time (expiration time of Refresh token should be longer, than Access token). 65 | 66 | 4. The **JWT** Access token should be added in HTTP `Authorization` header to all requests that requires authentication. Proxy all the requests (except `auth/signup`, `auth/login`, `/doc`, `/`) and check that HTTP `Authorization` header has the correct value of **JWT** Access token. 67 | HTTP authentication must follow `Bearer` scheme: 68 | ``` 69 | Authorization: Bearer 70 | ``` 71 | 72 | 5. In case of the HTTP `Authorization` header in the request is absent or invalid or doesn’t follow `Bearer` scheme or Access token has expired, further router method execution should be stopped and lead to response with HTTP **401** code and the corresponding error message. 73 | 74 | 6. Secrets used for signing the tokens should be stored in `.env` file. 75 | 76 | ### `bcrypt` installation issues: 77 | 78 | #### If you see an error that starts with: 79 | 80 | ```console 81 | gyp ERR! stack Error: "pre" versions of node cannot be installed, use the --nodedir flag instead 82 | ``` 83 | Please check [compatibility between Node.JS and Bcrypt versions](https://www.npmjs.com/package/bcrypt#version-compatibility). 84 | 85 | #### If you face an error like this: 86 | 87 | ```console 88 | 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 89 | ``` 90 | 91 | 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). 92 | -------------------------------------------------------------------------------- /assignments/logging-error-authentication-authorization/score.md: -------------------------------------------------------------------------------- 1 | # REST service: Logging & Error Handling and Authentication and Authorization 2 | 3 | ## Basic Scope 4 | 5 | # 1) Logging & Error Handling: 6 | 7 | - **+20** Custom `LoggingService` is implemented and used for logging 8 | - **+20** Custom `Exception Filter` is implemented and used for handling exceptions during request processing 9 | - **+20** Logging for request (of at least `url`, `query parameters`, `body`) and response with `status code` is implemented. 10 | - **+20** Error handling is implemented including sending response with an appropriate `http status code` and errors logging. 11 | - **+10** Error handling and logging is implemented for `uncaughtException` event. 12 | - **+10** Error handling and logging is implemented for `unhandledRejection` event. 13 | 14 | 15 | # 2) Authentication and Authorization: 16 | 17 | - **+30** Route `/auth/signup` implemented correctly, related logic is divided between controller and corresponding service 18 | - **+30** Route `/auth/login` has been implemented, related logic is divided between controller and corresponding service 19 | - **+10** `User` `password` saved into database as hash 20 | - **+20** Access Token is implemented,`JWT` payload contains `userId` and `login`, secret key is saved in `.env`. 21 | - **+40** Authentication is required for the access to all routes except `/auth/signup`, `/auth/login`, `/doc` and `/`. 22 | - **+10** Separate module is implemented **within application scope** to check that all requests to all routes except mentioned above contain required JWT token 23 | 24 | ## Advanced Scope 25 | 26 | # 1) Logging & Error Handling: 27 | 28 | - **+20** Logs are written to a file. 29 | - **+10** Logs files are rotated with size. 30 | - **+10** Add environment variable to specify max file size. 31 | - **+10** Error logs are written to a separate file (either only to a separate file or in addition to logging into a common file). 32 | - **+20** Add environment variable to specify logging level and corresponding functionality. 33 | Logs with configured level to be registered as well as other higher priority levels. For example if you set level 2, all messages with levels 0, 1 and 2 should be logged. You should use Nest.js logging levels. 34 | 35 | 36 | # 2) Authentication and Authorization: 37 | - **+30** Route `/auth/refresh` implemented correctly, related logic is divided between controller and corresponding service 38 | 39 | 40 | ## Forfeits 41 | 42 | - **-10** for each failing test 43 | (for authentication and authorization module tests to be run with `npm run test:auth` ) 44 | - **-30% of max task score** Commits after deadline, except commits that affect only Readme.md, .gitignore, etc. 45 | - **-10 points** for each error either on `npm run lint` on the basis of the **local config** or for compilation errors on the basis of the **local tsconfig** (`errors` not `warnings`). 46 | - **-20** No separate development branch 47 | - **-20** No Pull Request 48 | - **-10** Pull Request description is incorrect 49 | - **-20** Less than 3 commits in the development branch, not including commits that make changes only to `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 50 | 51 | 52 | -------------------------------------------------------------------------------- /assignments/logging-error-handling/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/logging-error-handling/README.md) 2 | 3 | # REST service: Logging & Error Handling 4 | 5 | ## Description 6 | 7 | Your task is to implement logging functionality to the already existing REST service. 8 | 9 | ## Technical requirements 10 | 11 | - Only `@nestjs/common` and `@nestjs-core` Nest.js modules can be used for the logger and error handling feature assignment, other Nest.js modules are prohibited 12 | - Use 22.x.x version (22.14.0 or upper) of Node.js 13 | 14 | ## Implementation details 15 | 16 | 1. Implement custom `LoggingService` which will be used for logging and provided via `dependency injection` 17 | 2. Incoming requests to service (at least `url`, `query parameters`, `body`) and response with `status code` should be logged by `LoggingService`. 18 | 3. Implement custom `Exception Filter` and use it for handling errors during request processing. In case of unexpected error response with HTTP code `500` (Internal Server Error) and standard message should be sent 19 | 4. `LoggingService` should log all `errors` 20 | 5. Add listener and logging to `uncaughtException` event 21 | 6. Add listener and logging to `unhandledRejection` event 22 | 7. Writing to `process.stdout` or to a file both can be used for logging 23 | 8. There should be multiple logging levels and logging level should be stored in environment variable 24 | 9. Log file rotation should be setup with file size (kB) parameter. 25 | -------------------------------------------------------------------------------- /assignments/logging-error-handling/score.md: -------------------------------------------------------------------------------- 1 | # REST service: Logging & Error Handling 2 | 3 | ## Basic Scope 4 | 5 | - **+20** Custom `LoggingService` is implemented and used for logging 6 | - **+20** Custom `Exception Filter` is implemented and used for handling exceptions during request processing 7 | - **+20** Logging for request (of at least `url`, `query parameters`, `body`) and response with `status code` is implemented. 8 | - **+20** Error handling is implemented including sending response with an appropriate `http status code` and errors logging. 9 | - **+10** Error handling and logging is implemented for `uncaughtException` event. 10 | - **+10** Error handling and logging is implemented for `unhandledRejection` event. 11 | 12 | ## Advanced Scope 13 | 14 | - **+20** Logs are written to a file. 15 | - **+10** Logs files are rotated with size. 16 | - **+10** Add environment variable to specify max file size. 17 | - **+10** Error logs are written to a separate file (either only to a separate file or in addition to logging into a common file). 18 | - **+20** Add environment variable to specify logging level and corresponding functionality. 19 | Logs with configured level to be registered as well as other higher priority levels. For example if you set level 2, all messages with levels 0, 1 and 2 should be logged. You should use Nest.js logging levels. 20 | 21 | ## Forfeits 22 | 23 | - **-10** for each failing test with `npm run test:auth` (this forfeit applied once if coincides with same forfeit in different assignments in case there are multiple assignments in task) 24 | - **-30% of max task score** Commits after deadline, except commits that affect only Readme.md, .gitignore, etc.(this forfeit applied once if coincides with same forfeit in different assignments in case there are multiple assignments in task) 25 | - **-20** Missing PR or its description is incorrect 26 | - **-20** No separate development branch 27 | - **-20** Less than 3 commits in the development branch, not including commits that make changes only to `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 28 | - **-10 points** for each lint error either on `npm run lint` on the basis of the **local config** or for compilation errors on the basis of the **local tsconfig** (`errors` not `warnings`). 29 | -------------------------------------------------------------------------------- /assignments/nodejs-basics/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/nodejs-basics/README.md) 2 | 3 | # Assignment: Node.js basics 4 | 5 | ## Description 6 | 7 | Your task is to complete several simple tasks to learn Node.js basics 8 | 9 | Fork [this repository](https://github.com/AlreadyBored/node-nodejs-basics) 10 | 11 | Assignment contains several nested folders inside `src`. Your task is to implement necessary functionality inside them 12 | 13 | ## Technical requirements 14 | 15 | - Any external tools and libraries are prohibited 16 | - Use 22.x.x version (22.14.0 or upper) of Node.js 17 | - Don't change signature of pre-written functions (e.g. don't rename them, don't make them synchronous, etc.) 18 | - Prefer asynchronous API whenever possible 19 | 20 | ## Subtasks 21 | 22 | ### File system (src/fs) 23 | 24 | You should implement several functions in dedicated files 25 | 26 | - `create.js` - implement function that creates new file `fresh.txt` with content `I am fresh and young` inside of the `files` folder (if file already exists `Error` with message `FS operation failed` must be thrown) 27 | - `copy.js` - implement function that copies folder `files` files with all its content into folder `files_copy` at the same level (if `files` folder doesn't exist or `files_copy` has already been created `Error` with message `FS operation failed` must be thrown) 28 | - `rename.js` - implement function that renames file `wrongFilename.txt` to `properFilename` with extension `.md` (if there's no file `wrongFilename.txt` or `properFilename.md` already exists `Error` with message `FS operation failed` must be thrown) 29 | - `delete.js` - implement function that deletes file `fileToRemove.txt` (if there's no file `fileToRemove.txt` `Error` with message `FS operation failed` must be thrown) 30 | - `list.js` - implement function that prints array of all filenames from `files` folder into console (if `files` folder doesn't exists `Error` with message `FS operation failed` must be thrown) 31 | - `read.js` - implement function that prints content of the `fileToRead.txt` into console (if there's no file `fileToRead.txt` `Error` with message `FS operation failed` must be thrown) 32 | 33 | ### Command line interface(src/cli) 34 | 35 | You should implement several functions in dedicated files 36 | 37 | - `env.js` - implement function that parses environment variables with prefix `RSS_` and prints them to the console in the format `RSS_name1=value1; RSS_name2=value2` 38 | - `args.js` - implement function that parses command line arguments (given in format `--propName value --prop2Name value2`, you don't need to validate it) and prints them to the console in the format `propName is value, prop2Name is value2` 39 | 40 | ### Modules(src/modules) 41 | 42 | You should refactor file (you can add additional imports if needed) 43 | 44 | - `cjsToEsm.cjs` - rewrite it to it's equivalent in ECMAScript notation (and rename it to `esm.mjs`) 45 | 46 | ### Hash (src/hash) 47 | 48 | You should implement several functions in dedicated files 49 | 50 | - `calcHash.js` - implement function that calculates SHA256 hash for file `fileToCalculateHashFor.txt` and logs it into console as `hex` using Streams API 51 | 52 | ### Streams (src/streams) 53 | 54 | You should implement several functions in dedicated files 55 | 56 | - `read.js` - implement function that reads file `fileToRead.txt` content using Readable Stream and prints it's content into `process.stdout` 57 | - `write.js` - implement function that writes `process.stdin` data into file `fileToWrite.txt` content using Writable Stream 58 | - `transform.js` - implement function that reads data from `process.stdin`, reverses text using Transform Stream and then writes it into `process.stdout` 59 | 60 | ### Zlib (src/zip) 61 | 62 | You should implement several functions in dedicated files 63 | 64 | - `compress.js` - implement function that compresses file `fileToCompress.txt` to `archive.gz` using `zlib` and Streams API 65 | - `decompress.js` - implement function that decompresses `archive.gz` back to the `fileToCompress.txt` with same content as before compression using `zlib` and Streams API 66 | 67 | ### Worker Threads (src/wt) 68 | 69 | You should implement several functions in dedicated files 70 | 71 | - `worker.js` - extend given function to work with data received from main thread and implement function which sends result of the computation to the main thread 72 | - `main.js` - implement function that creates number of worker threads (equal to the number of host machine logical CPU cores) from file `worker.js` and able to send data to those threads and to receive result of the computation from them. You should send incremental number starting from `10` to each `worker`. For example: on host machine with **4** cores you should create **4** workers and send **10** to first `worker`, **11** to second `worker`, **12** to third `worker`, **13** to fourth `worker`. After all workers will finish, function should log array of results into console. The results are array of objects with 2 properties: 73 | - `status` - `'resolved'` in case of successfully received value from `worker` or `'error'` in case of error in `worker` 74 | - `data` - value from `worker` in case of success or `null` in case of error in worker 75 | 76 | The results in the array must be in the same order that the workers were created 77 | 78 | ### Child Processes (src/cp) 79 | 80 | You should implement several functions in dedicated files 81 | 82 | - `cp.js` - implement function `spawnChildProcess` that receives array of arguments `args` and creates child process from file `script.js`, passing these `args` to it. This function should create IPC-channel between `stdin` and `stdout` of master process and child process: 83 | - child process `stdin` should receive input from master process `stdin` 84 | - child process `stdout` should send data to master process `stdout` 85 | -------------------------------------------------------------------------------- /assignments/nodejs-basics/cross-check-manual.md: -------------------------------------------------------------------------------- 1 | # Module "Node.js basics" 2 | 3 | ## Technical requirements 4 | 5 | - Use 22.x.x version (22.14.0 or upper) of Node.js 6 | 7 | # How to check student's project 8 | 9 | 1. Clone repository with the project to check with `git clone [HTTPS]` or download it. 10 | (where HTTPS is the GitHub URL of the project to be used to clone. To get it: 11 | a) go to GitHub repository that you want to clone 12 | b) click _Code_ and copy given URL.) 13 | 14 | 2. Open following files: 15 | 16 | - [Assignment](https://github.com/AlreadyBored/nodejs-assignments/blob/main/assignments/nodejs-basics/assignment.md) 17 | - [Score calculation](https://github.com/AlreadyBored/nodejs-assignments/blob/main/assignments/nodejs-basics/score.md) 18 | 19 | 3. Open project in Visual Studio Code or any other code editor. 20 | 21 | 4. Switch from main branch to branch with solution, if you haven't done it yet. 22 | 23 | 5. Start to check subtasks according to the assignment description. 24 | For check simplification students expected to have npm-scripts in `package.json` how to run every subtask. 25 | If not, follow below instruction: 26 | 27 | All tasks are located inside `src` folder. Open terminal in **src** folder of downloaded project. 28 | For example 1st subtask **create.js** located in _fs_ folder: 29 | 30 | - Run `node fs/create.js` in your terminal opened in _src_ folder. 31 | or go into fs/ subfolder of the task and run `node create.js`. 32 | 33 | ## Steps to check subtask 34 | 35 | - According to this subtask after running this function there should be file named `fresh.txt` created in _files_ folder ( At the beggining there was no such file, if found - delete it). 36 | - Open this file `fresh.txt` and you have to see following text created by the function after you run it: 37 | _I am fresh and young_. 38 | - Try to run `node fs/create.js` again and the error _FS operation failed_ must be thrown. 39 | - If all above works as expected then add _+6_ points to the total score as written in `Score calculation`. 40 | - If function works partly deduct points from the maximum allowed for this task. 41 | (For example function creates `fresh.txt` file, but on a second run it doesn't throw an error, half of task is executed only. Add only _+3_ points for this subtask). 42 | 43 | - If function is not implemented at all mark it as _0_. 44 | 45 | - Continue to check all other subtasks in a same way. Add points for each to grand total. 46 | 47 | 5. Once you finish to check all subtasks then check for a forfeit if any: 48 | 49 | - `package.json` should not have any external tools/libraries as dependencies. 50 | **-95% of total task score** Any external tools/libraries are used 51 | - Check that there are no commits made after deadline. 52 | **-30% of total task score** Commits after deadline (except commits that affect only Readme.md, .gitignore, etc.). 53 | 54 | 6. Submit total score with details check description to cross-check section of this task at [App RS School](https://app.rs.school/) before deadline. 55 | -------------------------------------------------------------------------------- /assignments/nodejs-basics/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: Node.js basics 2 | 3 | ## Check 4 | For check simplification you have npm-scripts in `package.json`. 5 | NB! Some scripts have predefined data (e.g. environment variables, CLI arguments). Feel free to change it during the check if necessary. 6 | 7 | ## Basic Scope 8 | 9 | - File system (src/fs) 10 | - **+6** `create.js` implemented properly 11 | - **+10** `copy.js` implemented properly 12 | - **+10** `rename.js` implemented properly 13 | - **+6** `delete.js` implemented properly 14 | - **+6** `list.js` implemented properly 15 | - **+6** `read.js` implemented properly 16 | - Command line interface(src/cli) 17 | - **+6** `env.js` implemented properly 18 | - **+6** `args.js` implemented properly 19 | - Modules(src/modules) 20 | - **+20** `cjsToEsm.cjs` refactored properly 21 | - Hash (src/hash) 22 | - **+10** `calcHash.js` implemented properly 23 | - Streams (src/streams) 24 | - **+10** `read.js` implemented properly 25 | - **+10** `write.js` implemented properly 26 | - **+10** `transform.js` implemented properly 27 | - Zlib (src/zip) 28 | - **+10** `compress.js` implemented properly 29 | - **+10** `decompress.js` implemented properly 30 | 31 | ## Advanced Scope 32 | 33 | - Worker Threads (src/wt) 34 | - **+10** `worker.js` implemented properly 35 | - **+30** `main.js` implemented properly 36 | - Child Processes (src/cp) 37 | - **+10** spawns child process 38 | - **+10** child process `stdin` receives input from master process `stdin` 39 | - **+10** child process `stdout` sends data to master process `stdout` 40 | 41 | ## Forfeits 42 | 43 | - **-95% of total task score** Any external tools/libraries are used 44 | - **-30% of total task score** Commits after deadline (except commits that affect only Readme.md, .gitignore, etc.) -------------------------------------------------------------------------------- /assignments/remote-control/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/websocket/README.md) 2 | 3 | # Assignment: Websocket Remote Control 4 | 5 | ## Description 6 | 7 | Your task is to implement remote control backend using `nutjs.dev` library and websocket. 8 | 9 | User interface for your remote control backend is [here](https://github.com/rolling-scopes-school/websockets-ui/tree/remote-control). You should clone this repository and write the code there. 10 | 11 | The backend should be able to do the following: 12 | 13 | - Start websocket server 14 | - Handle websocket connection 15 | - Move mouse (Up, Down, Left, Right) 16 | - Draw circle, rectangle and square 17 | - Send current mouse coordinates 18 | - Send desktop capture (optionally) 19 | 20 | ## Technical requirements 21 | 22 | - Task can be implemented on Javascript or Typescript 23 | - Use 22.x.x version (22.14.0 or upper) of Node.js 24 | - Only [ws](https://www.npmjs.com/package/ws), [nutjs.dev](https://www.npmjs.com/package/@nut-tree/nut-js), [jimp](https://www.npmjs.com/package/jimp), `cross-env`, `typescript`, `ts-node`, `ts-node-dev`, `nodemon`, `dotenv`, `eslint` and its plugins, `webpack` and its plugins, `prettier`, `@types/*` and testing tools (for example, Jest, Mocha, AVA, Jasmine, Cypress, Storybook, Puppeteer) are allowed 25 | - The program is started by npm script `start` in following way: 26 | ```bash 27 | npm run start 28 | ``` 29 | - After starting the program displays websocket parameters 30 | - After program work finished the program should end websocket work correctly 31 | - After each received command program should display the command and result 32 | 33 | List of websocket commands and their syntax (<- - cmd from frontend, -> - answer): 34 | - Navigation over the x and y axis 35 | - Move mouse up 36 | ```bash 37 | <- mouse_up {y px} 38 | ``` 39 | - Move mouse down 40 | ```bash 41 | <- mouse_down {y px} 42 | ``` 43 | - Move mouse left 44 | ```bash 45 | <- mouse_left {x px} 46 | ``` 47 | - Move mouse right 48 | ```bash 49 | <- mouse_right {x px} 50 | ``` 51 | - Send mouse coordinates 52 | ```bash 53 | <- mouse_position 54 | -> mouse_position {x px},{y px} 55 | ``` 56 | - Drawing 57 | - Draw circle with pushed left button: 58 | ```bash 59 | <- draw_circle {px} 60 | ``` 61 | - Draw rectangle with pushed left button: 62 | ```bash 63 | <- draw_rectangle {px} {px} 64 | ``` 65 | - Draw square with pushed left button: 66 | ```bash 67 | <- draw_square {px} 68 | ``` 69 | - Print screen 70 | - Make print screen command and send image (a base64 buffer of the 200 px square around the mouse position): 71 | ```bash 72 | <- prnt_scrn 73 | -> prnt_scrn {base64 string (png buf)} 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /assignments/remote-control/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: Websocket remote control 2 | 3 | ## Basic Scope 4 | 5 | - Websocket 6 | - **+6** Implemented workable websocket server 7 | - **+10** Websocket server message handler implemented properly 8 | - **+10** Websocket server message sender implemented properly 9 | - Navigation 10 | - **+4** Move mouse up implemented properly 11 | - **+4** Move mouse down implemented properly 12 | - **+4** Move mouse left implemented properly 13 | - **+4** Move mouse right implemented properly 14 | - **+4** Send mouse coordinates implemented properly 15 | - Drawing 16 | - **+6** Draw circle implemented properly 17 | - **+6** Draw rectangle implemented properly 18 | - **+6** Draw square implemented properly 19 | - Screen image 20 | - **+10** Send screen image implemented properly 21 | - **+20** Get screen image without file saving (optionally) 22 | 23 | ## Advanced Scope 24 | 25 | - **+30** Task implemented on Typescript 26 | - **+20** All data transfer operations with send/get should be performed using Streams API 27 | - **+20** Codebase is separated (at least 4 modules) 28 | 29 | ## Forfeits 30 | 31 | - **-95% of total task score** any external tools except `ws`, `nutjs.dev`, `jimp`, `cross-env`, `dotenv`, `typescript`, `ts-node`, `ts-node-dev`, `nodemon`, `eslint` and its plugins, `webpack` and its plugins, `prettier`, `@types/*` and testing tools (for example, Jest, Mocha, AVA, Jasmine, Cypress, Storybook, Puppeteer) 32 | - **-30% of total task score** Commits after deadline (except commits that affect only Readme.md, .gitignore, etc.) 33 | - **-10** Missing PR or its description is incorrect 34 | - **-10** No separate development branch 35 | - **-10** Less than 3 commits in the development branch, not including commits that make changes only to `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 36 | -------------------------------------------------------------------------------- /assignments/rest-service/assignment.md: -------------------------------------------------------------------------------- 1 | # [Course program module (for RS School students)](https://github.com/rolling-scopes-school/tasks/blob/master/node/modules/rest/rest/README.md) 2 | 3 | # Assignment: REST Service 4 | 5 | ## Description 6 | 7 | Let's try to create a Home Library Service! `Users` can create, read, update, delete data about `Artists`, `Tracks` and `Albums`, add them to `Favorites` in their own Home Library! 8 | 9 | NB! You must create new repository from [template](https://github.com/rolling-scopes-school/nodejs-course-template/generate) for this task. Its name must be nodejs2025Q2-service i.e. full link to the repository must be https://github.com/%your-gihub-id%/nodejs2025Q2-service. 10 | 11 | **Create an application, the application should operate with the following resources:** 12 | 13 | - `User` (with attributes): 14 | ```typescript 15 | interface User { 16 | id: string; // uuid v4 17 | login: string; 18 | password: string; 19 | version: number; // integer number, increments on update 20 | createdAt: number; // timestamp of creation 21 | updatedAt: number; // timestamp of last update 22 | } 23 | ``` 24 | 25 | - `Artist` (with attributes): 26 | ```typescript 27 | interface Artist { 28 | id: string; // uuid v4 29 | name: string; 30 | grammy: boolean; 31 | } 32 | ``` 33 | 34 | - `Track` (with attributes): 35 | ```typescript 36 | interface Track { 37 | id: string; // uuid v4 38 | name: string; 39 | artistId: string | null; // refers to Artist 40 | albumId: string | null; // refers to Album 41 | duration: number; // integer number 42 | } 43 | ``` 44 | 45 | - `Album` (with attributes): 46 | ```typescript 47 | interface Album { 48 | id: string; // uuid v4 49 | name: string; 50 | year: number; 51 | artistId: string | null; // refers to Artist 52 | } 53 | ``` 54 | 55 | - `Favorites` (with attributes): 56 | ```typescript 57 | interface Favorites { 58 | artists: string[]; // favorite artists ids 59 | albums: string[]; // favorite albums ids 60 | tracks: string[]; // favorite tracks ids 61 | } 62 | ``` 63 | 64 | **Details:** 65 | 66 | 1. For `Users`, `Artists`, `Albums`, `Tracks` and `Favorites` REST endpoints with separate router paths should be created 67 | * `Users` (`/user` route) 68 | * `GET /user` - get all users 69 | - Server should answer with `status code` **200** and all users records 70 | * `GET /user/:id` - get single user by id 71 | - Server should answer with `status code` **200** and and record with `id === userId` if it exists 72 | - Server should answer with `status code` **400** and corresponding message if `userId` is invalid (not `uuid`) 73 | - Server should answer with `status code` **404** and corresponding message if record with `id === userId` doesn't exist 74 | * `POST /user` - create user (following DTO should be used) 75 | `CreateUserDto` 76 | ```typescript 77 | interface CreateUserDto { 78 | login: string; 79 | password: string; 80 | } 81 | ``` 82 | - Server should answer with `status code` **201** and newly created record if request is valid 83 | - Server should answer with `status code` **400** and corresponding message if request `body` does not contain **required** fields 84 | * `PUT /user/:id` - update user's password 85 | `UpdatePasswordDto` (with attributes): 86 | ```typescript 87 | interface UpdatePasswordDto { 88 | oldPassword: string; // previous password 89 | newPassword: string; // new password 90 | } 91 | ``` 92 | - Server should answer with` status code` **200** and updated record if request is valid 93 | - Server should answer with` status code` **400** and corresponding message if `userId` is invalid (not `uuid`) 94 | - Server should answer with` status code` **404** and corresponding message if record with `id === userId` doesn't exist 95 | - Server should answer with` status code` **403** and corresponding message if `oldPassword` is wrong 96 | * `DELETE /user/:id` - delete user 97 | - Server should answer with `status code` **204** if the record is found and deleted 98 | - Server should answer with `status code` **400** and corresponding message if `userId` is invalid (not `uuid`) 99 | - Server should answer with `status code` **404** and corresponding message if record with `id === userId` doesn't exist 100 | 101 | * `Tracks` (`/track` route) 102 | * `GET /track` - get all tracks 103 | - Server should answer with `status code` **200** and all tracks records 104 | * `GET /track/:id` - get single track by id 105 | - Server should answer with `status code` **200** and and record with `id === trackId` if it exists 106 | - Server should answer with `status code` **400** and corresponding message if `trackId` is invalid (not `uuid`) 107 | - Server should answer with `status code` **404** and corresponding message if record with `id === trackId` doesn't exist 108 | * `POST /track` - create new track 109 | - Server should answer with `status code` **201** and newly created record if request is valid 110 | - Server should answer with `status code` **400** and corresponding message if request `body` does not contain **required** fields 111 | * `PUT /track/:id` - update track info 112 | - Server should answer with` status code` **200** and updated record if request is valid 113 | - Server should answer with` status code` **400** and corresponding message if `trackId` is invalid (not `uuid`) 114 | - Server should answer with` status code` **404** and corresponding message if record with `id === trackId` doesn't exist 115 | * `DELETE /track/:id` - delete track 116 | - Server should answer with `status code` **204** if the record is found and deleted 117 | - Server should answer with `status code` **400** and corresponding message if `trackId` is invalid (not `uuid`) 118 | - Server should answer with `status code` **404** and corresponding message if record with `id === trackId` doesn't exist 119 | 120 | * `Artists` (`/artist` route) 121 | * `GET /artist` - get all artists 122 | - Server should answer with `status code` **200** and all artists records 123 | * `GET /artist/:id` - get single artist by id 124 | - Server should answer with `status code` **200** and and record with `id === artistId` if it exists 125 | - Server should answer with `status code` **400** and corresponding message if `artistId` is invalid (not `uuid`) 126 | - Server should answer with `status code` **404** and corresponding message if record with `id === artistId` doesn't exist 127 | * `POST /artist` - create new artist 128 | - Server should answer with `status code` **201** and newly created record if request is valid 129 | - Server should answer with `status code` **400** and corresponding message if request `body` does not contain **required** fields 130 | * `PUT /artist/:id` - update artist info 131 | - Server should answer with` status code` **200** and updated record if request is valid 132 | - Server should answer with` status code` **400** and corresponding message if `artist` is invalid (not `uuid`) 133 | - Server should answer with` status code` **404** and corresponding message if record with `id === artistId` doesn't exist 134 | * `DELETE /artist/:id` - delete album 135 | - Server should answer with `status code` **204** if the record is found and deleted 136 | - Server should answer with `status code` **400** and corresponding message if `artistId` is invalid (not `uuid`) 137 | - Server should answer with `status code` **404** and corresponding message if record with `id === artistId` doesn't exist 138 | 139 | * `Albums` (`/album` route) 140 | * `GET /album` - get all albums 141 | - Server should answer with `status code` **200** and all albums records 142 | * `GET /album/:id` - get single album by id 143 | - Server should answer with `status code` **200** and and record with `id === albumId` if it exists 144 | - Server should answer with `status code` **400** and corresponding message if `albumId` is invalid (not `uuid`) 145 | - Server should answer with `status code` **404** and corresponding message if record with `id === albumId` doesn't exist 146 | * `POST /album` - create new album 147 | - Server should answer with `status code` **201** and newly created record if request is valid 148 | - Server should answer with `status code` **400** and corresponding message if request `body` does not contain **required** fields 149 | * `PUT /album/:id` - update album info 150 | - Server should answer with` status code` **200** and updated record if request is valid 151 | - Server should answer with` status code` **400** and corresponding message if `albumId` is invalid (not `uuid`) 152 | - Server should answer with` status code` **404** and corresponding message if record with `id === albumId` doesn't exist 153 | * `DELETE /album/:id` - delete album 154 | - Server should answer with `status code` **204** if the record is found and deleted 155 | - Server should answer with `status code` **400** and corresponding message if `albumId` is invalid (not `uuid`) 156 | - Server should answer with `status code` **404** and corresponding message if record with `id === albumId` doesn't exist 157 | 158 | * `Favorites` 159 | * `GET /favs` - get all favorites 160 | - Server should answer with `status code` **200** and all favorite records (**not their ids**), split by entity type: 161 | ```typescript 162 | interface FavoritesResponse{ 163 | artists: Artist[]; 164 | albums: Album[]; 165 | tracks: Track[]; 166 | } 167 | ``` 168 | * `POST /favs/track/:id` - add track to the favorites 169 | - Server should answer with `status code` **201** and corresponding message if track with `id === trackId` exists 170 | - Server should answer with `status code` **400** and corresponding message if `trackId` is invalid (not `uuid`) 171 | - Server should answer with `status code` **422** and corresponding message if track with `id === trackId` doesn't exist 172 | * `DELETE /favs/track/:id` - delete track from favorites 173 | - Server should answer with `status code` **204** if the track was in favorites and now it's deleted id is found and deleted 174 | - Server should answer with `status code` **400** and corresponding message if `trackId` is invalid (not `uuid`) 175 | - Server should answer with `status code` **404** and corresponding message if corresponding track is not favorite 176 | * `POST /favs/album/:id` - add album to the favorites 177 | - Server should answer with `status code` **201** and corresponding message if album with `id === albumId` exists 178 | - Server should answer with `status code` **400** and corresponding message if `albumId` is invalid (not `uuid`) 179 | - Server should answer with `status code` **422** and corresponding message if album with `id === albumId` doesn't exist 180 | * `DELETE /favs/album/:id` - delete album from favorites 181 | - Server should answer with `status code` **204** if the album was in favorites and now it's deleted id is found and deleted 182 | - Server should answer with `status code` **400** and corresponding message if `albumId` is invalid (not `uuid`) 183 | - Server should answer with `status code` **404** and corresponding message if corresponding album is not favorite 184 | * `POST /favs/artist/:id` - add artist to the favorites 185 | - Server should answer with `status code` **201** and corresponding message if artist with `id === artistId` exists 186 | - Server should answer with `status code` **400** and corresponding message if `artistId` is invalid (not `uuid`) 187 | - Server should answer with `status code` **422** and corresponding message if artist with `id === artistId` doesn't exist 188 | * `DELETE /favs/artist/:id` - delete artist from favorites 189 | - Server should answer with `status code` **204** if the artist was in favorites and now it's deleted id is found and deleted 190 | - Server should answer with `status code` **400** and corresponding message if `artistId` is invalid (not `uuid`) 191 | - Server should answer with `status code` **404** and corresponding message if corresponding artist is not favorite 192 | 193 | 2. For now, these endpoints should operate only with **in-memory** (hardcoded) data, in the next tasks we will use a DB for it. You should organize your modules with the consideration that the data source will be changed soon. 194 | 195 | 3. An `application/json` format should be used for request and response body. 196 | 197 | 4. 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, artist-related, etc...). 198 | 199 | 5. `User`'s password should be excluded from server response. 200 | 201 | 6. When you delete `Artist`, `Album` or `Track`, it's `id` should be deleted from favorites (if was there) and references to it in other entities should become `null`. For example: `Artist` is deleted => this `artistId` in corresponding `Albums`'s and `Track`'s become `null` + this artist's `id` is deleted from favorites, same logic for `Album` and `Track`. 202 | 203 | 7. Non-existing entity can't be added to `Favorites`. 204 | 205 | 8. To run the service `npm start` command should be used. 206 | 207 | 9. Service should listen on PORT `4000` by default, PORT value is stored in `.env` file. 208 | 209 | 10. Incoming requests should be validated. 210 | 211 | 11. You can fix and use OpenAPI file in `doc` folder. 212 | 213 | **Hints** 214 | 215 | * To generate all entities `id`s use [Node.js randomUUID](https://nodejs.org/dist/latest-v22.x/docs/api/crypto.html#cryptorandomuuidoptions). 216 | -------------------------------------------------------------------------------- /assignments/rest-service/score.md: -------------------------------------------------------------------------------- 1 | # Scoring: REST Service 2 | 3 | ## Basic Scope 4 | 5 | - **+10** The repository with the application contains a `Readme.md` file containing detailed instructions for installing, running and using the application 6 | - **+10** The application code that worked with `Users` instance divided into modules according to to its purpose and Nest.js architecture conventions (work with request and response in controller, business logic in service, etc.) 7 | - **+10** The application code that worked with `Tracks` instance divided into modules according to to its purpose and Nest.js architecture conventions (work with request and response in controller, business logic in service, etc.) 8 | - **+10** The application code that worked with `Albums` instance divided into modules according to to its purpose and Nest.js architecture conventions (work with request and response in controller, business logic in service, etc.) 9 | - **+10** The application code that worked with `Artists` instance divided into modules according to to its purpose and Nest.js architecture conventions (work with request and response in controller, business logic in service, etc.) 10 | - **+10** The application code that worked with `Favorites` instance divided into modules according to to its purpose and Nest.js architecture conventions (work with request and response in controller, business logic in service, etc.) 11 | - **+10** For each successfully passed test 12 | 13 | ## Advanced Scope 14 | - **+10** PORT value is stored into `.env` file 15 | - **+20** OpenAPI spec in `doc` folder corresponds with assignment 16 | 17 | ## Forfeits 18 | - **-670** Changes in tests 19 | - **-30% of max task score** Commits after deadline (except commits that affect only Readme.md, .gitignore, etc.) 20 | - **-20** No separate development branch 21 | - **-20** No Pull Request 22 | - **-10** Pull Request description is incorrect 23 | - **-10** Every lint error after npm run lint using local config (errors, not warnings) 24 | - **-20** Less than 3 commits in the development branch, not including commits that make changes only to `Readme.md` or similar files (`tsconfig.json`, `.gitignore`, `.prettierrc.json`, etc.) 25 | --------------------------------------------------------------------------------