How to use Gatsby createResolver with nested data

Viewed 301

I'm transforming markdown to html using Gatsby's createResolver API. It works fine at the top level of data. However, I've not been able to get it to work on a more deeply nested array.

Here's what's working:

function markdownToHTMLResolver(nodeType, node, type) {
  return {
    [nodeType]: {
      [`${node}_html`]: {
        type: type,
        resolve: (source, args, context, info) => {
          return remark().use(html).processSync(source[node]).contents;
        },
      },
    },
  };
}

exports.createResolvers = ({ createResolvers }) => {
  const resolvers = {
    ...markdownToHTMLResolver(BLOG_NODE_TYPE, 'body', 'String'),
    ...markdownToHTMLResolver(FRONT_NODE_TYPE, 'body', 'String'),
    ...markdownToHTMLResolver(EVENT_NODE_TYPE, 'body', 'String'),
    ...markdownToHTMLPageResolver(PAGE_NODE_TYPE, 'body', 'String'),
  };
  createResolvers(resolvers);
};

This works for data from my REST API structured like this:

{
    title: 'Title',
    body: '## Heading 2 \n\nParagraph Text.'
}

However, I can't quite figure out to use it for nested data like this:

{ 
    title: 'Title',
    body: '## Heading 2 \n\nParagraph Text.'
    list: {
       data: [
          { title: 'Nested Title 1', body: 'Nested body markdown text 1.'},
          { title: 'Nested Title 2', body: 'Nested body markdown text 2.'},
          { title: 'Nested Title 3', body: 'Nested body markdown text 3.'},
       [
    }
}

I'm not sure what the type should be for this nested data. I've tried something like this, but it's pretty obviously flawed:

function markdownToHTMLPageResolver(nodeType, node, type) {
  return {
    [nodeType]: {
      [`${node}_html`]: {
        type: type,
        resolve: (source, args, context, info) => {
          return remark().use(html).processSync(source[node]).contents;
        },
      },
      list_html: {
        type: ['String'],
        resolve: (source, args, context, info) => {
          return source.list.data.forEach((item) => ({
            title: item.title,
            body: remark().use(html).processSync(source[node]).contents,
          }));
        },
      },
    },
  };
}

Any direction or help would be appreciated.

1 Answers

So I think I figured it out. I was able to discover the inferred type in the GraphiQL interface using __typename. Then I was able to iterate over the data and process the markdown like this:

list_html: {
        type: 'PageList',
        resolve: (source, args, context, info) => {
          const dataArray = source.list.data.map((item) => {
            return {
              title: item.title,
              body: remark().use(html).processSync(item.body).contents,
            };
          });
          return {
            data: dataArray,
          };
        },
      },

It seems keeping the object structure thee same as the original is important.

Related