Skip to main content

NestJS Prompt Templates

Cập nhật: 03/2026


Essential Aspects & Templates

1. REST Controllers

<role>NestJS backend developer chuyên API design</role>

<action>
Tạo REST controller [TÊN_CONTROLLER] để handle [RESOURCE] CRUD operations
</action>

<context>
- Resource: [TÊN_RESOURCE]
- Endpoints: [GET_ALL, GET_BY_ID, POST, PUT, DELETE]
- DTOs: [CREATE/UPDATE/RESPONSE]
- Service: [TÊN_SERVICE]
- Validation: class-validator
- Cần đọc existing controllers để học patterns
</context>

<expectation>
- @Controller('resource') decorator với route prefix
- Constructor injection: constructor(private service: ResourceService)
- HTTP method decorators: @Get(), @Post(), @Put(), @Delete()
- Route parameters: @Param('id', ParseIntPipe) id: number
- Request body: @Body() dto: CreateResourceDto
- Query parameters: @Query() query: PaginationDto
- HTTP status: @HttpCode(201) cho custom status
- Swagger: @ApiTags('Resource'), @ApiOperation(), @ApiResponse()
- File: src/[module]/[resource].controller.ts
</expectation>

2. Services & Business Logic

<role>NestJS architect chuyên service layer design</role>

<action>
Tạo service [TÊN_SERVICE] để implement business logic cho [FEATURE]
</action>

<context>
- Feature: [MÔ_TẢ_FEATURE]
- Repository/ORM: [TypeORM/Prisma]
- Dependencies: [OTHER_SERVICES]
- Operations: [LIỆT_KÊ_OPERATIONS]
- Error handling: [NotFoundException, ConflictException]
</context>

<expectation>
- @Injectable() decorator
- Constructor injection: constructor(@InjectRepository(Entity) private repo: Repository<Entity>)
- Async methods: async findAll(): Promise<Entity[]>
- Error handling: throw new NotFoundException('Resource not found')
- Transaction support: @Transaction(), @TransactionManager()
- TypeScript return types: Promise<T>
- Logging: private logger = new Logger(ServiceName.name)
- File: src/[module]/[service].service.ts
</expectation>

3. Modules & Dependency Injection

<role>NestJS architect chuyên modular design</role>

<action>
Tạo feature module [TÊN_MODULE] để organize [COMPONENTS]
</action>

<context>
- Feature: [TÊN_FEATURE]
- Components: [CONTROLLERS/SERVICES/REPOSITORIES/ENTITIES]
- Dependencies: [OTHER_MODULES]
- Exports: [SHARED_PROVIDERS]
- Database: TypeORM entities hoặc Prisma
</context>

<expectation>
- @Module() decorator
- imports: [TypeOrmModule.forFeature([Entity]), OtherModule]
- controllers: [ResourceController]
- providers: [ResourceService, CustomRepository]
- exports: [ResourceService] để share với other modules
- Folder structure:
• controllers/
• services/
• entities/
• dto/
• [module].module.ts
- File: src/[module]/[module].module.ts
</expectation>

4. TypeORM Entities

<role>Database developer chuyên TypeORM</role>

<action>
Tạo TypeORM entity [TÊN_ENTITY] cho table [TÊN_TABLE]
</action>

<context>
- Table name: [TÊN_TABLE]
- Columns: [LIỆT_KÊ_COLUMNS]
- Relationships: [ONE_TO_MANY/MANY_TO_ONE/MANY_TO_MANY]
- Indexes: [UNIQUE/COMPOSITE]
- Timestamps: created_at, updated_at
</context>

<expectation>
- @Entity('table_name') decorator
- @PrimaryGeneratedColumn() cho id
- @Column() với options: { type, length, nullable, unique, default }
- Relationships:
• @OneToMany(() => Related, related => related.entity)
• @ManyToOne(() => Parent, parent => parent.children)
• @ManyToMany(() => Related)
• @JoinTable() cho owning side của many-to-many
- @Index(['column'], { unique: true })
- @CreateDateColumn(), @UpdateDateColumn()
- TypeScript types: số, string, boolean, Date
- File: src/[module]/entities/[entity].entity.ts
</expectation>

5. DTOs & Validation

<role>NestJS developer chuyên validation</role>

<action>
Tạo DTOs cho [RESOURCE] với class-validator decorators
</action>

<context>
- Resource: [TÊN_RESOURCE]
- Operations: [CREATE/UPDATE/RESPONSE]
- Fields: [LIỆT_KÊ_FIELDS]
- Validation rules: [REQUIRED/EMAIL/MIN/MAX/CUSTOM]
- Swagger documentation: YES
</context>

