Customizing Gatsby Graphql schema

kzuraw

Krzysztof Żuraw

Posted on March 4, 2020

Customizing Gatsby Graphql schema

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',
    },
  }
}
Enter fullscreen mode Exit fullscreen mode

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>;
};
Enter fullscreen mode Exit fullscreen mode

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);
};
Enter fullscreen mode Exit fullscreen mode

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;
};
Enter fullscreen mode Exit fullscreen mode

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 🙇🏻‍♂️.

💖 💪 🙅 🚩
kzuraw
Krzysztof Żuraw

Posted on March 4, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Parsing Markdown from a CMS
gatsby Parsing Markdown from a CMS

June 18, 2020

How to set up a TypeScript + Gatsby app
featuredposts How to set up a TypeScript + Gatsby app

August 14, 2019