GraphQL15 min read

Federatsiya

Federatsiya monolit GraphQL serveringizni mustaqil mikroservislarga bo'lish imkonini beradi. U ikki komponentdan iborat: gateway va bir yoki bir nechta federatsiyalangan mikroservi

Federatsiya monolit GraphQL serveringizni mustaqil mikroservislarga bo'lish imkonini beradi. U ikki komponentdan iborat: gateway va bir yoki bir nechta federatsiyalangan mikroservis. Har bir mikroservis schema ning bir qismini saqlaydi va gateway ularni bitta schema ga birlashtirib, klientga taqdim etadi.

Apollo docsdan iqtibos keltirsak, Federatsiya quyidagi asosiy tamoyillar bilan yaratilgan:

  • Grafni qurish deklarativ bo'lishi kerak. Federatsiyada grafni schema ichida deklarativ tarzda kompozitsiya qilasiz, imperativ schema stitching kodini yozmaysiz.
  • Kod turlar bo'yicha emas, concern bo'yicha ajratilishi kerak. Ko'pincha User yoki Product kabi muhim turlarning barcha jihatlarini bitta jamoa boshqarmaydi, shuning uchun bu turlar ta'rifi markazlashtirilgan emas, balki jamoalar va kod bazalari bo'ylab taqsimlangan bo'lishi kerak.
  • Graf klientlar uchun foydalanishga qulay bo'lishi kerak. Federatsiyalangan servislar birgalikda klientdagi iste'mol uslubini aniq aks ettiradigan to'liq, mahsulotga yo'naltirilgan grafni hosil qiladi.
  • Bu shunchaki GraphQL bo'lib, tilning faqat spetsifikatsiyaga mos imkoniyatlaridan foydalanadi. Federatsiyani faqat JavaScript emas, istalgan til implementatsiya qilishi mumkin.
Warning

Federatsiya hozircha subscriptions ni qo'llab-quvvatlamaydi.

Quyidagi bo'limlarda gateway va ikki federatsiyalangan endpointdan (Users service va Posts service) iborat demo ilovani sozlaymiz.

Apollo bilan Federatsiya

Avval kerakli bog'liqliklarni o'rnating:

Terminal
1$ npm install --save @apollo/subgraph

Schema first

"User service" oddiy schema taqdim etadi. @key direktiviga e'tibor bering: u Apollo query plannerga Userning muayyan instansiyasini id ko'rsatilsa olish mumkinligini bildiradi. Shuningdek, Query turini extend qilayotganimizga e'tibor bering.

Graphql
1type User @key(fields: "id") {
2  id: ID!
3  name: String!
4}
5
6extend type Query {
7  getUser(id: ID!): User
8}

Resolver qo'shimcha resolveReference() metodini taqdim etadi. Bu metod Apollo Gateway boshqa bog'liq resursga User instansiyasi kerak bo'lganda ishga tushadi. Buni keyinroq Posts service misolida ko'ramiz. Eslatma: metod @ResolveReference() dekoratori bilan belgilanishi kerak.

TypeScript
1import { Args, Query, Resolver, ResolveReference } from '@nestjs/graphql';
2import { UsersService } from './users.service';
3
4@Resolver('User')
5export class UsersResolver {
6  constructor(private usersService: UsersService) {}
7
8  @Query()
9  getUser(@Args('id') id: string) {
10    return this.usersService.findById(id);
11  }
12
13  @ResolveReference()
14  resolveReference(reference: { __typename: string; id: string }) {
15    return this.usersService.findById(reference.id);
16  }
17}

Oxirida hammasini GraphQLModule ga ApolloFederationDriver driverini konfiguratsiya obyektida ko'rsatib ulaymiz:

TypeScript
1import {
2  ApolloFederationDriver,
3  ApolloFederationDriverConfig,
4} from '@nestjs/apollo';
5import { Module } from '@nestjs/common';
6import { GraphQLModule } from '@nestjs/graphql';
7import { UsersResolver } from './users.resolver';
8
9@Module({
10  imports: [
11    GraphQLModule.forRoot<ApolloFederationDriverConfig>({
12      driver: ApolloFederationDriver,
13      typePaths: ['**/*.graphql'],
14    }),
15  ],
16  providers: [UsersResolver],
17})
18export class AppModule {}

