GraphQL2 min read

Direktivlar

Direktiv field yoki fragment inclusion ga biriktirilishi va server xohlagan tarzda so'rov bajarilishiga ta'sir qilishi mumkin (batafsil bu yerda). GraphQL spetsifikatsiyasi bir nec

Direktiv field yoki fragment inclusion ga biriktirilishi va server xohlagan tarzda so'rov bajarilishiga ta'sir qilishi mumkin (batafsil bu yerda). GraphQL spetsifikatsiyasi bir nechta default direktivlarni taqdim etadi:

  • @include(if: Boolean) - argument true bo'lsa, bu fieldni natijaga qo'shadi
  • @skip(if: Boolean) - argument true bo'lsa, bu fieldni o'tkazib yuboradi
  • @deprecated(reason: String) - fieldni deprecate qilib belgilaydi va xabar ko'rsatadi

Direktiv - bu @ belgisi bilan boshlanadigan identifikator bo'lib, ixtiyoriy ravishda nomlangan argumentlar ro'yxati bilan keladi; u GraphQL so'rovi va schema tillarining deyarli istalgan elementidan keyin yozilishi mumkin.

Custom direktivlar

Apollo/Mercurius sizning direktivingizga duch kelganda nima qilishini belgilash uchun transformer funksiyasini yaratishingiz mumkin. Bu funksiya mapSchemadan foydalanib schema ichidagi joylarni (field ta'riflari, type ta'riflari va h.k.) aylanib chiqadi va mos transformatsiyalarni bajaradi.

TypeScript
1import { getDirective, MapperKind, mapSchema } from '@graphql-tools/utils';
2import { defaultFieldResolver, GraphQLSchema } from 'graphql';
3
4export function upperDirectiveTransformer(
5  schema: GraphQLSchema,
6  directiveName: string,
7) {
8  return mapSchema(schema, {
9    [MapperKind.OBJECT_FIELD]: (fieldConfig) => {
10      const upperDirective = getDirective(
11        schema,
12        fieldConfig,
13        directiveName,
14      )?.[0];
15
16      if (upperDirective) {
17        const { resolve = defaultFieldResolver } = fieldConfig;
18
19        // Replace the original resolver with a function that *first* calls
20        // the original resolver, then converts its result to upper case
21        fieldConfig.resolve = async function (source, args, context, info) {
22          const result = await resolve(source, args, context, info);
23          if (typeof result === 'string') {
24            return result.toUpperCase();
25          }
26          return result;
27        };
28        return fieldConfig;
29      }
30    },
31  });
32}

Endi upperDirectiveTransformer transformatsiya funksiyasini GraphQLModule#forRoot metodida transformSchema funksiyasi orqali qo'llang:

TypeScript
1GraphQLModule.forRoot({
2  // ...
3  transformSchema: (schema) => upperDirectiveTransformer(schema, 'upper'),
4});

Ro'yxatdan o'tkazilgach, @upper direktivini schemamizda ishlatish mumkin. Biroq direktivni qo'llash usuli siz ishlatayotgan yondashuvga bog'liq bo'ladi (code first yoki schema first).

Code first

Code first yondashuvida direktivni qo'llash uchun @Directive() dekoratoridan foydalaning.

TypeScript
1@Directive('@upper')
2@Field()
3title: string;
Hint

@Directive() dekoratori @nestjs/graphql paketidan eksport qilinadi.

Direktivlar fieldlar, field resolverlar, input va object turlar, shuningdek query, mutation va subscriptionlarda qo'llanishi mumkin. Quyida query handler darajasida direktivni qo'llash misoli keltirilgan:

TypeScript
1@Directive('@deprecated(reason: "This query will be removed in the next version")')
2@Query(() => Author, { name: 'author' })
3async getAuthor(@Args({ name: 'id', type: () => Int }) id: number) {
4  return this.authorsService.findOneById(id);
5}

warn Warning @Directive() dekoratori orqali qo'llangan direktivlar generatsiya qilingan schema definition faylida aks ettirilmaydi.

Oxirida direktivlarni GraphQLModule da quyidagicha e'lon qilishni unutmang:

TypeScript
1GraphQLModule.forRoot({
2  // ...,
3  transformSchema: schema => upperDirectiveTransformer(schema, 'upper'),
4  buildSchemaOptions: {
5    directives: [
6      new GraphQLDirective({
7        name: 'upper',
8        locations: [DirectiveLocation.FIELD_DEFINITION],
9      }),
10    ],
11  },
12}),
Hint

GraphQLDirective va DirectiveLocation ikkalasi ham graphql paketidan eksport qilinadi.

Schema first

Schema first yondashuvida direktivlarni bevosita SDL ichida qo'llang.

Graphql
1directive @upper on FIELD_DEFINITION
2
3type Post {
4  id: Int!
5  title: String! @upper
6  votes: Int
7}