3

I have a custom api endpoint that i'm accessing with gatsby-source-apiserver. I have images in my database that aren't transforming into image nodes - i.e. allowing childimagesharp

In my graphql i have this structure:

query MyQuery {
  allSubmissions {
    edges {
      node {
        works {
          mediaItems {
            sourceFilename
          }
        }
      }
    }
  }
}

the sourceFilename is a string, like 'thisisanimage.jpg' - if i append a url onto it like "http://example.com/media" the image works fine. I'm not sure how to proceed, i've looked at createResolvers but dont fully understand how to implement it.

This is what i've tried so far - not seeming to do much (aside from getting the 'anything happening' comment in my terminal, but not the next one...

exports.createResolvers = ({
  actions,
  cache,
  createNodeId,
  createResolvers,
  store,
  reporter,
}) => {
  const { createNode } = actions
  reporter.info(anything happening?)
  createResolvers({
    submissions: {
      works: {
        mediaItems: {
          type: File,
          resolve(sourceFilename, args, context, info) {
            reporter.info(
              Resolving source: ${sourceFilename} ${args} ${context} ${info}
            )
            return createRemoteFileNode({
              url:
                "https://example.com/media/" +
                sourceFilename.sourceFilename,
              store,
              cache,
              createNode,
              createNodeId,
              reporter,
            })
          },
        },
      },
    },
  })
}

Its probably important to mention that works is an array of mediaItems, which itself is an array of fields, of which sourceFilename is one. See the attached screenshot

graphQL result from above query

amcc
  • 523
  • 5
  • 16
  • So i've got this working now I believe with some help from the spectrum forum - thanks for the help... this is what the code should have looked like - see below - the trick was getting the right name for the media file, which I did with "gatsby repl" then "schema" in the CLI. That enables you to find the right name for your media field. Then replace the "CMS_Asset" in the example below: https://www.gatsbyjs.org/docs/schema-customization/#feeding-remote-images-into-gatsby-image Also include this in gatsby-node.js: const { createRemoteFileNode } = require("gatsby-source-filesystem") – amcc Apr 16 '20 at 22:08
  • Do you want to add your full solution as an answer here? – ksav Apr 17 '20 at 05:57
  • 1
    Yeah i'll do that - i was still in the middle of changing things with the last answer up there - got more feedback since then – amcc Apr 17 '20 at 14:33

1 Answers1

1

So after some great advice on the Spectrum Gatsby chat I've some solutions: https://spectrum.chat/gatsby-js/general/getting-relative-images-to-work-with-a-custom-api-using-gatsby-source-apiserver~a0805b02-6e2b-4be6-ab1a-ae6d3cc53fab

One way of doing this is to put code in gatsby-node.js. This may not be the best way of doing this, but it works.

The first issue is finding the name of the field in the way GraphQL sees it. You can use the Documentation Explorer to mine through the query to find the type name of the media item that contains your image URL. This is normally in Pascal Case. In my case it wasn't due to the odd way I had things set up!

An easier way to find it for me was to use the CLI: type gatsby repl, and issuing the schema command.

In my case the type name was submissionsWorksMediaItems

Then I found that I could use this to get the images to download and provide me with childImageSharp functionality:

const { createRemoteFileNode } = require("gatsby-source-filesystem")

exports.createResolvers = ({
  actions,
  cache,
  createNodeId,
  createResolvers,
  store,
  reporter,
}) => {
  const { createNode } = actions
  createResolvers({
    submissionsWorksMediaItems: {
      imageFile: {
        type: `File`,
        resolve(source, args, context, info) {
          return createRemoteFileNode({
            url:
              `https://example.com/media/${source.filename}`,
            store,
            cache,
            createNode,
            createNodeId,
            reporter,
            })

        },
      },
    },
  })
}

In my case I then found i had issues where some files were not on the server - this created a 404 error which cause the build to fail (though it worked in develop mode). So I then used the following code instead (again read the thread from spectrum.chat for all the context:

const { createRemoteFileNode } = require("gatsby-source-filesystem")

const imageNodes = new Map()
const getImageUrl = source =>
  `https://example.com/media/${source.filename}`
exports.sourceNodes = ({
  actions,
  cache,
  createNodeId,
  getNodesByType,
  store,
  reporter,
}) => {
  const { createNode } = actions
  const imageDownloads = []
  const submissions = getNodesByType("submissions")
  submissions.forEach(node => {
    node.works &&
      node.works.forEach(({ mediaItems }) => {
        mediaItems &&
          mediaItems.forEach(mediaSource => {
            const imageUrl = getImageUrl(mediaSource)
            imageDownloads.push(
              createRemoteFileNode({
                url: imageUrl,
                store,
                cache,
                createNode,
                createNodeId,
                reporter,
              })
                .then(result => {
                  if (!result) {
                    return reporter.warn(`Could not download ${imageUrl}`)
                  }
                  imageNodes.set(imageUrl, result)
                })
                .catch(err => {
                  reporter.warn(err)
                })
            )
          })
      })
  })
  return Promise.all(imageDownloads)
}
exports.createResolvers = ({ createResolvers }) => {
  createResolvers({
    submissionsWorksMediaItems: {
      imageFile: {
        type: `File`,
        resolve(source, args, context, info) {
          const imageUrl = getImageUrl(source)
          if (imageNodes.has(imageUrl)) {
            return imageNodes.get(imageUrl)
          }
          return null
        },
      },
    },
  })
}
amcc
  • 523
  • 5
  • 16