Code first

User entityga bir nechta qo'shimcha dekoratorlarni qo'shishdan boshlaymiz.

TypeScript
1import { Directive, Field, ID, ObjectType } from '@nestjs/graphql';
2
3@ObjectType()
4@Directive('@key(fields: "id")')
5export class User {
6  @Field(() => ID)
7  id: number;
8
9  @Field()
10  name: string;
11}

Resolver qo'shimcha resolveReference() metodini taqdim etadi. Bu metod Apollo Gateway boshqa bog'liq resursga User instansiyasi kerak bo'lganda ishga tushadi. Buni keyinroq Posts service misolida ko'ramiz. Eslatma: metod @ResolveReference() dekoratori bilan belgilanishi kerak.

TypeScript
1import { Args, Query, Resolver, ResolveReference } from '@nestjs/graphql';
2import { User } from './user.entity';
3import { UsersService } from './users.service';
4
5@Resolver(() => User)
6export class UsersResolver {
7  constructor(private usersService: UsersService) {}
8
9  @Query(() => User)
10  getUser(@Args('id') id: number): User {
11    return this.usersService.findById(id);
12  }
13
14  @ResolveReference()
15  resolveReference(reference: { __typename: string; id: number }): User {
16    return this.usersService.findById(reference.id);
17  }
18}

Oxirida hammasini GraphQLModule ga ApolloFederationDriver driverini konfiguratsiya obyektida ko'rsatib ulaymiz:

TypeScript
1import {
2  ApolloFederationDriver,
3  ApolloFederationDriverConfig,
4} from '@nestjs/apollo';
5import { Module } from '@nestjs/common';
6import { UsersResolver } from './users.resolver';
7import { UsersService } from './users.service'; // Not included in this example
8
9@Module({
10  imports: [
11    GraphQLModule.forRoot<ApolloFederationDriverConfig>({
12      driver: ApolloFederationDriver,
13      autoSchemaFile: true,
14    }),
15  ],
16  providers: [UsersResolver, UsersService],
17})
18export class AppModule {}

Ishlaydigan misol code first rejimida bu yerda va schema first rejimida bu yerda mavjud.

Federatsiyalangan misol: Posts

Posts service getPosts query orqali agregatsiya qilingan postlarni taqdim etishi, shuningdek User turini user.posts fieldi bilan kengaytirishi kerak.

Schema first

"Posts service" schema ichida extend keywordi orqali User turiga murojaat qiladi. U User turiga bitta qo'shimcha xossa (posts) qo'shadi. User instansiyalarini moslashtirish uchun ishlatiladigan @key direktiviga va id fieldi boshqa joyda boshqarilishini bildiruvchi @external direktivasiga e'tibor bering.

Graphql
1type Post @key(fields: "id") {
2  id: ID!
3  title: String!
4  body: String!
5  user: User
6}
7
8extend type User @key(fields: "id") {
9  id: ID! @external
10  posts: [Post]
11}
12
13extend type Query {
14  getPosts: [Post]
15}

Quyidagi misolda PostsResolver getUser() metodini taqdim etadi; u __typename va ilovangiz reference ni yechish uchun kerak bo'lishi mumkin bo'lgan qo'shimcha xossalar (bu holatda id)ni o'z ichiga olgan reference qaytaradi. __typename GraphQL Gatewayga User turi uchun mas'ul mikroservisni aniqlash va mos instansiyani olishga yordam beradi. Yuqorida tasvirlangan "Users service" resolveReference() metodi bajarilganda chaqiriladi.

TypeScript
1import { Query, Resolver, Parent, ResolveField } from '@nestjs/graphql';
2import { PostsService } from './posts.service';
3import { Post } from './posts.interfaces';
4
5@Resolver('Post')
6export class PostsResolver {
7  constructor(private postsService: PostsService) {}
8
9  @Query('getPosts')
10  getPosts() {
11    return this.postsService.findAll();
12  }
13
14  @ResolveField('user')
15  getUser(@Parent() post: Post) {
16    return { __typename: 'User', id: post.userId };
17  }
18}

