NestJS- Elegent way to create backend applications -series #1
- Introduction
NestJS is a framework for creating backend applications in TypeScript. It has one of the best documentation explaining concepts with examples, very active community on Discord and contributions on issues, new features, documentation etc.
Some numbers As of Today- Dec 31 2020
- Github stars: 33K
- Number of Pull Requests: 42
- Number of Open issues in Github: 62
- Number of closed issues: 3038
Links:
In this series of blogs, we will create backend system with NestJS using most of features provided by framework. This blog will focus on simple APIs with touching upon Modules, Controllers, Services, decorators. In upcoming blogs we will add more features to our application like configuration, validation, Swagger, logging, DTO( Data Transfer Objects), Repositories etc.
Github Link for project: https://github.com/vishwasrao/simplecrm
Building Blocks of NestJS
Modules Modules helps us to group components together. NestJS app has at least one module called root module. It is recommanded to organize components in module. e.g. customers module, users module, products module etc.
Controllers Controllers are responsible for handling incoming requests and returning responses to the client. You will feel like Spring boot when you actually create one with all decorators.
Services These are classes which has all your business logic. It provides encapsulation.
There are different concepts in NestJS e.g. pipes, guards, interceptor, custom decorators etc. which helps developers to create applications in elegant way.
Prerequisite: You should have Node.js installed.
Install nest cli:
npm i -g @nestjs/cli
Lets scaffold project with nest cli:
nest new simplecrm
It will ask for npm or yarn to be used as package manager. I have gone with yarn but you can choose any of these two.
Once nest cli has scaffolded application. You will see, it has created project structure for you. In src directory, you will see main.ts which is root file for application It will bootstrap our application. and app.modue.ts which is root module. To run application, Goto to directory 'simplecrm' and run command
yarn run start:dev
Once application is started, Open application in browser with http://localhost:3000 You will see Hello World! message. Our basic application is working fine.
Create new module customer Now lets create customer module in our application, Run all below commands in root of your project (i.e. simplecrm directory)
$ nest generate module customers
CREATE src/customers/customers.module.ts (86 bytes)
UPDATE src/app.module.ts (328 bytes)
What it did?
It created customers.module.ts file for you with basic structure but most importantly it has updated root module app.module.ts and imported CustomersModule. This way Nest application will know that you have module called customers which in your application and it will instantiate it while running app.
Create controller: Now we have customer module to organise all features/components for customers, lets create controller which will be handling input requests.
$ nest g controller customers
CREATE src/customers/customers.controller.spec.ts (513 bytes)
CREATE src/customers/customers.controller.ts (107 bytes)
UPDATE src/customers/customers.module.ts (186 bytes)
What it did?
It created customers.controller.spec.tc file which is testing file for controller. It created controller file and registered your controller in customer module
Create service Lets create service for customers which will have our business logic.
$ nest g service customers
CREATE src/customers/customers.service.spec.ts (481 bytes)
CREATE src/customers/customers.service.ts (93 bytes)
UPDATE src/customers/customers.module.ts (275 bytes)
What it did?
Again it created spec file for testing, service file and registered your service file with controller.
Add some basic APIs for our app
We will add methods to create customer, get all customers and get customer by Id. Open src/customers/customers.service.ts and replace with code below
import { Injectable } from '@nestjs/common';
import { v4 as uuidv4 } from 'uuid';
@Injectable()
export class CustomersService {
private customers = [];
getAllCustomers() {
return this.customers;
}
getCustomerById(id: string) {
return this.customers.filter((d) => d.id === id);
}
createCustomer(firstName: string, lastName: string, email: string) {
const customerObject = {
id: uuidv4(),
firstName: firstName,
lastName: lastName,
email: email,
};
this.customers.push(customerObject);
return this.customers.push();
}
}
Now we have methods available in services, lets use them in controller. Open file: src/customers/customers.controller.ts and replace code with below
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
import { CustomersService } from './customers.service';
@Controller('customers')
export class CustomersController {
constructor(private customerServices: CustomersService) {}
@Get()
getAllCustomers() {
return this.customerServices.getAllCustomers();
}
@Get(':id')
getCustomerById(@Param('id') id: string) {
return this.customerServices.getCustomerById(id);
}
@Post()
createCustomer(
@Body('firstName') firstName: string,
@Body('lastName') lastName: string,
@Body('email') email: string,
) {
return this.customerServices.createCustomer(firstName, lastName, email);
}
}
We are using decorators for methods in controller, This is similar to spring boot application. These are provided by framework out of the box. Along with that we can create custom decorators as well.
Now run your application from root of application. with command
$ yarn run start:dev
yarn run v1.22.4
$ nest start --watch
[4:45:04 PM] Starting compilation in watch mode...
[4:45:10 PM] Found 0 errors. Watching for file changes.
[Nest] 29912 - 12/31/2020, 4:45:14 PM [NestFactory] Starting Nest application...
[Nest] 29912 - 12/31/2020, 4:45:14 PM [InstanceLoader] AppModule dependencies initialized +36ms
[Nest] 29912 - 12/31/2020, 4:45:14 PM [InstanceLoader] CustomersModule dependencies initialized +2ms
[Nest] 29912 - 12/31/2020, 4:45:14 PM [RoutesResolver] CustomersController {/customers}: +26ms
[Nest] 29912 - 12/31/2020, 4:45:14 PM [RouterExplorer] Mapped {/customers, GET} route +8ms
[Nest] 29912 - 12/31/2020, 4:45:14 PM [RouterExplorer] Mapped {/customers/:id, GET} route +2ms
[Nest] 29912 - 12/31/2020, 4:45:14 PM [RouterExplorer] Mapped {/customers, POST} route +11ms
[Nest] 29912 - 12/31/2020, 4:45:14 PM [NestApplication] Nest application successfully started +5ms
We will test our application by calling APIs. We will use Postman to test APIs. Open Postman and create new API with
Method: GET URL: localhost:3000/customers

We got success response but empty array which is expected as we have not created any customer yet.
Lets create one customer, Create another API in postman with Method: POST Body:
{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@gmail.com"
}
Customer is successfully created and we got 201 response code.

Create another customer with body
{
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@gmail.com"
}

Now call get customer API again This time we got array with two customers which we created.

Now copy id of any of these customer from above response and call API to fetch specific customer Method: GET URL: localhost:3000/customers/Id of customer

Summary
In this blog
We have gone through some basic building blocks of NestJS framework like module, controller, services etc.
Created sample application using nest cli.
Created some APIs in our application which touched upon above building blocks.
In upcoming blog we will see how we can add swagger to our application.
Stay tuned !!!
Happy Learning!!!