docfy patch-spec
Faz patch de um documento OpenAPI já buildado, inteiramente via análise estática (ts-morph), sem require() de nenhum docs file.
Por que existe
Esta é uma forma manual, orientada a CI, de contornar a única coisa que o pipeline runtime do DocfyModule estruturalmente não consegue fazer: trabalhar sob o modo de build webpack: true do NestJS CLI (ver O plugin do CLI para a alternativa automática e recomendada, que computa essa mesma análise a cada build em vez de uma etapa separada). patch-spec contorna a barreira do webpack casando por path + método HTTP, computado do mesmo jeito que check/coverage/lint já fazem, em vez de precisar da referência viva da classe do controller.
Uso
npx nestjs-docfy patch-spec --spec <path-or-url> [options]# 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.jsonOptions
| 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 file format to look for: ts ou js |
--quiet | false | Suppress all output except errors |
What gets merged
Casado por path + método HTTP contra o documento base:
ApiTags→ unificado emtags(nunca dropa tags que o documento base já tinha)ApiOperation({ summary, description, deprecated })→ sobrescreve esses camposApiResponse({ status, description, schema, example, examples })→ mesclado por status code (outros status codes intactos); quando não háschema/type, cai no return type resolvido do método, a mesma inferência de DTO/class-validator/interface quegeneratejá faz, incluindo umoneOfde$refs quando o return type é uma union de ≥2 DTOs/entidades nomeadas (ex:Promise<UserDto | AdminDto>)ApiBody({ schema, examples })→ definerequestBody, com o mesmo fallback estilo return-type para o tipo resolvido do parâmetro@Body(), incluindo o mesmo tratamento union →oneOf(examplenão é lido aqui de propósito, já que o tipo realApiBodyOptionsdo@nestjs/swaggersó temexamples, ao contrário deApiResponse, que suporta os dois)ApiBearerAuth()→ anexado asecurityApiParam/ApiQuery/ApiHeader→ mesclados emparameterspor nome + localização: um parâmetro genuinamente novo é anexado, mas um que já existe (ex: o@nestjs/swaggerauto-gera uma entrada básicarequired: truevia reflection pra qualquer argumento decorado com@Query()/@Param()) tem seus campos sobrepostos, não descartados.enumé lido de um array literal (enum: ['a', 'b']) ou referência a umenumTS, incluindo um importado de outro arquivo (enum: Role), e otypedo schema é inferido comonumberquando todo valor resolvido é numérico,stringcaso contrário
What this does not do
Este comando é intencionalmente escopado, não é uma reimplementação completa da semântica de decorators do @nestjs/swagger: anyOf (nenhuma construção TS mapeia pra "qualquer um destes" do jeito que uma union mapeia naturalmente pra oneOf), links/callbacks (o próprio @nestjs/swagger não expõe opção de decorator pra nenhum dos dois), e qualquer argumento de decorator que não seja um literal (uma variável, uma chamada de função, um spread) são deixados como estão em vez de serem chutados. É melhor deixar um campo como o documento base já tinha do que dar patch de algo errado. Uma union no return type ou no payload de @Body() só vira oneOf quando todo membro resolve pra uma DTO/entidade nomeada. Rotas que um docs file documenta mas que não existem em --spec são reportadas como warnings, não silenciosamente dropadas nem tratadas como erro.