Oxirida GraphQLModule ni "Users service" bo'limida qilganimiz kabi ro'yxatdan o'tkazishimiz kerak.

TypeScript
1import {
2  ApolloFederationDriver,
3  ApolloFederationDriverConfig,
4} from '@nestjs/apollo';
5import { Module } from '@nestjs/common';
6import { GraphQLModule } from '@nestjs/graphql';
7import { PostsResolver } from './posts.resolver';
8
9@Module({
10  imports: [
11    GraphQLModule.forRoot<ApolloFederationDriverConfig>({
12      driver: ApolloFederationDriver,
13      typePaths: ['**/*.graphql'],
14    }),
15  ],
16  providers: [PostsResolvers],
17})
18export class AppModule {}

Code first

Avval User entityni ifodalovchi klassni e'lon qilishimiz kerak. Entityning o'zi boshqa servisda bo'lsa-da, bu yerda uni ishlatamiz (ta'rifini kengaytiramiz). @extends va @external direktivalariga e'tibor bering.

TypeScript
1import { Directive, ObjectType, Field, ID } from '@nestjs/graphql';
2import { Post } from './post.entity';
3
4@ObjectType()
5@Directive('@extends')
6@Directive('@key(fields: "id")')
7export class User {
8  @Field(() => ID)
9  @Directive('@external')
10  id: number;
11
12  @Field(() => [Post])
13  posts?: Post[];
14}

Endi User entitydagi kengaytma uchun mos resolverni quyidagicha yaratamiz:

TypeScript
1import { Parent, ResolveField, Resolver } from '@nestjs/graphql';
2import { PostsService } from './posts.service';
3import { Post } from './post.entity';
4import { User } from './user.entity';
5
6@Resolver(() => User)
7export class UsersResolver {
8  constructor(private readonly postsService: PostsService) {}
9
10  @ResolveField(() => [Post])
11  public posts(@Parent() user: User): Post[] {
12    return this.postsService.forAuthor(user.id);
13  }
14}

Post entity klassini ham aniqlashimiz kerak:

TypeScript
1import { Directive, Field, ID, Int, ObjectType } from '@nestjs/graphql';
2import { User } from './user.entity';
3
4@ObjectType()
5@Directive('@key(fields: "id")')
6export class Post {
7  @Field(() => ID)
8  id: number;
9
10  @Field()
11  title: string;
12
13  @Field(() => Int)
14  authorId: number;
15
16  @Field(() => User)
17  user?: User;
18}

Va uning resolvery:

TypeScript
1import { Query, Args, ResolveField, Resolver, Parent } from '@nestjs/graphql';
2import { PostsService } from './posts.service';
3import { Post } from './post.entity';
4import { User } from './user.entity';
5
6@Resolver(() => Post)
7export class PostsResolver {
8  constructor(private readonly postsService: PostsService) {}
9
10  @Query(() => Post)
11  findPost(@Args('id') id: number): Post {
12    return this.postsService.findOne(id);
13  }
14
15  @Query(() => [Post])
16  getPosts(): Post[] {
17    return this.postsService.all();
18  }
19
20  @ResolveField(() => User)
21  user(@Parent() post: Post): any {
22    return { __typename: 'User', id: post.authorId };
23  }
24}

Va nihoyat, hammasini modulda bog'laymiz. Schema build opsiyalariga e'tibor bering, bu yerda User yetim (tashqi) tur ekanini ko'rsatamiz.

TypeScript
1import {
2  ApolloFederationDriver,
3  ApolloFederationDriverConfig,
4} from '@nestjs/apollo';
5import { Module } from '@nestjs/common';
6import { User } from './user.entity';
7import { PostsResolvers } from './posts.resolvers';
8import { UsersResolvers } from './users.resolvers';
9import { PostsService } from './posts.service'; // Not included in example
10
11@Module({
12  imports: [
13    GraphQLModule.forRoot<ApolloFederationDriverConfig>({
14      driver: ApolloFederationDriver,
15      autoSchemaFile: true,
16      buildSchemaOptions: {
17        orphanedTypes: [User],
18      },
19    }),
20  ],
21  providers: [PostsResolver, UsersResolver, PostsService],
22})
23export class AppModule {}

Ishlaydigan misol code first rejimi uchun bu yerda va schema first rejimi uchun bu yerda mavjud.

