@@ -7,6 +7,7 @@ import type { Maybe } from '../jsutils/Maybe';
77
88import type {
99 DirectiveDefinitionNode ,
10+ DirectiveExtensionNode ,
1011 DocumentNode ,
1112 EnumTypeDefinitionNode ,
1213 EnumTypeExtensionNode ,
@@ -138,6 +139,7 @@ export function extendSchemaImpl(
138139 // Collect the type definitions and extensions found in the document.
139140 const typeDefs : Array < TypeDefinitionNode > = [ ] ;
140141 const typeExtensionsMap = Object . create ( null ) ;
142+ const directiveExtensionsMap = Object . create ( null ) ;
141143
142144 // New directives and types are separate because a directives and types can
143145 // have the same name. For example, a type named "skip".
@@ -162,6 +164,14 @@ export function extendSchemaImpl(
162164 : [ def ] ;
163165 } else if ( def . kind === Kind . DIRECTIVE_DEFINITION ) {
164166 directiveDefs . push ( def ) ;
167+ } else if ( def . kind === Kind . DIRECTIVE_EXTENSION ) {
168+ const extendedDirectiveName = def . name . value ;
169+ const existingDirectiveExtensions =
170+ directiveExtensionsMap [ extendedDirectiveName ] ;
171+ directiveExtensionsMap [ extendedDirectiveName ] =
172+ existingDirectiveExtensions
173+ ? existingDirectiveExtensions . concat ( [ def ] )
174+ : [ def ] ;
165175 }
166176 }
167177
@@ -170,6 +180,7 @@ export function extendSchemaImpl(
170180 if (
171181 Object . keys ( typeExtensionsMap ) . length === 0 &&
172182 typeDefs . length === 0 &&
183+ Object . keys ( directiveExtensionsMap ) . length === 0 &&
173184 directiveDefs . length === 0 &&
174185 schemaExtensions . length === 0 &&
175186 schemaDef == null
@@ -187,6 +198,11 @@ export function extendSchemaImpl(
187198 typeMap [ name ] = stdTypeMap [ name ] ?? buildType ( typeNode ) ;
188199 }
189200
201+ const directiveMap = Object . create ( null ) ;
202+ for ( const existingDirective of schemaConfig . directives ) {
203+ directiveMap [ existingDirective . name ] = extendDirective ( existingDirective ) ;
204+ }
205+
190206 const operationTypes = {
191207 // Get the extended root operation types.
192208 query : schemaConfig . query && replaceNamedType ( schemaConfig . query ) ,
@@ -199,12 +215,13 @@ export function extendSchemaImpl(
199215 } ;
200216
201217 // Then produce and return a Schema config with these types.
218+ const directives : Array < GraphQLDirective > = Object . values ( directiveMap ) ;
202219 return {
203220 description : schemaDef ?. description ?. value ,
204221 ...operationTypes ,
205222 types : Object . values ( typeMap ) ,
206223 directives : [
207- ...schemaConfig . directives . map ( replaceDirective ) ,
224+ ...directives . map ( replaceDirective ) ,
208225 ...directiveDefs . map ( buildDirective ) ,
209226 ] ,
210227 extensions : Object . create ( null ) ,
@@ -415,6 +432,20 @@ export function extendSchemaImpl(
415432 return opTypes ;
416433 }
417434
435+ function extendDirective ( directive : GraphQLDirective ) : GraphQLDirective {
436+ const config = directive . toConfig ( ) ;
437+ const extensions = directiveExtensionsMap [ config . name ] ?? [ ] ;
438+ const deprecatedReason = extensions
439+ . map ( ( ext : DirectiveExtensionNode ) => getDeprecationReason ( ext ) )
440+ . find ( ( reason : Maybe < string > ) => reason != null ) ;
441+
442+ return new GraphQLDirective ( {
443+ ...config ,
444+ deprecationReason : deprecatedReason ,
445+ extensionASTNodes : config . extensionASTNodes . concat ( extensions ) ,
446+ } ) ;
447+ }
448+
418449 function getNamedType ( node : NamedTypeNode ) : GraphQLNamedType {
419450 const name = node . name . value ;
420451 const type = stdTypeMap [ name ] ?? typeMap [ name ] ;
@@ -443,6 +474,7 @@ export function extendSchemaImpl(
443474 locations : node . locations . map ( ( { value } ) => value ) ,
444475 isRepeatable : node . repeatable ,
445476 args : buildArgumentMap ( node . arguments ) ,
477+ deprecationReason : getDeprecationReason ( node ) ,
446478 astNode : node ,
447479 } ) ;
448480 }
@@ -667,7 +699,9 @@ function getDeprecationReason(
667699 node :
668700 | EnumValueDefinitionNode
669701 | FieldDefinitionNode
670- | InputValueDefinitionNode ,
702+ | InputValueDefinitionNode
703+ | DirectiveDefinitionNode
704+ | DirectiveExtensionNode ,
671705) : Maybe < string > {
672706 const deprecated = getDirectiveValues ( GraphQLDeprecatedDirective , node ) ;
673707 // @ts -expect-error validated by `getDirectiveValues`
0 commit comments