skills/doanchienthangdev/omgkit/building-nestjs-apis

building-nestjs-apis

SKILL.md

NestJS

Quick Start

import { Controller, Get, Module, NestFactory } from '@nestjs/common';

@Controller('health')
class HealthController {
  @Get()
  check() {
    return { status: 'ok' };
  }
}

@Module({ controllers: [HealthController] })
class AppModule {}

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

Features

Feature Description Guide
Modules Dependency injection, providers MODULES.md
Controllers Routes, validation, guards CONTROLLERS.md
Services Business logic, repositories SERVICES.md
Database TypeORM, Prisma integration DATABASE.md
Auth Passport, JWT, guards AUTH.md
Testing Unit, e2e with Jest TESTING.md

Common Patterns

Controller with Validation

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

  @Get()
  @Roles('admin')
  findAll(@Query() query: PaginationDto) {
    return this.usersService.findAll(query);
  }

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

  @Post()
  create(@Body() dto: CreateUserDto) {
    return this.usersService.create(dto);
  }
}

Service with Repository

@Injectable()
export class UsersService {
  constructor(private readonly usersRepo: UsersRepository) {}

  async findAll(query: PaginationDto) {
    const [users, total] = await this.usersRepo.findAllWithCount({
      skip: query.skip,
      take: query.limit,
    });
    return { data: users, total, page: query.page };
  }

  async findOne(id: string) {
    const user = await this.usersRepo.findOne({ where: { id } });
    if (!user) throw new NotFoundException('User not found');
    return user;
  }

  async create(dto: CreateUserDto) {
    const exists = await this.usersRepo.findByEmail(dto.email);
    if (exists) throw new ConflictException('Email in use');
    return this.usersRepo.save(this.usersRepo.create(dto));
  }
}

DTO with Validation

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsString()
  @MinLength(2)
  name: string;

  @IsString()
  @MinLength(8)
  @Matches(/^(?=.*[A-Z])(?=.*\d)/, {
    message: 'Password must contain uppercase and number',
  })
  password: string;

  @IsOptional()
  @IsEnum(UserRole)
  role?: UserRole;
}

Workflows

API Development

  1. Create module with nest g module [name]
  2. Create controller and service
  3. Define DTOs with class-validator
  4. Add guards for auth/roles
  5. Write unit and e2e tests

Module Structure

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UsersController],
  providers: [UsersService, UsersRepository],
  exports: [UsersService],
})
export class UsersModule {}

Best Practices

Do Avoid
Use dependency injection Direct instantiation
Validate with DTOs Trusting input
Use guards for auth Auth logic in controllers
Use interceptors for cross-cutting Duplicating logging/transform
Write unit + e2e tests Skipping test coverage

Project Structure

src/
├── main.ts
├── app.module.ts
├── common/
│   ├── decorators/
│   ├── guards/
│   ├── interceptors/
│   └── pipes/
├── config/
├── users/
│   ├── users.module.ts
│   ├── users.controller.ts
│   ├── users.service.ts
│   ├── dto/
│   └── entities/
└── auth/
    ├── auth.module.ts
    ├── strategies/
    └── guards/

For detailed examples and patterns, see reference files above.

Weekly Installs
4
GitHub Stars
3
First Seen
Feb 20, 2026
Installed on
opencode4
gemini-cli4
antigravity4
github-copilot4
codex4
amp4