Federatsiyalangan misol: Gateway

Avval kerakli bog'liqlikni o'rnating:

Terminal
1$ npm install --save @apollo/gateway

Gateway endpointlar ro'yxatini talab qiladi va mos schemalarni avtomatik topadi. Shuning uchun gateway servisining implementatsiyasi code va schema first yondashuvlari uchun bir xil bo'ladi.

TypeScript
1import { IntrospectAndCompose } from '@apollo/gateway';
2import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '@nestjs/apollo';
3import { Module } from '@nestjs/common';
4import { GraphQLModule } from '@nestjs/graphql';
5
6@Module({
7  imports: [
8    GraphQLModule.forRoot<ApolloGatewayDriverConfig>({
9      driver: ApolloGatewayDriver,
10      server: {
11        // ... Apollo server options
12        cors: true,
13      },
14      gateway: {
15        supergraphSdl: new IntrospectAndCompose({
16          subgraphs: [
17            { name: 'users', url: 'http://user-service/graphql' },
18            { name: 'posts', url: 'http://post-service/graphql' },
19          ],
20        }),
21      },
22    }),
23  ],
24})
25export class AppModule {}

Ishlaydigan misol code first rejimi uchun bu yerda va schema first rejimi uchun bu yerda mavjud.

Mercurius bilan Federatsiya

Avval kerakli bog'liqliklarni o'rnating:

Terminal
1$ npm install --save @apollo/subgraph @nestjs/mercurius
Note

@apollo/subgraph paketi subgraph schema ni yaratish uchun kerak (buildSubgraphSchema, printSubgraphSchema funksiyalari).

Schema first

"User service" oddiy schema taqdim etadi. @key direktiviga e'tibor bering: u Mercurius query plannerga Userning muayyan instansiyasini id ko'rsatilsa olish mumkinligini bildiradi. Shuningdek, Query turini extend qilayotganimizga e'tibor bering.

Graphql
1type User @key(fields: "id") {
2  id: ID!
3  name: String!
4}
5
6extend type Query {
7  getUser(id: ID!): User
8}

Resolver qo'shimcha resolveReference() metodini taqdim etadi. Bu metod Mercurius Gateway boshqa bog'liq resursga User instansiyasi kerak bo'lganda ishga tushadi. Buni keyinroq Posts service misolida ko'ramiz. Eslatma: metod @ResolveReference() dekoratori bilan belgilanishi kerak.

TypeScript
1import { Args, Query, Resolver, ResolveReference } from '@nestjs/graphql';
2import { UsersService } from './users.service';
3
4@Resolver('User')
5export class UsersResolver {
6  constructor(private usersService: UsersService) {}
7
8  @Query()
9  getUser(@Args('id') id: string) {
10    return this.usersService.findById(id);
11  }
12
13  @ResolveReference()
14  resolveReference(reference: { __typename: string; id: string }) {
15    return this.usersService.findById(reference.id);
16  }
17}

Oxirida GraphQLModule ga MercuriusFederationDriver driverini konfiguratsiya obyektida ko'rsatib ulaymiz:

TypeScript
1import {
2  MercuriusFederationDriver,
3  MercuriusFederationDriverConfig,
4} from '@nestjs/mercurius';
5import { Module } from '@nestjs/common';
6import { GraphQLModule } from '@nestjs/graphql';
7import { UsersResolver } from './users.resolver';
8
9@Module({
10  imports: [
11    GraphQLModule.forRoot<MercuriusFederationDriverConfig>({
12      driver: MercuriusFederationDriver,
13      typePaths: ['**/*.graphql'],
14      federationMetadata: true,
15    }),
16  ],
17  providers: [UsersResolver],
18})
19export class AppModule {}

Code first

User entityga bir nechta qo'shimcha dekoratorlarni qo'shishdan boshlaymiz.

TypeScript
1import { Directive, Field, ID, ObjectType } from '@nestjs/graphql';
2
3@ObjectType()
4@Directive('@key(fields: "id")')
5export class User {
6  @Field(() => ID)
7  id: number;
8
9  @Field()
10  name: string;
11}

