Skip to main content

Drupal + GatsbyJS: GraphQL schema improperly handling multivalued objects

Published on Sunday 8, December 2019

I just discovered that there are some problems when working with the gatsby-source-drupal plugin. There is already a problem where empty data doesn't generate the schema type (even if it has no fields.) There is another one if you only receive one value.

In the Drupal Commerce demo, we have a clothing and simple product type. While testing some multi-store functionality, I excluded the clothing products from some stores. When I then built the GatsbyJS site, things exploded. And I wasted quite a bit of time unsure why.

Here's some code in my gatsby-node.js to create product pages for each product type.

  const productTypes = await graphql(`{
        allCommerceProductTypeCommerceProductType {
          nodes {
            id
            label
            drupal_internal__id
            variationType
            multipleVariations
          }
        }
      }`);

When there were only simple products and not clothing as well, the schema completely broke. The allCommerceProductTypeCommerceProductType was returning one type. The drupal_internal__id, variationType, and multipleVariations fields didn't exist. Instead, it was a very generic schema that contained Gatsby's internal UUID and the product type's label. 

Upon reviewing the source plugin, it looks like the problem was happening in the normalization: https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-drupal/src/normalize.js

const nodeFromData = (datum, createNodeId) => {
  const { attributes: { id: _attributes_id, ...attributes } = {} } = datum
  const preservedId =
    typeof _attributes_id !== `undefined` ? { _attributes_id } : {}
  return {
    id: createNodeId(datum.id),
    drupal_id: datum.id,
    parent: null,
    drupal_parent_menu_item: attributes.parent,
    children: [],
    ...attributes,
    ...preservedId,
    drupal_relationships: datum.relationships,
    relationships: {},
    internal: {
      type: datum.type.replace(/-|__|:|\.|\s/g, `_`),
    },
  }
}

It's like there were no attributes passed in the datum