Skip to main content
Advertisement

14.1 NestJS Introduction — Decorator-based TypeScript Framework

What is NestJS?

NestJS is a Node.js server framework written in TypeScript. Inspired by Angular, it is designed around Decorators and Dependency Injection (DI).

Features:
- TypeScript-first: full type safety
- Declarative code with decorators
- Separation of concerns with module system
- Runs on Express/Fastify
- Testability (DI container)

Installation and Project Setup

npm install -g @nestjs/cli
nest new my-project
cd my-project
npm run start:dev

Project Structure

src/
├── app.module.ts # Root module
├── app.controller.ts # Root controller
├── app.service.ts # Root service
├── main.ts # Entry point
└── users/
├── users.module.ts
├── users.controller.ts
├── users.service.ts
└── dto/
├── create-user.dto.ts
└── update-user.dto.ts

Core Components

Module

// 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], // Make available to other modules
})
export class UsersModule {}
// app.module.ts (root module)
import { Module } from '@nestjs/common'
import { UsersModule } from './users/users.module'
import { AuthModule } from './auth/auth.module'

@Module({
imports: [UsersModule, AuthModule],
})
export class AppModule {}

Controller

// users/users.controller.ts
import {
Controller,
Get,
Post,
Put,
Delete,
Body,
Param,
Query,
HttpCode,
HttpStatus,
} from '@nestjs/common'
import { UsersService } from './users.service'
import { CreateUserDto } from './dto/create-user.dto'
import { UpdateUserDto } from './dto/update-user.dto'

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

@Get()
findAll(@Query('page') page = '1', @Query('limit') limit = '10') {
return this.usersService.findAll({
page: parseInt(page),
limit: parseInt(limit),
})
}

@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(id)
}

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

@Put(':id')
update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
return this.usersService.update(id, updateUserDto)
}

@Delete(':id')
@HttpCode(HttpStatus.NO_CONTENT)
remove(@Param('id') id: string) {
return this.usersService.remove(id)
}
}

Service

// users/users.service.ts
import { Injectable, NotFoundException } from '@nestjs/common'
import { CreateUserDto } from './dto/create-user.dto'
import { UpdateUserDto } from './dto/update-user.dto'

interface User {
id: string
name: string
email: string
createdAt: Date
}

interface PaginationParams {
page: number
limit: number
}

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

findAll({ page, limit }: PaginationParams) {
const start = (page - 1) * limit
return {
data: this.users.slice(start, start + limit),
total: this.users.length,
page,
limit,
}
}

findOne(id: string): User {
const user = this.users.find(u => u.id === id)
if (!user) {
throw new NotFoundException(`User ID ${id} not found.`)
}
return user
}

create(createUserDto: CreateUserDto): User {
const user: User = {
id: Date.now().toString(),
...createUserDto,
createdAt: new Date(),
}
this.users.push(user)
return user
}

update(id: string, updateUserDto: UpdateUserDto): User {
const user = this.findOne(id)
Object.assign(user, updateUserDto)
return user
}

remove(id: string): void {
const index = this.users.findIndex(u => u.id === id)
if (index === -1) {
throw new NotFoundException(`User ID ${id} not found.`)
}
this.users.splice(index, 1)
}
}

main.ts Configuration

// 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)

// Global validation pipe
app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // Strip fields not in DTO
forbidNonWhitelisted: true, // Error if extra fields present
transform: true, // Auto type conversion
})
)

// CORS configuration
app.enableCors({
origin: process.env.ALLOWED_ORIGIN ?? '*',
})

// API prefix
app.setGlobalPrefix('api')

await app.listen(process.env.PORT ?? 3000)
console.log(`Server running: http://localhost:${process.env.PORT ?? 3000}`)
}

bootstrap()

Pro Tips

NestJS CLI Commands

# Generate module
nest generate module users
nest g mo users # shorthand

# Generate controller
nest generate controller users
nest g co users

# Generate service
nest generate service users
nest g s users

# Generate full CRUD resource
nest generate resource users
nest g res users # module + controller + service + DTO at once
Advertisement