mcpField
N
nestjs-code-review

nestjs-code-review

github.com/giuseppe-trisciuoglio测试与质量3653.8k 次安装7 周前更新
代码仓库

关于 nestjs-code-review

面向 NestJS 项目维护者,提供按严重程度分类的代码审查流程,检查模块组织、依赖注入、控制器、服务、安全与测试,并要求关键发现具备可复现证据。

主要功能

  1. 01检查模块边界与循环依赖
  2. 02审查依赖注入和控制器设计
  3. 03检查服务逻辑与安全实践
  4. 04评估测试覆盖与模拟方式
  5. 05按严重程度输出可执行建议

适用场景

  1. 01合并拉取请求前审查 NestJS 改动
  2. 02检查控制器和服务实现
  3. 03验证模块架构与授权模式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill nestjs-code-review

安装后在 Claude Code 中输入/nestjs-code-review确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
anti-patterns.md
checklist.md
patterns.md

详细介绍

NestJS 代码审查

概述

为 NestJS 应用提供结构化代码审查。审查结果按严重程度分类(严重、警告、建议),并附有可执行的改进建议。深度分析由 nestjs-code-review-expert Agent 负责。

适用场景

  • “审查 NestJS 代码”、“NestJS 代码审查”、“检查我的 NestJS 控制器/服务”
  • 合并拉取请求前或实现新功能后
  • 验证 NestJS 装饰器、DI 模式和守卫实现
  • 验证 NestJS 模块和提供者的架构
  • 审查 DTO、管道、拦截器和数据库集成(TypeORM、Prisma、Drizzle)

使用说明

  1. 确定范围:确定需要审查的 NestJS 文件和模块。使用 glob 和 grep 查找目标区域内的控制器、服务、模块、守卫、拦截器和管道。

  2. 分析模块结构:验证模块组织是否恰当——每个功能都应有自己的模块,并明确列出导入项、控制器、提供者和导出项。检查是否存在循环依赖,并确认模块边界设置合理。

  3. 审查依赖注入:验证所有可注入服务是否使用构造函数注入。检查提供者的作用域(单例、请求级、瞬态)是否符合预期生命周期。确保没有绕过 DI 容器直接实例化对象。

  4. 评估控制器:审查 HTTP 方法的使用、路由命名、状态码、请求/响应 DTO、验证管道和 OpenAPI 装饰器。确认控制器保持精简——业务逻辑应放在服务中。

  5. 评估服务和业务逻辑:检查服务是否恰当地封装业务逻辑。验证错误处理、事务管理,以及与基础设施关注点的分离是否合理。留意过于庞大或职责过多的服务方法。

  6. 检查安全性:审查守卫实现、身份验证/授权模式、使用 class-validator 进行的输入验证,以及针对常见漏洞(注入、XSS、CSRF)的防护。

  7. 审查测试:评估控制器、服务、守卫和管道的测试覆盖率。验证模拟策略是否恰当,以及测试验证的是行为而非实现细节。

  8. 验证审查结果(必要检查点):定稿前,验证每项严重和警告级问题都有可复现的证据(文件路径、行号、准确代码片段)和具体、可执行的修复方案。删除或降低仅涉及风格偏好、过于主观或缺乏具体修复方案的问题。

  9. 生成审查报告:生成结构化报告,包含按严重程度分类的审查结果(严重、警告、建议)、积极评价,以及附有代码示例的优先级建议。

示例

示例 1:审查控制器
// ❌ Bad: Fat controller with business logic and missing validation
@Controller('users')
export class UserController {
  constructor(private readonly userRepo: Repository<User>) {}

  @Post()
  async create(@Body() body: any) {
    const user = this.userRepo.create(body);
    return this.userRepo.save(user);
  }
}

// ✅ Good: Thin controller with proper DTOs, validation, and service delegation
@Controller('users')
@ApiTags('Users')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post()
  @HttpCode(HttpStatus.CREATED)
  @ApiOperation({ summary: 'Create a new user' })
  @ApiResponse({ status: 201, type: UserResponseDto })
  async create(
    @Body(ValidationPipe) createUserDto: CreateUserDto,
  ): Promise<UserResponseDto> {
    return this.userService.create(createUserDto);
  }
}
示例 2:审查依赖注入
// ❌ Bad: Direct instantiation bypasses DI
@Injectable()
export class OrderService {
  private readonly logger = new Logger();
  private readonly emailService = new EmailService();

