Building RESTful APIs with NestJS
NestJS is a progressive Node.js framework that helps you build efficient and scalable server-side applications. One of its most powerful features is the ability to build robust RESTful APIs with ease. In this guide, we will explore how to create a RESTful API using NestJS, covering the essentials from setting up a project to creating controllers, services, and connecting to a database.
Why Choose NestJS for RESTful APIs?
Modular Architecture: NestJS promotes a modular structure, making it easy to manage and scale your applications.
TypeScript Support: Built with TypeScript, NestJS provides strong typing and modern JavaScript features.
Built-in Tools: Features like dependency injection, middleware, and easy integration with other libraries enhance productivity.
Extensibility: Easily integrates with databases, validation libraries, authentication mechanisms, and more.
Setting Up a NestJS Project
Step 1: Install NestJS CLI
First, you need to install the NestJS Command Line Interface (CLI):
npm install -g @nestjs/cli
Step 2: Create a New Project
Create a new NestJS project using the CLI:
nest new my-rest-api
Step 3: Run the Application
To start the application, run:
npm run start
By default, the application runs on http://localhost:3000
.
Creating Your First Module, Controller, and Service
Step 1: Generate a Module
Use the NestJS CLI to generate a new module. For this example, we'll create a users
module:
nest generate module users
Step 2: Generate a Controller and Service
Next, generate a controller and a service for the users
module:
nest generate controller users
nest generate service users
Step 3: Define User Data Transfer Object (DTO)
Create a data transfer object (DTO) for user data validation:
// src/users/dto/create-user.dto.ts
export class CreateUserDto {
readonly name: string;
readonly age: number;
readonly email: string;
}
Step 4: Implement the Users Service
Open the src/users/users.service.ts
file and implement basic CRUD operations:
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
interface User {
id: number;
name: string;
age: number;
email: string;
}
@Injectable()
export class UsersService {
private readonly users: User[] = [];
private idCounter = 1;
create(createUserDto: CreateUserDto): User {
const newUser: User = { id: this.idCounter++, ...createUserDto };
this.users.push(newUser);
return newUser;
}
findAll(): User[] {
return this.users;
}
findOne(id: number): User {
return this.users.find(user => user.id === id);
}
update(id: number, updateUserDto: CreateUserDto): User {
const userIndex = this.users.findIndex(user => user.id === id);
if (userIndex === -1) return null;
const updatedUser = { ...this.users[userIndex], ...updateUserDto };
this.users[userIndex] = updatedUser;
return updatedUser;
}
remove(id: number): boolean {
const userIndex = this.users.findIndex(user => user.id === id);
if (userIndex === -1) return false;
this.users.splice(userIndex, 1);
return true;
}
}
Step 5: Implement the Users Controller
Open the src/users/users.controller.ts
file and implement the controller methods:
import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(+id);
}
@Put(':id')
update(@Param('id') id: string, @Body() updateUserDto: CreateUserDto) {
return this.usersService.update(+id, updateUserDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.usersService.remove(+id);
}
}
Step 6: Testing Your API
Use a tool like Postman or cURL to test your API endpoints. For example:
Create a user:
curl -X POST http://localhost:3000/users -H "Content-Type: application/json" -d '{"name": "John Doe", "age": 30, "email": "john.doe@example.com"}'
Get all users:
curl http://localhost:3000/users
Update a user:
curl -X PUT http://localhost:3000/users/1 -H "Content-Type: application/json" -d '{"name": "John Doe", "age": 31, "email": "john.updated@example.com"}'
Delete a user:
curl -X DELETE http://localhost:3000/users/1
Connecting to a Database
Step 1: Install TypeORM and Database Driver
For this example, we'll use PostgreSQL. Install TypeORM and the PostgreSQL driver:
npm install --save @nestjs/typeorm typeorm pg
Step 2: Configure TypeORM
Configure TypeORM in the src/app.module.ts
file:
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',
autoLoadEntities: true,
synchronize: true,
}),
UsersModule,
],
})
export class AppModule {}
Step 3: Create User Entity
Create a user entity in src/users/user.entity.ts
:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
age: number;
@Column()
email: string;
}
Step 4: Update Users Module
Update the UsersModule
to include TypeORM:
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 {}
Step 5: Update Users Service
Update the UsersService
to use TypeORM:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateUserDto } from './dto/create-user.dto';
import { User } from './user.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {}
create(createUserDto: CreateUserDto): Promise<User> {
const newUser = this.userRepository.create(createUserDto);
return this.userRepository.save(newUser);
}
findAll(): Promise<User[]> {
return this.userRepository.find();
}
findOne(id: number): Promise<User> {
return this.userRepository.findOneBy({ id });
}
async update(id: number, updateUserDto: CreateUserDto): Promise<User> {
await this.userRepository.update(id, updateUserDto);
return this.findOne(id);
}
async remove(id: number): Promise<void> {
await this.userRepository.delete(id);
}
}
Conclusion
Subscribe to my newsletter
Read articles from ByteScrum Technologies directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
ByteScrum Technologies
ByteScrum Technologies
Our company comprises seasoned professionals, each an expert in their field. Customer satisfaction is our top priority, exceeding clients' needs. We ensure competitive pricing and quality in web and mobile development without compromise.