Customizing the GraphQL schema of a Gatsby project with nested types breaks functionality of transformer plugins

Viewed 737

In a project where I'm sourcing data from NetlifyCMS I need to extend the GraphQL schema of Gatsby because there are optional fields in my CMS, which would cause errors trying to query non-existing data from GraphQL.

The below code extends the GraphQL types to always include the optional fields

// gatsby-node.js
// ADD OPTIONAL TYPES

// note: I have also tried exports.sourceNodes
exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    type SettingsJson implements Node {
      tags: String
      name: String
      phone: String
      email: String
      additional_info: [SettingsJsonAdditional_info]
    }

    type SettingsJsonAdditional_info {
      type: String
      text: String
    }
  `
  createTypes(typeDefs)
}

Sourcing and transforming the tags, name, phone and email work as expected. Queries return null if an optional field has not been filled out, and the query returns the correct value after being set. However, querying for additional_info always returns null even when containing data.

This is the json-file generated by NetlifyCMS:

{
  "name": "Name Nameson",
  "phone": "+41 1234 5678",
  "email": "mail@example.com",
  "additional-info": [
    {
      "type": "Booking",
      "text": "Booker McBookerson <book@book.com>"
    }
  ]
}

The following GraphQL query shows that the data is not being transformed properly when extending the GraphQL schema myself.

Query

query {
  file(relativePath: {eq: "settings/contacts.json"}) {
    internal {
      content
    }
    
    childSettingsJson {
      name
      phone
      email
      additional_info {
        type
        text
      }
    }
  }
}

Response

{
  "data": {
    "file": {
      "internal": {
        "content": "{\n  \"name\": \"Name Nameson\",\n  \"phone\": \"+41 1234 5678\",\n  \"email\": \"mail@example.com\",\n  \"additional-info\": [\n    {\n      \"type\": \"Booking\",\n      \"text\": \"Booker McBookerson <book@book.com>\"\n    },\n    {\n      \"type\": \"Booking2\",\n      \"text\": \"Booker2 McBookerson <book@book.com>\"\n    }\n  ]\n}"
      },
      "childSettingsJson": {
        "name": "Name Nameson",
        "phone": "+41 1234 5678",
        "email": "mail@example.com",
        "additional_info": null
      }
    }
  },
  "extensions": {}
}

When the types are inferred by the transformer plugin itself I get the expected data when querying

// ...
        "additional_info": [
          {
            "type": "Booking",
            "text": "Booker McBookerson <book@book.com>"
          }
        ]
// ...

This example uses json files with gatsby-transformer-json. I have tried with gatsby-transformer-yaml too with the same results.

Is it possible to add my array of SettingsJsonAdditional_info to the schema to get the "optional field" functionality I'm looking for?

1 Answers

One kind of hacky solution I have found is to make the transformer plugin infer the types by adding a dummy-file that will be sourced and transformed along with "real" files.

// dummy.json
{
    "name": "dummy",
    "phone": "dummy",
    "email": "dummy",
    "tags": "dummy",
    "additional-info": [
      {
        "type": "dummy",
        "text": "dummy"
      }
    ]
  }

This file can be hidden from NetlifyCMS (by simply not including a UI entry for it in the config.yml file of NetlifyCMS. It will guarantee that you can always query for the fields included in this file without getting GraphQL "field doesn't exist" errors.

Related