GraphQL8 min read

TypeScript va GraphQL qudratidan foydalanish

GraphQL - bu APIlar uchun kuchli query tili va mavjud ma'lumotlaringiz bilan ushbu so'rovlarni bajarish uchun runtime. Bu REST APIlarda ko'p uchraydigan muammolarni hal qiladigan n

GraphQL - bu APIlar uchun kuchli query tili va mavjud ma'lumotlaringiz bilan ushbu so'rovlarni bajarish uchun runtime. Bu REST APIlarda ko'p uchraydigan muammolarni hal qiladigan nafis yondashuv. Asosiy ma'lumot uchun GraphQL va REST taqqoslanadigan ushbu taqqoslashni o'qishni tavsiya qilamiz. GraphQL bilan birga TypeScriptdan foydalanish GraphQL so'rovlari uchun yaxshiroq type safety beradi va end-to-end typingni ta'minlaydi.

Bu bobda GraphQL haqida asosiy tushunchalar bor deb faraz qilamiz va ichki @nestjs/graphql moduli bilan qanday ishlashga e'tibor qaratamiz. GraphQLModuleni Apollo server ( @nestjs/apollo driveri bilan) va Mercurius (@nestjs/mercurius bilan) uchun sozlash mumkin. Biz ushbu ishonchli GraphQL paketlari uchun rasmiy integratsiyalarni taqdim etamiz, shunda Nest bilan GraphQLdan foydalanish oson bo'ladi (batafsil integratsiyalar bu yerda).

Shuningdek, o'zingizning maxsus driveringizni yaratishingiz ham mumkin (batafsil bu yerda).

O'rnatish

Avval kerakli paketlarni o'rnating:

Terminal
1# For Express and Apollo (default)
2$ npm i @nestjs/graphql @nestjs/apollo @apollo/server @as-integrations/express5 graphql
3
4# For Fastify and Apollo
5# npm i @nestjs/graphql @nestjs/apollo @apollo/server @as-integrations/fastify graphql
6
7# For Fastify and Mercurius
8# npm i @nestjs/graphql @nestjs/mercurius graphql mercurius
Warning

@nestjs/graphql@>=9 va @nestjs/apollo^10 paketlari Apollo v3 bilan mos (batafsil Apollo Server 3 migration guide), @nestjs/graphql@^8 esa faqat Apollo v2 ni qo'llab-quvvatlaydi (masalan, apollo-server-express@2.x.x paketi).

Umumiy ko'rinish

Nest GraphQL ilovalarini yaratishning ikki usulini taklif qiladi: code first va schema first. Sizga eng mos keladiganini tanlang. GraphQL bo'limining ko'p boblari ikki qismga bo'lingan: biri code first qabul qilganlar uchun, ikkinchisi schema first qabul qilganlar uchun.

Code first yondashuvida siz dekoratorlar va TypeScript klasslari yordamida GraphQL schema ni generatsiya qilasiz. Bu yondashuv faqat TypeScript bilan ishlashni afzal ko'radigan va til sintaksislari orasida kontekst almashishni istamaydiganlar uchun qulay.

Schema first yondashuvida asosiy manba GraphQL SDL (Schema Definition Language) fayllari bo'ladi. SDL - schema fayllarini turli platformalar o'rtasida bo'lishishning tilga bog'liq bo'lmagan usuli. Nest GraphQL schemalar asosida TypeScript ta'riflarini (klasslar yoki interfeyslar) avtomatik yaratadi, bu ortiqcha boilerplate yozishni kamaytiradi.

GraphQL va TypeScript bilan boshlash

Hint

Keyingi bo'limlarda @nestjs/apollo paketini integratsiya qilamiz. Agar mercuriusdan foydalanmoqchi bo'lsangiz, bu bo'limga o'ting.

Paketlar o'rnatilgach, GraphQLModuleni import qilib, uni forRoot() statik metodi bilan sozlashimiz mumkin.

TypeScript
1import { Module } from '@nestjs/common';
2import { GraphQLModule } from '@nestjs/graphql';
3import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
4
5@Module({
6  imports: [
7    GraphQLModule.forRoot<ApolloDriverConfig>({
8      driver: ApolloDriver,
9    }),
10  ],
11})
12export class AppModule {}
Hint

mercurius integratsiyasi uchun MercuriusDriver va MercuriusDriverConfig ishlatishingiz kerak. Ikkalasi ham @nestjs/mercurius paketidan eksport qilinadi.

