@@ -131,31 +131,35 @@ export function buildASTSchema(
131
131
}
132
132
133
133
let schemaDef : ?SchemaDefinitionNode ;
134
- const nodeMap : ObjMap < TypeDefinitionNode > = Object . create ( null ) ;
134
+ const typeDefs : Array < TypeDefinitionNode > = [ ] ;
135
135
const directiveDefs : Array < DirectiveDefinitionNode > = [ ] ;
136
136
137
137
for ( const def of documentAST . definitions ) {
138
138
if ( def . kind === Kind . SCHEMA_DEFINITION ) {
139
139
schemaDef = def ;
140
140
} else if ( isTypeDefinitionNode ( def ) ) {
141
- nodeMap [ def . name . value ] = def ;
141
+ typeDefs . push ( def ) ;
142
142
} else if ( def . kind === Kind . DIRECTIVE_DEFINITION ) {
143
143
directiveDefs . push ( def ) ;
144
144
}
145
145
}
146
146
147
+ const astBuilder = new ASTDefinitionBuilder ( options , typeName => {
148
+ const type = typeMap [ typeName ] ;
149
+ invariant ( type , `Type "${ typeName } " not found in document.` ) ;
150
+ return type ;
151
+ } ) ;
152
+
153
+ const typeMap = keyByNameNode ( typeDefs , node => astBuilder . buildType ( node ) ) ;
154
+
147
155
const operationTypes = schemaDef
148
156
? getOperationTypes ( schemaDef )
149
157
: {
150
- query : nodeMap . Query ,
151
- mutation : nodeMap . Mutation ,
152
- subscription : nodeMap . Subscription ,
158
+ query : ' Query' ,
159
+ mutation : ' Mutation' ,
160
+ subscription : ' Subscription' ,
153
161
} ;
154
162
155
- const astBuilder = new ASTDefinitionBuilder ( nodeMap , options , typeName => {
156
- throw new Error ( `Type "${ typeName } " not found in document.` ) ;
157
- } ) ;
158
-
159
163
const directives = directiveDefs . map ( def => astBuilder . buildDirective ( def ) ) ;
160
164
161
165
// If specified directives were not explicitly declared, add them.
@@ -171,20 +175,19 @@ export function buildASTSchema(
171
175
directives . push ( GraphQLDeprecatedDirective ) ;
172
176
}
173
177
174
- // Note: While this could make early assertions to get the correctly
175
- // typed values below, that would throw immediately while type system
176
- // validation with validateSchema() will produce more actionable results.
177
178
return new GraphQLSchema ( {
178
- query : operationTypes . query
179
- ? ( astBuilder . buildType ( operationTypes . query ) : any )
180
- : null ,
179
+ // Note: While this could make early assertions to get the correctly
180
+ // typed values below, that would throw immediately while type system
181
+ // validation with validateSchema() will produce more actionable results.
182
+ query : operationTypes . query ? ( typeMap [ operationTypes . query ] : any ) : null ,
181
183
mutation : operationTypes . mutation
182
- ? ( astBuilder . buildType ( operationTypes . mutation ) : any )
184
+ ? ( typeMap [ operationTypes . mutation ] : any )
183
185
: null ,
184
186
subscription : operationTypes . subscription
185
- ? ( astBuilder . buildType ( operationTypes . subscription ) : any )
187
+ ? ( typeMap [ operationTypes . subscription ] : any )
186
188
: null ,
187
- types : objectValues ( nodeMap ) . map ( node => astBuilder . buildType ( node ) ) ,
189
+
190
+ types : objectValues ( typeMap ) ,
188
191
directives,
189
192
astNode : schemaDef ,
190
193
assumeValid : options && options . assumeValid ,
@@ -194,62 +197,44 @@ export function buildASTSchema(
194
197
function getOperationTypes ( schema : SchemaDefinitionNode ) {
195
198
const opTypes = { } ;
196
199
for ( const operationType of schema . operationTypes ) {
197
- opTypes [ operationType . operation ] = operationType . type ;
200
+ opTypes [ operationType . operation ] = operationType . type . name . value ;
198
201
}
199
202
return opTypes ;
200
203
}
201
204
}
202
205
203
- type TypeDefinitionsMap = ObjMap < TypeDefinitionNode > ;
204
206
type TypeResolver = ( typeName : string ) => GraphQLNamedType ;
205
207
208
+ const stdTypeMap = keyMap (
209
+ specifiedScalarTypes . concat ( introspectionTypes ) ,
210
+ type => type . name ,
211
+ ) ;
212
+
206
213
export class ASTDefinitionBuilder {
207
- _typeDefinitionsMap : TypeDefinitionsMap ;
208
214
_options : ?BuildSchemaOptions ;
209
215
_resolveType : TypeResolver ;
210
- _cache : ObjMap < GraphQLNamedType > ;
211
216
212
- constructor (
213
- typeDefinitionsMap : TypeDefinitionsMap ,
214
- options : ?BuildSchemaOptions ,
215
- resolveType : TypeResolver ,
216
- ) {
217
- this . _typeDefinitionsMap = typeDefinitionsMap ;
217
+ constructor ( options : ?BuildSchemaOptions , resolveType : TypeResolver ) {
218
218
this . _options = options ;
219
219
this . _resolveType = resolveType ;
220
- // Initialize to the GraphQL built in scalars and introspection types.
221
- this . _cache = keyMap (
222
- specifiedScalarTypes . concat ( introspectionTypes ) ,
223
- type => type . name ,
224
- ) ;
225
220
}
226
221
227
- buildType ( node : NamedTypeNode | TypeDefinitionNode ) : GraphQLNamedType {
228
- const typeName = node . name . value ;
229
- if ( ! this . _cache [ typeName ] ) {
230
- if ( node . kind === Kind . NAMED_TYPE ) {
231
- const defNode = this . _typeDefinitionsMap [ typeName ] ;
232
- this . _cache [ typeName ] = defNode
233
- ? this . _makeSchemaDef ( defNode )
234
- : this . _resolveType ( node . name . value ) ;
235
- } else {
236
- this . _cache [ typeName ] = this . _makeSchemaDef ( node ) ;
237
- }
238
- }
239
- return this . _cache [ typeName ] ;
222
+ getNamedType ( node : NamedTypeNode ) : GraphQLNamedType {
223
+ const name = node . name . value ;
224
+ return stdTypeMap [ name ] || this . _resolveType ( name ) ;
240
225
}
241
226
242
- _buildWrappedType ( typeNode : TypeNode ) : GraphQLType {
243
- if ( typeNode . kind === Kind . LIST_TYPE ) {
244
- return GraphQLList ( this . _buildWrappedType ( typeNode . type ) ) ;
227
+ getWrappedType ( node : TypeNode ) : GraphQLType {
228
+ if ( node . kind === Kind . LIST_TYPE ) {
229
+ return GraphQLList ( this . getWrappedType ( node . type ) ) ;
245
230
}
246
- if ( typeNode . kind === Kind . NON_NULL_TYPE ) {
231
+ if ( node . kind === Kind . NON_NULL_TYPE ) {
247
232
return GraphQLNonNull (
248
233
// Note: GraphQLNonNull constructor validates this type
249
- ( this . _buildWrappedType ( typeNode . type ) : any ) ,
234
+ ( this . getWrappedType ( node . type ) : any ) ,
250
235
) ;
251
236
}
252
- return this . buildType ( typeNode ) ;
237
+ return this . getNamedType ( node ) ;
253
238
}
254
239
255
240
buildDirective ( directive : DirectiveDefinitionNode ) : GraphQLDirective {
@@ -271,7 +256,7 @@ export class ASTDefinitionBuilder {
271
256
// Note: While this could make assertions to get the correctly typed
272
257
// value, that would throw immediately while type system validation
273
258
// with validateSchema() will produce more actionable results.
274
- type : ( this . _buildWrappedType ( field . type ) : any ) ,
259
+ type : ( this . getWrappedType ( field . type ) : any ) ,
275
260
description : getDescription ( field , this . _options ) ,
276
261
args : keyByNameNode ( field . arguments || [ ] , arg => this . buildArg ( arg ) ) ,
277
262
deprecationReason : getDeprecationReason ( field ) ,
@@ -283,7 +268,7 @@ export class ASTDefinitionBuilder {
283
268
// Note: While this could make assertions to get the correctly typed
284
269
// value, that would throw immediately while type system validation
285
270
// with validateSchema() will produce more actionable results.
286
- const type : any = this . _buildWrappedType ( value . type ) ;
271
+ const type : any = this . getWrappedType ( value . type ) ;
287
272
return {
288
273
type,
289
274
description : getDescription ( value , this . _options ) ,
@@ -296,7 +281,7 @@ export class ASTDefinitionBuilder {
296
281
// Note: While this could make assertions to get the correctly typed
297
282
// value, that would throw immediately while type system validation
298
283
// with validateSchema() will produce more actionable results.
299
- const type : any = this . _buildWrappedType ( value . type ) ;
284
+ const type : any = this . getWrappedType ( value . type ) ;
300
285
return {
301
286
type,
302
287
description : getDescription ( value , this . _options ) ,
@@ -313,7 +298,12 @@ export class ASTDefinitionBuilder {
313
298
} ;
314
299
}
315
300
316
- _makeSchemaDef ( astNode : TypeDefinitionNode ) : GraphQLNamedType {
301
+ buildType ( astNode : TypeDefinitionNode ) : GraphQLNamedType {
302
+ const name = astNode . name . value ;
303
+ if ( stdTypeMap [ name ] ) {
304
+ return stdTypeMap [ name ] ;
305
+ }
306
+
317
307
switch ( astNode . kind ) {
318
308
case Kind . OBJECT_TYPE_DEFINITION :
319
309
return this . _makeTypeDef ( astNode ) ;
@@ -327,9 +317,11 @@ export class ASTDefinitionBuilder {
327
317
return this . _makeScalarDef ( astNode ) ;
328
318
case Kind . INPUT_OBJECT_TYPE_DEFINITION :
329
319
return this . _makeInputObjectDef ( astNode ) ;
330
- default :
331
- throw new Error ( `Type kind "${ astNode . kind } " not supported.` ) ;
332
320
}
321
+
322
+ // Not reachable. All possible type definition nodes have been considered.
323
+ /* istanbul ignore next */
324
+ throw new Error ( `Type kind "${ ( astNode : empty ) . kind } " not supported.` ) ;
333
325
}
334
326
335
327
_makeTypeDef ( astNode : ObjectTypeDefinitionNode ) {
@@ -341,7 +333,7 @@ export class ASTDefinitionBuilder {
341
333
// validation with validateSchema() will produce more actionable results.
342
334
const interfaces =
343
335
interfaceNodes && interfaceNodes . length > 0
344
- ? ( ) => interfaceNodes . map ( ref => ( this . buildType ( ref ) : any ) )
336
+ ? ( ) => interfaceNodes . map ( ref => ( this . getNamedType ( ref ) : any ) )
345
337
: [ ] ;
346
338
347
339
const fields =
@@ -393,7 +385,7 @@ export class ASTDefinitionBuilder {
393
385
// validation with validateSchema() will produce more actionable results.
394
386
const types =
395
387
typeNodes && typeNodes . length > 0
396
- ? ( ) => typeNodes . map ( ref => ( this . buildType ( ref ) : any ) )
388
+ ? ( ) => typeNodes . map ( ref => ( this . getNamedType ( ref ) : any ) )
397
389
: [ ] ;
398
390
399
391
return new GraphQLUnionType ( {
0 commit comments