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.
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:
1$ npm install --save @apollo/subgraphSchema 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.
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.
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:
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.
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.
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:
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.
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.
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.
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.
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:
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:
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:
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.
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:
1$ npm install --save @apollo/gatewayGateway 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.
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:
1$ npm install --save @apollo/subgraph @nestjs/mercurius@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.
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.
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:
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.
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.
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:
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.
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.
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.
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.
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:
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:
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:
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.
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.
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.
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.
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.
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.
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.
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.
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 {}