forRoot() metodi argument sifatida opsiyalar obyektini qabul qiladi. Bu opsiyalar ichki driver instansiyasiga uzatiladi (mavjud sozlamalar haqida batafsil: Apollo va Mercurius). Masalan, playgroundni o'chirish va debug rejimini o'chirishni xohlasangiz (Apollo uchun), quyidagi opsiyalarni bering:

TypeScript
1import { Module } from '@nestjs/common';
2import { GraphQLModule } from '@nestjs/graphql';
3import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
4
5@Module({
6  imports: [
7    GraphQLModule.forRoot<ApolloDriverConfig>({
8      driver: ApolloDriver,
9      playground: false,
10    }),
11  ],
12})
13export class AppModule {}

Bu holatda opsiyalar ApolloServer konstruktoriga uzatiladi.

GraphQL playground

Playground - bu GraphQL serverining o'zi bilan bir xil URLda default mavjud bo'lgan grafik, interaktiv, brauzerdagi GraphQL IDE. Playgroundga kirish uchun oddiy GraphQL server sozlangan va ishlayotgan bo'lishi kerak. Uni hoziroq ko'rish uchun bu yerda ishlaydigan misolni o'rnatib ishga tushirishingiz mumkin. Yoki agar shu kod namunalarini bosqichma-bosqich bajarayotgan bo'lsangiz, Resolvers bobidagi qadamlarni tugatganingizdan so'ng playgroundga kirishingiz mumkin.

Shu bilan va ilovangiz fon rejimida ishlayotganida, brauzeringizni ochib http://localhost:3000/graphql manziliga o'ting (host va port konfiguratsiyangizga qarab farq qiladi). Shunda siz quyida ko'rsatilgandek GraphQL playgroundni ko'rasiz.

Note

@nestjs/mercurius integratsiyasida built-in GraphQL Playground yo'q. Buning o'rniga GraphiQLdan foydalanishingiz mumkin (graphiql: true qilib qo'ying).

Warning

Yangilanish (04/14/2025): Default Apollo playground eskirgan va keyingi major release da olib tashlanadi. Buning o'rniga GraphiQLdan foydalanishingiz mumkin, shunchaki GraphQLModule konfiguratsiyasida graphiql: true qilib qo'ying, quyida ko'rsatilgandek:

GraphQLModule.forRoot<ApolloDriverConfig>({ driver: ApolloDriver, graphiql: true, }),

Agar ilovangizda subscriptions bo'lsa, graphql-wsdan foydalaning, chunki subscriptions-transport-ws GraphiQL tomonidan qo'llab-quvvatlanmaydi.

Code first

Code first yondashuvida siz dekoratorlar va TypeScript klasslari yordamida GraphQL schema ni generatsiya qilasiz.

Code first yondashuvini ishlatish uchun opsiyalar obyektiga autoSchemaFile xossasini qo'shing:

TypeScript
1GraphQLModule.forRoot<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
4}),

autoSchemaFile xossasi qiymati avtomatik generatsiya qilingan schema saqlanadigan yo'lni bildiradi. Muqobil ravishda, schema on-the-fly tarzda xotirada generatsiya qilinishi mumkin. Buni yoqish uchun autoSchemaFile ni true qilib qo'ying:

TypeScript
1GraphQLModule.forRoot<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  autoSchemaFile: true,
4}),

Default holatda generatsiya qilingan schemadagi turlar kiritilgan modullardagi ta'rif tartibida bo'ladi. Schemani leksikografik tartibda saralash uchun sortSchema xossasini true qiling:

TypeScript
1GraphQLModule.forRoot<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
4  sortSchema: true,
5}),

Misol

To'liq ishlaydigan code first misol bu yerda mavjud.

Schema first

Schema first yondashuvini ishlatish uchun opsiyalar obyektiga typePaths xossasini qo'shing. typePaths xossasi GraphQLModule qayerdan GraphQL SDL schema definition fayllarini qidirishini ko'rsatadi. Bu fayllar xotirada birlashtiriladi; bu esa schemalarni bir nechta faylga bo'lish va ularni resolverlar yonida joylashtirish imkonini beradi.

TypeScript
1GraphQLModule.forRoot<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  typePaths: ['./**/*.graphql'],
4}),

Odatda GraphQL SDL turlariga mos keladigan TypeScript ta'riflari (klasslar va interfeyslar) ham kerak bo'ladi. Bu ta'riflarni qo'lda yaratish ortiqcha va zerikarli. Bu bizni yagona haqiqat manbaisiz qoldiradi -- SDLdagi har bir o'zgarish TypeScript ta'riflarini ham moslashtirishni talab qiladi. Buni hal qilish uchun @nestjs/graphql paketi abstrakt sintaksis daraxti (AST) asosida TypeScript ta'riflarini avtomatik generatsiya qila oladi. Bu funksiyani yoqish uchun GraphQLModuleni sozlashda definitions opsiyasini qo'shing.

