docfy patch-spec
对一份已经构建好的 OpenAPI 文档打补丁,完全通过静态分析(ts-morph)完成,不会 require() 任何 docs 文件。
为什么需要它
这是一种手动的、由 CI 驱动的方式,用来绕开 DocfyModule 运行时管线在结构上做不到的那件事:在 NestJS CLI 的 webpack: true 构建模式下工作(推荐的自动替代方案见 CLI 插件,它在每次构建时都会计算同样的分析结果,而不需要额外一个步骤)。patch-spec 通过匹配 路径 + HTTP 方法 绕开了 webpack 造成的障碍——计算方式和 check/coverage/lint 已经在用的方式相同,不需要拿到运行中的控制器类引用。
用法
bash
npx nestjs-docfy patch-spec --spec <path-or-url> [options]bash
# Patch a running app's served document
npx nestjs-docfy patch-spec --spec http://localhost:3000/api-json --out openapi.json
# Patch a file already written to disk
npx nestjs-docfy patch-spec --spec dist/openapi.json --out dist/openapi.json选项
| Option | Default | Description |
|---|---|---|
--spec <path|url> | (required) | A local openapi.json, or a URL (e.g. a running app's /api-json) |
--out <path> | stdout | Where to write the patched document |
--root <path> | . | Project root directory |
--tsconfig <path> | auto-detected | Path to tsconfig.json |
--pattern <glob> | **/*.controller.ts | Glob pattern to find controllers |
--format <format> | ts | 要查找的 docs 文件格式:ts 或 js |
--quiet | false | Suppress all output except errors |
合并了什么
按 路径 + HTTP 方法与基础文档匹配:
ApiTags→ 并入tags(绝不会丢弃基础文档中已有的标签)ApiOperation({ summary, description, deprecated })→ 覆盖这几个字段ApiResponse({ status, description, schema, example, examples })→ 按状态码分别合并(其他状态码不受影响);未提供schema/type时,回退使用该方法自身解析出的返回类型,与generate已经在用的同一套 DTO/class-validator/接口推断逻辑一致,返回类型是 ≥2 个具名 DTO/实体的联合类型时(比如Promise<UserDto | AdminDto>),会生成$ref的oneOfApiBody({ schema, examples })→ 设置requestBody,同样以返回类型式的回退方式解析@Body()参数的类型,也包含相同的联合类型 →oneOf处理(这里故意不读取example,因为@nestjs/swagger真实的ApiBodyOptions类型只有examples,和支持两者的ApiResponse不同)ApiBearerAuth()→ 追加到securityApiParam/ApiQuery/ApiHeader→ 按名称 + 位置合并进parameters:真正新增的参数会被追加,但已经存在的参数(比如@nestjs/swagger仅凭反射就会为任何@Query()/@Param()装饰的参数自动生成一条裸的required: true条目)只会被叠加字段,不会被丢弃。enum可以来自数组字面量(enum: ['a', 'b']),也可以引用一个 TSenum,包括从另一个文件导入的(enum: Role);当解析出的每个值都是数字时,schema 的type会被推断为number,否则为string
What this does not do
刻意收窄的范围
这个命令刻意收窄了范围,不是对 @nestjs/swagger 装饰器语义的完整重新实现:anyOf(没有哪个 TS 结构能像联合类型天然映射到 oneOf 那样映射到“任意一种”)、links/callbacks(@nestjs/swagger 本身对这两者都没有对应的装饰器选项),以及任何不是字面量的装饰器参数(变量、函数调用、展开运算符)都会原样保留,而不是去猜测。让字段保持基础文档原有的样子,好过打上一个错误的补丁。只有当联合类型的每一个分支都能解析为具名 DTO/实体时,联合返回类型或 @Body() payload 才会变成 oneOf。docs 文件里记录了但在 --spec 中不存在的路由,只会作为警告报告出来,不会被静默丢弃或报错。