Customizing Gatsby Graphql schema
Krzysztof Żuraw
Posted on March 4, 2020
Recently I was doing redesign of my blog. As you may know, I'm using Gatsby.js. All in all, it is a very good static sitegenerator but I had one problem with it. Or to be more precise the issue waswith Gatsby and the TypeScript.
Problem
I try to help myself when writing frontend code so I decided that I will try toautomatically generate TypeScript interfaces from GraphQL schema that Gatsby.jsis using. Everything was fine until I found out that by design many fields areundefined. Take for example siteMetadata
object:
{
siteMetadata: {
siteName: 'Krzysztof Żuraw',
author: 'Krzysztof Żuraw',
description: 'Krzysztof Żuraw personal site & blog',
siteUrl: 'https://krzysztofzuraw.com',
social: {
linkedin: 'https://pl.linkedin.com/in/krzysztofzuraw',
github: 'https://github.com/krzysztofzuraw',
email: 'mailto:blog@kzuraw.com',
pinboard: 'https://pinboard.in/u:KZuraw',
newsletter: 'https://buttondown.email/krzysztof_zuraw',
},
}
}
You can see this file here.
I tried to generate TypeScript types for this structure using GraphQL Code Generator to get:
export type SiteSiteMetadata = {
__typename?: 'SiteSiteMetadata';
siteName?: Maybe<Scalars['String']>;
author?: Maybe<Scalars['String']>;
description?: Maybe<Scalars['String']>;
siteUrl?: Maybe<Scalars['String']>;
social?: Maybe<SiteSiteMetadataSocial>;
};
What? All of them are undefined
or null
? No way - I know they will be defined in the timewhen I generate a static site. I asked around and Hasparus give me a hint - youcan customize your GraphQL schema 🎉.
To do that I had to use createSchemaCustomization(you have to place it inside gatsby-node.js
):
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions;
const typeDefs = `
type MarkdownRemark implements Node {
frontmatter: Frontmatter!
}
type Frontmatter {
tags: [String!]!
title: String!
slug: String!
date(
difference: String
formatString: String
fromNow: Boolean
locale: String
): Date!
}
type Site implements Node {
siteMetadata: SiteSiteMetadata!
}
type SiteSiteMetadata {
siteName: String!
author: String!
description: String!
siteUrl: String!
social: SiteSiteMetadataSocial!
}
type SiteSiteMetadataSocial {
linkedin: String!
github: String!
email: String!
pinboard: String!
newsletter: String!
}
`;
createTypes(typeDefs);
};
What is happening here? I added my own GraphQL types where all the fields are not nullable.Thanks to that it generated types look like follows:
export type SiteSiteMetadata = {
__typename?: 'SiteSiteMetadata';
siteName: Scalars['String'];
author: Scalars['String'];
description: Scalars['String'];
siteUrl: Scalars['String'];
social: SiteSiteMetadataSocial;
};
One drawback of it - right now it is on me as a developer, to make sure that all thedata from e.g frontmatter
will be there.
Summary
I wanted to fix autogenerated GraphQL types in Gatsby. Thanks to Hasparus suggestion I’veused createSchemaCustomization to overrideguested Gatsby types.
Thank you Hasparus once again 🙇🏻♂️.
Posted on March 4, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.