My Experiments with NestJs

NestJS logo

During the lockdown, I was persistently trying to be as much productive as possible. That is the time when I came across an open-source disaster management platform Coronasafe Network. There was a project called Stay that was to be implemented for the organization. I and a few of my friends came together to build this platform. The technology stack was ReactJS, NestJS, and Database was Postgres. First, we divided the team into frontend and backend developers, and I was part of the backend team. That is where I first came across the framework NestJS. It is a progressive nodejs framework. Nest provides an out-of-the-box application architecture that allows developers and teams to create highly testable, scalable, loosely coupled, and easily maintainable applications. The architecture is heavily inspired by Angular.

Lets explore more on NestJS

Installation

npm i -g @nestjs/cli

This would install NestJS cli globally in our computer.

Now we can start a new project using the command,

nest new project-name

This command would create a new NestJS project with the desired project name we want.

? Which package manager would you ❤️ to use?
npm
yarn

I select npm you can select your desired package manager.

Folder structure

After completion of the command we would get such a folder structure.

src would have the following files,

src folder

App module is the main module of any nestJS application.

Lets see each file in detail,

First lets go for the app.controller.spec.ts,

app.controller.spec.ts,

This is a testing file for the app controller file. It tests whether the controller is working properly.

The next file is app.controller.ts,

app.controller.ts

Controllers are responsible for handling incoming requests and returning responses to the client.

In this file we define the get, post, put, patch, delete request routes using different decorators defined in the @nestjs/common library.

The constructor of AppController class calls a private readonly object of the AppService class so that the functions defined in the AppService class is accessible within the AppController class. In this case getHello() of appService Class is available to AppController class through the private readonly object appService.

Now lets look at app.service.ts file,

app.service.ts

Service files are responsible for data storage and retrieval. Here in this file the getHello function called in app.controller.ts file is defined. Service files are decorated with @Injectable() decorator. This says nestJS that the class is nestJS provider.

The main idea of a provider is that it can inject dependencies; this means objects can create various relationships with each other, and the function of “wiring up” instances of objects can largely be delegated to the Nest runtime system.

Next lets see app.module.ts,

app.module.ts

A module is a class annotated with a @Module() decorator. The @Module() decorator provides metadata that Nest makes use of to organize the application structure.

In app.module.ts file we import various modules in our nestJS application. Also we can connect to the databases throught app.module.ts file.

Connection with MongoDB

To connect to a database we need to first install a package @nestjs/typeorm.

npm i --save @nestjs/typeorm typeorm

Nest uses TypeORM because it’s the most mature Object Relational Mapper (ORM) available for TypeScript. Since it’s written in TypeScript, it integrates well with the Nest framework.

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
require('dotenv').config();
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mongodb',
url:
process.env.MONGOURL,
entities: [__dirname + '/**/*.entity{.ts,.js}'],
ssl: true,
synchronize: true,
logging: true,
useUnifiedTopology: true,
useNewUrlParser: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

Here the code above is an example for connecting nestJS application with a mongo database. TypeOrmModule is initialized with type mongodb the url of the mongo cluster is provided in as an environment variable then entities are the classes where the table structure is defined, for eg:-

import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
Unique,
} from 'typeorm';



@Entity('users')
@Unique(['email'])
export class User {

@PrimaryGeneratedColumn()
id: number;

@Column({ length: 128 })
name: string;

@Column({ length: 128 })
email: string;

@Column({ length: 128 })
password: string;

@Column({ length:128 })
type: string;

@Column({ length: 128 })
status: string;

@Column({ nullable: true })
referal: string;

@Column({nullable: true})
resetToken: string;

@Column({ nullable: true })
lastLogin: Date;

@CreateDateColumn()
createdAt: Date;

@CreateDateColumn()
updatedAt: Date;


}

This is an entity file for the class user or in other words this file describes the model of the user table.

Connection with Postgres

For connecting with postgres, we first create a DbConfig file that exports a constant DbConfig of type TypeOrmModuleOptions,

import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import * as config from 'config';

const dbConfig = config.get('db');


export const DbConfig: TypeOrmModuleOptions = {
type: 'postgres',
url: process.env.DATABASE_URL,//provide the database url
host: dbConfig.host, //provide the host
port: dbConfig.port , //provide the port number
username: dbConfig.username, //provide the dbusername
password: dbConfig.password , //provide the dbpassword
database: dbConfig.database , //provide the databasename
entities: [__dirname + '/../**/*.entity.{js,ts}'],
migrations: [__dirname + '/../**/migrations/*{.ts,.js}'],
synchronize: false,
migrationsRun: true,
cli: {
migrationsDir: 'migrations',
},
};

Then the app.module.ts would be like ,

import { Module } from '@nestjs/common';
import {DbConfig} from './config/db.config'
import {TypeOrmModule} from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
TypeOrmModule.forRoot(DbConfig),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

I have saved the db.config file inside config folder in src. Hence it is being imported from there. Now since we have completed the connection with postgres we have one more thing to look at since postgres is an sql database. We need to run migrations to add the tables in postgres database. For that first we need to create a migration folder and using cmd navigate into the migration folder and run the command

npm i -g typeorm

typeorm migration:create -n filename

This would create a migration file in the migration folder we created. An example file is,

import { MigrationInterface, QueryRunner, Table } from 'typeorm';

export class CreateUser1234567891012 implements MigrationInterface {

public async up(queryRunner: QueryRunner): Promise<any> {
return await queryRunner.createTable(new Table({
name: 'users',
columns: [
{
name: 'id',
type: 'bigint',
isPrimary: true,
isGenerated: true,
generationStrategy: 'increment',
},
{
name: 'name',
type: 'varchar',
},
{
name: 'email',
isUnique: true,
type: 'varchar',
},
{
name: 'referal',
type:'varchar',
isUnique: true,
isNullable: true,
},
{
name: 'resetToken',
type:'varchar',
isUnique: true,
isNullable: true,
},
{
name: 'type',
type:'varchar'
},
{
name: 'password',
type: 'varchar',
isNullable: false,
},
{
name: 'status',
type: 'varchar',
default: '\'ACTIVE\'',
},
{
name: 'lastLogin',
type: 'timestamp',
isNullable: true,
default: 'CURRENT_TIMESTAMP',
},
{

name: 'createdAt',
type: 'timestamp',
default: 'CURRENT_TIMESTAMP',
isNullable: false,
},
{

name: 'updatedAt',
type: 'timestamp',
default: 'CURRENT_TIMESTAMP',
isNullable: false,
},
],
}), true);
}

public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`DROP TABLE "users"`);
}

}

Now when we start the nest application using,

npm run

migrations will run automatically and the tables will be created in the postgres db. Up function creates the table whereas down function drops the table from the postgres db.

Conclusion

NestJS has a content rich documentation avaliable, you can refer to that if required. For more reference of nestjs application I am attaching some of my github repos that uses nestjs,

Pai026/tasks-manager-be: Backend of the todo(task) management website using nest (github.com)

Pai026/stay_be: CoronaSafe Stay BE NestJS (github.com)

Delivery-System-App/delivery-app-be (github.com)

Any queries , Mail me @ abhirampai1999@gmail.com,

or DM at,

https://www.linkedin.com/in/abhiram-r-pai-bb3288170

Abhiram R Pai (@pai_abhiram) / Twitter

Abhiram Pai (@abhiram_pai) • Instagram photos and videos

Web Dev

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store