NestJS Patterns
Overview
NestJS เป็น progressive Node.js framework ที่ใช้ TypeScript เป็นหลัก ออกแบบมาสำหรับ building scalable server-side applications โดยใช้ architectural patterns จาก Angular รวมถึง Dependency Injection, Modules, และ Decorators
Why This Matters
- •Scalability: Modular architecture ทำให้จัดการ codebase ขนาดใหญ่ได้ง่าย
- •Type Safety: Built-in TypeScript support ลด runtime errors
- •Enterprise Ready: มี patterns สำหรับ microservices, GraphQL, WebSocket out-of-the-box
- •Testability: DI system ทำให้ unit testing ง่าย
Core Concepts
1. Module Architecture
typescript
// feature.module.ts
@Module({
imports: [DatabaseModule, CacheModule],
controllers: [FeatureController],
providers: [FeatureService, FeatureRepository],
exports: [FeatureService], // expose to other modules
})
export class FeatureModule {}
Best Practices:
- •แบ่ง module ตาม domain/feature
- •ใช้ shared module สำหรับ common utilities
- •Export เฉพาะ services ที่จำเป็น
2. Dependency Injection
typescript
// ใช้ constructor injection
@Injectable()
export class OrderService {
constructor(
private readonly orderRepo: OrderRepository,
private readonly paymentService: PaymentService,
@Inject('CONFIG') private config: AppConfig,
) {}
}
// Custom providers
const configProvider = {
provide: 'CONFIG',
useFactory: (configService: ConfigService) => configService.get('app'),
inject: [ConfigService],
};
3. Controllers & DTOs
typescript
@Controller('orders')
@UseGuards(JwtAuthGuard)
export class OrderController {
@Post()
@HttpCode(HttpStatus.CREATED)
async create(
@Body() dto: CreateOrderDto,
@CurrentUser() user: User,
): Promise<OrderResponseDto> {
return this.orderService.create(dto, user.id);
}
@Get(':id')
@UseInterceptors(CacheInterceptor)
async findOne(@Param('id', ParseUUIDPipe) id: string) {
return this.orderService.findOne(id);
}
}
4. Exception Handling
typescript
// Custom exception filter
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const status = exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const message = exception instanceof HttpException
? exception.message
: 'Internal server error';
response.status(status).json({
statusCode: status,
message,
timestamp: new Date().toISOString(),
});
}
}
5. Interceptors & Pipes
typescript
// Transform response interceptor
@Injectable()
export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
return next.handle().pipe(
map(data => ({
success: true,
data,
timestamp: new Date().toISOString(),
})),
);
}
}
// Validation pipe (global)
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}));
Quick Start
- •
Create new project:
bashnest new my-project cd my-project
- •
Generate resources:
bashnest g module users nest g controller users nest g service users
- •
Setup validation:
bashnpm install class-validator class-transformer
- •
Configure global pipes in main.ts:
typescriptapp.useGlobalPipes(new ValidationPipe({ whitelist: true })); - •
Add Swagger documentation:
bashnpm install @nestjs/swagger swagger-ui-express
Production Checklist
- • Global exception filter configured
- • Validation pipes enabled globally
- • Health check endpoint (
/health) - • Swagger documentation enabled (dev only)
- • Rate limiting configured
- • Helmet security headers
- • CORS properly configured
- • Environment config validated on startup
- • Graceful shutdown handling
- • Request logging with correlation IDs
Anti-patterns
- •Fat Controllers: Controllers should only handle HTTP concerns, delegate logic to services
- •Circular Dependencies: Use
forwardRef()sparingly, refactor module structure instead - •Skipping DTOs: Always validate input with DTOs and class-validator
- •God Modules: Break large modules into smaller, focused modules
Integration Points
- •Database:
@nestjs/typeorm,@nestjs/mongoose,@nestjs/prisma - •Caching:
@nestjs/cache-managerwith Redis - •Queue:
@nestjs/bullfor job processing - •GraphQL:
@nestjs/graphqlwith Apollo - •Microservices:
@nestjs/microservicesfor distributed systems