DocumentationDirectives on Directives

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_DEFINITION

The new directive location is DIRECTIVE_DEFINITION.

import { DirectiveLocation } from 'graphql';
 
DirectiveLocation.DIRECTIVE_DEFINITION;

Parser surface

Directive definition directives are represented on the AST:

  • DirectiveDefinitionNode.directives
  • DirectiveExtensionNode.directives
  • Kind.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?.directives
  • GraphQLDirective.extensionASTNodes

GraphQL.js does derive directive deprecation metadata from those AST nodes. GraphQLDirective now includes:

  • deprecationReason
  • extensionASTNodes
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_DEFINITION

The introspection type __Directive includes:

  • isDeprecated
  • deprecationReason

__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.