<expectation>
DTOs (src/[module]/dto/):
- create-[resource].dto.ts
- update-[resource].dto.ts
- [resource]-response.dto.ts

Validation decorators:
- @IsString(), @IsNumber(), @IsBoolean(), @IsEmail(), @IsUrl()
- @IsNotEmpty(), @IsOptional()
- @MinLength(n), @MaxLength(n), @Min(n), @Max(n)
- @IsEnum(EnumType), @IsArray(), @ValidateNested()
- @Matches(/regex/, { message: 'error' })
- @Type(() => NestedDto) com nested objects

Swagger:
- @ApiProperty({ example, description, required })

Inheritance:
- UpdateDto: PartialType(CreateDto)
</expectation>

6. JWT Authentication

<role>Security engineer chuyên NestJS authentication</role>

<action>
Implement JWT authentication với Passport.js
</action>

<context>
- Auth flow: register → login → JWT → protected routes
- Strategy: JWT với HS256
- Password: bcrypt hashing
- User storage: [TypeORM/Prisma]
- Token expiry: 1 hour
</context>

<expectation>
Setup (auth module):
- Install: @nestjs/jwt, @nestjs/passport, passport, passport-jwt, bcrypt
- AuthModule: imports JwtModule.register({ secret, signOptions })
- AuthService: login(), register(), validateUser()

JWT Strategy (auth/strategies/jwt.strategy.ts):
- extends PassportStrategy(Strategy)
- validate(payload): return user object

Guards:
- @UseGuards(JwtAuthGuard) cho protected routes
- JwtAuthGuard extends AuthGuard('jwt')

Password hashing:
- bcrypt.hash(password, 10)
- bcrypt.compare(plain, hashed)

Endpoints:
- POST /auth/register: hash password, save user
- POST /auth/login: validate, sign JWT, return { access_token }

Protected routes:
- @UseGuards(JwtAuthGuard)
- @Request() req → req.user
</expectation>

7. Guards & Authorization

<role>Security engineer chuyên authorization</role>

<action>
Implement role-based access control với custom guards
</action>

<context>
- Roles: [ADMIN/USER/MODERATOR]
- Protected resources: [ENDPOINTS]
- Decorator: @Roles() custom decorator
- Check: user roles from JWT payload
</context>

<expectation>
Roles decorator (auth/decorators/roles.decorator.ts):
- export const Roles = (...roles: Role[]) => SetMetadata('roles', roles)

Roles guard (auth/guards/roles.guard.ts):
- @Injectable() implements CanActivate
- Reflector injection: constructor(private reflector: Reflector)
- canActivate(): get required roles, check user.roles
- Return true/false hoặc throw ForbiddenException

Usage:
- @UseGuards(JwtAuthGuard, RolesGuard)
- @Roles(Role.ADMIN)
- Combine guards: apply both

User object:
- req.user populated by JwtAuthGuard
- req.user.roles array checked
</expectation>

8. Interceptors & Middleware

<role>NestJS developer chuyên request/response processing</role>

<action>
Tạo interceptor để [TRANSFORM_RESPONSE/LOG_REQUESTS/CACHE]
</action>

<context>
- Purpose: [LOGGING/TRANSFORMATION/CACHING/ERROR_HANDLING]
- Apply: [GLOBALLY/PER_ROUTE/PER_CONTROLLER]
- RxJS operators: [map, tap, catchError]
</context>

<expectation>
Interceptor (common/interceptors/[name].interceptor.ts):
- @Injectable() implements NestInterceptor
- intercept(context: ExecutionContext, next: CallHandler)
- Access request: context.switchToHttp().getRequest()
- Transform response: next.handle().pipe(map(data => ({ success: true, data })))
- Logging: tap() để log without modifying
- Error handling: catchError()

Apply:
- Global: app.useGlobalInterceptors(new LoggingInterceptor())
- Route: @UseInterceptors(TransformInterceptor)
- Controller: @UseInterceptors() trên controller class

Common patterns:
- Response transformation: wrap data in standard format
- Logging: log request/response
- Cache: cache GET requests
</expectation>

9. Exception Filters

<role>Backend developer chuyên error handling</role>

<action>
Tạo global exception filter cho consistent error responses
</action>

<context>
- Error format: { statusCode, message, timestamp, path }
- HTTP exceptions: 400, 401, 403, 404, 409, 500
- Logging: log errors với stack traces
- Environment: hide details trong production
</context>