Resolver qo'shimcha resolveReference() metodini taqdim etadi. Bu metod Mercurius Gateway boshqa bog'liq resursga User instansiyasi kerak bo'lganda ishga tushadi. Buni keyinroq Posts service misolida ko'ramiz. Eslatma: metod @ResolveReference() dekoratori bilan belgilanishi kerak.

TypeScript
1import { Args, Query, Resolver, ResolveReference } from '@nestjs/graphql';
2import { User } from './user.entity';
3import { UsersService } from './users.service';
4
5@Resolver(() => User)
6export class UsersResolver {
7  constructor(private usersService: UsersService) {}
8
9  @Query(() => User)
10  getUser(@Args('id') id: number): User {
11    return this.usersService.findById(id);
12  }
13
14  @ResolveReference()
15  resolveReference(reference: { __typename: string; id: number }): User {
16    return this.usersService.findById(reference.id);
17  }
18}

Oxirida GraphQLModule ga MercuriusFederationDriver driverini konfiguratsiya obyektida ko'rsatib ulaymiz:

TypeScript
1import {
2  MercuriusFederationDriver,
3  MercuriusFederationDriverConfig,
4} from '@nestjs/mercurius';
5import { Module } from '@nestjs/common';
6import { UsersResolver } from './users.resolver';
7import { UsersService } from './users.service'; // Not included in this example
8
9@Module({
10  imports: [
11    GraphQLModule.forRoot<MercuriusFederationDriverConfig>({
12      driver: MercuriusFederationDriver,
13      autoSchemaFile: true,
14      federationMetadata: true,
15    }),
16  ],
17  providers: [UsersResolver, UsersService],
18})
19export class AppModule {}

Federatsiyalangan misol: Posts

Posts service getPosts query orqali agregatsiya qilingan postlarni taqdim etishi, shuningdek User turini user.posts fieldi bilan kengaytirishi kerak.

Schema first

"Posts service" schema ichida extend keywordi orqali User turiga murojaat qiladi. U User turiga bitta qo'shimcha xossa (posts) qo'shadi. User instansiyalarini moslashtirish uchun ishlatiladigan @key direktiviga va id fieldi boshqa joyda boshqarilishini bildiruvchi @external direktivasiga e'tibor bering.

Graphql
1type Post @key(fields: "id") {
2  id: ID!
3  title: String!
4  body: String!
5  user: User
6}
7
8extend type User @key(fields: "id") {
9  id: ID! @external
10  posts: [Post]
11}
12
13extend type Query {
14  getPosts: [Post]
15}

Quyidagi misolda PostsResolver getUser() metodini taqdim etadi; u __typename va ilovangiz reference ni yechish uchun kerak bo'lishi mumkin bo'lgan qo'shimcha xossalar (bu holatda id)ni o'z ichiga olgan reference qaytaradi. __typename GraphQL Gatewayga User turi uchun mas'ul mikroservisni aniqlash va mos instansiyani olishga yordam beradi. Yuqorida tasvirlangan "Users service" resolveReference() metodi bajarilganda chaqiriladi.

TypeScript
1import { Query, Resolver, Parent, ResolveField } from '@nestjs/graphql';
2import { PostsService } from './posts.service';
3import { Post } from './posts.interfaces';
4
5@Resolver('Post')
6export class PostsResolver {
7  constructor(private postsService: PostsService) {}
8
9  @Query('getPosts')
10  getPosts() {
11    return this.postsService.findAll();
12  }
13
14  @ResolveField('user')
15  getUser(@Parent() post: Post) {
16    return { __typename: 'User', id: post.userId };
17  }
18}

Oxirida GraphQLModule ni "Users service" bo'limida qilganimiz kabi ro'yxatdan o'tkazishimiz kerak.

TypeScript
1import {
2  MercuriusFederationDriver,
3  MercuriusFederationDriverConfig,
4} from '@nestjs/mercurius';
5import { Module } from '@nestjs/common';
6import { GraphQLModule } from '@nestjs/graphql';
7import { PostsResolver } from './posts.resolver';
8
9@Module({
10  imports: [
11    GraphQLModule.forRoot<MercuriusFederationDriverConfig>({
12      driver: MercuriusFederationDriver,
13      federationMetadata: true,
14      typePaths: ['**/*.graphql'],
15    }),
16  ],
17  providers: [PostsResolvers],
18})
19export class AppModule {}

