#StackBounty: #javascript #graphql #github-api Get results from different arrays in one Promise.All with Github GraphQL API

Bounty: 50

I’m making a custom source plugin for Gatsby, that will get markdown files from a GitHub repository. The repository has individual files (blobs) and folders (trees), which in their turn also contain files. I need to get all files (including files inside folders) in one Promise.all, but I can’t figure out how to do that. I’ve managed to get individual files from the repository and I have a function which returns an array of files from the trees. But I don’t know how to combine them.

Here is my code. GraphQL queries to get repository, trees and files information:

const repositoryQuery = `
{
  viewer {
    repository(name: "repository-name") {
      object(expression: "master:") {
        ... on Tree {
          entries {
            name
            oid
            type
          }
        }
      }
    }
  }
}
`

const treeQuery = `
  query getTree($id: GitObjectID!) {
    viewer {
      repository(name: "repository-name") {
        object(oid: $id) {
          ... on Tree {
            entries {
              name
              oid
              type
            }
          }
        }
      }
    }
  }
`

const fileQuery = `
  query getFile($id: GitObjectID!) {
    viewer {
      repository(name: "repository-name") {
        object(oid: $id) {
          ... on Blob {
            text
          }
        }
      }
    }
  }
` 

And the functions themselves:

const data = await client.request(repositoryQuery)

const getTree = async entry => {
  const data = await client.request(treeQuery, { id: entry.oid })
  const array = await data.viewer.repository.object.entries
  return array
}

const getFile = async entry => {
  const data = await client.request(fileQuery, { id: entry.oid })
  const result = await data.viewer.repository.object
  return result
}

const files = await Promise.all(
  data.viewer.repository.object.entries
    .filter(entry => entry.type !== "tree")
    .map(entry => {
      return (
        getFile(entry)
        .then(file => {
          return {
            data: file.text
          }
        })
      )
    }
  )
)

files.forEach(file =>
  createNode({...})
)

How can I update const files so that it will:

  1. Run getFile(), if entry.type !== "tree"
  2. If entry.type is tree, get an array of files inside the tree with getTree() and then run getFile() for each file.
  3. Combine all results in one array, so that I can apply to them createNode.

I would really appreciate your help.


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.