docs/source/schema/directives.md
Looking for Apollo Federation directives? See Federation-specific GraphQL directives.
A directive decorates part of a GraphQL schema or operation with additional configuration. Tools like Apollo Server (and Apollo Client) can read a GraphQL document's directives and perform custom logic as appropriate.
Directives are preceded by the @ character, like so:
type ExampleType {
oldField: String @deprecated(reason: "Use `newField`.")
newField: String
}
This example shows the @deprecated directive, which is a default directive (i.e., it's part of the GraphQL specification). It demonstrates the following about directives:
reason in this case).oldField field in this case)Each directive can only appear in certain locations within a GraphQL schema or operation. These locations are listed in the directive's definition.
For example, here's the GraphQL spec's definition of the @deprecated directive:
directive @deprecated(
reason: String = "No longer supported"
) on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE
This indicates that @deprecated can decorate any of the four listed locations. Also note that its reason argument is optional and provides a default value. Usage examples of each location are provided below:
# ARGUMENT_DEFINITION
# Note: @deprecated arguments _must_ be optional.
directive @withDeprecatedArgs(
deprecatedArg: String @deprecated(reason: "Use `newArg`")
newArg: String
) on FIELD
type MyType {
# ARGUMENT_DEFINITION (alternate example on a field's args)
fieldWithDeprecatedArgs(name: String @deprecated): String
# FIELD_DEFINITION
deprecatedField: String @deprecated
}
enum MyEnum {
# ENUM_VALUE
OLD_VALUE @deprecated(reason: "Use `NEW_VALUE`.")
NEW_VALUE
}
input SomeInputType {
nonDeprecated: String
# INPUT_FIELD_DEFINITION
deprecated: String @deprecated
}
If @deprecated appears elsewhere in a GraphQL document, it produces an error.
If you create a custom directive, you need to define it (and its valid locations) in your schema. You don't need to define default directives like
@deprecated.
Usually, a given directive appears exclusively in GraphQL type system documents (schemas) or exclusively in GraphQL executable documents (operations and fragments). They rarely appear in both, although the spec allows this.
For example, among the default directives, @deprecated is a type-system directive and @skip and @include are executable directives.
The GraphQL spec lists all possible directive locations. Type-system locations are listed under TypeSystemDirectiveLocation, and executable locations are listed under ExecutableDirectiveLocation.
(The term "operation directive" is ambiguous, and so discouraged in favor of "executable directive". Similarly "type-system directive" is preferred over "schema directive".)
The GraphQL specification defines the following default directives:
| Directive | Description |
|---|---|
@deprecated(reason: String) | Marks the schema definition of a field or enum value as deprecated with an optional reason. |
@skip(if: Boolean!) | If true, the decorated field or fragment in an operation is not resolved by the GraphQL server. |
@include(if: Boolean!) | If false, the decorated field or fragment in an operation is not resolved by the GraphQL server. |
⚠️ Apollo Server does not provide built-in support for custom directives that transform a schema.
Your schema can define custom directives that can then decorate other parts of your schema:
# Definition
directive @uppercase on FIELD_DEFINITION
type Query {
# Usage
hello: String @uppercase
}
If you want to define a custom schema directive to transform your executable schema's behavior before providing that schema to Apollo Server, we recommend using the @graphql-tools library. See our example of using a custom directive to transform a schema.
Before you use custom directives in a federated graph, make sure to consider the following:
@composeDirective directives@composeDirective directive.As our example shows, you can define a transformer function for each of your subgraph schema's custom directives.
To apply transformer functions to your executable subgraph schema, you first generate the subgraph schema with buildSubgraphSchema as usual:
let subgraphSchema = buildSubgraphSchema({ typeDefs, resolvers });
But instead of passing the result directly to the ApolloServer constructor, you first apply all of your transformer functions to it:
// Transformer function for an @upper directive
subgraphSchema = upperDirectiveTransformer(subgraphSchema, 'upper');
After applying all transformer functions, you provide your final subgraph schema to the ApolloServer constructor as usual:
const server = new ApolloServer({
schema: subgraphSchema,
// ...other options...
});