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 ,
@@ -131,7 +128,25 @@ export function extendSchemaImpl(
131128) : GraphQLSchemaNormalizedConfig {
132129 // Collect the type definitions and extensions found in the document.
133130 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+ > ( ) ;
135150
136151 // New directives and types are separate because a directives and types can
137152 // have the same name. For example, a type named "skip".
@@ -141,33 +156,57 @@ export function extendSchemaImpl(
141156 // Schema extensions are collected which may add additional operation types.
142157 const schemaExtensions : Array < SchemaExtensionNode > = [ ] ;
143158
159+ let isSchemaChanged = false ;
144160 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 ;
159203 }
204+ isSchemaChanged = true ;
160205 }
161206
162207 // If this document contains no new types, extensions, or directives then
163208 // 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 ) {
171210 return schemaConfig ;
172211 }
173212
@@ -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