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

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

Opcje

OptionDefaultDescription
--spec <path|url>(required)A local openapi.json, or a URL (e.g. a running app's /api-json)
--out <path>stdoutWhere to write the patched document
--root <path>.Project root directory
--tsconfig <path>auto-detectedPath to tsconfig.json
--pattern <glob>**/*.controller.tsGlob pattern to find controllers
--format <format>tsFormat pliku docs do wyszukania: ts albo js
--quietfalseSuppress all output except errors

Co jest scalane

Dopasowywane po path + metodzie HTTP względem bazowego dokumentu:

  • ApiTags → sumowane do tags (nigdy nie usuwa tagów, które bazowy dokument już miał)
  • ApiOperation({ summary, description, deprecated }) → nadpisuje te pola
  • ApiResponse({ status, description, schema, example, examples }) → scalane per kod statusu (inne kody statusu pozostają nietknięte); gdy nie podano schema/type, wraca do wnioskowanego typu zwracanego przez metodę, tego samego wnioskowania DTO/class-validator/interfejsu, którego już używa generate, łącznie z oneOf odniesień $ref, gdy typ zwracany to unia ≥2 nazwanych DTO/encji (np. Promise<UserDto | AdminDto>)
  • ApiBody({ schema, examples }) → ustawia requestBody, z tym samym mechanizmem awaryjnym w stylu typu zwracanego dla wnioskowanego typu parametru @Body(), łącznie z tą samą obsługą unii → oneOf (example celowo nie jest tu czytane, ponieważ prawdziwy typ ApiBodyOptions z @nestjs/swagger ma tylko examples, w przeciwieństwie do ApiResponse, które wspiera oba)
  • ApiBearerAuth() → dołączane do security
  • ApiParam / ApiQuery / ApiHeader → scalane do parameters po nazwie i lokalizacji: prawdziwie nowy parametr jest dołączany, ale ten, który już istnieje (np. @nestjs/swagger automatycznie generuje sam z siebie, na podstawie refleksji, gołe pole required: true dla dowolnego argumentu z dekoratorem @Query()/@Param()) ma swoje pola nałożone, a nie odrzucone. enum jest odczytywane z literału tablicowego (enum: ['a', 'b']) albo referencji do enum TS, w tym importowanego z innego pliku (enum: Role), a type schematu jest wnioskowane jako number, gdy każda wartość jest liczbowa, w przeciwnym razie string

What this does not do

Celowo ograniczony zakres

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.