Plugin CLI

Rekomendowana naprawa dla webpack: true, automatyczna, przy każdym buildzie, bez osobnego kroku do zapamiętania.

To ten sam mechanizm, którego używa własny plugin CLI @nestjs/swagger, by działać pod webpack: true. Dlatego @ApiProperty() nie jest wymagane na każdej właściwości DTO, nawet w buildzie webpackowym. Nest CLI podaje ten sam hook pluginu kompilatora TypeScript (compilerOptions.plugins) zarówno do tsc, jak i do buildera webpacka (ts-loader).

Zarejestruj plugin

Zarejestruj nestjs-docfy w nest-cli.json:

nest-cli.json
{
  "compilerOptions": {
    "webpack": true,
    "plugins": ["nestjs-docfy"]
  }
}
main.ts
import { applyDocfyMetadata } from 'nestjs-docfy';

const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, applyDocfyMetadata(document));
OptionTypeDefaultDescription
metadataPathstringdocfy-metadata.json next to the running entry fileWhere to read the plugin-generated metadata from.
strictbooleanfalseThrow instead of warning when the metadata file is missing or invalid.

Automatyczne wykrywanie

Łatwo przeoczyć rejestrację pluginu, dopóki build nie wyjedzie bez dokumentacji, więc każde uruchomienie generate już sprawdza nest-cli.json i wypisuje ostrzeżenie, gdy webpack: true jest ustawione bez pluginu. Przekaż --register-plugin, aby to naprawić za Ciebie zamiast ręcznie edytować plik:

bash
npx nestjs-docfy generate --register-plugin

To celowo opt-in, ponieważ niektóre zespoły świadomie trzymają się patch-spec zamiast pluginu kompilatora, więc generate nigdy nie edytuje nest-cli.json, dopóki wprost o to nie poprosisz. Dołącza do istniejącej tablicy compilerOptions.plugins (rozpoznając zarówno wpisy w formie stringa, jak i obiektu, jako już zarejestrowane) i respektuje --dry-run.

Jak to działa

Plugin nestjs-docfy nie przepisuje żadnej składni dekoratorów ani w ogóle nie dotyka AST. Przy każdej kompilacji ponownie uruchamia dokładnie tę samą analizę statyczną, którą już wykonują generate/check/patch-spec (przez ts-morph, na drzewie źródłowym, nie na bundlu), i zapisuje wynikową łatkę do docfy-metadata.json obok wyniku builda.

Potem, zaraz po SwaggerModule.createDocument(), applyDocfyMetadata() czyta ten plik i go scala. Nie ma tu żadnego require.cache ani problemu tożsamości klasy w bundlu, bo nigdy nie potrzebuje działającej aplikacji, żeby cokolwiek policzyć.

kontra patch-spec

Manual, CI-driven alternative

Jeśli wolisz nie dodawać pluginu kompilatora (na przykład pipeline builda inny niż Nest CLI, albo bardziej rygorystyczna polityka co do tego, co uruchamia się podczas kompilacji), patch-spec liczy identyczną łatkę ręcznie, względem już zbudowanego dokumentu. To była jedyna opcja, zanim powstał plugin, i pozostaje przydatna do jednorazowego łatania.

Builder SWC

@nestjs/cli traktuje builder SWC inaczej. Nigdy nie wywołuje before() pod "builder": "swc", tylko ReadonlyVisitor, i to tylko wtedy, gdy "typeCheck": true też jest ustawione (inaczej SWC w ogóle pomija sprawdzanie typów). Ten plugin eksportuje oba hooki, więc wystarczy włączyć to ustawienie:

nest-cli.json
{
  "compilerOptions": {
    "builder": "swc",
    "typeCheck": true,
    "plugins": ["nestjs-docfy"]
  }
}
Requires typeCheck: true

Jedna rzecz warta wiedzy: rejestracja pluginu w ten sposób zapisuje plik metadata.ts obok korzenia Twojego source przy każdym buildzie. To ten sam artefakt, który wsparcie SWC samego @nestjs/swagger już tam produkuje, pusty i nieszkodliwy, jeśli tamten plugin też nie jest zarejestrowany.

Pomiń typeCheck, a plugin po prostu ucichnie. Build nadal się powiedzie, ale żaden docfy-metadata.json nie zostanie zapisany, a applyDocfyMetadata() nie będzie mieć czego scalić. generate wyłapuje dokładnie tę kombinację i ostrzega.

Nic z tego nie dotyka runtime'owego wykrywania DocfyModule. Działa ono pod SWC dokładnie tak samo jak pod tsc, bo SWC nadal kompiluje jeden plik na moduł, więc require.cache i tak zostaje wypełniony tak samo. Jeśli ustawienie typeCheck nie wchodzi w grę, @WithDocs() razem z DocfyModule.forRoot() i tak Cię tam zaprowadzi, bez pluginu.