什么是 nestjs-docfy
一个 NestJS 工具层,把 Swagger 装饰器移出控制器,同时不丢失类型信息,也不会生成不同的 OpenAPI 输出。
问题
用 @nestjs/swagger 文档化的 NestJS 控制器很快就会堆满几十个 @ApiOperation、@ApiResponse、@ApiBody 和 @ApiTags,以至于路由真正的逻辑最后被埋在文档元数据下面。
解决方案
nestjs-docfy 引入一个简单的约定:每个 *.controller.ts 旁边都有一个 *.controller.docs.ts,装着所有文档内容。这和 Nest 已经在用的 *.spec.ts 是同一套模式。
- 生成的 OpenAPI 输出完全不变。
- 类型信息保留:companion 文件会导入控制器类。
- 在
SwaggerModule.createDocument()之前,通过require.cache完成发现。
前后对比
users.controller.ts
@WithDocs()
@Controller('users')
export class UsersController {
@Get(':id')
findOne(@Param('id') id: string) {
return this.users.findOne(id);
}
}users.controller.docs.ts
docs(UsersController, {
classDecorators: [ApiTags('Users')],
methods: {
findOne: [
ApiParam({ name: 'id', type: String }),
ApiOperation({ summary: 'Get user by id' }),
ApiResponse({ status: 200, type: UserDto }),
ApiResponse({ status: 404, description: 'User not found' }),
],
},
});webpack: true
Companion 文件发现依赖 require.cache,所以在 nest-cli.json 配置了 "webpack": true 的情况下,运行时无法工作。对这类项目,改为注册 CLI 插件:它会在每次构建时自动地从根本上解决这个问题。
什么时候该用
适合以下场景
- 你的 API 有几十个端点,每个路由有多种响应。
- 你的团队把 OpenAPI 当作一份有版本管理的契约。
- 你想要客观的 CI 门禁(最低覆盖率、文档 lint)。
AI-first
配套的包 docfy-ui 会渲染出 API 参考,每个端点都带一个 Copy for AI 按钮,特别适合粘贴进 LLM。