  async createOrder(dto: CreateOrderDto) {
    this.emailService.send(dto.email, 'Order created');
  }
}

// ✅ Good: Proper constructor injection
@Injectable()
export class OrderService {
  private readonly logger = new Logger(OrderService.name);

  constructor(
    private readonly orderRepository: OrderRepository,
    private readonly emailService: EmailService,
  ) {}

  async createOrder(dto: CreateOrderDto): Promise<Order> {
    const order = await this.orderRepository.create(dto);
    await this.emailService.send(dto.email, 'Order created');
    return order;
  }
}
示例 3:审查错误处理
// ❌ Bad: Generic error handling with information leakage
@Get(':id')
async findOne(@Param('id') id: string) {
  try {
    return await this.service.findOne(id);
  } catch (error) {
    throw new HttpException(error.message, 500);
  }
}

// ✅ Good: Domain-specific exceptions with proper HTTP mapping
@Get(':id')
async findOne(@Param('id', ParseUUIDPipe) id: string): Promise<UserResponseDto> {
  const user = await this.userService.findOne(id);
  if (!user) {
    throw new NotFoundException(`User with ID ${id} not found`);
  }
  return user;
}
示例 4:审查守卫实现
// ❌ Bad: Authorization logic in controller
@Get('admin/dashboard')
async getDashboard(@Req() req: Request) {
  if (req.user.role !== 'admin') {
    throw new ForbiddenException();
  }
  return this.dashboardService.getData();
}

// ✅ Good: Guard-based authorization with decorator
@Get('admin/dashboard')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(Role.ADMIN)
async getDashboard(): Promise<DashboardDto> {
  return this.dashboardService.getData();
}
示例 5:审查模块组织
// ❌ Bad: Monolithic module with everything
@Module({
  imports: [TypeOrmModule.forFeature([User, Order, Product, Review])],
  controllers: [UserController, OrderController, ProductController],
  providers: [UserService, OrderService, ProductService, ReviewService],
})
export class AppModule {}

// ✅ Good: Feature-based module organization
@Module({
  imports: [UserModule, OrderModule, ProductModule],
})
export class AppModule {}

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UserController],
  providers: [UserService, UserRepository],
  exports: [UserService],
})
export class UserModule {}

审查输出格式

所有代码审查结果均按以下结构组织:

1. 总结

简要概述整体质量评分(1-10)和关键观察结果。

2. 严重问题(必须修复)

可能导致安全漏洞、数据损坏或生产环境故障的问题。

3. 警告(应当修复)

违反最佳实践、降低可维护性或可能引发错误的问题。

4. 建议(可考虑改进)

提升代码可读性、性能或开发者体验的改进。

5. 积极评价

值得认可和鼓励的良好实现模式和实践。

6. 建议措施

按优先级列出后续步骤,并为影响最大的改进提供代码示例。

最佳实践

  • 控制器应保持精简——将所有业务逻辑交给服务处理
  • 所有请求和响应负载都应使用带有 class-validator 的 DTO
  • 使用 ParseUUIDPipe、ParseIntPipe 等进行参数验证
  • 使用继承自 HttpException 的领域专用异常类
  • 将代码组织到边界清晰、导出明确的功能模块中
  • 优先使用构造函数注入——不要使用 new 实例化可注入服务
  • 使用守卫进行身份验证和授权,不要在代码中内联检查
  • 使用拦截器处理横切关注点(日志记录、缓存、转换)
  • 为所有端点添加 OpenAPI 装饰器(@ApiTags、@ApiOperation、@ApiResponse)
  • 为服务编写单元测试,为控制器编写集成测试

限制和警告

  • 不要强制使用单一 ORM——代码库可能使用 TypeORM、Prisma、Drizzle 或 MikroORM
  • 即使现有项目约定与 NestJS 默认规范不同,也应遵循现有约定
  • 聚焦于高置信度的问题——避免将风格偏好误报为问题
  • 检查微服务模式时,应考虑特定于传输层的限制
  • 除非存在严重问题,否则不要建议重写架构

参考资料

详细的审查清单和模式文档见 references/ 目录:

  • references/patterns.md — NestJS 最佳实践模式及示例
  • references/anti-patterns.md — 审查时应标记的常见 NestJS 反模式
  • references/checklist.md — 按领域整理的综合审查清单

评论

支持 Markdown