About cookies on this site Our websites require some cookies to function properly (required). In addition, other cookies may be used with your consent to analyze site usage, improve the user experience and for advertising. For more information, please review your options. By visiting our website, you agree to our processing of information as described in IBM’sprivacy statement. To provide a smooth navigation, your cookie preferences will be shared across the IBM web domains listed here.
Article
GraphQL directives overview
Everything you need to know about GraphQL directives
On this page
GraphQL directives are an incredibly powerful aspect of the GraphQL specification. You might not be aware of these directives or had the opportunity to use them because the GraphQL specification only requires a small number of directives for an API to be spec compliant, and, even then, they aren't necessarily ones you'd encounter on a regular basis. However, GraphQL directives provide extensibility to a GraphQL API and server in a way that makes them incredibly important, especially to tools like IBM API Connect Essentials.
In this article, we'll look at what GraphQL directives are, how they are used, and review some examples of directives.
What are GraphQL directives?
Basically, a GraphQL directive is a way to annotate a GraphQL schema to indicate that the item being annotated needs to be evaluated differently. Directives in GraphQL offer a means to change runtime execution and type validation in a GraphQL document.
GraphQL directives allow you to modify the behavior of GraphQL's execution by providing options that are not available through field arguments. For example, you can conditionally include or exclude a field using directives.
You can use built-in or custom directives when building or consuming a GraphQL API. Built-in directives are defined by the GraphQL specification, while custom directives are defined by the GraphQL service or tool that you use.
Built-in GraphQL directives
The GraphQL specification defines a set of built-in directives. Directives have a specific name and can accept values of any input type as arguments. GraphQL directives can be applied to, for example, types, fields, fragments, and operations.
The following list has all the built-in directives that are defined by the GraphQL specification:
@skip
: This directive can be used to exclude fields from a query operation conditionally.@include
: Does the opposite of @skip and can be used to include fields in a query operation conditionally.@deprecated
: This directive can mark a field or an enum value as deprecated and can provide a reason for deprecation to the client.@specifiedBy
: This directive can be used to provide a URL for the specification of a custom scalar.
As GraphQL evolves, new execution capabilities might be introduced and exposed through directives. For example, the directives@defer
and @stream
have been announced by the GraphQL Working Group but aren't listed in the latest draft of the GraphQL specification.
GraphQL services and tools can also provide custom directives beyond those already mentioned.
Custom GraphQL directives
Custom directives can be used to extend the functionality of GraphQL and are the preferred way to add custom behavior to a GraphQL API. Different GraphQL server and client implementations are already using custom directives to add additional functionality to GraphQL.
For example, with GraphQL APIs built with API Connect Essentials, custom directives are defined to connect with your data sources, such as the @rest
, @dbquery
, and @graphql
directives. When using API Connect Essentials to develop your GraphQL API, you can use these directives to connect to REST APIs, databases, and other GraphQL APIs. Additionally, we have defined the @materializer
and @sequence
directives to mix and match data from multiple data sources in a single type.
Different locations of directives
Another distinction between directives is the location they are used in. Let's examine the difference between directives applied to type system and executable locations in GraphQL.
Directives in GraphQL can be applied to different locations, where the GraphQL Specification makes a distinction between type system directive locations and executable directive locations. Directives applied to either of these locations have the same syntax; therefore, their location determines how a GraphQL implementation handles them. However, while a directive might support both type system and executable locations, a single directive typically supports only one location.
For example, both @include
and @skip
can be included in a query that is being passed to the GraphQL server and will affect how the query is processed, by either skipping or including a part of the query based upon a given argument. However, @deprecated
would only ever be added to a schema definition.
Directives that apply to the type system
Directives that apply to the type system are used to annotate a schema, object type, or field definition written in GraphQL SDL (schema definition language) when building a GraphQL server. Both built-in and custom directives can be used in type system directive locations, and GraphQL server implementations can then use these annotations to take additional actions. Therefore, type system directive locations are also called "schema directives" as they only exist on the GraphQL schema itself.
The following locations in a GraphQL schema are valid type system directive locations:
SCHEMA
SCALAR
OBJECT
FIELD_DEFINITION
ARGUMENT_DEFINITION
INTERFACE
UNION
ENUM & ENUM_VALUE
INPUT_OBJECT & INPUT_FIELD_DEFINITION
Examples of directives that apply to the type system include @deprecated
, a built-in directive that can mark a field as deprecated. Let's see what it looks like in a schema:
In the example above, the @deprecated
directive marks the name field as deprecated. The reason argument provides a reason for deprecation available to services that introspect the schema. The client could then, for example, warn the user that the field name is deprecated and shouldn't be used anymore.
When you would look up the User
type in the documentation generated by GraphiQL, you should see warnings about using the field name:
Another example of a directive that can be applied to the type system is @rest
, a custom directive only available in API Connect Essentials implementations. The data for the User
type in the example above is fetched from a REST API using the @rest
directive, which is defined in the following way on a query field in a GraphQL schema:
When you run an operation that includes the user field, the API Connect Essentials GraphQL API fetches the data from the REST API and returns it to the client. The @rest
directive is applied to a type system location because it annotates the user field in the schema. It lets you declaratively define how the data for the user field should be fetched, rather than having to write a resolver function, as you might expect from other GraphQL server implementations.
Directives that apply to execution
You can use directives that apply to execution to modify the behavior of an operation, field, or fragment in runtime execution. For example, directives that apply to execution can include or exclude fields or perform additional data processing before the response is returned.
Executable directive locations in GraphQL are:
QUERY
MUTATION
SUBSCRIPTION
FIELD
FRAGMENT_DEFINITION
&FRAGMENT_SPREAD
INLINE_FRAGMENT
VARIABLE_DEFINITION
Similar to directives that apply to the type system directives, both built-in and custom directives can be applied to executable locations. Most built-in directives are executable, such as @skip
and @include
, which you can use to include or exclude fields in an operation conditionally.
Let's see what the @include
directive looks like in a query operation:
The @include
directive conditionally includes the firstName
and lastName
fields in the response. The if
argument specifies a boolean value determining whether to include the field in the response. In the example above, the if
argument is set to a variable $showName
, which is defined in the operation variables. The variable's value can be set to true
or false
to include or exclude the fields in the response.
When you pass this operation to a GraphQL API, the response should include the fields firstName
and lastName
in the response if the value of the variable $showName
is set to true
as you can see in the screenshot below:
Another example of an executable directive is @sort
, a custom directive only available in IBM API Connect Essentials implementations.
With the @sort
directive, you can sort the data returned by a field in a GraphQL operation. You can use the @sort
directive on a field that returns either a list of leaf fields or a list of objects.
For example, let's say you have a products
field that returns a list of tags
. You can use the @sort
directive to sort the tags by alphabetical order, even when the data source doesn't suppport this sorting order:
The list of tags will be transformed to this when the @sort
directive is used:
Next to a list of leaf fields, the same @sort
directive can be applied to a field that returns a list of objects. You can find more information on using the @sort
directive in the documentation.
Summary and next steps
If you're new to GraphQL, seeing directives can be disorienting and confusing, especially since you won't always encounter them. In this article, you learned about built-in and custom directives and how they can be applied to different locations in GraphQL. These locations are either type system or executable locations. Directives applied to the type system directives are used in GraphQL Schema Definition Language (SDL) only. At the same time, directives applied to executable locations are used to modify the response of GraphQL in runtime execution.
GraphQL directives can be quite powerful, but you might not have occassion to use them unless you come across a system that supports them in queries or you are implementing your own GraphQL API, whether using a tool like API Connect Essentials or manually writing the code yourself. What do you think? Join our Discord to stay updated with our community.