docfy patch-spec

Patche un document OpenAPI déjà construit, entièrement par analyse statique (ts-morph), sans aucun require() de fichier docs.

Pourquoi ça existe

C'est un moyen manuel, piloté par la CI, de contourner la seule chose que le pipeline runtime de DocfyModule ne peut structurellement pas faire : fonctionner sous le mode de build webpack: true du CLI NestJS (voir Le plugin CLI pour l'alternative automatique recommandée, qui calcule cette même analyse à chaque build au lieu d'une étape séparée). patch-spec contourne le mur webpack en faisant correspondre par chemin + méthode HTTP, calculé de la même façon que check/coverage/lint le font déjà, au lieu d'avoir besoin de la référence de classe du contrôleur en direct.

Usage

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

Options

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 de fichier docs à rechercher : ts ou js
--quietfalseSuppress all output except errors

Ce qui est fusionné

Rapproché par chemin + méthode HTTP avec le document de base :

  • ApiTags → fusionné dans tags (ne retire jamais les tags déjà présents dans le document de base)
  • ApiOperation({ summary, description, deprecated }) → écrase ces champs
  • ApiResponse({ status, description, schema, example, examples }) → fusionné par code de statut (les autres codes de statut restent intacts) ; quand aucun schema/type n'est donné, retombe sur le type de retour résolu de la méthode, la même inférence DTO/class-validator/interface que generate fait déjà, y compris un oneOf de $ref quand le type de retour est une union d'au moins 2 DTO/entités nommés (par ex. Promise<UserDto | AdminDto>)
  • ApiBody({ schema, examples }) → fixe requestBody, avec le même repli sur le type résolu du paramètre @Body(), y compris la même gestion union → oneOf (example n'est volontairement pas lu ici, car le vrai type ApiBodyOptions de @nestjs/swagger n'a que examples, contrairement à ApiResponse, qui supporte les deux)
  • ApiBearerAuth() → ajouté à security
  • ApiParam / ApiQuery / ApiHeader → fusionnés dans parameters par nom + emplacement : un paramètre réellement nouveau est ajouté, mais un qui existe déjà (par ex. @nestjs/swagger génère automatiquement une entrée nue required: true par simple réflexion pour tout argument décoré avec @Query()/@Param()) voit ses champs superposés, pas remplacés. enum est lu depuis un littéral de tableau (enum: ['a', 'b']) ou une référence à un enum TS, y compris importé d'un autre fichier (enum: Role), et le type du schéma est inféré comme number quand chaque valeur résolue est numérique, string sinon

What this does not do

Volontairement limité

Cette commande est volontairement limitée, pas une réimplémentation complète de la sémantique des décorateurs de @nestjs/swagger : anyOf (aucune construction TS ne correspond naturellement à « n'importe lequel de » comme une union type mappe naturellement sur oneOf), links/callbacks (@nestjs/swagger lui-même n'a aucune option de décorateur pour l'un ou l'autre), et tout argument de décorateur qui n'est pas un littéral (une variable, un appel de fonction, un spread) sont laissés tels quels plutôt que devinés. Il vaut mieux laisser un champ tel que le document de base l'avait déjà que d'y patcher quelque chose de faux. Un type de retour union ou un payload @Body() ne devient un oneOf que quand chaque branche résout vers un DTO/une entité nommé. Les routes qu'un fichier docs documente mais qui n'existent pas dans --spec sont signalées comme avertissements, jamais silencieusement ignorées ni en erreur.