Disclaimer: These are just my personal notes to help me articulate concepts I’m learning. They’re not meant to be used as a tutorial.
Why use a custom date scalar type in GraphQL?
Well first, what is a scalar?
A scalar is a type. GraphQL has four default scalar types:
IntFloatStringBoolean
Notice there is no Date type.
By default, GraphQL uses seconds internally. This means that even if your database stores a createdAt date in a readable format like 019-06-12 09:49:55.058+06:30, GraphQL will still convert it to a long seconds string like 1560310894541 before returning it to the client, which isn’t very readable.
Also, think about the semantics of this. Imagine you have a schema for a Post type where one of the fields is createdAt. For example:
type Post {
id: ID!
text: String!
createdAt: # what do we return here?
user: User!
comments: [Comment!]!
}What should we return for the createdAt field? There is no Date format. So the best we can do is return a string. But this means that the client will receive a non-human readable string of seconds for the createdAt field.
Luckily GraphQL lets us add our own custom scalar types.
We can use a package called graphql-iso-date.
1. Add a Date scalar in your root schema
const linkSchema = gql`
scalar Date
type Query {
...
}
type Mutation {
...
}
type Subscription {
...
}
`;2. Add a resolver at the highest level of the resolver map that tells the program to return a GraphQLDateTime for the type Date. In my case, I’m doing something like this:
import { GraphQLDateTime } from "graphql-iso-date";
const customScalarResolver = {
Date: GraphQLDateTime
};
export default [
customScalarResolver,
userResolvers,
postResolvers,
commentResolvers
];3. Then, in your schema, you can return an actual Date scalar type for the createdAt field on the Post
type Post {
id: ID!
text: String!
createdAt: Date!
user: User!
comments: [Comment!]!
}Now, when we run the post query, we get back a more readable date format:
{
"data": {
"post": {
"id": "1",
"text": "My first post.",
"createdAt": "2019-06-12T03:29:56.901Z"
}
}
}