TypeScript
1GraphQLModule.forRoot<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  typePaths: ['./**/*.graphql'],
4  definitions: {
5    path: join(process.cwd(), 'src/graphql.ts'),
6  },
7}),

definitions obyektidagi path xossasi generatsiya qilingan TypeScript outputni qayerga saqlashni bildiradi. Default holatda barcha generatsiya qilingan TypeScript turlar interfeys sifatida yaratiladi. Klasslar sifatida generatsiya qilish uchun outputAs xossasiga 'class' qiymatini bering.

TypeScript
1GraphQLModule.forRoot<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  typePaths: ['./**/*.graphql'],
4  definitions: {
5    path: join(process.cwd(), 'src/graphql.ts'),
6    outputAs: 'class',
7  },
8}),

Yuqoridagi yondashuv ilova ishga tushganida TypeScript ta'riflarini har safar dinamik generatsiya qiladi. Muqobil ravishda, bularni talab bo'yicha generatsiya qiladigan oddiy skript yozishni afzal ko'rishingiz mumkin. Masalan, generate-typings.ts nomli skript yaratamiz:

TypeScript
1import { GraphQLDefinitionsFactory } from '@nestjs/graphql';
2import { join } from 'node:path';
3
4const definitionsFactory = new GraphQLDefinitionsFactory();
5definitionsFactory.generate({
6  typePaths: ['./src/**/*.graphql'],
7  path: join(process.cwd(), 'src/graphql.ts'),
8  outputAs: 'class',
9});

Endi bu skriptni istalgan vaqtda ishga tushirishingiz mumkin:

Terminal
1$ ts-node generate-typings
Hint

Skriptni oldindan kompilyatsiya qilib (masalan, tsc bilan) so'ng node orqali ishga tushirishingiz mumkin.

.graphql fayllaridagi har qanday o'zgarishda typelar avtomatik generatsiya qilinishi uchun generate() metodiga watch opsiyasini uzating.

TypeScript
1definitionsFactory.generate({
2  typePaths: ['./src/**/*.graphql'],
3  path: join(process.cwd(), 'src/graphql.ts'),
4  outputAs: 'class',
5  watch: true,
6});

Har bir object type uchun qo'shimcha __typename fieldini avtomatik generatsiya qilish uchun emitTypenameField opsiyasini yoqing:

TypeScript
1definitionsFactory.generate({
2  // ...
3  emitTypenameField: true,
4});

Resolverlarni (queries, mutations, subscriptions) argumentlarsiz oddiy fieldlar sifatida generatsiya qilish uchun skipResolverArgs opsiyasini yoqing:

TypeScript
1definitionsFactory.generate({
2  // ...
3  skipResolverArgs: true,
4});

Enumlarni oddiy TypeScript enumlar o'rniga TypeScript union turlari sifatida generatsiya qilish uchun enumsAsTypes opsiyasini true qiling:

TypeScript
1definitionsFactory.generate({
2  // ...
3  enumsAsTypes: true,
4});

Apollo Sandbox

Mahalliy ishlab chiqish uchun GraphQL IDE sifatida graphql-playground o'rniga Apollo Sandboxdan foydalanish uchun quyidagi konfiguratsiyadan foydalaning:

TypeScript
1import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
2import { Module } from '@nestjs/common';
3import { GraphQLModule } from '@nestjs/graphql';
4import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
5
6@Module({
7  imports: [
8    GraphQLModule.forRoot<ApolloDriverConfig>({
9      driver: ApolloDriver,
10      playground: false,
11      plugins: [ApolloServerPluginLandingPageLocalDefault()],
12    }),
13  ],
14})
15export class AppModule {}

Misol

To'liq ishlaydigan schema first misol bu yerda mavjud.

Generatsiya qilingan schemaga kirish

Ba'zi holatlarda (masalan, end-to-end testlarda) generatsiya qilingan schema obyektiga murojaat qilishni xohlashingiz mumkin. End-to-end testlarda HTTP listenerlardan foydalanmasdan graphql obyektidan so'rov yuborishingiz mumkin.

Generatsiya qilingan schemaga (code first yoki schema first yondashuvida) GraphQLSchemaHost klassi orqali kirishingiz mumkin:

TypeScript
1const { schema } = app.get(GraphQLSchemaHost);
Hint

