Simplifying GraphQL Queries with a Custom Tag
When working with GraphQL, queries, mutations, and subscriptions are essential operations. However, the query structure is often determined by the backend, leaving the client to follow suit. While this isn’t a significant issue with GraphQL’s auto-generated docs, there are scenarios where the client needs to modify the query structure or arguments. This article explores one such use case and presents a solution.
Tools of the Trade
Before diving into the problem and solution, it’s essential to understand the following tools:
- Hasura: An open-source GraphQL service that connects to user databases and microservices, auto-generating a production-ready GraphQL backend.
- graphql-tag: A JavaScript template literal tag that parses GraphQL query strings into the standard GraphQL AST.
Background
A team of frontend and backend developers worked on a Covid-19 project in their spare time. With limited backend support, they opted for Hasura as the backend solution. Hasura’s features, such as automatic schema creation and direct data querying, made it an ideal choice.
The Problem
Initially, everything worked smoothly, but as the project progressed, the query string size increased dramatically, making it difficult to read and maintain. The team struggled to understand the queries, even with Hasura’s features.
A Clumsy Query Example
The query below demonstrates Hasura’s features, but its complexity affects readability:
query {
users(
where: {
AND: [
{ name: { eq: "John" } },
{ age: { gt: 18 } }
]
},
order_by: { created_at: desc }
) {
id
name
age
}
}
The Solution
To address the readability issue, the team decided to create a custom solution. They explored existing tooling and discovered that Hasura couldn’t help much in this scenario. Instead, they focused on finding a client-side solution.
Introducing hql-tag
The team created a wrapper over graphql-tag, called hql-tag, which converts the preferred query structure into the required backend format. This allows for elegant and readable queries.
Step 1: Preferred Query Structure
The team opted for a straight, single-word argument for where and order_by clauses instead of using nested objects as arguments.
Step 2: Create hql-tag
The hql-tag wrapper receives the query string, passes it down to graphql-tag, and then modifies the resulting AST to suit the backend’s needs.
Step 3: Modify AST
The team created AST node templates for different node types, traversed through the nodes, and processed the argument nodes. They extracted the argument name and values, loaded them into predefined templates, and constructed a new AST node.
Usage and Takeaways
The hql-tag library is available on GitHub and npm. Its usage is simple, and it works with all GraphQL client frameworks. This approach can be applied to various scenarios, enabling infinite possibilities for writing elegant, readable, and reusable code in the GraphQL world.
Next Steps
The library’s next steps include adding support for GraphiQL, building a Babel plugin, a plugin for Apollo, and more. By simplifying GraphQL queries, developers can focus on creating better digital experiences.