docfy patch-spec

すでに構築済みのOpenAPIドキュメントを、docsファイルのrequire()を一切行わず、完全に静的解析(ts-morph)だけでパッチします。

存在理由

これは、DocfyModuleのランタイムパイプラインが構造的にできない唯一のこと、すなわちNestJS CLIのwebpack: trueビルドモード下で動作することを、手動でCI駆動で回避する方法です(自動で推奨される代替手段についてはThe CLI pluginを参照してください。同じ解析をビルドのたびに、別ステップなしで計算します)。patch-specは、稼働中のコントローラークラス参照を必要とする代わりに、check/coverage/lintがすでに行っているのと同じ方法で計算したpath + HTTPメソッドで照合することにより、webpackの壁を回避します。

使い方

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

オプション

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>ts探索するdocsファイルの形式: tsまたはjs
--quietfalseSuppress all output except errors

マージされる内容

ベースドキュメントに対してpath + HTTPメソッドで照合されます:

  • ApiTagstagsにユニオンされます(ベースドキュメントがすでに持っていたタグを失うことはありません)
  • ApiOperation({ summary, description, deprecated }) → それらのフィールドを上書きします
  • ApiResponse({ status, description, schema, example, examples }) → ステータスコードごとにマージされます(他のステータスコードは変更されません)。schema/typeが指定されていない場合は、generateがすでに行っているのと同じDTO/class-validator/インターフェース推論により、メソッド自身の解決済み戻り値型にフォールバックします。戻り値型が2つ以上の名前付きDTO/エンティティのユニオンである場合(例: Promise<UserDto | AdminDto>)はoneOf$refになります
  • ApiBody({ schema, examples })requestBodyを設定します。戻り値型と同様のフォールバックが@Body()パラメータの解決済み型にも適用され、同じユニオン → oneOf変換も行われます(exampleはここでは意図的に読み取りません。@nestjs/swaggerの実際のApiBodyOptions型には、両方をサポートするApiResponseと異なりexamplesしか存在しないためです)
  • ApiBearerAuth()securityに追加されます
  • ApiParam / ApiQuery / ApiHeader → 名前と場所によってparametersにマージされます。真に新しいパラメータは追加されますが、すでに存在するもの(例えば@nestjs/swaggerは、@Query()/@Param()デコレーター付きの引数に対してリフレクションだけから素のrequired: trueエントリーを自動生成します)はフィールドが上書きされ、破棄はされません。enumは配列リテラル(enum: ['a', 'b'])、または別ファイルからインポートされたものを含むTSのenumへの参照(enum: Role)から読み取られ、解決済みの値がすべて数値であればスキーマのtypenumber、そうでなければstringと推論されます

What this does not do

意図的に範囲を絞っています

このコマンドは意図的に範囲を絞っており、@nestjs/swaggerのデコレーター意味論を完全に再実装するものではありません。anyOf(ユニオン型が自然にoneOfに対応するのと違い、「いずれか」に対応するTSの構文はありません)、links/callbacks(@nestjs/swagger自体、どちらのデコレーターオプションも持ちません)、そしてリテラルでないデコレーター引数(変数、関数呼び出し、スプレッド)は、推測せずそのままにしておきます。誤ったものをパッチするより、ベースドキュメントがすでに持っていたフィールドをそのまま残すほうが良いという判断です。ユニオン型の戻り値や@Body()ペイロードは、すべての分岐が名前付きDTO/エンティティに解決される場合にのみoneOfになります。--specに存在しないルートをdocsファイルがドキュメント化している場合は、黙って破棄したりエラーにしたりせず、警告として報告されます。