Creating RESTful APIs with NestJS

@rnab
3 min readDec 1, 2024

--

NestJS has rapidly gained popularity in the Node.js world for its ability to create highly maintainable and scalable server-side applications. Built with TypeScript, it leverages modern JavaScript, fully embraces the concept of modularity, and promotes the use of TypeScript as a first-class citizen.

In this article, we will walk through the steps to create a RESTful API using NestJS. We will cover the basics, including setting up a project, creating modules, controllers, services, and handling data with TypeORM and PostgreSQL.

Getting Started with NestJS

First, ensure you have Node.js and npm or yarn installed. You can install the NestJS CLI with the following command:

npm install -g @nestjs/cli

Next, we will create a new project:

nest new my-app
cd my-app

NestJS will create a boilerplate project structure, and you’ll be prompted to choose your package manager. For this tutorial, we’ll use yarn, but feel free to choose what suits you best.

Creating a Module

Modules are the fundamental building blocks in NestJS. Each application is composed of one or more modules.

Create a module for managing users:

nest generate module users

Creating a Controller

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

Generate a controller for the users module:

nest generate controller users

Then, in users.controller.ts file, you can define the basic CRUD operations:

import { Controller, Get, Post, Put, Delete, Param, Body } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Get()
findAll(): string {
return 'This action returns all users';
}
@Get(':id')
findOne(@Param('id') id: string): string {
return `This action returns a user with ID ${id}`;
}
@Post()
create(@Body() body: any): string {
return 'This action adds a new user';
}
@Put(':id')
update(@Param('id') id: string, @Body() body: any): string {
return `This action updates a user with ID ${id}`;
}
@Delete(':id')
remove(@Param('id') id: string): string {
return `This action removes a user with ID ${id}`;
}
}

Creating a Service

Services are responsible for handling business logic. They are typically used by controllers to get their job done.

Generate a service for users:

nest generate service users

In the users.service.ts, you might define the service methods:

import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
private readonly users: any[] = [];
create(user: any) {
this.users.push(user);
}
findAll(): any[] {
return this.users;
}
findOne(id: string): any {
return this.users.find(user => user.id === id);
}
update(id: string, user: any) {
const existingUser = this.findOne(id);
if (existingUser) {
// Code to update user
}
}
remove(id: string) {
const index = this.users.findIndex(user => user.id === id);
if (index !== -1) {
this.users.splice(index, 1);
}
}
}

Integrating with a Database

For managing persistent data, we’e going to use TypeORM with PostgreSQL.

First, install the necessary packages:

yarn add @nestjs/typeorm typeorm pg

Create a configuration for connecting to the PostgreSQL database in app.module.ts:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersModule } from './users/users.module';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'your-username',
password: 'your-password',
database: 'your-database',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
UsersModule,
],
})
export class AppModule {}

Then, define an entity for users:

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
age: number;
@Column()
email: string;
}

In the users.module.ts, import the TypeOrmModule and specify the User entity:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { User } from './user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}

Lastly, update the users.service.ts to interact with the database:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
create(user: User): Promise<User> {
return this.usersRepository.save(user);
}
findAll(): Promise<User[]> {
return this.usersRepository.find();
}
findOne(id: number): Promise<User> {
return this.usersRepository.findOneBy({ id });
}
async update(id: number, user: User): Promise<void> {
await this.usersRepository.update(id, user);
}
async remove(id: number): Promise<void> {
await this.usersRepository.delete(id);
}
}

Conclusion

We’ve built a simple, yet powerful RESTful API with NestJS. This covers basic CRUD operations and integrates a PostgreSQL database using TypeORM. NestJS’s modular architecture and TypeScript support make it an exceptional framework for building scalable server-side applications. Continue to explore its deep features like Middleware, Guards, Interceptors, and Pipes to enhance your API.

--

--

@rnab
@rnab

Written by @rnab

Typescript, Devops, Kubernetes, AWS, AI/ML, Algo Trading

No responses yet