How to design GraphQL queries and mutations: custom scalar

In the first part of this series we discussed the different built-in scalars available in the GraphQL specification. In the second part we moved to enums. In the last part of this series we will return to scalars. However, we will concentrate on the so-called “custom scalars”. We will first define the model scalar for DateTime, then we will extend the task definition for the fields createdAt and updatedAt, which will basically be time stamps for each new task.

David Mráz
Nov 14, 2017 · 4 min read

Checkout the upcoming free GraphQL language course with in browser exercices

From upcoming GraphQL Language course

Introduction

As we discussed in this article, in GraphQL specification we have different built-in scalar types. But what can we do if we need to use scalars which are not defined in the GraphQL specification? The answer is to use the so-called “custom scalar”. As in the previous articles we will use graphql-js. The implementation of the GraphQL custom scalar can vary across other GraphQL implementations. In some of these implementations, it may not be even possible to use custom scalars.

We will continue with the same repository as with the enums and built-in scalars. You can clone the GitHub repository using this command

git clone https://github.com/a7v8x/express-graphql-demo.git -b feature/3-graphql-scalars

Custom scalar definition

Now let’s go right into the designing of the DateTime scalar. We will use validator js library to test if the value is in ISO8601 date time string format. The simplified definition of the DateTime scalar can be as follows

Date time custom scalar

In graphql-js, each custom scalar type definition has different fields and methods that should be defined. Just as with input/output object types, we have to define the required field name of the scalar. The description field is once again mandatory. If you read the article on built-in scalars we went through input and result coercion for each type. This is defined in graphql-js library for built-in scalars. However, when we define our own custom scalar, we have to specify these rules. That is why we have to define a couple of methods for each custom scalar. These are:

  • serialize

The serialize function refers to the result coercion. The first argument for this function is the received value itself. In our case, we would like to check if the value is in ISO8601 date format. If the received value passes the validation, we want to return this value; otherwise, we would raise the GraphQL error.

  • parseValue, parseLiteral

The parseValue and parseLiteral function refers to the input coercion. The difference is that in parseValue, we refer to the input passed using the variables. When we use parseValue, the first argument of this function is the value itself. On the other hand, the parseLiteral function has its first argument the ast value in the following format

That is why we have to extract the value from the ast variable and again validate it by our rules.

Implementation

We have completed the definition of our custom scalar, and therefore it is possible to implement it in the schema. We will apply it on the timestamp fields createdAt and updatedAt. We can simply import our Date Time scalar and use it as a type for these fields.

task type definition

Now let’s check out if our rules, which we defined works as expected. Just go to /graphiql and try to call the basic getTasks query:

the getTasks query with the selections set which includes timestamp fields createdAt and updatedAt

If our custom Date Time scalar is implemented correctly, you should get something like this:

the result of the getTasks method with the correct Date Time scalars

Now let’s test out our serialize function. Just go to the taskDb.js file and reassign createdAt or updatedAt to a string which is not in ISO8601 date format. I will change the createdAt field to 2017–10–06T14:54:54+0. Now if we try to call the getTasks Query, the GraphQL server will raise the following error:

raising the error in our custom scalar serialize function when receiving invalid ISO-8601 Date instance

Summary

Custom scalars provide an even greater benefit when we have a collection of our predefined custom scalars. Then we can centralize most of our custom validations and move them from our resolver functions to our custom scalar types. Our simple Date Time scalar was a great model example. However, if you want to use more complex scalars like JSON or more precisely defined Date Time scalars, etc., it is possible to use some of the open sourced npm packages. These include:

Even that there are some of custom scalars published as an open source. There are just a few of them. If you have a good tips on some custom scalar definitions, feel free to share it in the comment section below!

Did you like this post? Then clap for this article as it is easier for others to find it. The repository with the examples and project setup can be cloned from this GitHub branch. You can get early access to upcoming free GraphQL course by subscribing at graphqlmastery.com.

Atheros Intelligence

Everything you need to know about building AI products. Check out free GraphQL language course https://graphqlmastery.com/course/graphql-language.

David Mráz

Written by

React | GraphQL | Node JS | AI | Machine learning, Free upcoming GraphQL course at http://graphqlmastery.com/course/graphql-language

Atheros Intelligence

Everything you need to know about building AI products. Check out free GraphQL language course https://graphqlmastery.com/course/graphql-language.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade