Defines the structure and responsibilities of the Module layer (Service, Controller, Module).
This skill defines the responsibilities of the core module files. A module consists of:
.service.ts): Business logic, calculations, and DTO transformation..controller.ts): HTTP routing, documentation (Swagger), and request delegation..module.ts): Dependency Injection wiring..service.ts)Responsibilities:
NotFoundException, ConflictException).Example: user.service.ts
import { Injectable, NotFoundException } from "@nestjs/common";
import { UserRepository } from "@repositories/user.repository";
import { UserCreateDto } from "./dto/user-create.dto";
import * as bcrypt from "bcrypt";
@Injectable()
export class UserService {
constructor(private readonly userRepository: UserRepository) {}
async create(dto: UserCreateDto) {
try {
// Business Logic: Hash password
const hashedPassword = await bcrypt.hash(dto.password, 10);
const fullName = `${dto.firstName} ${dto.lastName}`;
// Call Repository
const user = await this.userRepository.create({
...dto,
password: hashedPassword,
fullName,
});
// Sanitization
const { password, ...cleanUser } = user;
return cleanUser;
} catch (error) {
// Handle known errors
throw error;
}
}
}
.controller.ts)Responsibilities:
@Get, @Post, etc.).@ApiTags, @ApiOperation, @ApiResponse).@Body, @Query).any in DTOs or parameters; proper typing is required for Swagger to generate documentation and validation correctly.Example: user.controller.ts
import { Controller, Get, Post, Body, Query, UseGuards } from "@nestjs/common";
import {
ApiTags,
ApiOperation,
ApiResponse,
ApiBearerAuth,
} from "@nestjs/swagger";
import { UserService } from "./user.service";
import { UserListDto, UserListFiltersDto } from "./dto/user-list.dto";
import { UserCreateDto } from "./dto/user-create.dto";
import { HttpErrorDto } from "@models/http-error.dto";
@ApiTags("user")
@ApiBearerAuth()
@Controller("admin/user")
export class UserController {
constructor(private readonly userService: UserService) {}
@Get("find-all")
@ApiOperation({ summary: "Get all users paginated" })
@ApiResponse({ status: 200, type: UserListDto })
@ApiResponse({ status: 400, type: HttpErrorDto })
findAll(@Query() filters: UserListFiltersDto) {
return this.userService.findAllPaginated(filters);
}
@Post("create")
@ApiOperation({ summary: "Create a new user" })
@ApiResponse({ status: 200, type: UserListDto }) // Returns generic object, refine type as needed
@ApiResponse({ status: 400, type: HttpErrorDto })
create(@Body() dto: UserCreateDto) {
return this.userService.create(dto);
}
}
.module.ts)Responsibilities:
Example: user.module.ts
import { Module } from "@nestjs/common";
import { UserService } from "./user.service";
import { UserController } from "./user.controller";
import { UserRepository } from "@repositories/user.repository";
@Module({
controllers: [UserController],
providers: [UserService, UserRepository],
exports: [UserService, UserRepository],
})
export class UserModule {}
Common DTOs like error responses should be placed in src/models/.
File: src/models/http-error.dto.ts
import { ApiProperty } from "@nestjs/swagger";
export class HttpErrorDto {
@ApiProperty({
description: "Error message(s)",
example: ["Validation failed"],
})
message: string | string[];
@ApiProperty({ description: "Error type", example: "Bad Request" })
error: string;
@ApiProperty({ description: "Status code", example: 400 })
statusCode: number;
}