Code first

Avval User entityni ifodalovchi klassni e'lon qilishimiz kerak. Entityning o'zi boshqa servisda bo'lsa-da, bu yerda uni ishlatamiz (ta'rifini kengaytiramiz). @extends va @external direktivalariga e'tibor bering.

TypeScript
1import { Directive, ObjectType, Field, ID } from '@nestjs/graphql';
2import { Post } from './post.entity';
3
4@ObjectType()
5@Directive('@extends')
6@Directive('@key(fields: "id")')
7export class User {
8  @Field(() => ID)
9  @Directive('@external')
10  id: number;
11
12  @Field(() => [Post])
13  posts?: Post[];
14}

Endi User entitydagi kengaytma uchun mos resolverni quyidagicha yaratamiz:

TypeScript
1import { Parent, ResolveField, Resolver } from '@nestjs/graphql';
2import { PostsService } from './posts.service';
3import { Post } from './post.entity';
4import { User } from './user.entity';
5
6@Resolver(() => User)
7export class UsersResolver {
8  constructor(private readonly postsService: PostsService) {}
9
10  @ResolveField(() => [Post])
11  public posts(@Parent() user: User): Post[] {
12    return this.postsService.forAuthor(user.id);
13  }
14}

Post entity klassini ham aniqlashimiz kerak:

TypeScript
1import { Directive, Field, ID, Int, ObjectType } from '@nestjs/graphql';
2import { User } from './user.entity';
3
4@ObjectType()
5@Directive('@key(fields: "id")')
6export class Post {
7  @Field(() => ID)
8  id: number;
9
10  @Field()
11  title: string;
12
13  @Field(() => Int)
14  authorId: number;
15
16  @Field(() => User)
17  user?: User;
18}

Va uning resolvery:

TypeScript
1import { Query, Args, ResolveField, Resolver, Parent } from '@nestjs/graphql';
2import { PostsService } from './posts.service';
3import { Post } from './post.entity';
4import { User } from './user.entity';
5
6@Resolver(() => Post)
7export class PostsResolver {
8  constructor(private readonly postsService: PostsService) {}
9
10  @Query(() => Post)
11  findPost(@Args('id') id: number): Post {
12    return this.postsService.findOne(id);
13  }
14
15  @Query(() => [Post])
16  getPosts(): Post[] {
17    return this.postsService.all();
18  }
19
20  @ResolveField(() => User)
21  user(@Parent() post: Post): any {
22    return { __typename: 'User', id: post.authorId };
23  }
24}

Va nihoyat, hammasini modulda bog'laymiz. Schema build opsiyalariga e'tibor bering, bu yerda User yetim (tashqi) tur ekanini ko'rsatamiz.

TypeScript
1import {
2  MercuriusFederationDriver,
3  MercuriusFederationDriverConfig,
4} from '@nestjs/mercurius';
5import { Module } from '@nestjs/common';
6import { User } from './user.entity';
7import { PostsResolvers } from './posts.resolvers';
8import { UsersResolvers } from './users.resolvers';
9import { PostsService } from './posts.service'; // Not included in example
10
11@Module({
12  imports: [
13    GraphQLModule.forRoot<MercuriusFederationDriverConfig>({
14      driver: MercuriusFederationDriver,
15      autoSchemaFile: true,
16      federationMetadata: true,
17      buildSchemaOptions: {
18        orphanedTypes: [User],
19      },
20    }),
21  ],
22  providers: [PostsResolver, UsersResolver, PostsService],
23})
24export class AppModule {}

Federatsiyalangan misol: Gateway

Gateway endpointlar ro'yxatini talab qiladi va mos schemalarni avtomatik topadi. Shuning uchun gateway servisining implementatsiyasi code va schema first yondashuvlari uchun bir xil bo'ladi.

