Directives
Configure GraphQL types, fields, and arguments
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:
1type ExampleType {
2 oldField: String @deprecated(reason: "Use `newField`.")
3 newField: String
4}
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:
Directives can take arguments of their own (
reason
in this case).Directives appear after the declaration of what they decorate (the
oldField
field in this case)
Valid locations
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:
1directive @deprecated(
2 reason: String = "No longer supported"
3) on FIELD_DEFINITION | ENUM_VALUE
This indicates that @deprecated
can decorate either a schema FIELD_DEFINITION
(as shown at the top of the article) or a schema ENUM_VALUE
definition (as shown here):
1enum MyEnum {
2 OLD_VALUE @deprecated(reason: "Use `NEW_VALUE`.")
3 NEW_VALUE
4}
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
.
Schema directives vs. operation directives
Usually, a given directive appears exclusively in GraphQL schemas or exclusively in GraphQL operations (rarely both, although the spec allows this).
For example, among the default directives, @deprecated
is a schema-exclusive directive and @skip
and @include
are operation-exclusive directives.
The GraphQL spec lists all possible directive locations. Schema locations are listed under TypeSystemDirectiveLocation
, and operation locations are listed under ExecutableDirectiveLocation
.
Default directives
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. |
Custom schema directives
You can extend Apollo Server with custom schema directives created by you or a third party.
To learn how to create custom directives, see Creating schema directives.
To use a custom directive:
Make sure the directive is defined in your schema with all valid locations listed.
If the directive uses a
SchemaDirectiveVisitor
subclass to perform custom logic, provide it to theApolloServer
constructor via theschemaDirectives
object.The
schemaDirectives
object maps the name of a directive (e.g.,upper
) to the subclass that implements its behavior (e.g.,UpperCaseDirective
).
The following example defines an UpperCaseDirective
subclass for use with the @upper
custom directive. Because it's decorated with @upper
, the Query.hello
field returns HELLO WORLD!
instead of Hello world!
.
1const { ApolloServer, gql, SchemaDirectiveVisitor } = require('apollo-server');
2const { defaultFieldResolver } = require('graphql');
3
4// Subclass definition for @upper directive logic
5class UpperCaseDirective extends SchemaDirectiveVisitor {
6 visitFieldDefinition(field) {
7 const { resolve = defaultFieldResolver } = field;
8 field.resolve = async function (...args) {
9 const result = await resolve.apply(this, args);
10 if (typeof result === 'string') {
11 return result.toUpperCase();
12 }
13 return result;
14 };
15 }
16}
17
18// Schema definition (including custom directive)
19const typeDefs = gql`
20 directive @upper on FIELD_DEFINITION
21
22 type Query {
23 hello: String @upper
24 }
25`;
26
27// Resolvers
28const resolvers = {
29 Query: {
30 hello: (parent, args, context) => {
31 return 'Hello world!';
32 },
33 },
34};
35
36// Add directive to the ApolloServer constructor
37const server = new ApolloServer({
38 typeDefs,
39 resolvers,
40 schemaDirectives: {
41 upper: UpperCaseDirective,
42 }
43});
44
45server.listen().then(({ url }) => {
46 console.log(`🚀 Server ready at ${url}`)
47});