GraphQLSchemaHost#schema getterini ilova initsializatsiya qilingandan keyin ( app.listen() yoki app.init() metodi onModuleInit hookni ishga tushirgandan so'ng) chaqirishingiz kerak.

Async konfiguratsiya

Modul opsiyalarini statik emas, asinxron tarzda uzatish kerak bo'lganda forRootAsync() metodidan foydalaning. Aksariyat dinamik modullar kabi, Nest asinxron konfiguratsiya bilan ishlash uchun bir nechta usullarni taqdim etadi.

Usullardan biri - factory funksiyasidan foydalanish:

TypeScript
1 GraphQLModule.forRootAsync<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  useFactory: () => ({
4    typePaths: ['./**/*.graphql'],
5  }),
6}),

Boshqa factory providerlar kabi, factory funksiyamiz async bo'lishi va inject orqali bog'liqliklarni qabul qilishi mumkin.

TypeScript
1GraphQLModule.forRootAsync<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  imports: [ConfigModule],
4  useFactory: async (configService: ConfigService) => ({
5    typePaths: configService.get<string>('GRAPHQL_TYPE_PATHS'),
6  }),
7  inject: [ConfigService],
8}),

Muqobil ravishda, quyida ko'rsatilgandek, GraphQLModuleni factory o'rniga klass yordamida sozlashingiz mumkin:

TypeScript
1GraphQLModule.forRootAsync<ApolloDriverConfig>({
2  driver: ApolloDriver,
3  useClass: GqlConfigService,
4}),

Yuqoridagi konstruktsiya GqlConfigService ni GraphQLModule ichida instansiyalaydi va opsiyalar obyektini yaratish uchun undan foydalanadi. E'tibor bering, bu misolda GqlConfigService GqlOptionsFactory interfeysini implementatsiya qilishi kerak, bu quyida ko'rsatilgan. GraphQLModule taqdim etilgan klass obyektining createGqlOptions() metodini chaqiradi.

TypeScript
1@Injectable()
2class GqlConfigService implements GqlOptionsFactory {
3  createGqlOptions(): ApolloDriverConfig {
4    return {
5      typePaths: ['./**/*.graphql'],
6    };
7  }
8}

Agar GraphQLModule ichida private nusxa yaratmasdan mavjud opsiyalar providerni qayta ishlatmoqchi bo'lsangiz, useExisting sintaksisidan foydalaning.

TypeScript
1GraphQLModule.forRootAsync<ApolloDriverConfig>({
2  imports: [ConfigModule],
3  useExisting: ConfigService,
4}),

Mercurius integratsiyasi

Apolloodan foydalanish o'rniga, Fastify foydalanuvchilari (batafsil bu yerda) muqobil ravishda @nestjs/mercurius driveridan foydalanishi mumkin.

TypeScript
1import { Module } from '@nestjs/common';
2import { GraphQLModule } from '@nestjs/graphql';
3import { MercuriusDriver, MercuriusDriverConfig } from '@nestjs/mercurius';
4
5@Module({
6  imports: [
7    GraphQLModule.forRoot<MercuriusDriverConfig>({
8      driver: MercuriusDriver,
9      graphiql: true,
10    }),
11  ],
12})
13export class AppModule {}
Hint

Ilova ishga tushgach, brauzeringizni ochib http://localhost:3000/graphiql manziliga o'ting. Shunda GraphQL IDEni ko'rasiz.

forRoot() metodi argument sifatida opsiyalar obyektini qabul qiladi. Bu opsiyalar ichki driver instansiyasiga uzatiladi. Mavjud sozlamalar haqida batafsil bu yerda o'qing.

Bir nechta endpoint

@nestjs/graphql modulining yana bir foydali imkoniyati - bir vaqtning o'zida bir nechta endpointlarni xizmat qilish. Bu qaysi modullar qaysi endpointga kirishini tanlash imkonini beradi. Default holatda GraphQL butun ilova bo'ylab resolverlarni qidiradi. Bu skanni faqat modulning bir qismiga cheklash uchun include xossasidan foydalaning.

TypeScript
1GraphQLModule.forRoot({
2  include: [CatsModule],
3}),
Warning

Agar bitta ilovada bir nechta GraphQL endpoint bilan @apollo/server va @as-integrations/fastify paketlaridan foydalansangiz, GraphQLModule konfiguratsiyasida disableHealthCheck sozlamasini yoqishni unutmang.

Uchinchi tomon integratsiyalari

  • GraphQL Yoga

Misol

Ishlaydigan misol bu yerda mavjud.