Directives on Directive Definitions
GraphQL.js v17 includes support for directives applied to directive definitions, directive extensions, and directive deprecation metadata.
GraphQL directives can now be applied to directive definitions. This is the SDL shape introduced by the directives-on-directives proposal:
directive @tag(name: String!) on DIRECTIVE_DEFINITION
directive @cacheControl(maxAge: Int) @tag(name: "runtime") on FIELD_DEFINITIONThe new directive location is DIRECTIVE_DEFINITION.
import { DirectiveLocation } from 'graphql';
DirectiveLocation.DIRECTIVE_DEFINITION;Parser surface
Directive definition directives are represented on the AST:
DirectiveDefinitionNode.directivesDirectiveExtensionNode.directivesKind.DIRECTIVE_EXTENSION
Parsing this syntax is controlled by
experimentalDirectivesOnDirectiveDefinitions.
import { parse } from 'graphql';
const document = parse(source, {
experimentalDirectivesOnDirectiveDefinitions: true,
});Directive extensions use the same option:
extend directive @cacheControl @tag(name: "performance")Runtime schema surface
GraphQL.js does not add a generic GraphQLDirective.directives property. The
applied directives remain available through the AST nodes:
GraphQLDirective.astNode?.directivesGraphQLDirective.extensionASTNodes
GraphQL.js does derive directive deprecation metadata from those AST nodes.
GraphQLDirective now includes:
deprecationReasonextensionASTNodes
const directive = schema.getDirective('cacheControl');
directive.deprecationReason;
directive.astNode?.directives;
directive.extensionASTNodes;Deprecating custom directives
@deprecated can now be used on directive definitions. The built-in
GraphQLDeprecatedDirective includes DIRECTIVE_DEFINITION in its locations.
directive @oldAuth @deprecated(reason: "Use @auth instead") on FIELD_DEFINITIONThe introspection type __Directive includes:
isDeprecateddeprecationReason
__Schema.directives accepts includeDeprecated: Boolean! = false when
directive deprecation support is present.
query DeprecatedDirectives {
__schema {
directives(includeDeprecated: true) {
name
isDeprecated
deprecationReason
}
}
}Directive extensions
Directive extensions can attach deprecation metadata to a directive defined in another document:
directive @oldAuth on FIELD_DEFINITION
extend directive @oldAuth @deprecated(reason: "Use @auth instead")When a schema is extended, GraphQL.js preserves directive extension AST nodes on
GraphQLDirective.extensionASTNodes and uses them when computing
deprecationReason.
Validation
KnownDirectivesRule understands DIRECTIVE_DEFINITION, so a directive applied
to a directive definition must itself be declared for that location.
UniqueDirectivesPerLocationRule also treats a directive definition and its
extensions as one directive location for non-repeatable directive uniqueness.