📄 OpenAPI 文档导出功能 - 更新总结
✅ 已完成的工作
1. 实现 OpenAPI JSON 导出接口
创建了 /api/swagger/json 接口,直接返回标准 OpenAPI 3.0 JSON 格式,可用于 Apifox、Postman 等工具自动导入。
关键特性:
- ✅ 直接返回 OpenAPI JSON(不包装在
{ success, data }中) - ✅ 公开访问,无需认证
- ✅ 符合 OpenAPI 3.0 规范
- ✅ 包含所有接口定义、Schema、认证配置
2. 创建 @SkipTransform() 装饰器
实现了跳过全局响应转换的机制,用于需要返回原始格式的接口。
文件: src/common/decorators/skip-transform.decorator.ts
typescript
export const SkipTransform = () => SetMetadata(SKIP_TRANSFORM_KEY, true);3. 更新 TransformInterceptor
增强了全局拦截器,支持检查 @SkipTransform() 装饰器。
文件: src/common/interceptors/transform.interceptor.ts
新增功能:
- 检查是否标记为
@SkipTransform() - 如果标记,直接返回原始数据
- 否则包装成统一响应格式
4. 创建 Swagger 模块
新增文件:
src/modules/swagger/swagger.controller.ts- 控制器src/modules/swagger/swagger.service.ts- 服务src/modules/swagger/swagger.module.ts- 模块
提供接口:
GET /api/swagger/json- OpenAPI JSON 文档(不包装)GET /api/swagger/stats- API 统计信息(包装)
5. 更新配置和文档
更新的文件:
src/main.ts- 注入 document 到 SwaggerServicesrc/config/swagger.config.ts- 添加服务器配置src/app.module.ts- 注册 SwaggerModuleREADME.md- 添加 OpenAPI 导出说明CLAUDE.md- 更新 API 端点列表
新增文档:
APIFOX_IMPORT_GUIDE.md- Apifox 导入详细指南OPENAPI_IMPLEMENTATION.md- 技术实现说明test-swagger-api.sh- API 测试脚本
🎯 使用方式
在 Apifox 中导入
URL 自动导入(推荐):
http://localhost:3000/api/swagger/json手动下载导入:
bashcurl http://localhost:3000/api/swagger/json > openapi.json # 然后在 Apifox 中导入该文件
查看 API 统计
bash
curl http://localhost:3000/api/swagger/stats📊 响应格式对比
OpenAPI JSON 接口(不包装)
bash
curl http://localhost:3000/api/swagger/json响应:
json
{
"openapi": "3.0.0",
"info": { ... },
"paths": { ... },
"components": { ... }
}API 统计接口(包装)
bash
curl http://localhost:3000/api/swagger/stats响应:
json
{
"success": true,
"data": {
"totalEndpoints": 20,
"totalPaths": 16,
...
},
"message": "success",
"timestamp": "..."
}🔧 技术实现要点
问题:统一响应格式导致 Apifox 无法解析
原因: 全局的 TransformInterceptor 会将所有响应包装成:
json
{
"success": true,
"data": { ... }
}但 OpenAPI 规范要求直接返回 JSON,不能有额外包装。
解决方案
- 创建
@SkipTransform()装饰器标记需要跳过包装的接口 - 在
TransformInterceptor中检查该装饰器 - 如果标记了,直接返回原始数据
- 在 SwaggerController 的
getOpenApiJson()方法上使用该装饰器
📁 创建/修改的文件
新增文件(7个)
src/common/decorators/
└── skip-transform.decorator.ts # 跳过转换装饰器
src/modules/swagger/
├── swagger.controller.ts # Swagger 控制器
├── swagger.service.ts # Swagger 服务
└── swagger.module.ts # Swagger 模块
APIFOX_IMPORT_GUIDE.md # Apifox 导入指南
OPENAPI_IMPLEMENTATION.md # 技术实现说明
test-swagger-api.sh # 测试脚本修改文件(5个)
src/common/interceptors/
└── transform.interceptor.ts # 添加跳过转换逻辑
src/config/
└── swagger.config.ts # 添加服务器配置
src/
├── main.ts # 注入 document
└── app.module.ts # 注册 SwaggerModule
README.md # 添加 OpenAPI 导出说明
CLAUDE.md # 更新 API 列表✅ 验证清单
- [x] OpenAPI JSON 接口直接返回标准格式(不包装)
- [x] API 统计接口正常包装响应
- [x] 在 Swagger UI 中隐藏 OpenAPI JSON 接口(避免递归)
- [x] 所有其他接口仍然正常包装
- [x] TypeScript 编译通过
- [x] 文档已更新
🎓 学习价值
这次实现展示了以下技术点:
- 装饰器模式 - 使用自定义装饰器控制行为
- 拦截器灵活性 - 在全局拦截器中实现条件逻辑
- Reflector 元数据 - 使用 NestJS Reflector 读取装饰器元数据
- OpenAPI 规范 - 符合标准的 API 文档格式
- 响应格式控制 - 精细控制不同接口的响应格式
💡 扩展用法
@SkipTransform() 装饰器还可用于其他场景:
typescript
// 文件下载
@Get('download')
@SkipTransform()
downloadFile() {
return streamFile();
}
// Webhook 回调
@Post('webhook')
@SkipTransform()
handleWebhook() {
return { status: 'ok' }; // 第三方要求的格式
}
// 健康检查
@Get('health')
@SkipTransform()
healthCheck() {
return { status: 'healthy' };
}📚 相关文档
- APIFOX_IMPORT_GUIDE.md - 详细的 Apifox 导入步骤
- OPENAPI_IMPLEMENTATION.md - 技术实现细节
- README.md - 快速使用说明
更新日期: 2025-10-16 版本: 1.0.0 状态: ✅ 已完成并测试通过