What You Need to Know About GraphQL Directives


title: What You Need to Know About GraphQL Directives published: true description: GraphQL directives are a powerful aspect of the GraphQL spec that you may not even be aware of. They provide extensibility to to a GraphQL API. This post looks at what GraphQL directives are, how they are used and some examples of directives in use. tags: graphql cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6sxmy6h8stceq0t1afjb.jpg canonical_url: https://stepzen.com/blog/graphql-directives

GraphQL directives are an incredibly powerful aspect of the GraphQL specification, but you may not be aware of them or have had the opportunity to ever use them. This is partly because the GraphQL spec only defines two "required" 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 to a GraphQL API and server in a way that makes them incredibly important, especially to tools like StepZen. In this post, we'll look at what GraphQL directives are, how they are used and some examples of directives in use.

What Are GraphQL Directives

At a basic level, a GraphQL directive is a way to annotate a GraphQL schema to indicate that the item being annotated needs to be evaluated differently. Yes, that is vague, partly because directives can do a lot of different things depending on where they are applied (we'll look more at some of the possibilities in a moment). They are always preceded by the @ symbol, making them easy to recognize.

Types of Directives

There are two types of directives based upon where they are applied:

  1. Schema directives – A schema directive is applied to the schema in the SDL (schema definition language), so they are executed when the schema is being created. For example, all of StepZen's custom directives fall under this category since they are all applied to the schema and tell StepZen how to generate the API. The spec defines the locations where these can be applied under Type System Directive locations.
  2. Operation directives – These are applied to a query and therefore affect how that query is processed by the resolvers. The spec defines where these can be applied under Executable Type Directive locations.

To better understand the differences between these two types, let's look at the "required" directives defined in the spec.

Required Directives

There are technically three "required" directives for creating a spec-compliant server. I put required in quotes because you definitely can create a GraphQL API server that doesn't implement them, but it just wouldn't technically be fully spec-compliant (if that matters to you).

  1. @include - This is an operation type directive that can be added to a query to include a field, fragment spread or inline fragment if the supplied argument is true.
  2. @skip - Similar to the above, this operation type directive can be added to a query to skip this field, fragment spread or inline fragment if the argument is true.
  3. @depracated - This is a schema type directive that indicates that a field or enum value has been deprecated in the schema and can supply a reason for the deprecation.

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.

Why Should You Care About Directives?

None of the required directives really make a case for why they are important. It's also possible that, as a consumer of GraphQL APIs, you haven't even encountered a directive. The critical thing to know about directives is that they essentially offer a way to extend the GraphQL spec to add new functionality not defined in the spec. What kind of functionality? Well, pretty much anything.

As Leonardo Losoviz states in his excellent article GraphQL directives are underrated:

Directives are a playground for both GraphQL server implementers and end users alike. GraphQL server implementers can develop features not currently supported by the spec, and users can develop features not yet implemented by the GraphQL server.

Directives’ unregulated nature is a feature, not a bug.

Let's explore some of the uses of directives to see what this can mean in action.

Examples

The @computed directive is a community example of a schema type directive that can help avoid having to create resolvers for values that can be computed from the value of other fields in the schema. The common example is providing a full name field that is comprised of the value of first name plus last name.

type User {
  firstName: String
  lastName: String
  fullName: String @computed(value: "$firstName $lastName")
}

In this example, the resolver does not need to handle the fullName field because the @computed directive takes care of that.

StepZen primarily uses GraphQL directives to tell our system how to generate the full schema and resolvers that StepZen deploys on your behalf. Thus, StepZen's custom directives are also all schema type directives.

For example, if you wanted to connect a query to a REST endpoint in a schema on StepZen.

type Query {
  getArticles(username: String!): [Article]
    @rest(
      endpoint: "https://dev.to/api/articles?username=$username"
    )
}

In this case, @rest is a custom directive that can be applied to a query. In the above example, we've supplied only one argument to the directive (endpoint). StepZen uses this directive to write the resolver that handles the getArticles query so that it can connect this query to data from the supplied REST endpoint. StepZen has a similar directive, @dbquery, for connecting a database backend. There are also community implementations of a similar @rest directive.

To learn more about how to connect a REST API to StepZen, check out my post "Turning a REST API into GraphQL Using StepZen."

Where to Go From Here

If you're new to GraphQL, seeing directives can be disorienting and confusing, especially since you won't always encounter them. Hopefully this has given you a general understanding of what they are and how they are used. As you can see, they can be quite powerful, but you may 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 via a tool like StepZen or manually writing the code yourself.

If you'd like to learn more about directives, here are some useful resources.