<expectation>
Exception filter (common/filters/http-exception.filter.ts):
- @Catch(HttpException) implements ExceptionFilter
- catch(exception: HttpException, host: ArgumentsHost)
- Extract context: host.switchToHttp()
- Response format:
{
statusCode: exception.getStatus(),
timestamp: new Date().toISOString(),
path: request.url,
message: exception.message
}
- Logger injection: log errors
- Apply globally: app.useGlobalFilters(new HttpExceptionFilter())

Custom exceptions:
- Extend HttpException
- Throw: throw new CustomException('message')
</expectation>

10. Configuration

<role>DevOps engineer chuyên configuration</role>

<action>
Setup configuration management với @nestjs/config
</action>

<context>
- Environments: [DEVELOPMENT/STAGING/PRODUCTION]
- Variables: [DATABASE_URL/JWT_SECRET/PORT/NODE_ENV]
- Files: .env, .env.development, .env.production
- Validation: Joi schema
</context>

<expectation>
Setup (app.module.ts):
- import { ConfigModule } from '@nestjs/config'
- ConfigModule.forRoot({ isGlobal: true, envFilePath })

Config files (config/):
- configuration.ts: export default () => ({ ... })
- database.config.ts: database-specific config
- auth.config.ts: auth-specific config

Usage:
- Inject: constructor(private configService: ConfigService)
- Access: this.configService.get<string>('DATABASE_URL')
- Type-safe: this.configService.get<number>('PORT')

Validation:
- validationSchema: Joi.object({ ... })
- Validate on startup
- Required variables throw error if missing

Environment:
- .env (gitignored)
- .env.example (committed, no secrets)
</expectation>

11. Testing

<role>QA Engineer chuyên NestJS testing</role>

<action>
Viết unit tests cho [SERVICE/CONTROLLER] với Jest
</action>

<context>
- Test subject: [SERVICE/CONTROLLER/GUARD]
- Dependencies: [REPOSITORY/OTHER_SERVICES]
- Test framework: Jest (built-in)
- Coverage target: >= 80%
</context>

<expectation>
Setup ([name].spec.ts):
- TestingModule = Test.createTestingModule({ providers, imports })
- Mock dependencies: { provide: Repository, useValue: mockRepository }
- Compile: module.compile()

Service tests:
- Mock TypeORM repository: jest.fn()
- Test methods: describe('methodName'), it('should...')
- Arrange-Act-Assert
- Mock return values: mockRepo.findOne.mockResolvedValue(user)
- Test errors: expect(promise).rejects.toThrow(NotFoundException)

Controller tests:
- Mock service: jest.fn()
- Test routes: expect(result).toEqual(expected)
- HTTP context: mock Request/Response if needed

E2E tests (test/[feature].e2e-spec.ts):
- supertest: request(app.getHttpServer())
- Real database: test database
- Complete flows: register → login → CRUD
- Assertions: .expect(200).expect({ ... })
</expectation>

12. Swagger/OpenAPI Documentation

<role>API documentation specialist</role>

<action>
Setup comprehensive Swagger documentation cho [API]
</action>

<context>
- API version: [VERSION]
- Authentication: Bearer JWT
- Endpoints: [SỐ_LƯỢNG] endpoints
- Tags: [LIỆT_KÊ_RESOURCE_GROUPS]
</context>

<expectation>
Setup (main.ts):
- import { SwaggerModule, DocumentBuilder }
- const config = new DocumentBuilder()
.setTitle('API Title')
.setDescription('Description')
.setVersion('1.0')
.addBearerAuth()
.build()
- const document = SwaggerModule.createDocument(app, config)
- SwaggerModule.setup('api/docs', app, document)

Decorators:
- Controllers: @ApiTags('Resource')
- Routes: @ApiOperation({ summary: '...' })
- Responses: @ApiResponse({ status: 200, type: ResponseDto })
- Auth: @ApiBearerAuth()
- DTOs: @ApiProperty({ example, description })

Access:
- Navigate to /api/docs
- Interactive API testing
- Schema download
</expectation>

Best Practices Checklist

  • ✅ TypeScript strict mode
  • ✅ Dependency injection cho all services
  • ✅ DTOs với class-validator
  • ✅ Proper module organization
  • ✅ ConfigModule cho environment
  • ✅ JWT authentication với guards
  • ✅ Exception filters
  • ✅ Swagger documentation
  • ✅ Testing >= 80% coverage
  • ✅ Logging với Logger
  • ✅ Proper HTTP status codes