UNPKG

gatsby-source-contentful

Version:

Gatsby source plugin for building websites using the Contentful CMS as a data source

118 lines (113 loc) 3.96 kB
"use strict"; exports.__esModule = true; exports.addNodeToExistingNodesCache = addNodeToExistingNodesCache; exports.existingNodes = void 0; exports.getExistingCachedNodes = getExistingCachedNodes; exports.is = void 0; exports.removeNodeFromExistingNodesCache = removeNodeFromExistingNodesCache; var _index = require("gatsby-plugin-utils/index"); var _datastore = require("gatsby/dist/datastore"); var _utils = require("./utils"); // @ts-check // Array of all existing Contentful nodes. Make it global and incrementally update it because it's hella slow to recreate this on every data update for large sites. const existingNodes = new Map(); exports.existingNodes = existingNodes; let allNodesLoopCount = 0; // "is" === object so it can be overridden by tests const is = { firstSourceNodesCallOfCurrentNodeProcess: true }; exports.is = is; async function getExistingCachedNodes({ actions, getNode, pluginConfig }) { const { touchNode } = actions; const needToTouchNodes = !(0, _index.hasFeature)(`stateful-source-nodes`) && is.firstSourceNodesCallOfCurrentNodeProcess; if (existingNodes.size === 0) { memoryNodeCountsBySysType.Asset = 0; memoryNodeCountsBySysType.Entry = 0; const dataStore = (0, _datastore.getDataStore)(); const allNodeTypeNames = Array.from(dataStore.getTypes()); for (const typeName of allNodeTypeNames) { const typeNodes = dataStore.iterateNodesByType(typeName); const firstNodeOfType = Array.from(typeNodes.slice(0, 1))[0]; if (!firstNodeOfType || firstNodeOfType.internal.owner !== `gatsby-source-contentful`) { continue; } for (const node of typeNodes) { if (needToTouchNodes) { var _node$fields; touchNode(node); if (node !== null && node !== void 0 && (_node$fields = node.fields) !== null && _node$fields !== void 0 && _node$fields.includes(`localFile`)) { // Prevent GraphQL type inference from crashing on this property const fullNode = getNode(node.id); const localFileNode = getNode(fullNode.fields.localFile); touchNode(localFileNode); } } if (++allNodesLoopCount % 5000 === 0) { // dont block the event loop await (0, _utils.untilNextEventLoopTick)(); } addNodeToExistingNodesCache(node); } // dont block the event loop await (0, _utils.untilNextEventLoopTick)(); } } is.firstSourceNodesCallOfCurrentNodeProcess = false; return { existingNodes, memoryNodeCountsBySysType }; } const memoryNodeCountsBySysType = { Asset: 0, Entry: 0 }; // store only the fields we need to compare to reduce memory usage. if a node is updated we'll use getNode to grab the whole node before updating it function addNodeToExistingNodesCache(node) { if (node.internal.type === `ContentfulTag`) { return; } if (node.sys.type in memoryNodeCountsBySysType && !existingNodes.has(node.id)) { memoryNodeCountsBySysType[node.sys.type] ||= 0; memoryNodeCountsBySysType[node.sys.type]++; } const cacheNode = { id: node.id, contentful_id: node.contentful_id, sys: { type: node.sys.type }, node_locale: node.node_locale, children: node.children, internal: { owner: node.internal.owner }, __memcache: true }; for (const key of Object.keys(node)) { if (key.endsWith(`___NODE`)) { cacheNode[key] = node[key]; } } existingNodes.set(node.id, cacheNode); } function removeNodeFromExistingNodesCache(node) { if (node.internal.type === `ContentfulTag`) { return; } if (node.sys.type in memoryNodeCountsBySysType && existingNodes.has(node.id)) { memoryNodeCountsBySysType[node.sys.type] ||= 0; memoryNodeCountsBySysType[node.sys.type]--; if (memoryNodeCountsBySysType[node.sys.type] < 0) { memoryNodeCountsBySysType[node.sys.type] = 0; } } existingNodes.delete(node.id); }