Getting Started with NestJS: Your First REST API

Enock Omondi

Introduction

NestJS has been gaining popularity among developers for building efficient, scalable, and maintainable server-side applications. In this comprehensive guide, we'll walk through the process of setting up your first REST API using NestJS.

Whether you're new to backend development or coming from other Node.js frameworks, this tutorial will help you get up and running with NestJS quickly.

What is NestJS?

NestJS is a progressive Node.js framework for building efficient and scalable server-side applications. It uses modern JavaScript features and is built with TypeScript, which brings a superior developer experience. NestJS leverages Express.js under the hood but provides a more opinionated and structured approach to application architecture.

Key features of NestJS include:

  1. Dependency Injection
  2. Decorators for defining routes and middleware
  3. TypeScript support out of the box
  4. Modular architecture
  5. Easy integration with various databases and ORMs

Prerequisites

Before we begin, make sure you have the following installed on your system:

Setting Up Your NestJS Project

Let's start by creating a new NestJS project. Open your terminal and run the following commands:

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

Project Structure

After creating your project, you'll see a folder structure similar to this:

nestjs-rest-api/
├── src/
 ├── app.controller.spec.ts
 ├── app.controller.ts
 ├── app.module.ts
 ├── app.service.ts
 └── main.ts
├── test/
├── node_modules/
├── package.json
├── tsconfig.json
└── nest-cli.json

Let's briefly go over the key files:

Creating Your First REST API

Now that we have our project set up, let's create a simple REST API for managing a list of books. We'll implement CRUD (Create, Read, Update, Delete) operations for our book resource.

Step 1: Generate a Books Module

First, let's create a module for our books resource:

nest generate module books

This command will create a books folder in the src directory with a books.module.ts file.

Step 2: Create a Book DTO (Data Transfer Object)

Create a new file src/books/dto/create-book.dto.ts:

export class CreateBookDto {
  readonly title: string;
  readonly author: string;
  readonly published: number;
}

Step 3: Create a Book Service

Generate a service for handling book-related operations:

nest generate service books

Update the src/books/books.service.ts file:

import { Injectable } from '@nestjs/common';
import { CreateBookDto } from './dto/create-book.dto';

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

  findAll() {
    return this.books;
  }

  findOne(id: number) {
    return this.books.find(book => book.id === id);
  }

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

  update(id: number, updateBookDto: CreateBookDto) {
    const book = this.findOne(id);
    if (book) {
      Object.assign(book, updateBookDto);
      return book;
    }
    return null;
  }

  remove(id: number) {
    const index = this.books.findIndex(book => book.id === id);
    if (index !== -1) {
      return this.books.splice(index, 1)[0];
    }
    return null;
  }
}

Step 4: Create a Books Controller

Generate a controller for handling HTTP requests:

nest generate controller books

Update the src/books/books.controller.ts file:

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

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

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

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

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

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

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

Step 5: Update the Books Module

Update the src/books/books.module.ts file:

import { Module } from '@nestjs/common';
import { BooksController } from './books.controller';
import { BooksService } from './books.service';

@Module({
  controllers: [BooksController],
  providers: [BooksService],
})
export class BooksModule {}

Step 6: Update the App Module

Update the src/app.module.ts file:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { BooksModule } from './books/books.module';

@Module({
  imports: [BooksModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Testing Your API

Now that we have our REST API set up, let's test it using cURL or a tool like Postman.

  1. Start your NestJS application:
npm run start:dev
  1. Create a new book:
curl -X POST http://localhost:3000/books -H "Content-Type: application/json" -d '{"title": "The Great Gatsby", "author": "F. Scott Fitzgerald", "published": 1925}'
  1. Get all books:
curl http://localhost:3000/books
  1. Get a specific book:
curl http://localhost:3000/books/1
  1. Update a book:
curl -X PUT http://localhost:3000/books/1 -H "Content-Type: application/json" -d '{"title": "The Great Gatsby", "author": "F. Scott Fitzgerald", "published": 1926}'
  1. Delete a book:
curl -X DELETE http://localhost:3000/books/1

Conclusion

Congratulations! You've just created your first REST API using NestJS. We've covered the basics of setting up a NestJS project, creating modules, services, and controllers, and implementing CRUD operations for a simple resource.

This is just the beginning of what you can do with NestJS. As you continue to explore the framework, you'll discover more advanced features like:

NestJS provides a robust set of tools for building scalable and maintainable server-side applications. Its modular architecture and use of TypeScript make it an excellent choice for developers looking to build enterprise-grade Node.js applications.

Happy coding with NestJS!