Intro to NestJS

·

4 min read

Preface

I recently started exploring NestJs , this blog covers the very basics of what i understood.

Introduction

Nest is a framework for building efficient and scalable NodeJS backend services. It supports JavaScript and TypeScript. It also supports Object Oriented Programming , Functional Programming and Functional Reactive Programming.

It also supports HTTP frameworks like Express and Fastify.

Getting started with a Nest Project

For the beginner level one can scaffold a project using Nest CLI or clone an existing project.

To create a new project using the Nest CLI , run the following command that will create a basic structure of the project and populate it with the necessary files required for getting started.

npm i -g @nestjs/cli
nest new project-name

Following are the in-built files present in the starter project:

  • app.controller.spec.ts - This file consists of the unit tests for the controller used in Nest projects.

  • app.controller.ts - This file consists of a basic controller with a single route.

  • app.module.ts - This file is the root module of the application.

  • app.service.ts- This file consists of a basic service / provider with one single method.

main.ts - This file is the starting point of the application , just like the main() method in languages like Java , C and etc.

Basics of Nest

  • Modules: A module is like a single unit/ part of the application that basically simplifies the structure of the application. Inside the module is controller or the routes that will basically route the requests to various endpoints , apart from controllers a module consists of providers that basically handles the behavior of the routes that are defined.

We can create a module using the Nest CLI , with the help of the following command

nest g module module-name

The above command creates a a basic module with the specified name , it comes with a module.ts file that consists of the providers , controllers in that particular module.

It looks something like this:

Controllers: The controllers in Nest are basically used for the purpose of deciding what operation (GET,POST , PATCH , UPDATE ,DELETE) will be carried out at a specific endpoint and what will be the final output at the endpoint.

  • Creating a controller in Nest:

      nest g controller controller-name
    

    Note: The name of the controller should be same as the name of module in which it is created.

  • This is what a very simple controller.ts file looks like in a nest application:

  •       import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from '@nestjs/common';
          import { LoginService } from './login.service';
    
          @Controller('login')
          export class LoginController {
    
              constructor(private readonly usersService: LoginService) { }
    
              @Get() // GET /users or /users?role=value
              findAll(@Query('role') role?: 'INTERN' | 'ENGINEER' | 'ADMIN') {
                  return this.usersService.findAll(role)
              }
              @Get(':id') // GET /users/:id
              findOne(@Param('id') id: string) {
                  return this.usersService.findOne(+id)
              }
                  @Post() // POST /users 
                  create(@Body() user: { name: string, email: string, role: 'INTERN' | 'ENGINEER' | 'ADMIN' }) {
                  return this.usersService.create(user)
              }
              @Patch(':id') // PATCH /users/:id
              update(@Param('id') id: string, @Body() userUpdate: { name?: string, email?: string, role?: 'INTERN' | 'ENGINEER' | 'ADMIN' }) {
                  return this.usersService.update(+id, userUpdate)
              }
    
              @Delete(':id') // DELETE /users/:id
              delete(@Param('id') id: string) {
                  return this.usersService.delete(+id)
              }
          }
    

Services/Providers: In the services/providers file , basically tasks like caching , logging , Database Interaction , etc. It basically is used to handle how exactly the request should be handled like validation or any kind of transformation.

Given below is an example of a service:

import { Injectable } from '@nestjs/common';

@Injectable()
export class LoginService {
    private users = [
        {
            "id": 1,
            "name": "Leanne Graham",
            "email": "Sincere@april.biz",
            "role": "INTERN",
        },
        {
            "id": 2,
            "name": "Ervin Howell",
            "email": "Shanna@melissa.tv",
            "role": "INTERN",
        },
        {
            "id": 3,
            "name": "Clementine Bauch",
            "email": "Nathan@yesenia.net",
            "role": "ENGINEER",
        },
        {
            "id": 4,
            "name": "Patricia Lebsack",
            "email": "Julianne.OConner@kory.org",
            "role": "ENGINEER",
        },
        {
            "id": 5,
            "name": "Chelsey Dietrich",
            "email": "Lucio_Hettinger@annie.ca",
            "role": "ADMIN",
        }
    ]

    findAll(role?: 'INTERN' | 'ENGINEER' | 'ADMIN') {
        if (role) {
            return this.users.filter(user => user.role === role)
        }
        return this.users
    }

    findOne(id: number) {
        const user = this.users.find(user => user.id === id)

        return user
    }

    create(user: { name: string, email: string, role: 'INTERN' | 'ENGINEER' | 'ADMIN' }) {
        const usersByHighestId = [...this.users].sort((a, b) => b.id - a.id)
        const newUser = {
            id: usersByHighestId[0].id + 1,
            ...user
        }
        this.users.push(newUser)
        return newUser
    }

    update(id: number, updatedUser: { name?: string, email?: string, role?: 'INTERN' | 'ENGINEER' | 'ADMIN' }) {
        this.users = this.users.map(user => {
            if (user.id === id) {
                return { ...user, ...updatedUser }
            }
            return user
        })

        return this.findOne(id)
    }

    delete(id: number) {
        const removedUser = this.findOne(id)

        this.users = this.users.filter(user => user.id !== id)

        return removedUser
    }
}

So these 3 are the main components we can say that work under the hood in order for a nestjs application to work. Further , many changes are done in controllers in order to optimize the performance.

This blog covered the absolute basics of NestJS , further blogs will cover some more advanced topis.