0
# Schema Building and Generation
1
2
Advanced schema building utilities, type loading, and definition generation for both code-first and schema-first approaches. This module provides the core infrastructure for generating executable GraphQL schemas from TypeScript classes and SDL files.
3
4
## Capabilities
5
6
### GraphQL Factory
7
8
Main factory service for creating executable GraphQL schemas from NestJS module configuration.
9
10
```typescript { .api }
11
/**
12
* Injectable factory service for generating executable GraphQL schemas
13
* Core service that orchestrates schema creation from decorators and metadata
14
*/
15
export class GraphQLFactory {
16
/**
17
* Create an executable GraphQL schema from module options
18
* @param options - GraphQL module configuration options
19
* @returns Promise resolving to executable GraphQL schema
20
*/
21
create(options: GqlModuleOptions): Promise<GraphQLSchema>;
22
23
/**
24
* Create schema with custom build options
25
* @param options - Module options
26
* @param buildOptions - Custom schema building options
27
* @returns Promise resolving to executable GraphQL schema
28
*/
29
createWithBuildOptions(
30
options: GqlModuleOptions,
31
buildOptions: BuildSchemaOptions
32
): Promise<GraphQLSchema>;
33
34
/**
35
* Merge multiple schemas into a single executable schema
36
* @param schemas - Array of GraphQL schemas to merge
37
* @returns Merged executable schema
38
*/
39
mergeSchemas(schemas: GraphQLSchema[]): GraphQLSchema;
40
}
41
```
42
43
**Usage Examples:**
44
45
```typescript
46
import { Injectable } from "@nestjs/common";
47
import { GraphQLFactory, GqlModuleOptions } from "@nestjs/graphql";
48
49
@Injectable()
50
export class CustomSchemaService {
51
constructor(private readonly graphqlFactory: GraphQLFactory) {}
52
53
async createCustomSchema(): Promise<GraphQLSchema> {
54
const options: GqlModuleOptions = {
55
autoSchemaFile: true,
56
buildSchemaOptions: {
57
dateScalarMode: 'isoDate',
58
orphanedTypes: [CustomType],
59
},
60
};
61
62
return this.graphqlFactory.create(options);
63
}
64
}
65
```
66
67
### Schema Factory
68
69
Low-level factory for creating GraphQL schemas from metadata and build options.
70
71
```typescript { .api }
72
/**
73
* Factory class for creating GraphQL schemas from metadata
74
* Provides fine-grained control over schema construction process
75
*/
76
export class GraphQLSchemaFactory {
77
/**
78
* Create GraphQL schema from build options and metadata
79
* @param metadata - Schema building options and metadata
80
* @returns Executable GraphQL schema
81
*/
82
create(metadata: BuildSchemaOptions): GraphQLSchema;
83
84
/**
85
* Create schema with custom type definitions
86
* @param typeDefs - GraphQL SDL type definitions
87
* @param resolvers - Resolver map
88
* @param options - Additional build options
89
* @returns Executable GraphQL schema
90
*/
91
createFromTypeDefs(
92
typeDefs: string,
93
resolvers: any,
94
options?: BuildSchemaOptions
95
): GraphQLSchema;
96
97
/**
98
* Transform existing schema with build options
99
* @param schema - Existing GraphQL schema
100
* @param options - Transformation options
101
* @returns Transformed schema
102
*/
103
transformSchema(schema: GraphQLSchema, options: BuildSchemaOptions): GraphQLSchema;
104
}
105
```
106
107
### Types Loader
108
109
Service for loading and merging GraphQL type definitions from files (schema-first approach).
110
111
```typescript { .api }
112
/**
113
* Injectable service for loading and merging GraphQL type definitions from files
114
* Used in schema-first approach to combine SDL files into unified schema
115
*/
116
export class GraphQLTypesLoader {
117
/**
118
* Load and merge GraphQL type definitions from specified file paths
119
* @param paths - Array of file paths or glob patterns
120
* @returns Merged GraphQL SDL string
121
*/
122
mergeTypesByPaths(paths: string[]): string;
123
124
/**
125
* Load type definitions from a single file
126
* @param path - File path to load
127
* @returns GraphQL SDL string from file
128
*/
129
loadFromFile(path: string): string;
130
131
/**
132
* Load type definitions from multiple files
133
* @param paths - Array of file paths
134
* @returns Array of GraphQL SDL strings
135
*/
136
loadFromFiles(paths: string[]): string[];
137
138
/**
139
* Merge multiple GraphQL SDL strings
140
* @param typeDefs - Array of GraphQL SDL strings
141
* @returns Single merged GraphQL SDL string
142
*/
143
mergeTypeDefs(typeDefs: string[]): string;
144
}
145
```
146
147
**Usage Examples:**
148
149
```typescript
150
import { Injectable } from "@nestjs/common";
151
import { GraphQLTypesLoader } from "@nestjs/graphql";
152
153
@Injectable()
154
export class SchemaService {
155
constructor(private readonly typesLoader: GraphQLTypesLoader) {}
156
157
loadSchemaFiles(): string {
158
// Load from multiple paths
159
const typeDefs = this.typesLoader.mergeTypesByPaths([
160
'src/**/*.graphql',
161
'schemas/*.gql',
162
'types/user.graphql',
163
]);
164
165
return typeDefs;
166
}
167
168
loadSpecificSchema(): string {
169
// Load from specific files
170
const userTypes = this.typesLoader.loadFromFile('schemas/user.graphql');
171
const postTypes = this.typesLoader.loadFromFile('schemas/post.graphql');
172
173
return this.typesLoader.mergeTypeDefs([userTypes, postTypes]);
174
}
175
}
176
177
// Schema-first module configuration
178
@Module({
179
imports: [
180
GraphQLModule.forRoot({
181
typePaths: ['./**/*.graphql'],
182
definitions: {
183
path: join(process.cwd(), 'src/graphql.ts'),
184
outputAs: 'class',
185
},
186
}),
187
],
188
})
189
export class SchemaFirstModule {}
190
```
191
192
### Definitions Factory
193
194
Factory for generating TypeScript definitions from GraphQL schemas.
195
196
```typescript { .api }
197
/**
198
* Factory for generating TypeScript definitions from GraphQL schemas
199
* Converts GraphQL SDL to TypeScript interfaces and types
200
*/
201
export class GraphQLDefinitionsFactory {
202
/**
203
* Generate TypeScript definitions from GraphQL schema
204
* @param options - Configuration options for generation
205
* @returns Promise that resolves when generation is complete
206
*/
207
generate(options: GenerateOptions): Promise<void>;
208
209
/**
210
* Generate definitions from schema object
211
* @param schema - GraphQL schema object
212
* @param options - Generation options
213
* @returns Generated TypeScript code string
214
*/
215
generateFromSchema(schema: GraphQLSchema, options: GenerateOptions): string;
216
217
/**
218
* Generate definitions from SDL string
219
* @param typeDefs - GraphQL SDL string
220
* @param options - Generation options
221
* @returns Generated TypeScript code string
222
*/
223
generateFromTypeDefs(typeDefs: string, options: GenerateOptions): string;
224
}
225
226
/**
227
* Options for TypeScript definitions generation
228
*/
229
interface GenerateOptions {
230
/** Output file path for generated definitions */
231
path: string;
232
/** Output format: 'class' or 'interface' */
233
outputAs?: 'class' | 'interface';
234
/** Whether to watch for schema changes */
235
watch?: boolean;
236
/** Custom scalar type mappings */
237
customScalarTypeMapping?: Record<string, string>;
238
/** Additional type imports to include */
239
additionalTypeImports?: string[];
240
/** Whether to emit decorator metadata */
241
emitDecoratorMetadata?: boolean;
242
/** Whether to skip schema validation */
243
skipSchemaValidation?: boolean;
244
}
245
246
type DefinitionsGeneratorOptions = GenerateOptions;
247
```
248
249
**Usage Examples:**
250
251
```typescript
252
import { GraphQLDefinitionsFactory } from "@nestjs/graphql";
253
254
// Generate TypeScript definitions
255
const definitionsFactory = new GraphQLDefinitionsFactory();
256
257
await definitionsFactory.generate({
258
path: join(process.cwd(), 'src/generated/graphql.ts'),
259
outputAs: 'interface',
260
customScalarTypeMapping: {
261
DateTime: 'Date',
262
JSON: 'any',
263
},
264
additionalTypeImports: [
265
"import { CustomType } from '../types/custom';"
266
],
267
});
268
269
// Generated file content example:
270
/*
271
export interface User {
272
id: string;
273
name: string;
274
email: string;
275
createdAt: Date; // DateTime scalar mapped to Date
276
}
277
278
export interface CreateUserInput {
279
name: string;
280
email: string;
281
}
282
283
export interface Query {
284
users(): User[];
285
user(id: string): User;
286
}
287
288
export interface Mutation {
289
createUser(input: CreateUserInput): User;
290
}
291
*/
292
```
293
294
### Schema Host
295
296
Service providing runtime access to the compiled GraphQL schema.
297
298
```typescript { .api }
299
/**
300
* Injectable service providing access to the compiled GraphQL schema
301
* Useful for runtime schema introspection and manipulation
302
*/
303
export class GraphQLSchemaHost {
304
/**
305
* Get the compiled GraphQL schema
306
* @returns Executable GraphQL schema instance
307
*/
308
get schema(): GraphQLSchema;
309
310
/**
311
* Check if schema is available
312
* @returns True if schema has been compiled and is available
313
*/
314
get isSchemaAvailable(): boolean;
315
316
/**
317
* Get schema SDL representation
318
* @returns GraphQL SDL string of the compiled schema
319
*/
320
getSchemaString(): string;
321
322
/**
323
* Get specific type from schema
324
* @param typeName - Name of the GraphQL type
325
* @returns GraphQL type object or undefined
326
*/
327
getType(typeName: string): GraphQLType | undefined;
328
329
/**
330
* Get all types from schema
331
* @returns Map of type names to GraphQL type objects
332
*/
333
getTypeMap(): GraphQLTypeMap;
334
}
335
```
336
337
**Usage Examples:**
338
339
```typescript
340
import { Injectable } from "@nestjs/common";
341
import { GraphQLSchemaHost } from "@nestjs/graphql";
342
import { printSchema } from "graphql";
343
344
@Injectable()
345
export class SchemaIntrospectionService {
346
constructor(private readonly schemaHost: GraphQLSchemaHost) {}
347
348
getSchemaSDL(): string {
349
const schema = this.schemaHost.schema;
350
return printSchema(schema);
351
}
352
353
hasType(typeName: string): boolean {
354
return !!this.schemaHost.getType(typeName);
355
}
356
357
getAllTypeNames(): string[] {
358
const typeMap = this.schemaHost.getTypeMap();
359
return Object.keys(typeMap).filter(name => !name.startsWith('__'));
360
}
361
362
validateSchemaIntegrity(): boolean {
363
return this.schemaHost.isSchemaAvailable;
364
}
365
}
366
```
367
368
### AST Explorer
369
370
Service for exploring GraphQL AST and generating TypeScript definitions.
371
372
```typescript { .api }
373
/**
374
* Injectable service for exploring GraphQL AST and generating TypeScript definitions
375
* Provides low-level access to GraphQL schema analysis
376
*/
377
export class GraphQLAstExplorer {
378
/**
379
* Explore GraphQL document AST and extract type information
380
* @param documentAST - GraphQL document AST
381
* @returns Extracted type information
382
*/
383
explore(documentAST: DocumentNode): any;
384
385
/**
386
* Generate TypeScript definitions from AST
387
* @param documentAST - GraphQL document AST
388
* @param options - Generation options
389
* @returns Generated TypeScript code
390
*/
391
generateDefinitions(documentAST: DocumentNode, options: DefinitionsGeneratorOptions): string;
392
393
/**
394
* Extract field information from type definition
395
* @param typeNode - GraphQL type definition node
396
* @returns Field information array
397
*/
398
extractFields(typeNode: any): any[];
399
400
/**
401
* Build type reference from AST node
402
* @param typeNode - GraphQL type node
403
* @returns TypeScript type reference string
404
*/
405
buildTypeReference(typeNode: any): string;
406
}
407
```
408
409
### File System Helper
410
411
Utility class for file system operations during schema building.
412
413
```typescript { .api }
414
/**
415
* Helper class for file system operations during schema building
416
* Provides utilities for file watching, path resolution, and file I/O
417
*/
418
export class FileSystemHelper {
419
/**
420
* Write content to file with proper directory creation
421
* @param path - File path to write to
422
* @param content - Content to write
423
* @returns Promise that resolves when write is complete
424
*/
425
writeFile(path: string, content: string): Promise<void>;
426
427
/**
428
* Read file content
429
* @param path - File path to read from
430
* @returns Promise resolving to file content
431
*/
432
readFile(path: string): Promise<string>;
433
434
/**
435
* Check if file exists
436
* @param path - File path to check
437
* @returns True if file exists
438
*/
439
fileExists(path: string): boolean;
440
441
/**
442
* Watch files for changes
443
* @param paths - File paths or patterns to watch
444
* @param callback - Callback function for file changes
445
* @returns File watcher instance
446
*/
447
watchFiles(paths: string[], callback: (path: string) => void): any;
448
449
/**
450
* Resolve glob patterns to file paths
451
* @param patterns - Glob patterns to resolve
452
* @returns Array of resolved file paths
453
*/
454
resolveGlobPatterns(patterns: string[]): string[];
455
}
456
```
457
458
### Build Schema Options
459
460
Comprehensive configuration options for schema building process.
461
462
```typescript { .api }
463
/**
464
* Options for GraphQL schema construction and building
465
*/
466
interface BuildSchemaOptions {
467
/** Date scalar handling mode */
468
dateScalarMode?: 'isoDate' | 'timestamp';
469
470
/** Custom scalar type mappings */
471
scalarsMap?: ScalarsTypeMap[];
472
473
/** Types to include in schema even if not referenced */
474
orphanedTypes?: Function[];
475
476
/** Global pipes for all fields */
477
globalPipes?: PipeTransform[];
478
479
/** Field-level middleware */
480
fieldMiddleware?: FieldMiddleware[];
481
482
/** Validation options for resolvers */
483
resolverValidationOptions?: ResolverValidationOptions;
484
485
/** Custom schema directives */
486
directives?: DirectiveNode[];
487
488
/** Schema-level extensions */
489
extensions?: Record<string, any>;
490
491
/** Number type handling */
492
numberScalarMode?: 'float' | 'integer';
493
494
/** Custom type name formatter */
495
typeNameFormatter?: (name: string) => string;
496
497
/** Schema transformation functions */
498
schemaTransformers?: SchemaTransformer[];
499
}
500
501
/**
502
* Schema transformer function type
503
*/
504
type SchemaTransformer = (schema: GraphQLSchema) => GraphQLSchema;
505
506
/**
507
* Scalar type mapping configuration
508
*/
509
interface ScalarsTypeMap {
510
/** TypeScript/JavaScript type constructor */
511
type: Function;
512
/** Corresponding GraphQL scalar type */
513
scalar: GraphQLScalarType;
514
}
515
516
/**
517
* Resolver validation configuration
518
*/
519
interface ResolverValidationOptions {
520
/** Whether to require resolvers for resolve type */
521
requireResolversForResolveType?: boolean;
522
/** Whether to require resolvers for args */
523
requireResolversForArgs?: boolean;
524
/** Whether to require resolvers for non-scalar fields */
525
requireResolversForNonScalar?: boolean;
526
/** Whether to require resolvers for all fields */
527
requireResolversForAllFields?: boolean;
528
/** Whether to allow resolve type on interfaces */
529
allowResolveTypeOnInterface?: boolean;
530
}
531
```
532
533
**Advanced Schema Building Example:**
534
535
```typescript
536
import { Module } from "@nestjs/common";
537
import { GraphQLModule } from "@nestjs/graphql";
538
import { ApolloDriver, ApolloDriverConfig } from "@nestjs/apollo";
539
import { GraphQLScalarType } from "graphql";
540
541
// Custom scalar
542
const DateTimeScalar = new GraphQLScalarType({
543
name: 'DateTime',
544
serialize: (value: Date) => value.toISOString(),
545
parseValue: (value: string) => new Date(value),
546
parseLiteral: (ast) => new Date(ast.value),
547
});
548
549
@Module({
550
imports: [
551
GraphQLModule.forRoot<ApolloDriverConfig>({
552
driver: ApolloDriver,
553
autoSchemaFile: true,
554
buildSchemaOptions: {
555
dateScalarMode: 'isoDate',
556
scalarsMap: [
557
{ type: Date, scalar: DateTimeScalar },
558
],
559
orphanedTypes: [UnreferencedType],
560
fieldMiddleware: [LoggingMiddleware],
561
resolverValidationOptions: {
562
requireResolversForNonScalar: false,
563
allowResolveTypeOnInterface: true,
564
},
565
schemaTransformers: [
566
(schema) => {
567
// Custom schema transformation
568
return addCustomDirectives(schema);
569
},
570
],
571
},
572
}),
573
],
574
})
575
export class AdvancedSchemaModule {}
576
```