docfy patch-spec
Łata już zbudowany dokument OpenAPI, wyłącznie przez analizę statyczną (ts-morph), bez require() żadnego pliku docs.
Dlaczego istnieje
To ręczny, sterowany przez CI sposób obejścia jedynej rzeczy, której pipeline runtime'owy DocfyModule strukturalnie nie potrafi zrobić: działać w trybie builda webpack: true Nest CLI (automatyczną, rekomendowaną alternatywę opisuje The CLI plugin, która liczy tę samą analizę przy każdym buildzie zamiast osobnego kroku). patch-spec omija ścianę webpacka, dopasowując po path + metodzie HTTP, liczonych tak samo jak już robią check/coverage/lint, zamiast potrzebować żywej referencji klasy kontrolera.
Użycie
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.jsonOpcje
| 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 | Format pliku docs do wyszukania: ts albo js |
--quiet | false | Suppress all output except errors |
Co jest scalane
Dopasowywane po path + metodzie HTTP względem bazowego dokumentu:
ApiTags→ sumowane dotags(nigdy nie usuwa tagów, które bazowy dokument już miał)ApiOperation({ summary, description, deprecated })→ nadpisuje te polaApiResponse({ status, description, schema, example, examples })→ scalane per kod statusu (inne kody statusu pozostają nietknięte); gdy nie podanoschema/type, wraca do wnioskowanego typu zwracanego przez metodę, tego samego wnioskowania DTO/class-validator/interfejsu, którego już używagenerate, łącznie zoneOfodniesień$ref, gdy typ zwracany to unia ≥2 nazwanych DTO/encji (np.Promise<UserDto | AdminDto>)ApiBody({ schema, examples })→ ustawiarequestBody, z tym samym mechanizmem awaryjnym w stylu typu zwracanego dla wnioskowanego typu parametru@Body(), łącznie z tą samą obsługą unii →oneOf(examplecelowo nie jest tu czytane, ponieważ prawdziwy typApiBodyOptionsz@nestjs/swaggerma tylkoexamples, w przeciwieństwie doApiResponse, które wspiera oba)ApiBearerAuth()→ dołączane dosecurityApiParam/ApiQuery/ApiHeader→ scalane doparameterspo nazwie i lokalizacji: prawdziwie nowy parametr jest dołączany, ale ten, który już istnieje (np.@nestjs/swaggerautomatycznie generuje sam z siebie, na podstawie refleksji, gołe polerequired: truedla dowolnego argumentu z dekoratorem@Query()/@Param()) ma swoje pola nałożone, a nie odrzucone.enumjest odczytywane z literału tablicowego (enum: ['a', 'b']) albo referencji doenumTS, w tym importowanego z innego pliku (enum: Role), atypeschematu jest wnioskowane jakonumber, gdy każda wartość jest liczbowa, w przeciwnym raziestring
What this does not do
Ta komenda ma celowo ograniczony zakres, to nie pełna reimplementacja semantyki dekoratorów @nestjs/swagger: anyOf (żadna konstrukcja TS nie mapuje się na „którekolwiek z” tak naturalnie, jak unia typów mapuje się na oneOf), links/callbacks (sam @nestjs/swagger nie ma opcji dekoratora dla żadnego z nich), oraz każdy argument dekoratora, który nie jest literałem (zmienna, wywołanie funkcji, spread), są pozostawiane bez zmian zamiast być zgadywane. Lepiej zostawić pole takim, jakim już było w bazowym dokumencie, niż wkleić w nie coś błędnego. Unia typu zwracanego albo payload @Body() staje się oneOf tylko wtedy, gdy każda gałąź rozwiązuje się do nazwanego DTO/encji. Trasy, które plik docs dokumentuje, a których nie ma w --spec, są raportowane jako ostrzeżenia, nie ciche pominięcia ani błędy.