Source: plugins/gatsby-source-hecate/gatsby-node.js

require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` })
const axios = require("axios")

/**
 * Module to source data from drupal API.
 *
 * First - getDrupal() frunction is used to pull all data.
 *
 * Then - data() function is used to create nodes in gatsby internal source system with createNode native method.
 *
 * @module gatsby-source-hecate
 * @param {Object} actions - Object that holds gatsby method for managing nodes.
 * @param {function} createNode - Function from the actions object, used to create nodes. {@link https://www.gatsbyjs.com/docs/reference/config-files/actions/#createNode|Gatsby Doc : createNode}
 * @param {function} createContentDigest - Function to create hash for caching purpose.
 * @param {Object} configOptions - Object with the configurations declared in gatsby-config.js file at the root of the project.
 */

exports.sourceNodes = async (
  { actions, createContentDigest },
  configOptions
) => {
  const { createNode } = actions
  const { drupal } = configOptions
  const livepreview =
    process.env.API_LIVEPREVIEW === "true" ? "&mode=live_preview" : ""

  /**
   * Function that loop and pull from every endpoints.
   * @async
   * @function getDrupal
   * @returns {Array<Array>} - returns an array of promises that when resolved will holds datas from all sources
   *
   */

  const getDrupal = () =>
    Promise.all(
      drupal.enpoints.map(enpoint => {
        return axios.get(
          drupal.host + enpoint.url + "?offset=0&limit=10000" + livepreview
        )
      })
    ).then(values => {
      return values.map((item, index) => {
        return {
          [drupal.enpoints[index].type]: item.data,
        }
      })
    })

  try {
    const result = await getDrupal()
    /**
     * After pulling all the data and mapping data into the desired shape,
     *
     * createNode is used to create the data node in Gatsby File system via gatsby-source-filesystem plugin
     *
     * @function data
     * @param {Object} data - The data of the node pulled from drupal
     */
    result.map(item => {
      const type = Object.keys(item)[0]
      const data = node => {
        if (node.id) {
          return createNode(
            Object.assign(
              {},
              {
                children: [],
                id: node.id.toString(),
                uuid: node.uuid ? node.uuid : "",
                fr: node.fr ? JSON.stringify(node.fr) : "",
                en: node.en ? JSON.stringify(node.en) : "",
                ...(type === "page" && {
                  drupalType: node.fr.type,
                }),
                category: node.fr ? node.fr.category_id : "",
                type,
                internal: {
                  type,
                  content: JSON.stringify(node),
                  contentDigest: createContentDigest(node),
                },
                parent: null,
              }
            )
          )
        }
      }
      if (Array.isArray(item[type])) {
        // If there are multiple items
        return item[type].map(element => {
          return data(element)
        })
      } else {
        // If not, just create an object
        return data(item[type])
      }
    })
    return
  } catch (error) {
    console.log(error)
  }
}