Skip to content

Ifycode-study/nestjs-car-api

Repository files navigation

Nestjs (used) car API

Course: "NestJS: The Complete Developer's Guide" by Stephen Grider.

App overview API design Module design
Car api overview Car api design Car apii module design

Install typeorm and DB

npm i @nestjs/typeorm typeorm sqlite3

Database connection setup

Database name is db.sqlite as written in the appModuleinside the TypeOrmModule object. Starting your development server in the terminal will cause a file called db.sqlite to be generated in the root of the project (I've added this file to gitignore since I don't know if iit's safe to upload it to github). https://github.com/follow-course/nestjs-car-api/blob/d631aadd2303e97bd730b16bee615be66ebb7e6d/src/app.module.ts#L12

Creating an entity

  • Create an entity file: The class in the fiile will list all the properties that your entity will have.
  • Connect the entity to it's parent moduule - this creates an entity.
  • Connect the entity to the root i.e. the appModule.

Viewing a DB's content: Using vscode SQLite extension

You will only be able to view the generated db.sqlite file the first time you open it up with the editor. To view the DB's content, you need to install an external extension or program. Using vscode extension:

  • Install "SQLite" from vscode extension
  • Still in vscode, go to view > command pallete
  • Search for "SQLite: open database"
  • Click on the database name which is same as the one in the root of your project

After these, you'll find a "sqlite explorer" collapsible dropdown towards the bottom of your vscode explorer. You will find your DB content in there.

TypeORM synchronize property

https://github.com/follow-course/nestjs-car-api/blob/2da777c4862cdf7e4cbdbeb687116b0284e07240/src/app.module.ts#L16

Synchronize: true should only be used in development, and should not be used in production. SQL database is usually very rigid. To make any changes to the structure of an SQL database/table (e.g. create or remove tables or columns, or even changing the type of data stored iin the columns), you would usually need to write "migration" code. By setting synchronize to true, typeORM will automatically do such migration. It is dangerous to use this in production so that you don't accidentally delete data for example. You need to write migration code for production.

Understanding typeORM decorators

TypeORM decorators to tables

Quick note on repositories

Check out the repository API for the different methods you can use on a DB at the typeORM's official documentation. The diagram below shows and gives brief explanation of some repository methods used in this project:

Screenshot 2022-02-22 at 1 54 48 AM

A few extra routes: Just to help understand typeORM

Note: Yellow portin not needed for our app. Those routes are only created to help understand typeORM.

Screenshot 2022-02-20 at 4 15 52 AM Screenshot 2022-02-20 at 4 18 17 AM

Validation pipe's white list property

The white list property on the validation pipe is a security measure that helps to weed out properties not stated upfront in the Dto file. For example, the user is only allowed to submit email and password fields. If user tries to add a field or property e.g. admin and sets it to true (so that he/she can do things that only admins are supposed to be ale to do), the whitelist property on the validation pipe will ensure such is does not padd through. https://github.com/follow-course/nestjs-car-api/blob/54980c6be3074d2507c68defb787b392d5c1ad7d/src/main.ts#L9

Notes on serialzation

The password property for example shouldn't be passed along with data from our api when we attempt to get, post, delete etc. Nest js suggests that you Exclude the response property from within thhe .entity.ts file and with the in built ClassSerializerInterceptor used inside of the controller. While this works/helps for the case we are currently using it for, it can't help if you need to separate the response for a regular user from that of the admin. The best way is to build your own custom interceptor and create a Dto file that will expose only properties you want to be included in the response (See commits on Feb 23, 2022).

Authentication Overview

Screenshot_20220225-065325 Screenshot_20220225-072451

Note: The methods inside AuthService can instead be inside of the UserService if the application is small. But in large applications it is better that this separate AuthService is created. The AuthService depends on the UserService.

Notes on salting and hashing

Passwords should not be stored directly as plain strings in the database... Salt and hash the password before storing for security reasons.

Screenshot_20220225-075636 Screenshot_20220225-075737 Screenshot_20220225-075846

Use these inbuilt node packages: randomBytes to generate a salt (i.e. a string of random letters) and scrypt which is thhe hashing function for hashing your password. Note that naturally, scrypt would make us uuse a callback - the promisify package ensures that it instead returns a promise not a callback.

Diagrams: Auth system features, (why a) decorator and interceptor

Screenshot 2022-02-26 at 11 20 24 PM Screenshot 2022-02-27 at 12 58 51 AM Screenshot 2022-02-27 at 1 00 18 AM

Notes on testing

Screenshot 2022-02-28 at 12 34 40 PM Screenshot 2022-03-01 at 12 34 37 AM

Run test with:

npm run test:watch

Testing auth service: AuthService depends on the usersService, the usersService also depends on the (user) repository. We will therefore need to create a fake usersService to avoid complications. We are also only using/testing the .find() and .create() methods of the (fake) usersService since those are the only methods called (somewhere in the signin and signup methods of the authService). See diagrams and comments in the test file for more details.

About .find() and .create() methods, they are asynchronous in nature (i.e. it takes some amount of time to read or write data into the sqlite database). This is why they are made to return a promise. Promise.resolve(value) method creates a promise and immedately resolves it with a given value. It ensures that we get the exact api functionality that exists on the real usersService.

Quick Note to Help Speed Up Your Tests

You can dramatically speed up your tests by updating the package.json file.

In the scripts section, find the following line:

"test:watch": "jest --watch",

And change it to:

"test:watch": "jest --watch --maxWorkers=1",

Restart your test runner at your terminal after making this change