NestJS Development Skill
Quick Reference
# Scaffold a new module with CRUD
python scripts/scaffold.py user --crud
# Generate specific component
python scripts/generate.py controller user
python scripts/generate.py service user --repository
# Run tests with coverage
python scripts/test.py --coverage --threshold 80
Load Additional Resources
| Scenario | Reference | Description |
|---|
| Architecture decisions | references/architecture.md | Clean arch, DDD, CQRS |
| Auth/Authorization | references/security.md | JWT, Passport, RBAC |
| Database integration | references/database.md | TypeORM, Prisma |
| Testing strategies | references/testing.md | Unit, E2E, mocking |
| Performance | references/performance.md | Caching, queues |
Core Patterns
Module Structure
// REQ-XXX: Feature module
@Module({
imports: [TypeOrmModule.forFeature([User]), ConfigModule],
controllers: [UserController],
providers: [UserService, UserRepository],
exports: [UserService],
})
export class UserModule {}
Service Pattern
@Injectable()
export class UserService {
constructor(
private readonly userRepository: UserRepository,
private readonly eventEmitter: EventEmitter2,
) {}
async create(dto: CreateUserDto): Promise<User> {
const user = await this.userRepository.create(dto);
this.eventEmitter.emit('user.created', user);
return user;
}
}
Controller Pattern
@ApiTags('users')
@Controller('users')
@UseGuards(JwtAuthGuard, RolesGuard)
export class UserController {
constructor(private readonly userService: UserService) {}
@Post()
@Roles(Role.ADMIN)
@ApiOperation({ summary: 'Create user' })
@ApiResponse({ status: 201, type: UserResponseDto })
async create(@Body() dto: CreateUserDto): Promise<UserResponseDto> {
return this.userService.create(dto);
}
}
DTO with Validation
export class CreateUserDto {
@ApiProperty({ example: 'john@example.com' })
@IsEmail()
@IsNotEmpty()
email: string;
@ApiProperty({ minLength: 8 })
@IsString()
@MinLength(8)
@Matches(/^(?=.*[A-Za-z])(?=.*\d)/)
password: string;
}
Guard Pattern
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(
ROLES_KEY, [context.getHandler(), context.getClass()],
);
if (!requiredRoles) return true;
const { user } = context.switchToHttp().getRequest();
return requiredRoles.some((role) => user.roles?.includes(role));
}
}
Project Structure
src/
├── main.ts # Bootstrap
├── app.module.ts # Root module
├── common/ # Shared utilities
│ ├── decorators/ # @Roles, @User, @Public
│ ├── dto/ # PaginationDto, ResponseDto
│ ├── filters/ # HttpExceptionFilter
│ ├── guards/ # JwtAuthGuard, RolesGuard
│ ├── interceptors/ # TransformInterceptor
│ └── pipes/ # ValidationPipe extensions
├── config/ # Configuration
└── modules/ # Feature modules
└── {feature}/
├── {feature}.module.ts
├── {feature}.controller.ts
├── {feature}.service.ts
├── {feature}.repository.ts
├── dto/
├── entities/
└── __tests__/
F5 Quality Gates
| Gate | Requirement | Implementation |
|---|
| D3 | Architecture | Module structure documented |
| D4 | Detailed Design | DTOs, entities defined |
| G2.5 | Code Review | NestJS best practices |
| G3 | 80% Coverage | Jest + supertest |
Scripts
| Script | Usage | Gate |
|---|
scaffold.py | scaffold.py <name> --crud | D4 |
generate.py | generate.py <type> <name> | G2.5 |
test.py | test.py --coverage | G3 |
Common Packages
{
"@nestjs/core": "^10.0.0",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.0.0",
"@nestjs/typeorm": "^10.0.0",
"@nestjs/passport": "^10.0.0",
"@nestjs/jwt": "^10.0.0",
"@nestjs/swagger": "^7.0.0",
"class-validator": "^0.14.0"
}