TypeScript
1import {
2  MercuriusGatewayDriver,
3  MercuriusGatewayDriverConfig,
4} from '@nestjs/mercurius';
5import { Module } from '@nestjs/common';
6import { GraphQLModule } from '@nestjs/graphql';
7
8@Module({
9  imports: [
10    GraphQLModule.forRoot<MercuriusGatewayDriverConfig>({
11      driver: MercuriusGatewayDriver,
12      gateway: {
13        services: [
14          { name: 'users', url: 'http://user-service/graphql' },
15          { name: 'posts', url: 'http://post-service/graphql' },
16        ],
17      },
18    }),
19  ],
20})
21export class AppModule {}

Federatsiya 2

Apollo docsdan iqtibos keltirsak, Federatsiya 2 original Apollo Federation (bu hujjatda Federation 1 deb ataladi)ga nisbatan developer tajribasini yaxshilaydi va original supergraphlarning ko'pchiligi bilan orqaga mos keladi.

Warning

Mercurius Federatsiya 2 ni to'liq qo'llab-quvvatlamaydi. Federatsiya 2 ni qo'llab-quvvatlaydigan kutubxonalar ro'yxatini bu yerda ko'rishingiz mumkin.

Quyidagi bo'limlarda oldingi misolni Federatsiya 2 ga yangilaymiz.

Federatsiyalangan misol: Users

Federatsiya 2 dagi o'zgarishlardan biri - entitylarning originating subgraphi yo'q, shuning uchun endi Queryni extend qilish shart emas. Batafsil ma'lumot uchun Apollo Federation 2 hujjatlaridagi entities mavzusiga qarang.

Schema first

Schemadan extend keywordini olib tashlash kifoya.

Graphql
1type User @key(fields: "id") {
2  id: ID!
3  name: String!
4}
5
6type Query {
7  getUser(id: ID!): User
8}

Code first

Federatsiya 2 dan foydalanish uchun autoSchemaFile opsiyasida federatsiya versiyasini ko'rsatish kerak.

TypeScript
1import {
2  ApolloFederationDriver,
3  ApolloFederationDriverConfig,
4} from '@nestjs/apollo';
5import { Module } from '@nestjs/common';
6import { UsersResolver } from './users.resolver';
7import { UsersService } from './users.service'; // Not included in this example
8
9@Module({
10  imports: [
11    GraphQLModule.forRoot<ApolloFederationDriverConfig>({
12      driver: ApolloFederationDriver,
13      autoSchemaFile: {
14        federation: 2,
15      },
16    }),
17  ],
18  providers: [UsersResolver, UsersService],
19})
20export class AppModule {}

Federatsiyalangan misol: Posts

Yuqoridagi sabab bilan, endi User va Queryni extend qilish shart emas.

Schema first

Schemadan extend va external direktivlarini olib tashlash kifoya.

Graphql
1type Post @key(fields: "id") {
2  id: ID!
3  title: String!
4  body: String!
5  user: User
6}
7
8type User @key(fields: "id") {
9  id: ID!
10  posts: [Post]
11}
12
13type Query {
14  getPosts: [Post]
15}

Code first

Endi User entityni extend qilmaganimiz uchun, User dan extends va external direktivalarini olib tashlash kifoya.

TypeScript
1import { Directive, ObjectType, Field, ID } from '@nestjs/graphql';
2import { Post } from './post.entity';
3
4@ObjectType()
5@Directive('@key(fields: "id")')
6export class User {
7  @Field(() => ID)
8  id: number;
9
10  @Field(() => [Post])
11  posts?: Post[];
12}

Shuningdek, User service dagi kabi, GraphQLModule da Federatsiya 2 ni ishlatishni ko'rsatishimiz kerak.

TypeScript
1import {
2  ApolloFederationDriver,
3  ApolloFederationDriverConfig,
4} from '@nestjs/apollo';
5import { Module } from '@nestjs/common';
6import { User } from './user.entity';
7import { PostsResolvers } from './posts.resolvers';
8import { UsersResolvers } from './users.resolvers';
9import { PostsService } from './posts.service'; // Not included in example
10
11@Module({
12  imports: [
13    GraphQLModule.forRoot<ApolloFederationDriverConfig>({
14      driver: ApolloFederationDriver,
15      autoSchemaFile: {
16        federation: 2,
17      },
18      buildSchemaOptions: {
19        orphanedTypes: [User],
20      },
21    }),
22  ],
23  providers: [PostsResolver, UsersResolver, PostsService],
24})
25export class AppModule {}