Unlocking the Power of GraphQL Directives
When it comes to creating a GraphQL server, there are two primary approaches: SDL-first and code-first. While both have their benefits and drawbacks, one of the significant limitations of the code-first approach is its inability to support schema-type directives naturally. However, this doesn’t mean that code-first servers can’t provide support for these directives. In this article, we’ll explore a strategy for implementing schema-type directives via code, and how it can be achieved through the use of IFTTT (if this, then that) rules.
The Difference Between Schema- and Query-Type Directives
Before diving into the implementation, it’s essential to understand the distinction between schema-type and query-type directives. Schema-type directives, such as @deprecated
, are declared on the schema via the SDL, while query-type directives, like @include
and @skip
, are added to the query in the client. While it may seem like a trivial difference, it has significant implications for how directives are implemented and executed.
Decoupling the Requested and Executable Queries
One of the key insights that enables the implementation of schema-type directives via code is the recognition that there are two queries involved in the GraphQL request process: the requested query and the executable query. The executable query is produced by applying transformations to the requested query, including the inclusion of special-type directives like @validate
and @resolveValueAndMerge
. This decoupling allows us to transform the query to add any directive, not just the special-type ones, and provides a solution for implementing schema-type directives via code.
IFTTT Through Directives
To implement schema-type directives via code, we need a mechanism to tell the server when and how to add the directives to the query. This is where IFTTT rules come in. IFTTT rules define pairs of events and actions, such as “if field X is found on the query, then attach directive Y to field X.” This approach allows us to execute functionality through directives, making it possible to add directives to the schema via configuration rather than code.
Adding Directives to the Schema via IFTTT
To illustrate how IFTTT rules can be used to add directives to the schema, let’s consider an example. Suppose we want to create a custom directive @authorize(role: String!)
to validate that the user executing field myPosts
has the expected role “author,” or show an error otherwise. Using IFTTT rules, we can define the same intent as the SDL, but through code. This approach provides a flexible and configurable way to execute functionality through directives.
Dealing with Multiple Configurations Through Field Aliases
One of the challenges of implementing schema-type directives via code is dealing with multiple configurations. For instance, if we want to translate our site from English to French, we can create an IFTTT rule to attach the @translate
directive to specific fields. However, this approach can lead to issues when we want to retrieve the data without any processing, back in English. The solution is to create field aliases on the server-side, which allows us to define different versions of the fields and attach directives to specific aliases.
Improving the Legibility of the Schema Through Aliases
Server-side field aliases can also be used to improve the legibility of the schema. For instance, we can use aliases to expose all versions of the fields in the schema, making it easier to manage different versions of the API. Additionally, aliases can be used to avoid namespacing custom directives, making the schema more elegant and easier to read.
Conclusion
In conclusion, schema-type directives are a powerful feature of GraphQL, and providing good access to them should be a top priority for any GraphQL server. By using IFTTT rules to implement schema-type directives via code, we can provide a flexible and configurable way to execute functionality through directives. This approach can be particularly useful for code-first servers that don’t have an SDL, but can also be beneficial for SDL-first servers that want to provide more flexibility and customization options.