DEV Community

Krzysztof Żuraw
Krzysztof Żuraw

Posted on • Originally published at krzysztofzuraw.com on

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

Top comments (1)

Collapse
 
hey-amit profile image
Amit Kumar • Edited

Krzysztof Thanks for this article. I have one doubt here, say if you have Post and post has array of Tag, using createSchemaCustomization how would you solve this i.e in Post instead of string tag, populating post with all tag data.

I tried couple of things but still no luck.

---
//below is tag sample post markdown for post1.md
title: The first post
published: true
tags:
  js
  react
---

---
// below is tag sample tag markdown js.md
title: js
published: true,
slug: /js
---

Thanks buddy.