Plugin CLI
TypeScript a un système de réflexion des métadonnées qui présente plusieurs limitations, rendant, par exemple, impossible de déterminer quelles propriétés compose une classe ou de reconnaître si une propriété donnée est optionnelle ou requise. Cependant, certaines de ces contraintes peuvent être abordées au moment de la compilation. Nest fournit un plugin qui améliore le processus de compilation TypeScript afin de réduire la quantité de code répétitif nécessaire.
Vue d’ensemble
Le plugin Swagger annotera automatiquement :
- toutes les propriétés DTO avec
@ApiProperty
sauf si@ApiHideProperty
est utilisé - la propriété
required
en fonction du point d’interrogation (par exemple,name?: string
définirarequired: false
) - la propriété
type
ouenum
en fonction du type (prend également en charge les tableaux) - la propriété
default
basée sur la valeur par défaut assignée - plusieurs règles de validation basées sur les décorateurs de
class-validator
(siclassValidatorShim
est défini surtrue
) - ajouter un décorateur de réponse à chaque point final avec un statut approprié et
type
(modèle de réponse) - générer des descriptions pour les propriétés et les points finaux basées sur les commentaires (si
introspectComments
est défini surtrue
) - générer des valeurs d’exemple pour les propriétés basées sur les commentaires (si
introspectComments
est défini surtrue
)
Veuillez noter que vos noms de fichiers doivent avoir l’un des suffixes suivants : ['.dto.ts', '.entity.ts']
(par exemple, create-user.dto.ts
) afin d’être analysés par le plugin.
Si vous utilisez un suffixe différent, vous pouvez ajuster le comportement du plugin en spécifiant l’option dtoFileNameSuffix
.
Auparavant, si vous vouliez fournir une expérience interactive avec l’interface utilisateur Swagger, vous deviez dupliquer une grande quantité de code pour faire savoir au package comment vos modèles/composants devaient être déclarés dans la spécification. Par exemple, vous pourriez définir une simple classe CreateUserDto
comme suit :
export class CreateUserDto { @ApiProperty() email: string;
@ApiProperty() password: string;
@ApiProperty({ enum: RoleEnum, default: [], isArray: true }) roles: RoleEnum[] = [];
@ApiProperty({ required: false, default: true }) isEnabled?: boolean = true;}
Bien que cela ne soit pas un problème significatif avec des projets de taille moyenne, cela devient verbeux et difficile à maintenir une fois que vous avez un grand ensemble de classes.
En activant le plugin Swagger, la définition de classe ci-dessus peut être déclarée simplement :
export class CreateUserDto { email: string; password: string; roles: RoleEnum[] = []; isEnabled?: boolean = true;}
Ainsi, si vous prévoyez de vous fier aux annotations automatiques pour la génération de documentations tout en souhaitant des validations à l’exécution, alors les décorateurs de validation de classe sont toujours nécessaires.
Le plugin ajoute les décorateurs appropriés à la volée en fonction de l’Arbre de syntaxe abstraite. Ainsi, vous n’aurez pas à vous battre avec les décorateurs @ApiProperty
éparpillés dans le code.
Introspection des commentaires
Avec la fonctionnalité d’introspection des commentaires activée, le plugin CLI générera des descriptions et des valeurs d’exemple pour les propriétés en fonction des commentaires.
Par exemple, étant donné une propriété roles
:
/** * A list of user's roles * @example ['admin'] */@ApiProperty({ description: `A list of user's roles`, example: ['admin'],})roles: RoleEnum[] = [];
Vous devez dupliquer à la fois la description et les valeurs d’exemple. Avec introspectComments
activé, le plugin CLI peut extraire ces commentaires et fournir automatiquement des descriptions (et des exemples, si définis) pour les propriétés. Maintenant, la propriété ci-dessus peut être déclarée simplement comme suit :
/** * A list of user's roles * @example ['admin'] */roles: RoleEnum[] = [];
Il existe dtoKeyOfComment
et controllerKeyOfComment
, options de plugin que vous pouvez utiliser pour personnaliser comment le plugin définira la valeur pour les décorateurs ApiProperty
et ApiOperation
respectivement. Prenons un exemple :
export class SomeController { /** * Create some resource */ @Post() create() {}}
Par défaut, ces options sont définies sur "description"
. Cela signifie que le plugin assignera "Create some resource"
à la clé description
sur l’opérateur ApiOperation
. Ainsi :
@ApiOperation({ description: "Create some resource" })
Utilisation du plugin CLI
Pour activer le plugin, ouvrez nest-cli.json
(si vous utilisez Nest CLI) et ajoutez la configuration suivante dans plugins
:
{ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { "plugins": ["@nestjs/swagger"] }}
Vous pouvez utiliser la propriété options
pour personnaliser le comportement du plugin.
"plugins": [ { "name": "@nestjs/swagger", "options": { "classValidatorShim": false, "introspectComments": true } }]
La propriété options
doit remplir l’interface suivante :
export interface PluginOptions { dtoFileNameSuffix?: string[]; controllerFileNameSuffix?: string[]; classValidatorShim?: boolean; dtoKeyOfComment?: string; controllerKeyOfComment?: string; introspectComments?: boolean;}
Option | Par défaut | Description |
---|---|---|
dtoFileNameSuffix | ['.dto.ts', '.entity.ts'] | Suffixes de fichiers DTO (Objet de transfert de données) |
controllerFileNameSuffix | .controller.ts | Suffixe de fichiers de contrôleur |
classValidatorShim | true | S’il est défini sur true, le module réutilisera les décorateurs de validation class-validator |
dtoKeyOfComment | 'description' | La clé de propriété pour définir le texte de commentaire sur ApiProperty . |
controllerKeyOfComment | 'description' | La clé de propriété pour définir le texte de commentaire sur ApiOperation . |
introspectComments | false | S’il est défini sur true, le plugin générera des descriptions et des valeurs d’exemple pour les propriétés basées sur les commentaires |
Assurez-vous de supprimer le dossier /dist
et de reconstruire votre application chaque fois que les options du plugin sont mises à jour. Si vous n’utilisez pas le CLI mais avez plutôt une configuration personnalisée webpack
, vous pouvez utiliser ce plugin en combinaison avec ts-loader
:
getCustomTransformers: (program) => ({ before: [ require('@nestjs/swagger/plugin').before({}, program), ],}),
Constructeur SWC
Pour les configurations standard (non-monorepo), pour utiliser les plugins CLI avec le constructeur SWC, vous devez activer la vérification des types, comme décrit ici.
$ nest start -b swc --type-check
Pour les configurations monorepo, suivez les instructions ici.
$ npx ts-node src/generate-metadata.ts# OU npx ts-node apps/{YOUR_APP}/src/generate-metadata.ts
Maintenant, le fichier de métadonnées sérialisé doit être chargé par la méthode SwaggerModule#loadPluginMetadata
, comme montré ci-dessous :
import metadata from './metadata'; // <-- fichier généré automatiquement par le "PluginMetadataGenerator"
await SwaggerModule.loadPluginMetadata(metadata); // <-- iciconst document = SwaggerModule.createDocument(app, config);
Intégration avec ts-jest
(tests e2e)
Pour exécuter des tests e2e, ts-jest
compile vos fichiers source à la volée, en mémoire. Cela signifie qu’il n’utilise pas le compilateur CLI de Nest et n’applique pas de plugins ni de transformations AST.
Pour activer le plugin, créez le fichier suivant dans votre répertoire de tests e2e :
const transformer = require('@nestjs/swagger/plugin');
module.exports.name = 'nestjs-swagger-transformer';// vous devriez changer le numéro de version à chaque fois que vous changez la configuration ci-dessous - sinon, jest ne détectera pas les changementsmodule.exports.version = 1;
module.exports.factory = (cs) => { return transformer.before( { // options pour @nestjs/swagger/plugin (peuvent être vides) }, cs.program, // "cs.tsCompiler.program" pour les anciennes versions de Jest (<= v27) );};
Avec cela en place, importez le transformateur AST dans votre fichier de configuration jest
. Par défaut (dans l’application de démarrage), le fichier de configuration des tests e2e se trouve sous le dossier test
et est nommé jest-e2e.json
.
{ ... // autre configuration "globals": { "ts-jest": { "astTransformers": { "before": [ "<path to the file created above>" ] } } }}
Si vous utilisez jest@^29
, alors utilisez le code suivant, car l’approche précédente a été dépréciée.
{ ... // autre configuration "transform": { "^.+\\.(t|j)s$": [ "ts-jest", { "astTransformers": { "before": [ "<path to the file created above>" ] } } ] }}
Dépannage de jest
(tests e2e)
Dans le cas où jest
ne semble pas prendre en compte vos modifications de configuration, il est possible que Jest ait déjà mis en cache le résultat de la construction. Pour appliquer la nouvelle configuration, vous devez effacer le répertoire de cache de Jest.
Pour effacer le répertoire de cache, exécutez la commande suivante dans votre dossier de projet NestJS :
$ npx jest --clearCache
Dans le cas où l’effacement automatique du cache échoue, vous pouvez toujours supprimer manuellement le dossier de cache avec les commandes suivantes :
# Trouvez le répertoire de cache jest (généralement /tmp/jest_rs)# en exécutant la commande suivante dans la racine de votre projet NestJS$ npx jest --showConfig | grep cache# ex résultat :# "cache": true,# "cacheDirectory": "/tmp/jest_rs"
# Supprimez ou videz le répertoire de cache de Jest$ rm -rf <cacheDirectory value># ex :# rm -rf /tmp/jest_rs