docfy patch-spec
Applica una patch a un documento OpenAPI già costruito, interamente tramite analisi statica (ts-morph), senza alcun require() di file docs.
Perché esiste
Questo è un modo manuale, guidato dalla CI, per aggirare l'unica cosa che la pipeline a runtime di DocfyModule non può strutturalmente fare: funzionare sotto la modalità build webpack: true della NestJS CLI (vedi Il plugin CLI per l'alternativa automatica consigliata, che calcola la stessa analisi a ogni build invece che come step separato). patch-spec aggira il muro di webpack facendo il match su path + metodo HTTP, calcolato nello stesso modo in cui già fanno check/coverage/lint, invece di aver bisogno del riferimento live alla classe controller.
Utilizzo
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.jsonOpzioni
| 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 | Formato del file docs da cercare: ts o js |
--quiet | false | Suppress all output except errors |
Cosa viene unito
Match su path + metodo HTTP contro il documento base:
ApiTags→ unito intags(non elimina mai i tag già presenti nel documento base)ApiOperation({ summary, description, deprecated })→ sovrascrive quei campiApiResponse({ status, description, schema, example, examples })→ unito per codice di stato (gli altri codici restano intoccati); quando non viene indicatoschema/type, ricade sul tipo di ritorno risolto del metodo, la stessa inferenza DTO/class-validator/interface chegenerategià fa, incluso unoneOfdi$refquando il tipo di ritorno è una union di ≥2 DTO/entità nominate (es.Promise<UserDto | AdminDto>)ApiBody({ schema, examples })→ impostarequestBody, con lo stesso fallback in stile tipo-di-ritorno sul tipo risolto del parametro@Body(), incluso lo stesso trattamento union →oneOf(examplenon viene letto qui di proposito, dato che il vero tipoApiBodyOptionsdi@nestjs/swaggerha soloexamples, a differenza diApiResponse, che supporta entrambi)ApiBearerAuth()→ aggiunto asecurityApiParam/ApiQuery/ApiHeader→ uniti inparametersper nome + posizione: un parametro genuinamente nuovo viene aggiunto, ma uno già esistente (ad es.@nestjs/swaggergenera automaticamente per pura reflection una vocerequired: truenuda per ogni argomento decorato con@Query()/@Param()) viene sovrapposto nei suoi campi, non scartato.enumviene letto da un array letterale (enum: ['a', 'b']) o da un riferimento a unenumTS, incluso uno importato da un altro file (enum: Role), e iltypedello schema viene inferito comenumberquando ogni valore risolto è numerico,stringaltrimenti
What this does not do
Questo comando ha un ambito intenzionalmente limitato, non è una reimplementazione completa della semantica dei decorator di @nestjs/swagger: anyOf (nessun costrutto TS mappa su "any of" nel modo in cui un union type mappa naturalmente su oneOf), links/callbacks (@nestjs/swagger stesso non ha un'opzione decorator per nessuno dei due), e qualsiasi argomento di decorator che non sia un letterale (una variabile, una chiamata di funzione, uno spread) vengono lasciati intoccati invece di essere indovinati. È meglio lasciare un campo com'era già nel documento base che applicare una patch sbagliata. Un tipo di ritorno union o un payload @Body() diventa un oneOf solo quando ogni ramo risolve a un DTO/entità nominata. Le rotte che un file docs documenta ma che non esistono in --spec vengono riportate come avvisi, non scartate né trattate come errore in silenzio.