Plugin CLI
TypeScript dispose d’un système de réflexion de métadonnées qui a plusieurs limitations, rendant impossible, par exemple, la détermination des propriétés d’une classe ou la reconnaissance d’une propriété donnée comme optionnelle ou requise. Cependant, certaines de ces contraintes peuvent être abordées lors de la compilation. Nest fournit un plugin qui améliore le processus de compilation TypeScript afin de réduire la quantité de code boilerplate requis.
Aperçu
Le plugin GraphQL fera automatiquement :
- annoter toutes les classes de type objet, types d’objet et propriétés d’args avec
@Field
sauf si@HideField
est utilisé - définir la propriété
nullable
en fonction du point d’interrogation (par exemple,name?: string
définiranullable: true
) - définir la propriété
type
en fonction du type (les tableaux sont également supportés) - générer des descriptions 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 pour être analysés par le plugin : ['.input.ts', '.args.ts', '.entity.ts', '.model.ts']
(par exemple, author.entity.ts
). Si vous utilisez un suffixe différent, vous pouvez ajuster le comportement du plugin en spécifiant l’option typeFileNameSuffix
.
Avec ce que nous avons appris jusqu’à présent, vous devez dupliquer beaucoup de code pour faire savoir au paquet comment votre type devrait être déclaré dans GraphQL. Par exemple, vous pourriez définir une classe Author
simple comme suit :
@ObjectType()export class Author { @Field(type => ID) id: number;
@Field({ nullable: true }) firstName?: string;
@Field({ nullable: true }) lastName?: string;
@Field(type => [Post]) posts: Post[];}
Bien que cela ne soit pas un problème significatif pour 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 GraphQL, la définition de classe ci-dessus peut être déclarée simplement :
authors/models/author.model.ts@ObjectType()export class Author { @Field(type => ID) id: number; firstName?: string; lastName?: string; posts: Post[];}
Le plugin ajoute les décorateurs appropriés à la volée, basés sur l’Arbre de Syntaxe Abstrait. Ainsi, vous n’aurez pas à lutter avec les décorateurs @Field
disséminés dans le code.
Introspection des commentaires
Avec la fonction d’introspection des commentaires activée, le plugin CLI générera des descriptions pour les champs basées sur les commentaires.
Par exemple, pour une propriété d’exemple roles
:
/** * Une liste des rôles de l'utilisateur */@Field(() => [String], { description: `Une liste des rôles de l'utilisateur`})roles: string[];
Vous devez dupliquer les valeurs de description. Avec introspectComments
activé, le plugin CLI peut extraire ces commentaires et fournir automatiquement des descriptions pour les propriétés. Désormais, le champ ci-dessus peut être déclaré simplement comme suit :
/** * Une liste des rôles de l'utilisateur */roles: string[];
Utilisation du plugin CLI
Pour activer le plugin, ouvrez nest-cli.json
(si vous utilisez Nest CLI) et ajoutez la configuration suivante sous plugins
:
{ "collection": "@nestjs/schematics", "sourceRoot": "src", "compilerOptions": { "plugins": [ "@nestjs/graphql" ] }}
Vous pouvez utiliser la propriété options
pour personnaliser le comportement du plugin.
"plugins": [ { "name": "@nestjs/graphql", "options": { "typeFileNameSuffix": [".input.ts", ".args.ts"], "introspectComments": true } }]
La propriété options
doit respecter l’interface suivante :
export interface PluginOptions { typeFileNameSuffix?: string[]; introspectComments?: boolean;}
Option | Par défaut | Description |
---|---|---|
typeFileNameSuffix | ['.input.ts', '.args.ts', '.entity.ts', '.model.ts'] | Suffixes pour les fichiers de types GraphQL |
introspectComments | false | Si défini sur true , le plugin générera des descriptions pour les propriétés basées sur les commentaires |
Si vous n’utilisez pas le CLI mais que vous avez une configuration webpack
personnalisée, vous pouvez utiliser ce plugin en combinaison avec ts-loader
:
getCustomTransformers: (program: any) => ({ before: [ require('@nestjs/graphql/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 de type, 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 GraphQLModule
, comme montré ci-dessous :
import metadata from './metadata'; // <--- fichier auto-généré par le "PluginMetadataGenerator"
GraphQLModule.forRoot({ ... // autres options metadata,}),
Intégration avec ts-jest
(tests e2e)
Lors de l’exécution des tests e2e avec ce plugin activé, vous pourriez rencontrer des problèmes avec la compilation du schéma. Par exemple, l’une des erreurs les plus courantes est :
Object type <name> must define one or more fields.
Cela se produit parce que la configuration de jest
n’importe pas le plugin @nestjs/graphql/plugin
nulle part.
Pour corriger cela, créez le fichier suivant dans votre répertoire de tests e2e :
const transformer = require('@nestjs/graphql/plugin');
module.exports.name = 'nestjs-graphql-transformer';// vous devez 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/graphql/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
, utilisez alors le snippet ci-dessous, 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>"] } } ] }}