Scalarlar
GraphQL object type ning nomi va fieldlari bor, ammo oxir-oqibat bu fieldlar aniq ma'lumotga yechilishi kerak. Bu yerda scalar turlar kerak bo'ladi: ular queryning barglarini ifoda
GraphQL object type ning nomi va fieldlari bor, ammo oxir-oqibat bu fieldlar aniq ma'lumotga yechilishi kerak. Bu yerda scalar turlar kerak bo'ladi: ular queryning barglarini ifodalaydi (batafsil bu yerda). GraphQL quyidagi default turlarni o'z ichiga oladi: Int, Float, String, Boolean va ID. Bu built-in turlardan tashqari, sizga custom atomic data turlarini (masalan, Date) qo'llab-quvvatlash kerak bo'lishi mumkin.
Code first
Code-first yondashuvi besh ta scalar bilan keladi, ulardan uchtasi mavjud GraphQL turlari uchun oddiy aliaslardir.
ID(GraphQLIDuchun alias) - noyob identifikatorni ifodalaydi, ko'pincha obyektni qayta fetch qilish yoki cache kaliti sifatida ishlatiladiInt(GraphQLIntuchun alias) - signed 32-bit integerFloat(GraphQLFloatuchun alias) - signed double-precision floating-point qiymatGraphQLISODateTime- UTCdagi date-time satri (default holatdaDateturini ifodalash uchun ishlatiladi)GraphQLTimestamp- UNIX epoch boshidan millisekundlar soni sifatida sana va vaqtni ifodalovchi signed integer
GraphQLISODateTime (masalan, 2019-12-03T09:54:33Z) default holatda Date turini ifodalash uchun ishlatiladi. Buning o'rniga GraphQLTimestampdan foydalanish uchun buildSchemaOptions obyektida dateScalarModeni 'timestamp' qilib o'rnating:
1GraphQLModule.forRoot({
2 buildSchemaOptions: {
3 dateScalarMode: 'timestamp',
4 }
5}),Xuddi shuningdek, GraphQLFloat default holatda number turini ifodalash uchun ishlatiladi. Buning o'rniga GraphQLIntdan foydalanish uchun buildSchemaOptions obyektida numberScalarModeni 'integer' qilib o'rnating:
1GraphQLModule.forRoot({
2 buildSchemaOptions: {
3 numberScalarMode: 'integer',
4 }
5}),Bundan tashqari, custom scalarlar yaratishingiz mumkin.
Default scalarni override qilish
Date scalarining custom implementatsiyasini yaratish uchun yangi klass yarating.
1import { Scalar, CustomScalar } from '@nestjs/graphql';
2import { Kind, ValueNode } from 'graphql';
3
4@Scalar('Date', () => Date)
5export class DateScalar implements CustomScalar<number, Date> {
6 description = 'Date custom scalar type';
7
8 parseValue(value: number): Date {
9 return new Date(value); // value from the client
10 }
11
12 serialize(value: Date): number {
13 return value.getTime(); // value sent to the client
14 }
15
16 parseLiteral(ast: ValueNode): Date {
17 if (ast.kind === Kind.INT) {
18 return new Date(ast.value);
19 }
20 return null;
21 }
22}Shu bilan, DateScalarni provider sifatida ro'yxatdan o'tkazing.
1@Module({
2 providers: [DateScalar],
3})
4export class CommonModule {}Endi klasslarimizda Date turidan foydalanishimiz mumkin.
1@Field()
2creationDate: Date;Custom scalarni import qilish
Custom scalardan foydalanish uchun uni import qilib resolver sifatida ro'yxatdan o'tkazing. Namoyish uchun graphql-type-json paketidan foydalanamiz. Bu npm paket JSON GraphQL scalar turini belgilaydi.
Avval paketni o'rnating:
1$ npm i --save graphql-type-jsonPaket o'rnatilgach, forRoot() metodiga custom resolver uzatamiz:
1import GraphQLJSON from 'graphql-type-json';
2
3@Module({
4 imports: [
5 GraphQLModule.forRoot({
6 resolvers: { JSON: GraphQLJSON },
7 }),
8 ],
9})
10export class AppModule {}Endi klasslarimizda JSON turidan foydalanishimiz mumkin.
1@Field(() => GraphQLJSON)
2info: JSON;Foydali scalarlar to'plami uchun graphql-scalars paketiga qarang.
Custom scalar yaratish
Custom scalarni aniqlash uchun yangi GraphQLScalarType instansiyasini yarating. Biz UUID custom scalarini yaratamiz.
1const regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2
3function validate(uuid: unknown): string | never {
4 if (typeof uuid !== 'string' || !regex.test(uuid)) {
5 throw new Error('invalid uuid');
6 }
7 return uuid;
8}
9
10export const CustomUuidScalar = new GraphQLScalarType({
11 name: 'UUID',
12 description: 'A simple UUID parser',
13 serialize: (value) => validate(value),
14 parseValue: (value) => validate(value),
15 parseLiteral: (ast) => validate(ast.value),
16});Custom resolverni forRoot() metodiga uzatamiz:
1@Module({
2 imports: [
3 GraphQLModule.forRoot({
4 resolvers: { UUID: CustomUuidScalar },
5 }),
6 ],
7})
8export class AppModule {}Endi klasslarimizda UUID turidan foydalanishimiz mumkin.
1@Field(() => CustomUuidScalar)
2uuid: string;Schema first
Custom scalarni aniqlash uchun (scalarlarga oid batafsil ma'lumot bu yerda), type ta'rifi va maxsus resolver yarating. Bu yerda (rasmiy hujjatlardagi kabi) namoyish uchun graphql-type-json paketidan foydalanamiz. Bu npm paket JSON GraphQL scalar turini belgilaydi.
Avval paketni o'rnating:
1$ npm i --save graphql-type-jsonPaket o'rnatilgach, forRoot() metodiga custom resolver uzatamiz:
1import GraphQLJSON from 'graphql-type-json';
2
3@Module({
4 imports: [
5 GraphQLModule.forRoot({
6 typePaths: ['./**/*.graphql'],
7 resolvers: { JSON: GraphQLJSON },
8 }),
9 ],
10})
11export class AppModule {}Endi type ta'riflarimizda JSON scalaridan foydalanamiz:
1scalar JSON
2
3type Foo {
4 field: JSON
5}Scalar turini aniqlashning yana bir usuli - oddiy klass yaratish. Masalan, schemamizni Date turi bilan boyitmoqchi bo'lsak.
1import { Scalar, CustomScalar } from '@nestjs/graphql';
2import { Kind, ValueNode } from 'graphql';
3
4@Scalar('Date')
5export class DateScalar implements CustomScalar<number, Date> {
6 description = 'Date custom scalar type';
7
8 parseValue(value: number): Date {
9 return new Date(value); // value from the client
10 }
11
12 serialize(value: Date): number {
13 return value.getTime(); // value sent to the client
14 }
15
16 parseLiteral(ast: ValueNode): Date {
17 if (ast.kind === Kind.INT) {
18 return new Date(ast.value);
19 }
20 return null;
21 }
22}Shu bilan, DateScalarni provider sifatida ro'yxatdan o'tkazing.
1@Module({
2 providers: [DateScalar],
3})
4export class CommonModule {}Endi type ta'riflarimizda Date scalaridan foydalanamiz.
1scalar DateDefault holatda barcha scalarlar uchun generatsiya qilingan TypeScript ta'rifi any bo'ladi - bu unchalik typesafe emas.
Biroq, turlarni qanday generatsiya qilishni belgilayotganda custom scalarlar uchun Nest typingsni qanday generatsiya qilishini sozlashingiz mumkin:
1import { GraphQLDefinitionsFactory } from '@nestjs/graphql';
2import { join } from 'path';
3
4const definitionsFactory = new GraphQLDefinitionsFactory();
5
6definitionsFactory.generate({
7 typePaths: ['./src/**/*.graphql'],
8 path: join(process.cwd(), 'src/graphql.ts'),
9 outputAs: 'class',
10 defaultScalarType: 'unknown',
11 customScalarTypeMapping: {
12 DateTime: 'Date',
13 BigNumber: '_BigNumber',
14 },
15 additionalHeader: "import _BigNumber from 'bignumber.js'",
16});Muqobil ravishda type reference ham berishingiz mumkin, masalan: DateTime: Date. Bu holatda GraphQLDefinitionsFactory ko'rsatilgan tur (Date.name)ning name xossasini ajratib olib TS ta'riflarini generatsiya qiladi. Eslatma: built-in bo'lmagan turlar (custom turlar) uchun import bayonotini qo'shish kerak.
Endi quyidagi GraphQL custom scalar turlarini olamiz:
1scalar DateTime
2scalar BigNumber
3scalar PayloadEndi src/graphql.ts faylida quyidagi generatsiya qilingan TypeScript ta'riflarini ko'ramiz:
1import _BigNumber from 'bignumber.js';
2
3export type DateTime = Date;
4export type BigNumber = _BigNumber;
5export type Payload = unknown;Bu yerda customScalarTypeMapping xossasidan foydalanib custom scalarlar uchun istalgan turlar xaritasini berdik. Shuningdek, bu ta'riflar uchun kerakli importlarni qo'shish uchun additionalHeader xossasini ham berdik. Nihoyat, defaultScalarTypeni 'unknown' qilib o'rnatdik, shunda customScalarTypeMappingda ko'rsatilmagan har qanday custom scalar any o'rniga unknownga map qilinadi (TypeScript 3.0 dan beri TypeScript tavsiyasi type safety uchun).
_BigNumberni bignumber.jsdan import qilganimizga e'tibor bering; bu circular type referencesdan qochish uchun.