1
+ import { AccumulatorMap } from '../jsutils/AccumulatorMap' ;
1
2
import { inspect } from '../jsutils/inspect' ;
2
3
import { invariant } from '../jsutils/invariant' ;
3
4
import { keyMap } from '../jsutils/keyMap' ;
@@ -29,10 +30,6 @@ import type {
29
30
UnionTypeExtensionNode ,
30
31
} from '../language/ast' ;
31
32
import { Kind } from '../language/kinds' ;
32
- import {
33
- isTypeDefinitionNode ,
34
- isTypeExtensionNode ,
35
- } from '../language/predicates' ;
36
33
37
34
import type {
38
35
GraphQLArgumentConfig ,
@@ -131,7 +128,25 @@ export function extendSchemaImpl(
131
128
) : GraphQLSchemaNormalizedConfig {
132
129
// Collect the type definitions and extensions found in the document.
133
130
const typeDefs : Array < TypeDefinitionNode > = [ ] ;
134
- const typeExtensionsMap = Object . create ( null ) ;
131
+
132
+ const scalarExtensions = new AccumulatorMap <
133
+ string ,
134
+ ScalarTypeExtensionNode
135
+ > ( ) ;
136
+ const objectExtensions = new AccumulatorMap <
137
+ string ,
138
+ ObjectTypeExtensionNode
139
+ > ( ) ;
140
+ const interfaceExtensions = new AccumulatorMap <
141
+ string ,
142
+ InterfaceTypeExtensionNode
143
+ > ( ) ;
144
+ const unionExtensions = new AccumulatorMap < string , UnionTypeExtensionNode > ( ) ;
145
+ const enumExtensions = new AccumulatorMap < string , EnumTypeExtensionNode > ( ) ;
146
+ const inputObjectExtensions = new AccumulatorMap <
147
+ string ,
148
+ InputObjectTypeExtensionNode
149
+ > ( ) ;
135
150
136
151
// New directives and types are separate because a directives and types can
137
152
// have the same name. For example, a type named "skip".
@@ -141,33 +156,57 @@ export function extendSchemaImpl(
141
156
// Schema extensions are collected which may add additional operation types.
142
157
const schemaExtensions : Array < SchemaExtensionNode > = [ ] ;
143
158
159
+ let isSchemaChanged = false ;
144
160
for ( const def of documentAST . definitions ) {
145
- if ( def . kind === Kind . SCHEMA_DEFINITION ) {
146
- schemaDef = def ;
147
- } else if ( def . kind === Kind . SCHEMA_EXTENSION ) {
148
- schemaExtensions . push ( def ) ;
149
- } else if ( isTypeDefinitionNode ( def ) ) {
150
- typeDefs . push ( def ) ;
151
- } else if ( isTypeExtensionNode ( def ) ) {
152
- const extendedTypeName = def . name . value ;
153
- const existingTypeExtensions = typeExtensionsMap [ extendedTypeName ] ;
154
- typeExtensionsMap [ extendedTypeName ] = existingTypeExtensions
155
- ? existingTypeExtensions . concat ( [ def ] )
156
- : [ def ] ;
157
- } else if ( def . kind === Kind . DIRECTIVE_DEFINITION ) {
158
- directiveDefs . push ( def ) ;
161
+ switch ( def . kind ) {
162
+ case Kind . SCHEMA_DEFINITION :
163
+ schemaDef = def ;
164
+ break ;
165
+ case Kind . SCHEMA_EXTENSION :
166
+ schemaExtensions . push ( def ) ;
167
+ break ;
168
+ case Kind . DIRECTIVE_DEFINITION :
169
+ directiveDefs . push ( def ) ;
170
+ break ;
171
+
172
+ // Type Definitions
173
+ case Kind . SCALAR_TYPE_DEFINITION :
174
+ case Kind . OBJECT_TYPE_DEFINITION :
175
+ case Kind . INTERFACE_TYPE_DEFINITION :
176
+ case Kind . UNION_TYPE_DEFINITION :
177
+ case Kind . ENUM_TYPE_DEFINITION :
178
+ case Kind . INPUT_OBJECT_TYPE_DEFINITION :
179
+ typeDefs . push ( def ) ;
180
+ break ;
181
+
182
+ // Type System Extensions
183
+ case Kind . SCALAR_TYPE_EXTENSION :
184
+ scalarExtensions . add ( def . name . value , def ) ;
185
+ break ;
186
+ case Kind . OBJECT_TYPE_EXTENSION :
187
+ objectExtensions . add ( def . name . value , def ) ;
188
+ break ;
189
+ case Kind . INTERFACE_TYPE_EXTENSION :
190
+ interfaceExtensions . add ( def . name . value , def ) ;
191
+ break ;
192
+ case Kind . UNION_TYPE_EXTENSION :
193
+ unionExtensions . add ( def . name . value , def ) ;
194
+ break ;
195
+ case Kind . ENUM_TYPE_EXTENSION :
196
+ enumExtensions . add ( def . name . value , def ) ;
197
+ break ;
198
+ case Kind . INPUT_OBJECT_TYPE_EXTENSION :
199
+ inputObjectExtensions . add ( def . name . value , def ) ;
200
+ break ;
201
+ default :
202
+ continue ;
159
203
}
204
+ isSchemaChanged = true ;
160
205
}
161
206
162
207
// If this document contains no new types, extensions, or directives then
163
208
// return the same unmodified GraphQLSchema instance.
164
- if (
165
- Object . keys ( typeExtensionsMap ) . length === 0 &&
166
- typeDefs . length === 0 &&
167
- directiveDefs . length === 0 &&
168
- schemaExtensions . length === 0 &&
169
- schemaDef == null
170
- ) {
209
+ if ( ! isSchemaChanged ) {
171
210
return schemaConfig ;
172
211
}
173
212
@@ -275,7 +314,7 @@ export function extendSchemaImpl(
275
314
type : GraphQLInputObjectType ,
276
315
) : GraphQLInputObjectType {
277
316
const config = type . toConfig ( ) ;
278
- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
317
+ const extensions = inputObjectExtensions . get ( config . name ) ?? [ ] ;
279
318
280
319
return new GraphQLInputObjectType ( {
281
320
...config ,
@@ -292,7 +331,7 @@ export function extendSchemaImpl(
292
331
293
332
function extendEnumType ( type : GraphQLEnumType ) : GraphQLEnumType {
294
333
const config = type . toConfig ( ) ;
295
- const extensions = typeExtensionsMap [ type . name ] ?? [ ] ;
334
+ const extensions = enumExtensions . get ( type . name ) ?? [ ] ;
296
335
297
336
return new GraphQLEnumType ( {
298
337
...config ,
@@ -306,7 +345,7 @@ export function extendSchemaImpl(
306
345
307
346
function extendScalarType ( type : GraphQLScalarType ) : GraphQLScalarType {
308
347
const config = type . toConfig ( ) ;
309
- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
348
+ const extensions = scalarExtensions . get ( config . name ) ?? [ ] ;
310
349
311
350
let specifiedByURL = config . specifiedByURL ;
312
351
for ( const extensionNode of extensions ) {
@@ -322,7 +361,7 @@ export function extendSchemaImpl(
322
361
323
362
function extendObjectType ( type : GraphQLObjectType ) : GraphQLObjectType {
324
363
const config = type . toConfig ( ) ;
325
- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
364
+ const extensions = objectExtensions . get ( config . name ) ?? [ ] ;
326
365
327
366
return new GraphQLObjectType ( {
328
367
...config ,
@@ -342,7 +381,7 @@ export function extendSchemaImpl(
342
381
type : GraphQLInterfaceType ,
343
382
) : GraphQLInterfaceType {
344
383
const config = type . toConfig ( ) ;
345
- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
384
+ const extensions = interfaceExtensions . get ( config . name ) ?? [ ] ;
346
385
347
386
return new GraphQLInterfaceType ( {
348
387
...config ,
@@ -360,7 +399,7 @@ export function extendSchemaImpl(
360
399
361
400
function extendUnionType ( type : GraphQLUnionType ) : GraphQLUnionType {
362
401
const config = type . toConfig ( ) ;
363
- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
402
+ const extensions = unionExtensions . get ( config . name ) ?? [ ] ;
364
403
365
404
return new GraphQLUnionType ( {
366
405
...config ,
@@ -579,10 +618,10 @@ export function extendSchemaImpl(
579
618
580
619
function buildType ( astNode : TypeDefinitionNode ) : GraphQLNamedType {
581
620
const name = astNode . name . value ;
582
- const extensionASTNodes = typeExtensionsMap [ name ] ?? [ ] ;
583
621
584
622
switch ( astNode . kind ) {
585
623
case Kind . OBJECT_TYPE_DEFINITION : {
624
+ const extensionASTNodes = objectExtensions . get ( name ) ?? [ ] ;
586
625
const allNodes = [ astNode , ...extensionASTNodes ] ;
587
626
588
627
return new GraphQLObjectType ( {
@@ -595,6 +634,7 @@ export function extendSchemaImpl(
595
634
} ) ;
596
635
}
597
636
case Kind . INTERFACE_TYPE_DEFINITION : {
637
+ const extensionASTNodes = interfaceExtensions . get ( name ) ?? [ ] ;
598
638
const allNodes = [ astNode , ...extensionASTNodes ] ;
599
639
600
640
return new GraphQLInterfaceType ( {
@@ -607,6 +647,7 @@ export function extendSchemaImpl(
607
647
} ) ;
608
648
}
609
649
case Kind . ENUM_TYPE_DEFINITION : {
650
+ const extensionASTNodes = enumExtensions . get ( name ) ?? [ ] ;
610
651
const allNodes = [ astNode , ...extensionASTNodes ] ;
611
652
612
653
return new GraphQLEnumType ( {
@@ -618,6 +659,7 @@ export function extendSchemaImpl(
618
659
} ) ;
619
660
}
620
661
case Kind . UNION_TYPE_DEFINITION : {
662
+ const extensionASTNodes = unionExtensions . get ( name ) ?? [ ] ;
621
663
const allNodes = [ astNode , ...extensionASTNodes ] ;
622
664
623
665
return new GraphQLUnionType ( {
@@ -629,6 +671,7 @@ export function extendSchemaImpl(
629
671
} ) ;
630
672
}
631
673
case Kind . SCALAR_TYPE_DEFINITION : {
674
+ const extensionASTNodes = scalarExtensions . get ( name ) ?? [ ] ;
632
675
return new GraphQLScalarType ( {
633
676
name,
634
677
description : astNode . description ?. value ,
@@ -638,6 +681,7 @@ export function extendSchemaImpl(
638
681
} ) ;
639
682
}
640
683
case Kind . INPUT_OBJECT_TYPE_DEFINITION : {
684
+ const extensionASTNodes = inputObjectExtensions . get ( name ) ?? [ ] ;
641
685
const allNodes = [ astNode , ...extensionASTNodes ] ;
642
686
643
687
return new GraphQLInputObjectType ( {
0 commit comments