Menu

React & Next.js Topic

Introduction to NestJS

What is NestJS?

NestJS is a progressive, TypeScript-first Node.js framework for building efficient, reliable, and scalable server-side applications. It combines elements of:

  • Object-Oriented Programming (OOP)

  • Functional Programming (FP)

  • Functional Reactive Programming (FRP)

Built on top of Express.js (or optionally Fastify), NestJS provides an out-of-the-box application architecture that helps developers create highly testable, scalable, and maintainable applications.

Key Features:

  • Built-in TypeScript support (also supports JavaScript)

  • Modular architecture inspired by Angular

  • Dependency Injection system

  • Extensive ecosystem of modules

  • Excellent for building microservices, REST APIs, GraphQL APIs, and real-time applications

  • Strong emphasis on testing


Architecture Overview

1. Modules

Modules are the building blocks of NestJS applications. Each application has at least one module (the root module). Modules organize code into cohesive blocks of functionality.

typescript

@Module({
  imports: [/* other modules */],
  controllers: [/* controllers */],
  providers: [/* services */],
  exports: [/* providers to export */],
})
export class AppModule {}

2. Controllers

Controllers handle incoming HTTP requests and return responses. They define routes and delegate business logic to providers.

typescript

@Controller('users')
export class UsersController {
  @Get()
  findAll(): string {
    return 'All users';
  }
}

3. Providers

Providers are services, repositories, factories, etc., that can be injected into controllers or other providers. The most common type is a Service.

typescript

@Injectable()
export class UsersService {
  private users = [];

  findAll() {
    return this.users;
  }
}

4. Dependency Injection

NestJS has a built-in IoC (Inversion of Control) container that manages dependencies automatically.


Setting Up a Basic REST API Project

Step 1: Prerequisites

  • Node.js (v16 or newer)

  • npm or yarn

  • Basic TypeScript knowledge

Step 2: Install NestJS CLI

bash

npm install -g @nestjs/cli
# or
yarn global add @nestjs/cli

Step 3: Create a New Project

bash

nest new project-name
# Choose your package manager (npm or yarn)

Step 4: Project Structure

text

project-name/
├── src/
│   ├── app.controller.ts
│   ├── app.controller.spec.ts
│   ├── app.module.ts
│   ├── app.service.ts
│   └── main.ts
├── test/
├── nest-cli.json
├── package.json
├── tsconfig.json
└── README.md

Step 5: Create a Basic REST API

1. Generate Resources:

bash

nest generate module users
nest generate controller users
nest generate service users

2. User Entity (optional):

typescript

// src/users/entities/user.entity.ts
export class User {
  id: number;
  name: string;
  email: string;
}

3. User Service:

typescript

// src/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { User } from './entities/user.entity';

@Injectable()
export class UsersService {
  private users: User[] = [
    { id: 1, name: 'John Doe', email: 'john@example.com' },
    { id: 2, name: 'Jane Smith', email: 'jane@example.com' },
  ];

  findAll(): User[] {
    return this.users;
  }

  findOne(id: number): User {
    return this.users.find(user => user.id === id);
  }

  create(user: Omit<User, 'id'>): User {
    const newUser = {
      id: this.users.length + 1,
      ...user,
    };
    this.users.push(newUser);
    return newUser;
  }

  update(id: number, updatedUser: Partial<User>): User {
    const index = this.users.findIndex(user => user.id === id);
    this.users[index] = { ...this.users[index], ...updatedUser };
    return this.users[index];
  }

  remove(id: number): boolean {
    const index = this.users.findIndex(user => user.id === id);
    if (index > -1) {
      this.users.splice(index, 1);
      return true;
    }
    return false;
  }
}

4. User Controller:

typescript

// src/users/users.controller.ts
import { 
  Controller, 
  Get, 
  Post, 
  Put, 
  Delete, 
  Body, 
  Param, 
  ParseIntPipe,
  HttpCode,
  HttpStatus 
} from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './entities/user.entity';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll(): User[] {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number): User {
    return this.usersService.findOne(id);
  }

  @Post()
  @HttpCode(HttpStatus.CREATED)
  create(@Body() user: Omit<User, 'id'>): User {
    return this.usersService.create(user);
  }

  @Put(':id')
  update(
    @Param('id', ParseIntPipe) id: number,
    @Body() updatedUser: Partial<User>,
  ): User {
    return this.usersService.update(id, updatedUser);
  }

  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  remove(@Param('id', ParseIntPipe) id: number): void {
    this.usersService.remove(id);
  }
}

5. User Module:

typescript

// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

@Module({
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}
6. Update App Module:

typescript

// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UsersModule } from './users/users.module';

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

Step 6: Run the Application

Development mode (with hot reload):

bash

npm run start:dev

Production mode:

bash

npm run build
npm run start:prod

Step 7: Test the API

Use Postman, cURL, or any API client:

bash

# Get all users
curl http://localhost:3000/users

# Get single user
curl http://localhost:3000/users/1

# Create user
curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice","email":"alice@example.com"}'

# Update user
curl -X PUT http://localhost:3000/users/1 \
  -H "Content-Type: application/json" \
  -d '{"name":"John Updated"}'

# Delete user
curl -X DELETE http://localhost:3000/users/1

Step 8: Add Validation (Optional)

Install class-validator and class-transformer:

bash

npm install class-validator class-transformer

Update main.ts to enable validation:

typescript

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

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  // Enable validation globally
  app.useGlobalPipes(new ValidationPipe({
    whitelist: true,
    forbidNonWhitelisted: true,
    transform: true,
  }));
  
  await app.listen(3000);
}
bootstrap();
Create a DTO (Data Transfer Object):

typescript

// src/users/dto/create-user.dto.ts
import { IsEmail, IsString, MinLength } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @MinLength(2)
  name: string;

  @IsEmail()
  email: string;
}

Update the controller to use DTO:

typescript

@Post()
@HttpCode(HttpStatus.CREATED)
create(@Body() createUserDto: CreateUserDto): User {
  return this.usersService.create(createUserDto);
}

In Short

You've now set up a basic NestJS REST API with:

  • ✅ Project initialization

  • ✅ Modular architecture

  • ✅ CRUD operations

  • ✅ Controllers, Services, and Modules

  • ✅ Basic validation (optional)

NestJS provides much more including:

  • Guards for authentication

  • Interceptors for request/response transformation

  • Pipes for data transformation/validation

  • Custom decorators

  • WebSockets support

  • GraphQL support

  • Microservices architecture

  • Testing utilities

The framework's structured approach makes it excellent for large-scale applications where maintainability and scalability are crucial.

Comments (0)

No comments yet. Be the first to comment!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?