diff --git a/.changeset/stupid-geckos-lay.md b/.changeset/stupid-geckos-lay.md new file mode 100644 index 00000000000..c955bd92c20 --- /dev/null +++ b/.changeset/stupid-geckos-lay.md @@ -0,0 +1,5 @@ +--- +'@graphql-tools/utils': patch +--- + +Respect `extensionASTNodes` in directable GraphQLSchema object diff --git a/packages/utils/src/getDirectiveExtensions.ts b/packages/utils/src/getDirectiveExtensions.ts index 69accc6e3c1..b63be51abf9 100644 --- a/packages/utils/src/getDirectiveExtensions.ts +++ b/packages/utils/src/getDirectiveExtensions.ts @@ -5,6 +5,7 @@ import { getArgumentValues } from './getArgumentValues.js'; export type DirectableASTNode = ASTNode & { directives?: readonly DirectiveNode[] }; export type DirectableObject = { astNode?: DirectableASTNode | null; + extensionASTNodes?: readonly DirectableASTNode[] | null; extensions?: { directives?: Record } | null; }; @@ -24,36 +25,46 @@ export function getDirectiveExtensions< TDirectiveAnnotationsMap[directiveName] >; } = {}; - if (directableObj.astNode?.directives?.length) { - for (const directive of directableObj.astNode.directives) { - const directiveName: keyof TDirectiveAnnotationsMap = directive.name.value; - let existingDirectiveExtensions = directiveExtensions[directiveName]; - if (!existingDirectiveExtensions) { - existingDirectiveExtensions = []; - directiveExtensions[directiveName] = existingDirectiveExtensions; - } - const directiveInSchema = schema?.getDirective(directiveName); - let value: any = {}; - if (directiveInSchema) { - value = getArgumentValues(directiveInSchema, directive); - } - if (directive.arguments) { - for (const argNode of directive.arguments) { - const argName = argNode.name.value; - if (value[argName] == null) { - const argInDirective = directiveInSchema?.args.find(arg => arg.name === argName); - if (argInDirective) { - value[argName] = valueFromAST(argNode.value, argInDirective.type); + const astNodes: DirectableASTNode[] = []; + if (directableObj.astNode) { + astNodes.push(directableObj.astNode); + } + if (directableObj.extensionASTNodes) { + astNodes.push(...directableObj.extensionASTNodes); + } + for (const astNode of astNodes) { + if (astNode.directives?.length) { + for (const directive of astNode.directives) { + const directiveName: keyof TDirectiveAnnotationsMap = directive.name.value; + let existingDirectiveExtensions = directiveExtensions[directiveName]; + if (!existingDirectiveExtensions) { + existingDirectiveExtensions = []; + directiveExtensions[directiveName] = existingDirectiveExtensions; + } + const directiveInSchema = schema?.getDirective(directiveName); + let value: any = {}; + if (directiveInSchema) { + value = getArgumentValues(directiveInSchema, directive); + } + if (directive.arguments) { + for (const argNode of directive.arguments) { + const argName = argNode.name.value; + if (value[argName] == null) { + const argInDirective = directiveInSchema?.args.find(arg => arg.name === argName); + if (argInDirective) { + value[argName] = valueFromAST(argNode.value, argInDirective.type); + } + } + if (value[argName] == null) { + value[argName] = valueFromASTUntyped(argNode.value); } - } - if (value[argName] == null) { - value[argName] = valueFromASTUntyped(argNode.value); } } + existingDirectiveExtensions.push(value); } - existingDirectiveExtensions.push(value); } } + if (directableObj.extensions) { let directivesInExtensions = directableObj.extensions; for (const pathSegment of pathToDirectivesInExtensions) { diff --git a/packages/utils/tests/get-directives.spec.ts b/packages/utils/tests/get-directives.spec.ts index 2ec0ac0d47c..02c250dad91 100644 --- a/packages/utils/tests/get-directives.spec.ts +++ b/packages/utils/tests/get-directives.spec.ts @@ -1,4 +1,4 @@ -import { GraphQLSchema } from 'graphql'; +import { GraphQLObjectType, GraphQLSchema, GraphQLString, Kind } from 'graphql'; import { makeExecutableSchema } from '@graphql-tools/schema'; import { assertGraphQLObjectType } from '../../testing/assertion.js'; import { getDirectives } from '../src/index.js'; @@ -133,4 +133,38 @@ describe('getDirectives', () => { }, ]); }); + it('gets the directives from extensionASTNodes', () => { + const schema = new GraphQLSchema({ + query: new GraphQLObjectType({ + name: 'Query', + fields: { + first: { + type: GraphQLString, + }, + }, + }), + extensionASTNodes: [ + { + kind: Kind.SCHEMA_EXTENSION, + directives: [ + { + kind: 'Directive', + name: { + kind: 'Name', + value: 'mydir', + }, + arguments: [], + }, + ], + }, + ], + }); + const directives = getDirectives(schema, schema); + expect(directives).toEqual([ + { + name: 'mydir', + args: {}, + }, + ]); + }); });