1+ import { AccumulatorMap } from '../jsutils/AccumulatorMap' ;
12import { inspect } from '../jsutils/inspect' ;
23import { invariant } from '../jsutils/invariant' ;
34import { keyMap } from '../jsutils/keyMap' ;
@@ -29,10 +30,6 @@ import type {
2930 UnionTypeExtensionNode ,
3031} from '../language/ast' ;
3132import { Kind } from '../language/kinds' ;
32- import {
33- isTypeDefinitionNode ,
34- isTypeExtensionNode ,
35- } from '../language/predicates' ;
3633
3734import type {
3835 GraphQLArgumentConfig ,
@@ -132,7 +129,25 @@ export function extendSchemaImpl(
132129) : GraphQLSchemaNormalizedConfig {
133130 // Collect the type definitions and extensions found in the document.
134131 const typeDefs : Array < TypeDefinitionNode > = [ ] ;
135- const typeExtensionsMap = Object . create ( null ) ;
132+
133+ const scalarExtensions = new AccumulatorMap <
134+ string ,
135+ ScalarTypeExtensionNode
136+ > ( ) ;
137+ const objectExtensions = new AccumulatorMap <
138+ string ,
139+ ObjectTypeExtensionNode
140+ > ( ) ;
141+ const interfaceExtensions = new AccumulatorMap <
142+ string ,
143+ InterfaceTypeExtensionNode
144+ > ( ) ;
145+ const unionExtensions = new AccumulatorMap < string , UnionTypeExtensionNode > ( ) ;
146+ const enumExtensions = new AccumulatorMap < string , EnumTypeExtensionNode > ( ) ;
147+ const inputObjectExtensions = new AccumulatorMap <
148+ string ,
149+ InputObjectTypeExtensionNode
150+ > ( ) ;
136151
137152 // New directives and types are separate because a directives and types can
138153 // have the same name. For example, a type named "skip".
@@ -142,33 +157,57 @@ export function extendSchemaImpl(
142157 // Schema extensions are collected which may add additional operation types.
143158 const schemaExtensions : Array < SchemaExtensionNode > = [ ] ;
144159
160+ let isSchemaChanged = false ;
145161 for ( const def of documentAST . definitions ) {
146- if ( def . kind === Kind . SCHEMA_DEFINITION ) {
147- schemaDef = def ;
148- } else if ( def . kind === Kind . SCHEMA_EXTENSION ) {
149- schemaExtensions . push ( def ) ;
150- } else if ( isTypeDefinitionNode ( def ) ) {
151- typeDefs . push ( def ) ;
152- } else if ( isTypeExtensionNode ( def ) ) {
153- const extendedTypeName = def . name . value ;
154- const existingTypeExtensions = typeExtensionsMap [ extendedTypeName ] ;
155- typeExtensionsMap [ extendedTypeName ] = existingTypeExtensions
156- ? existingTypeExtensions . concat ( [ def ] )
157- : [ def ] ;
158- } else if ( def . kind === Kind . DIRECTIVE_DEFINITION ) {
159- directiveDefs . push ( def ) ;
162+ switch ( def . kind ) {
163+ case Kind . SCHEMA_DEFINITION :
164+ schemaDef = def ;
165+ break ;
166+ case Kind . SCHEMA_EXTENSION :
167+ schemaExtensions . push ( def ) ;
168+ break ;
169+ case Kind . DIRECTIVE_DEFINITION :
170+ directiveDefs . push ( def ) ;
171+ break ;
172+
173+ // Type Definitions
174+ case Kind . SCALAR_TYPE_DEFINITION :
175+ case Kind . OBJECT_TYPE_DEFINITION :
176+ case Kind . INTERFACE_TYPE_DEFINITION :
177+ case Kind . UNION_TYPE_DEFINITION :
178+ case Kind . ENUM_TYPE_DEFINITION :
179+ case Kind . INPUT_OBJECT_TYPE_DEFINITION :
180+ typeDefs . push ( def ) ;
181+ break ;
182+
183+ // Type System Extensions
184+ case Kind . SCALAR_TYPE_EXTENSION :
185+ scalarExtensions . add ( def . name . value , def ) ;
186+ break ;
187+ case Kind . OBJECT_TYPE_EXTENSION :
188+ objectExtensions . add ( def . name . value , def ) ;
189+ break ;
190+ case Kind . INTERFACE_TYPE_EXTENSION :
191+ interfaceExtensions . add ( def . name . value , def ) ;
192+ break ;
193+ case Kind . UNION_TYPE_EXTENSION :
194+ unionExtensions . add ( def . name . value , def ) ;
195+ break ;
196+ case Kind . ENUM_TYPE_EXTENSION :
197+ enumExtensions . add ( def . name . value , def ) ;
198+ break ;
199+ case Kind . INPUT_OBJECT_TYPE_EXTENSION :
200+ inputObjectExtensions . add ( def . name . value , def ) ;
201+ break ;
202+ default :
203+ continue ;
160204 }
205+ isSchemaChanged = true ;
161206 }
162207
163208 // If this document contains no new types, extensions, or directives then
164209 // return the same unmodified GraphQLSchema instance.
165- if (
166- Object . keys ( typeExtensionsMap ) . length === 0 &&
167- typeDefs . length === 0 &&
168- directiveDefs . length === 0 &&
169- schemaExtensions . length === 0 &&
170- schemaDef == null
171- ) {
210+ if ( ! isSchemaChanged ) {
172211 return schemaConfig ;
173212 }
174213
@@ -275,7 +314,7 @@ export function extendSchemaImpl(
275314 type : GraphQLInputObjectType ,
276315 ) : GraphQLInputObjectType {
277316 const config = type . toConfig ( ) ;
278- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
317+ const extensions = inputObjectExtensions . get ( config . name ) ?? [ ] ;
279318
280319 return new GraphQLInputObjectType ( {
281320 ...config ,
@@ -292,7 +331,7 @@ export function extendSchemaImpl(
292331
293332 function extendEnumType ( type : GraphQLEnumType ) : GraphQLEnumType {
294333 const config = type . toConfig ( ) ;
295- const extensions = typeExtensionsMap [ type . name ] ?? [ ] ;
334+ const extensions = enumExtensions . get ( type . name ) ?? [ ] ;
296335
297336 return new GraphQLEnumType ( {
298337 ...config ,
@@ -306,7 +345,7 @@ export function extendSchemaImpl(
306345
307346 function extendScalarType ( type : GraphQLScalarType ) : GraphQLScalarType {
308347 const config = type . toConfig ( ) ;
309- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
348+ const extensions = scalarExtensions . get ( config . name ) ?? [ ] ;
310349
311350 let specifiedByURL = config . specifiedByURL ;
312351 for ( const extensionNode of extensions ) {
@@ -322,7 +361,7 @@ export function extendSchemaImpl(
322361
323362 function extendObjectType ( type : GraphQLObjectType ) : GraphQLObjectType {
324363 const config = type . toConfig ( ) ;
325- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
364+ const extensions = objectExtensions . get ( config . name ) ?? [ ] ;
326365
327366 return new GraphQLObjectType ( {
328367 ...config ,
@@ -342,7 +381,7 @@ export function extendSchemaImpl(
342381 type : GraphQLInterfaceType ,
343382 ) : GraphQLInterfaceType {
344383 const config = type . toConfig ( ) ;
345- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
384+ const extensions = interfaceExtensions . get ( config . name ) ?? [ ] ;
346385
347386 return new GraphQLInterfaceType ( {
348387 ...config ,
@@ -360,7 +399,7 @@ export function extendSchemaImpl(
360399
361400 function extendUnionType ( type : GraphQLUnionType ) : GraphQLUnionType {
362401 const config = type . toConfig ( ) ;
363- const extensions = typeExtensionsMap [ config . name ] ?? [ ] ;
402+ const extensions = unionExtensions . get ( config . name ) ?? [ ] ;
364403
365404 return new GraphQLUnionType ( {
366405 ...config ,
@@ -579,10 +618,10 @@ export function extendSchemaImpl(
579618
580619 function buildType ( astNode : TypeDefinitionNode ) : GraphQLNamedType {
581620 const name = astNode . name . value ;
582- const extensionASTNodes = typeExtensionsMap [ name ] ?? [ ] ;
583621
584622 switch ( astNode . kind ) {
585623 case Kind . OBJECT_TYPE_DEFINITION : {
624+ const extensionASTNodes = objectExtensions . get ( name ) ?? [ ] ;
586625 const allNodes = [ astNode , ...extensionASTNodes ] ;
587626
588627 return new GraphQLObjectType ( {
@@ -595,6 +634,7 @@ export function extendSchemaImpl(
595634 } ) ;
596635 }
597636 case Kind . INTERFACE_TYPE_DEFINITION : {
637+ const extensionASTNodes = interfaceExtensions . get ( name ) ?? [ ] ;
598638 const allNodes = [ astNode , ...extensionASTNodes ] ;
599639
600640 return new GraphQLInterfaceType ( {
@@ -607,6 +647,7 @@ export function extendSchemaImpl(
607647 } ) ;
608648 }
609649 case Kind . ENUM_TYPE_DEFINITION : {
650+ const extensionASTNodes = enumExtensions . get ( name ) ?? [ ] ;
610651 const allNodes = [ astNode , ...extensionASTNodes ] ;
611652
612653 return new GraphQLEnumType ( {
@@ -618,6 +659,7 @@ export function extendSchemaImpl(
618659 } ) ;
619660 }
620661 case Kind . UNION_TYPE_DEFINITION : {
662+ const extensionASTNodes = unionExtensions . get ( name ) ?? [ ] ;
621663 const allNodes = [ astNode , ...extensionASTNodes ] ;
622664
623665 return new GraphQLUnionType ( {
@@ -629,6 +671,7 @@ export function extendSchemaImpl(
629671 } ) ;
630672 }
631673 case Kind . SCALAR_TYPE_DEFINITION : {
674+ const extensionASTNodes = scalarExtensions . get ( name ) ?? [ ] ;
632675 return new GraphQLScalarType ( {
633676 name,
634677 description : astNode . description ?. value ,
@@ -638,6 +681,7 @@ export function extendSchemaImpl(
638681 } ) ;
639682 }
640683 case Kind . INPUT_OBJECT_TYPE_DEFINITION : {
684+ const extensionASTNodes = inputObjectExtensions . get ( name ) ?? [ ] ;
641685 const allNodes = [ astNode , ...extensionASTNodes ] ;
642686
643687 return new GraphQLInputObjectType ( {
0 commit comments