Passer au contenu

Directives

Une directive peut être attachée à un champ ou une inclusion de fragment, et peut affecter l’exécution de la requête comme le souhaite le serveur (lisez-en plus ici). La spécification GraphQL fournit plusieurs directives par défaut :

  • @include(if: Boolean) - n’incluez ce champ dans le résultat que si l’argument est vrai
  • @skip(if: Boolean) - sautez ce champ si l’argument est vrai
  • @deprecated(reason: String) - marque le champ comme obsolète avec un message

Une directive est un identifiant précédé d’un caractère @, éventuellement suivi d’une liste d’arguments nommés, qui peuvent apparaître après presque n’importe quel élément dans les langages de requêtes et de schéma GraphQL.

Directives personnalisées

Pour indiquer ce qui doit se passer lorsque Apollo/Mercurius rencontre votre directive, vous pouvez créer une fonction de transformation. Cette fonction utilise la fonction mapSchema pour itérer à travers les emplacements de votre schéma (définitions de champ, définitions de type, etc.) et effectuer les transformations correspondantes.

Fonction de transformation des directives supérieures
import { getDirective, MapperKind, mapSchema } from '@graphql-tools/utils';
import { defaultFieldResolver, GraphQLSchema } from 'graphql';
export function upperDirectiveTransformer(
schema: GraphQLSchema,
directiveName: string,
) {
return mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
const upperDirective = getDirective(schema, fieldConfig, directiveName)?.[0];
if (upperDirective) {
const { resolve = defaultFieldResolver } = fieldConfig;
// Remplacez le résolveur original par une fonction qui d'abord appelle
// le résolveur original, puis convertit son résultat en majuscules
fieldConfig.resolve = async function (source, args, context, info) {
const result = await resolve(source, args, context, info);
if (typeof result === 'string') {
return result.toUpperCase();
}
return result;
};
return fieldConfig;
}
},
});
}

Maintenant, appliquez la fonction de transformation upperDirectiveTransformer dans la méthode GraphQLModule#forRoot en utilisant la fonction transformSchema :

Application du transformateur de directive supérieure
GraphQLModule.forRoot({
// ...
transformSchema: (schema) => upperDirectiveTransformer(schema, 'upper'),
});

Une fois enregistrée, la directive @upper peut être utilisée dans notre schéma. Toutefois, la manière d’appliquer la directive variera selon l’approche que vous utilisez (premier code ou premier schéma).

Premier code

Dans l’approche premier code, utilisez le décorateur @Directive() pour appliquer la directive.

Utilisation de @Directive()
@Directive('@upper')
@Field()
title: string;

Les directives peuvent être appliquées sur des champs, des résolveurs de champ, des types d’entrée et d’objet, ainsi que sur des requêtes, des mutations et des abonnements. Voici un exemple de la directive appliquée au niveau du gestionnaire de requêtes :

Exemple de gestionnaire de requêtes
@Directive('@deprecated(reason: "Cette requête sera supprimée dans la prochaine version")')
@Query(returns => Author, { name: 'author' })
async getAuthor(@Args({ name: 'id', type: () => Int }) id: number) {
return this.authorsService.findOneById(id);
}

Enfin, assurez-vous de déclarer les directives dans le GraphQLModule, comme suit :

Déclaration des directives dans GraphQLModule
GraphQLModule.forRoot({
// ...
transformSchema: (schema) => upperDirectiveTransformer(schema, 'upper'),
buildSchemaOptions: {
directives: [
new GraphQLDirective({
name: 'upper',
locations: [DirectiveLocation.FIELD_DEFINITION],
}),
],
},
});

Premier schéma

Dans l’approche premier schéma, appliquez les directives directement dans SDL.

Exemple en SDL
directive @upper on FIELD_DEFINITION
type Post {
id: Int!
title: String! @upper
votes: Int
}