Intro to NestJS
Table of contents
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.