Как сообщить GraphQL, что имена файлов являются изображениями - пользовательский API не создает фиксированные / текучие изображения - PullRequest
2 голосов
/ 16 апреля 2020

У меня есть пользовательская конечная точка API, к которой я получаю доступ с помощью gatsby-source-apiserver. У меня есть изображения в моей базе данных, которые не преобразуются в узлы изображений - то есть, позволяющие использовать childimagesharp

В моем GraphQL у меня есть такая структура:

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

sourceFilename является строкой, как 'thisisanimage .jpg '- если я добавлю URL, например, "http://example.com/media", изображение будет работать нормально. Я не уверен, что делать дальше, я смотрел на createResolvers, но не до конца понимаю, как его реализовать.

Это то, что я пробовал до сих пор - похоже, не очень много (кроме получения комментарий «все происходит» в моем терминале, но не следующий ...

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,
            })
          },
        },
      },
    },
  })
}

Вероятно, важно упомянуть, что works - это массив mediaItems, который сам является массивом полей, из которых sourceFilename 1. Смотрите прикрепленный скриншот

graphQL result from above query

1 Ответ

1 голос
/ 17 апреля 2020

Итак, после некоторых замечательных советов по поводу чата Spectrum Gatsby у меня есть несколько решений: https://spectrum.chat/gatsby-js/general/getting-relative-images-to-work-with-a-custom-api-using-gatsby-source-apiserver~a0805b02-6e2b-4be6-ab1a-ae6d3cc53fab

Один из способов сделать это - поместить код в gatsby- node.js. Возможно, это не лучший способ сделать это, но он работает.

Первая проблема - это найти имя поля в том виде, в котором GraphQL его видит. Вы можете использовать проводник документации для поиска по запросу, чтобы найти имя типа элемента мультимедиа, содержащего URL вашего изображения. Это обычно в Pascal случае. В моем случае это было не из-за странного способа, которым я все настроил!

Более простой способ найти его для меня - использовать CLI: type gatsby repl и выполнить команду schema .

В моем случае имя типа было submissionsWorksMediaItems

Затем я обнаружил, что могу использовать это, чтобы получить изображения для загрузки и предоставить мне функциональность childImageSharp:

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,
            })

        },
      },
    },
  })
}

В моем случае я обнаружил, что у меня возникли проблемы, когда некоторые файлы отсутствовали на сервере - это привело к ошибке 404, которая привела к сбою сборки (хотя она работала в режиме разработки). Поэтому вместо этого я использовал следующий код (снова прочитайте ветку из spectrum.chat для всего контекста:

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
        },
      },
    },
  })
}
...