Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Gatsby createResolver with nested data

Tags:

gatsby

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.

like image 524
Aaron Austin Avatar asked Dec 10 '25 02:12

Aaron Austin


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.

like image 162
Aaron Austin Avatar answered Dec 12 '25 13:12

Aaron Austin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!