@gqlkit-ts/runtime 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts ADDED
@@ -0,0 +1,764 @@
1
+ import type { GraphQLResolveInfo } from "graphql";
2
+
3
+ /**
4
+ * Represents the locations where a directive can be applied.
5
+ * This corresponds to GraphQL Type System Directive Locations.
6
+ */
7
+ export type DirectiveLocation =
8
+ | "SCHEMA"
9
+ | "SCALAR"
10
+ | "OBJECT"
11
+ | "FIELD_DEFINITION"
12
+ | "ARGUMENT_DEFINITION"
13
+ | "INTERFACE"
14
+ | "UNION"
15
+ | "ENUM"
16
+ | "ENUM_VALUE"
17
+ | "INPUT_OBJECT"
18
+ | "INPUT_FIELD_DEFINITION";
19
+
20
+ /**
21
+ * Represents a GraphQL directive with name, arguments, and location.
22
+ * Used to define custom directives that can be attached to types and fields.
23
+ *
24
+ * @typeParam Name - The directive name (without @)
25
+ * @typeParam Args - The argument types for the directive
26
+ * @typeParam Location - The location(s) where the directive can be applied
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * type AuthDirective<R extends string[]> = GqlDirective<"auth", { roles: R }, "FIELD_DEFINITION">;
31
+ * type CacheDirective = GqlDirective<"cache", { maxAge: number }, "FIELD_DEFINITION" | "OBJECT">;
32
+ * ```
33
+ */
34
+ export type GqlDirective<
35
+ Name extends string,
36
+ Args extends Record<string, unknown> = Record<string, never>,
37
+ Location extends DirectiveLocation | DirectiveLocation[] = DirectiveLocation,
38
+ > = {
39
+ readonly " $directiveName": Name;
40
+ readonly " $directiveArgs": Args;
41
+ readonly " $directiveLocation": Location;
42
+ };
43
+
44
+ /**
45
+ * Metadata structure for field-level GraphQL metadata.
46
+ * Used to attach directives, default values, and other metadata to individual fields.
47
+ *
48
+ * @typeParam Meta - The metadata configuration object
49
+ */
50
+ export interface GqlFieldMetaShape<
51
+ Meta extends {
52
+ directives?: ReadonlyArray<
53
+ GqlDirective<
54
+ string,
55
+ Record<string, unknown>,
56
+ DirectiveLocation | DirectiveLocation[]
57
+ >
58
+ >;
59
+ defaultValue?: unknown;
60
+ },
61
+ > {
62
+ readonly directives?: Meta["directives"];
63
+ readonly defaultValue?: Meta["defaultValue"];
64
+ }
65
+
66
+ /**
67
+ * Attaches metadata to a field type.
68
+ * The metadata is embedded as optional properties to maintain compatibility
69
+ * with the underlying type.
70
+ *
71
+ * The structure uses two properties:
72
+ * - `$gqlkitFieldMeta`: Contains the metadata object with directives and defaultValue
73
+ * - `$gqlkitOriginalType`: Preserves the original type T to maintain nullability information
74
+ *
75
+ * This design is necessary because TypeScript normalizes `(T | null) & { metadata }` to
76
+ * `(T & { metadata }) | never`, which loses the null part of the union. By storing
77
+ * the original type in `$gqlkitOriginalType`, we can recover the full type information
78
+ * during CLI analysis.
79
+ *
80
+ * @typeParam T - The base type to attach metadata to
81
+ * @typeParam Meta - The metadata configuration object containing directives and/or defaultValue
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * // With directives
86
+ * type User = {
87
+ * id: GqlField<IDString, { directives: [AuthDirective<{ role: ["USER"] }>] }>;
88
+ * bio: GqlField<string | null, { directives: [AuthDirective<{ role: ["ADMIN"] }>] }>;
89
+ * };
90
+ *
91
+ * // With default value
92
+ * type PaginationInput = {
93
+ * limit: GqlField<Int, { defaultValue: 10 }>;
94
+ * offset: GqlField<Int, { defaultValue: 0 }>;
95
+ * };
96
+ *
97
+ * // With both directives and default value
98
+ * type SearchInput = {
99
+ * query: GqlField<string, { defaultValue: ""; directives: [SomeDirective] }>;
100
+ * };
101
+ * ```
102
+ */
103
+ export type GqlField<
104
+ T,
105
+ Meta extends {
106
+ directives?: ReadonlyArray<
107
+ GqlDirective<
108
+ string,
109
+ Record<string, unknown>,
110
+ DirectiveLocation | DirectiveLocation[]
111
+ >
112
+ >;
113
+ defaultValue?: unknown;
114
+ } = object,
115
+ > = T & {
116
+ readonly " $gqlkitFieldMeta"?: GqlFieldMetaShape<Meta>;
117
+ readonly " $gqlkitOriginalType"?: T;
118
+ };
119
+
120
+ /**
121
+ * Marker type for GqlInterface - used internally for type discrimination.
122
+ */
123
+ export type GqlInterfaceMarker = Record<string, unknown>;
124
+
125
+ /**
126
+ * Interface metadata structure embedded in intersection types.
127
+ * Used by CLI to detect and identify interface types through type analysis.
128
+ *
129
+ * @typeParam Meta - The metadata configuration object containing implements
130
+ */
131
+ export interface GqlInterfaceMetaShape<
132
+ Meta extends {
133
+ implements?: ReadonlyArray<GqlInterfaceMarker>;
134
+ } = object,
135
+ > {
136
+ readonly " $gqlkitInterface": true;
137
+ readonly implements?: Meta["implements"];
138
+ }
139
+
140
+ /**
141
+ * GraphQL interface type definition utility.
142
+ * Use this to define GraphQL interface types that can be implemented by object types.
143
+ *
144
+ * @typeParam T - The interface field definitions as an object type
145
+ * @typeParam Meta - Optional metadata containing implements for interface inheritance
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * // Basic interface definition
150
+ * export type Node = GqlInterface<{
151
+ * id: IDString;
152
+ * }>;
153
+ *
154
+ * export type Timestamped = GqlInterface<{
155
+ * createdAt: DateTime;
156
+ * updatedAt: DateTime;
157
+ * }>;
158
+ *
159
+ * // Interface inheriting other interfaces
160
+ * export type Entity = GqlInterface<
161
+ * {
162
+ * id: IDString;
163
+ * createdAt: DateTime;
164
+ * updatedAt: DateTime;
165
+ * },
166
+ * { implements: [Node, Timestamped] }
167
+ * >;
168
+ * ```
169
+ */
170
+ export type GqlInterface<
171
+ T extends Record<string, unknown>,
172
+ Meta extends {
173
+ implements?: ReadonlyArray<GqlInterfaceMarker>;
174
+ } = object,
175
+ > = T & {
176
+ readonly " $gqlkitInterfaceMeta"?: GqlInterfaceMetaShape<Meta>;
177
+ };
178
+
179
+ /**
180
+ * Metadata structure for type-level GraphQL metadata.
181
+ * Used to attach directives and other metadata to types.
182
+ *
183
+ * @typeParam Meta - The metadata configuration object
184
+ */
185
+ export interface GqlTypeMetaShape<
186
+ Meta extends {
187
+ directives?: ReadonlyArray<
188
+ GqlDirective<
189
+ string,
190
+ Record<string, unknown>,
191
+ DirectiveLocation | DirectiveLocation[]
192
+ >
193
+ >;
194
+ implements?: ReadonlyArray<GqlInterfaceMarker>;
195
+ },
196
+ > {
197
+ readonly directives?: Meta["directives"];
198
+ readonly implements?: Meta["implements"];
199
+ }
200
+
201
+ /**
202
+ * Attaches metadata to a type definition.
203
+ * The metadata is embedded as optional properties to maintain compatibility
204
+ * with the underlying type.
205
+ *
206
+ * The structure uses two properties:
207
+ * - `$gqlkitTypeMeta`: Contains the metadata object with directives and implements
208
+ * - `$gqlkitOriginalType`: Preserves the original type T to maintain nullability information
209
+ *
210
+ * @typeParam T - The base type to attach metadata to
211
+ * @typeParam Meta - The metadata configuration object containing directives and/or implements
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * // Type with directives only
216
+ * type User = GqlObject<
217
+ * {
218
+ * id: string;
219
+ * name: string;
220
+ * },
221
+ * { directives: [CacheDirective<{ maxAge: 60 }>] }
222
+ * >;
223
+ *
224
+ * // Type implementing an interface
225
+ * type User = GqlObject<
226
+ * {
227
+ * id: IDString;
228
+ * name: string;
229
+ * },
230
+ * { implements: [Node] }
231
+ * >;
232
+ *
233
+ * // Type with both directives and implements
234
+ * type Post = GqlObject<
235
+ * {
236
+ * id: IDString;
237
+ * title: string;
238
+ * createdAt: DateTime;
239
+ * },
240
+ * {
241
+ * implements: [Node, Timestamped],
242
+ * directives: [CacheDirective<{ maxAge: 60 }>]
243
+ * }
244
+ * >;
245
+ * ```
246
+ */
247
+ export type GqlObject<
248
+ T,
249
+ Meta extends {
250
+ directives?: ReadonlyArray<
251
+ GqlDirective<
252
+ string,
253
+ Record<string, unknown>,
254
+ DirectiveLocation | DirectiveLocation[]
255
+ >
256
+ >;
257
+ implements?: ReadonlyArray<GqlInterfaceMarker>;
258
+ } = { directives: [] },
259
+ > = T & {
260
+ readonly " $gqlkitTypeMeta"?: GqlTypeMetaShape<Meta>;
261
+ readonly " $gqlkitOriginalType"?: T;
262
+ };
263
+
264
+ /**
265
+ * Scalar metadata structure embedded in intersection types.
266
+ * Used by CLI to detect and identify scalar types through type analysis.
267
+ *
268
+ * @example
269
+ * ```typescript
270
+ * // A type with scalar metadata
271
+ * type MyScalar = Base & { " $gqlkitScalar"?: ScalarMetadataShape };
272
+ * ```
273
+ */
274
+ export interface ScalarMetadataShape {
275
+ readonly name: string;
276
+ readonly only?: "input" | "output";
277
+ }
278
+
279
+ /**
280
+ * Utility type for defining custom scalar types with metadata.
281
+ * The metadata is embedded as an optional property to maintain compatibility
282
+ * with the underlying base type.
283
+ *
284
+ * @typeParam Name - The GraphQL scalar name
285
+ * @typeParam Base - The underlying TypeScript type
286
+ * @typeParam Only - Usage constraint: "input" for input-only, "output" for output-only, undefined for both
287
+ *
288
+ * @example
289
+ * ```typescript
290
+ * // Basic custom scalar
291
+ * type DateTime = GqlScalar<"DateTime", Date>;
292
+ *
293
+ * // Input-only scalar
294
+ * type DateTimeInput = GqlScalar<"DateTime", Date, "input">;
295
+ *
296
+ * // Output-only scalar (can accept multiple base types)
297
+ * type DateTimeOutput = GqlScalar<"DateTime", Date | string, "output">;
298
+ * ```
299
+ */
300
+ export type GqlScalar<
301
+ Name extends string,
302
+ Base,
303
+ Only extends "input" | "output" | undefined = undefined,
304
+ > = Base & {
305
+ " $gqlkitScalar"?: {
306
+ name: Name;
307
+ only: Only;
308
+ };
309
+ };
310
+
311
+ /**
312
+ * GraphQL Int scalar type.
313
+ * Use this to explicitly mark a field as an integer.
314
+ * Includes metadata for CLI detection.
315
+ */
316
+ export type Int = GqlScalar<"Int", number>;
317
+
318
+ /**
319
+ * GraphQL Float scalar type.
320
+ * Use this to explicitly mark a field as a floating-point number.
321
+ * Note: Plain `number` type will also map to Float by default.
322
+ * Includes metadata for CLI detection.
323
+ */
324
+ export type Float = GqlScalar<"Float", number>;
325
+
326
+ /**
327
+ * GraphQL ID scalar type (string-based).
328
+ * Use this when the ID is represented as a string in your system.
329
+ * Includes metadata for CLI detection.
330
+ */
331
+ export type IDString = GqlScalar<"ID", string>;
332
+
333
+ /**
334
+ * GraphQL ID scalar type (number-based).
335
+ * Use this when the ID is represented as a number in your system.
336
+ * Includes metadata for CLI detection.
337
+ */
338
+ export type IDNumber = GqlScalar<"ID", number>;
339
+
340
+ /**
341
+ * Type alias representing no arguments for a resolver.
342
+ * Use this when defining resolvers that don't accept any arguments.
343
+ */
344
+ export type NoArgs = Record<string, never>;
345
+
346
+ /**
347
+ * Type for Query resolver functions.
348
+ * @typeParam TArgs - The type of arguments the resolver accepts
349
+ * @typeParam TResult - The return type of the resolver
350
+ * @typeParam TContext - The context type (defaults to unknown)
351
+ */
352
+ export type QueryResolverFn<TArgs, TResult, TContext = unknown> = (
353
+ root: undefined,
354
+ args: TArgs,
355
+ context: TContext,
356
+ info: GraphQLResolveInfo,
357
+ ) => TResult | Promise<TResult>;
358
+
359
+ /**
360
+ * Type for Mutation resolver functions.
361
+ * @typeParam TArgs - The type of arguments the resolver accepts
362
+ * @typeParam TResult - The return type of the resolver
363
+ * @typeParam TContext - The context type (defaults to unknown)
364
+ */
365
+ export type MutationResolverFn<TArgs, TResult, TContext = unknown> = (
366
+ root: undefined,
367
+ args: TArgs,
368
+ context: TContext,
369
+ info: GraphQLResolveInfo,
370
+ ) => TResult | Promise<TResult>;
371
+
372
+ /**
373
+ * Type for Field resolver functions.
374
+ * @typeParam TParent - The parent type this field belongs to
375
+ * @typeParam TArgs - The type of arguments the resolver accepts
376
+ * @typeParam TResult - The return type of the resolver
377
+ * @typeParam TContext - The context type (defaults to unknown)
378
+ */
379
+ export type FieldResolverFn<TParent, TArgs, TResult, TContext = unknown> = (
380
+ parent: TParent,
381
+ args: TArgs,
382
+ context: TContext,
383
+ info: GraphQLResolveInfo,
384
+ ) => TResult | Promise<TResult>;
385
+
386
+ /**
387
+ * The kind of resolver.
388
+ */
389
+ export type ResolverKind = "query" | "mutation" | "field";
390
+
391
+ /**
392
+ * The kind of abstract type resolver.
393
+ */
394
+ export type AbstractResolverKind = "resolveType" | "isTypeOf";
395
+
396
+ /**
397
+ * Type for resolveType resolver functions.
398
+ * Used to resolve the concrete type of a union or interface type at runtime.
399
+ * @typeParam TAbstract - The abstract type (union or interface) to resolve
400
+ * @typeParam TContext - The context type (defaults to unknown)
401
+ */
402
+ export type ResolveTypeResolverFn<TAbstract, TContext = unknown> = (
403
+ value: TAbstract,
404
+ context: TContext,
405
+ info: GraphQLResolveInfo,
406
+ ) => string | Promise<string>;
407
+
408
+ /**
409
+ * Type for isTypeOf resolver functions.
410
+ * Used to check if a value belongs to a specific object type.
411
+ * @typeParam TContext - The context type (defaults to unknown)
412
+ */
413
+ export type IsTypeOfResolverFn<TContext = unknown> = (
414
+ value: unknown,
415
+ context: TContext,
416
+ info: GraphQLResolveInfo,
417
+ ) => boolean | Promise<boolean>;
418
+
419
+ /**
420
+ * Abstract type resolver metadata structure embedded in intersection types.
421
+ * Used by CLI to detect and identify abstract type resolvers through type analysis.
422
+ */
423
+ export interface AbstractResolverMetadataShape {
424
+ readonly kind: AbstractResolverKind;
425
+ readonly targetType: unknown;
426
+ }
427
+
428
+ /**
429
+ * resolveType resolver type with metadata.
430
+ * The metadata is embedded as an optional property with space-prefixed key
431
+ * to avoid collision with user-defined properties.
432
+ * @typeParam TAbstract - The abstract type (union or interface) to resolve
433
+ * @typeParam TContext - The context type (defaults to unknown)
434
+ */
435
+ export type ResolveTypeResolver<
436
+ TAbstract,
437
+ TContext = unknown,
438
+ > = ResolveTypeResolverFn<TAbstract, TContext> & {
439
+ " $gqlkitAbstractResolver"?: {
440
+ kind: "resolveType";
441
+ targetType: TAbstract;
442
+ };
443
+ };
444
+
445
+ /**
446
+ * isTypeOf resolver type with metadata.
447
+ * The metadata is embedded as an optional property with space-prefixed key
448
+ * to avoid collision with user-defined properties.
449
+ * @typeParam TObject - The object type to check
450
+ * @typeParam TContext - The context type (defaults to unknown)
451
+ */
452
+ export type IsTypeOfResolver<
453
+ TObject,
454
+ TContext = unknown,
455
+ > = IsTypeOfResolverFn<TContext> & {
456
+ " $gqlkitAbstractResolver"?: {
457
+ kind: "isTypeOf";
458
+ targetType: TObject;
459
+ };
460
+ };
461
+
462
+ /**
463
+ * Resolver metadata structure embedded in intersection types.
464
+ * Used by CLI to detect and identify resolver types through type analysis.
465
+ */
466
+ export interface ResolverMetadataShape {
467
+ readonly kind: ResolverKind;
468
+ readonly args: unknown;
469
+ readonly result: unknown;
470
+ readonly parent?: unknown;
471
+ }
472
+
473
+ /**
474
+ * Query resolver type with metadata.
475
+ * The metadata is embedded as an optional property with space-prefixed key
476
+ * to avoid collision with user-defined properties.
477
+ * @typeParam TArgs - The type of arguments the resolver accepts
478
+ * @typeParam TResult - The return type of the resolver
479
+ * @typeParam TContext - The context type (defaults to unknown)
480
+ * @typeParam TDirectives - Array of directives to attach to this field (defaults to [])
481
+ */
482
+ export type QueryResolver<
483
+ TArgs,
484
+ TResult,
485
+ TContext = unknown,
486
+ TDirectives extends ReadonlyArray<
487
+ GqlDirective<
488
+ string,
489
+ Record<string, unknown>,
490
+ DirectiveLocation | DirectiveLocation[]
491
+ >
492
+ > = [],
493
+ > = QueryResolverFn<TArgs, TResult, TContext> & {
494
+ " $gqlkitResolver"?: {
495
+ kind: "query";
496
+ args: TArgs;
497
+ result: TResult;
498
+ directives: TDirectives;
499
+ };
500
+ };
501
+
502
+ /**
503
+ * Mutation resolver type with metadata.
504
+ * The metadata is embedded as an optional property with space-prefixed key
505
+ * to avoid collision with user-defined properties.
506
+ * @typeParam TArgs - The type of arguments the resolver accepts
507
+ * @typeParam TResult - The return type of the resolver
508
+ * @typeParam TContext - The context type (defaults to unknown)
509
+ * @typeParam TDirectives - Array of directives to attach to this field (defaults to [])
510
+ */
511
+ export type MutationResolver<
512
+ TArgs,
513
+ TResult,
514
+ TContext = unknown,
515
+ TDirectives extends ReadonlyArray<
516
+ GqlDirective<
517
+ string,
518
+ Record<string, unknown>,
519
+ DirectiveLocation | DirectiveLocation[]
520
+ >
521
+ > = [],
522
+ > = MutationResolverFn<TArgs, TResult, TContext> & {
523
+ " $gqlkitResolver"?: {
524
+ kind: "mutation";
525
+ args: TArgs;
526
+ result: TResult;
527
+ directives: TDirectives;
528
+ };
529
+ };
530
+
531
+ /**
532
+ * Field resolver type with metadata.
533
+ * The metadata is embedded as an optional property with space-prefixed key
534
+ * to avoid collision with user-defined properties.
535
+ * @typeParam TParent - The parent type this field belongs to
536
+ * @typeParam TArgs - The type of arguments the resolver accepts
537
+ * @typeParam TResult - The return type of the resolver
538
+ * @typeParam TContext - The context type (defaults to unknown)
539
+ * @typeParam TDirectives - Array of directives to attach to this field (defaults to [])
540
+ */
541
+ export type FieldResolver<
542
+ TParent,
543
+ TArgs,
544
+ TResult,
545
+ TContext = unknown,
546
+ TDirectives extends ReadonlyArray<
547
+ GqlDirective<
548
+ string,
549
+ Record<string, unknown>,
550
+ DirectiveLocation | DirectiveLocation[]
551
+ >
552
+ > = [],
553
+ > = FieldResolverFn<TParent, TArgs, TResult, TContext> & {
554
+ " $gqlkitResolver"?: {
555
+ kind: "field";
556
+ parent: TParent;
557
+ args: TArgs;
558
+ result: TResult;
559
+ directives: TDirectives;
560
+ };
561
+ };
562
+
563
+ /**
564
+ * The API set returned by createGqlkitApis.
565
+ * Contains typed define functions for Query, Mutation, and Field resolvers.
566
+ * @typeParam TContext - The context type for all resolvers in this API set
567
+ */
568
+ export interface GqlkitApis<TContext> {
569
+ /**
570
+ * Defines a Query field resolver with the specified Context type.
571
+ * @typeParam TArgs - The type of arguments the resolver accepts
572
+ * @typeParam TResult - The return type of the resolver
573
+ * @typeParam TDirectives - Array of directives to attach to this field (defaults to [])
574
+ * @param resolver - The resolver function
575
+ * @returns The resolver with metadata for CLI detection
576
+ *
577
+ * @example
578
+ * ```typescript
579
+ * // Without directives
580
+ * export const users = defineQuery<NoArgs, User[]>(() => []);
581
+ *
582
+ * // With directives
583
+ * export const me = defineQuery<NoArgs, User, [AuthDirective<{ role: ["USER"] }>]>(
584
+ * (root, args, ctx) => ctx.currentUser
585
+ * );
586
+ * ```
587
+ */
588
+ defineQuery: <
589
+ TArgs,
590
+ TResult,
591
+ TDirectives extends ReadonlyArray<
592
+ GqlDirective<
593
+ string,
594
+ Record<string, unknown>,
595
+ DirectiveLocation | DirectiveLocation[]
596
+ >
597
+ > = [],
598
+ >(
599
+ resolver: QueryResolverFn<TArgs, TResult, TContext>,
600
+ ) => QueryResolver<TArgs, TResult, TContext, TDirectives>;
601
+
602
+ /**
603
+ * Defines a Mutation field resolver with the specified Context type.
604
+ * @typeParam TArgs - The type of arguments the resolver accepts
605
+ * @typeParam TResult - The return type of the resolver
606
+ * @typeParam TDirectives - Array of directives to attach to this field (defaults to [])
607
+ * @param resolver - The resolver function
608
+ * @returns The resolver with metadata for CLI detection
609
+ *
610
+ * @example
611
+ * ```typescript
612
+ * // Without directives
613
+ * export const createUser = defineMutation<CreateUserInput, User>((root, args) => ({ ... }));
614
+ *
615
+ * // With directives
616
+ * export const deleteUser = defineMutation<{ id: string }, boolean, [AuthDirective<{ role: ["ADMIN"] }>]>(
617
+ * (root, args, ctx) => true
618
+ * );
619
+ * ```
620
+ */
621
+ defineMutation: <
622
+ TArgs,
623
+ TResult,
624
+ TDirectives extends ReadonlyArray<
625
+ GqlDirective<
626
+ string,
627
+ Record<string, unknown>,
628
+ DirectiveLocation | DirectiveLocation[]
629
+ >
630
+ > = [],
631
+ >(
632
+ resolver: MutationResolverFn<TArgs, TResult, TContext>,
633
+ ) => MutationResolver<TArgs, TResult, TContext, TDirectives>;
634
+
635
+ /**
636
+ * Defines an object type field resolver with the specified Context type.
637
+ * @typeParam TParent - The parent type this field belongs to
638
+ * @typeParam TArgs - The type of arguments the resolver accepts
639
+ * @typeParam TResult - The return type of the resolver
640
+ * @typeParam TDirectives - Array of directives to attach to this field (defaults to [])
641
+ * @param resolver - The resolver function
642
+ * @returns The resolver with metadata for CLI detection
643
+ *
644
+ * @example
645
+ * ```typescript
646
+ * // Without directives
647
+ * export const userPosts = defineField<User, NoArgs, Post[]>((parent) => []);
648
+ *
649
+ * // With directives
650
+ * export const userEmail = defineField<User, NoArgs, string, [AuthDirective<{ role: ["ADMIN"] }>]>(
651
+ * (parent) => parent.email
652
+ * );
653
+ * ```
654
+ */
655
+ defineField: <
656
+ TParent,
657
+ TArgs,
658
+ TResult,
659
+ TDirectives extends ReadonlyArray<
660
+ GqlDirective<
661
+ string,
662
+ Record<string, unknown>,
663
+ DirectiveLocation | DirectiveLocation[]
664
+ >
665
+ > = [],
666
+ >(
667
+ resolver: FieldResolverFn<TParent, TArgs, TResult, TContext>,
668
+ ) => FieldResolver<TParent, TArgs, TResult, TContext, TDirectives>;
669
+
670
+ /**
671
+ * Defines a resolveType resolver for union or interface types.
672
+ * Used to determine the concrete type of an abstract type at runtime.
673
+ * @typeParam TAbstract - The abstract type (union or interface) to resolve
674
+ * @param resolver - The resolver function that returns the concrete type name
675
+ * @returns The resolver with metadata for CLI detection
676
+ *
677
+ * @example
678
+ * ```typescript
679
+ * type Animal = Dog | Cat;
680
+ *
681
+ * export const animalResolveType = defineResolveType<Animal>((value) => {
682
+ * return value.kind === "dog" ? "Dog" : "Cat";
683
+ * });
684
+ * ```
685
+ */
686
+ defineResolveType: <TAbstract>(
687
+ resolver: ResolveTypeResolverFn<TAbstract, TContext>,
688
+ ) => ResolveTypeResolver<TAbstract, TContext>;
689
+
690
+ /**
691
+ * Defines an isTypeOf resolver for object types.
692
+ * Used to check if a value belongs to a specific object type.
693
+ * @typeParam TObject - The object type to check
694
+ * @param resolver - The resolver function that returns true if the value is of this type
695
+ * @returns The resolver with metadata for CLI detection
696
+ *
697
+ * @example
698
+ * ```typescript
699
+ * export const dogIsTypeOf = defineIsTypeOf<Dog>((value) => {
700
+ * return typeof value === "object" && value !== null && "kind" in value && value.kind === "dog";
701
+ * });
702
+ * ```
703
+ */
704
+ defineIsTypeOf: <TObject>(
705
+ resolver: IsTypeOfResolverFn<TContext>,
706
+ ) => IsTypeOfResolver<TObject, TContext>;
707
+ }
708
+
709
+ /**
710
+ * Creates a set of typed define functions for GraphQL resolvers.
711
+ * Use this factory to create API sets with custom Context types.
712
+ *
713
+ * @typeParam TContext - The context type for all resolvers (defaults to unknown)
714
+ * @returns An object containing defineQuery, defineMutation, and defineField functions
715
+ *
716
+ * @example
717
+ * ```typescript
718
+ * type MyContext = { userId: string; db: Database };
719
+ *
720
+ * const { defineQuery, defineMutation, defineField } = createGqlkitApis<MyContext>();
721
+ *
722
+ * export const me = defineQuery<NoArgs, User>(
723
+ * (root, args, ctx, info) => ctx.db.findUser(ctx.userId)
724
+ * );
725
+ * ```
726
+ *
727
+ * @example
728
+ * ```typescript
729
+ * // Multiple schemas with different contexts
730
+ * type AdminContext = { adminId: string };
731
+ * type PublicContext = { sessionId: string };
732
+ *
733
+ * const adminApis = createGqlkitApis<AdminContext>();
734
+ * const publicApis = createGqlkitApis<PublicContext>();
735
+ * ```
736
+ */
737
+ export function createGqlkitApis<TContext = unknown>(): GqlkitApis<TContext> {
738
+ const apis = {
739
+ defineQuery: <TArgs, TResult>(
740
+ resolver: QueryResolverFn<TArgs, TResult, TContext>,
741
+ ) => {
742
+ return resolver;
743
+ },
744
+ defineMutation: <TArgs, TResult>(
745
+ resolver: MutationResolverFn<TArgs, TResult, TContext>,
746
+ ) => {
747
+ return resolver;
748
+ },
749
+ defineField: <TParent, TArgs, TResult>(
750
+ resolver: FieldResolverFn<TParent, TArgs, TResult, TContext>,
751
+ ) => {
752
+ return resolver;
753
+ },
754
+ defineResolveType: <TAbstract>(
755
+ resolver: ResolveTypeResolverFn<TAbstract, TContext>,
756
+ ) => {
757
+ return resolver;
758
+ },
759
+ defineIsTypeOf: (resolver: IsTypeOfResolverFn<TContext>) => {
760
+ return resolver;
761
+ },
762
+ };
763
+ return apis as unknown as GqlkitApis<TContext>;
764
+ }