Introduction

NestJS is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications. In this guide, we'll walk through creating a RESTful API using NestJS, highlighting its key features and best practices.

Prerequisites

  • Node.js (v14 or later)
  • npm or yarn
  • Basic TypeScript knowledge
  • Understanding of REST principles

Setting Up the Project

First, let's install the NestJS CLI and create a new project:

npm i -g @nestjs/cli
nest new nestjs-api
cd nestjs-api

Project Structure

After initialization, you'll have a basic project structure:

src/
├── app.controller.ts
├── app.module.ts
├── app.service.ts
└── main.ts

Creating a Basic REST API

Let's create a simple API for managing books. We'll implement CRUD operations (Create, Read, Update, Delete).

1. Generate Resources

nest generate resource books

This command creates all necessary files for the books module.

2. Define the Book Entity

Create src/books/entities/book.entity.ts:

export class Book {
  id: number;
  title: string;
  author: string;
  published: Date;
  price: number;
}

3. Create DTOs

In src/books/dto/create-book.dto.ts:

import { IsNotEmpty, IsNumber, IsString, IsDate } from 'class-validator';

export class CreateBookDto {
  @IsNotEmpty()
  @IsString()
  title: string;

  @IsNotEmpty()
  @IsString()
  author: string;

  @IsDate()
  published: Date;

  @IsNumber()
  price: number;
}

4. Implement the Controller

Update src/books/books.controller.ts:

import { Controller, Get, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { BooksService } from './books.service';
import { CreateBookDto } from './dto/create-book.dto';
import { UpdateBookDto } from './dto/update-book.dto';

@Controller('books')
export class BooksController {
  constructor(private readonly booksService: BooksService) {}

  @Post()
  create(@Body() createBookDto: CreateBookDto) {
    return this.booksService.create(createBookDto);
  }

  @Get()
  findAll() {
    return this.booksService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.booksService.findOne(+id);
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() updateBookDto: UpdateBookDto) {
    return this.booksService.update(+id, updateBookDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.booksService.remove(+id);
  }
}

5. Implement the Service

Update src/books/books.service.ts:

import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateBookDto } from './dto/create-book.dto';
import { UpdateBookDto } from './dto/update-book.dto';
import { Book } from './entities/book.entity';

@Injectable()
export class BooksService {
  private books: Book[] = [];

  create(createBookDto: CreateBookDto) {
    const book = {
      id: this.books.length + 1,
      ...createBookDto,
    };
    this.books.push(book);
    return book;
  }

  findAll() {
    return this.books;
  }

  findOne(id: number) {
    const book = this.books.find(book => book.id === id);
    if (!book) {
      throw new NotFoundException(`Book #${id} not found`);
    }
    return book;
  }

  update(id: number, updateBookDto: UpdateBookDto) {
    const bookIndex = this.books.findIndex(book => book.id === id);
    if (bookIndex === -1) {
      throw new NotFoundException(`Book #${id} not found`);
    }
    this.books[bookIndex] = {
      ...this.books[bookIndex],
      ...updateBookDto,
    };
    return this.books[bookIndex];
  }

  remove(id: number) {
    const bookIndex = this.books.findIndex(book => book.id === id);
    if (bookIndex === -1) {
      throw new NotFoundException(`Book #${id} not found`);
    }
    this.books.splice(bookIndex, 1);
    return { message: `Book #${id} deleted` };
  }
}

Adding Validation

To implement validation, install required packages:

npm install class-validator class-transformer

Update main.ts:

import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();

Testing the API

You can test your API using tools like Postman or curl:

Create a Book

curl -X POST http://localhost:3000/books \
  -H "Content-Type: application/json" \
  -d '{"title":"The Great Gatsby","author":"F. Scott Fitzgerald","published":"1925-04-10","price":9.99}'

Get All Books

curl http://localhost:3000/books

Get One Book

curl http://localhost:3000/books/1

Update a Book

curl -X PUT http://localhost:3000/books/1 \
  -H "Content-Type: application/json" \
  -d '{"price":14.99}'

Delete a Book

curl -X DELETE http://localhost:3000/books/1

Error Handling

NestJS provides built-in exception filters. Here's how to create a custom exception filter:

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const status = exception.getStatus();
    const error = exception.getResponse();

    response
      .status(status)
      .json({
        statusCode: status,
        timestamp: new Date().toISOString(),
        error: error
      });
  }
}

Conclusion

This guide covered the basics of creating a RESTful API with NestJS. You've learned how to:

  • Set up a NestJS project
  • Create CRUD operations
  • Implement validation
  • Handle errors
  • Test the API

To expand this application, consider adding:

  • Database integration (TypeORM/Mongoose)
  • Authentication/Authorization
  • Swagger documentation
  • Unit tests
  • Environment configuration
  • Logging middleware

NestJS provides a robust foundation for building scalable Node.js applications. Its modular architecture and TypeScript support make it an excellent choice for enterprise-grade applications.

Related Posts

API management solutionsAPI management softwarebest API management toolsBlog

5 min read

APIs (Application Programming Interfaces) are the backbone of modern digital applications. They allow different software systems to communicate, exchange data, and collaborate seamlessly. As businesse...

API security measuressecuring APIsAPI vulnerabilitiesBlog

4 min read

In today’s interconnected digital world, APIs (Application Programming Interfaces) are the backbone of communication between different software applications. From mobile apps to cloud services, APIs e...

API design guidelinesbest practices for APIsAPI architectureBlog

5 min read

Ready to bring your ideas to life?

Let's collaborate and create something amazing together.