diff --git a/packages/gatsby-source-contentful/src/normalize.js b/packages/gatsby-source-contentful/src/normalize.js index 974d4df2e0e3f..b77593dcf3551 100644 --- a/packages/gatsby-source-contentful/src/normalize.js +++ b/packages/gatsby-source-contentful/src/normalize.js @@ -220,11 +220,89 @@ function prepareJSONNode(id, node, key, content) { return JSONNode } +let numberOfContentSyncDebugLogs = 0 +const maxContentSyncDebugLogTimes = 50 + +/** + * This fn creates node manifests which are used for Gatsby Cloud Previews via the Content Sync API/feature. + * Content Sync routes a user from Contentful to a page created from the entry data they're interested in previewing. + */ +function contentfulCreateNodeManifest({ + pluginConfig, + syncToken, + entryItem, + entryNode, + space, + unstable_createNodeManifest, +}) { + const isPreview = pluginConfig.get(`host`) === `preview.contentful.com` + + const createNodeManifestIsSupported = + typeof unstable_createNodeManifest === `function` + + const cacheExists = !!syncToken + + const shouldCreateNodeManifest = + isPreview && + createNodeManifestIsSupported && + // and this is a delta update + (cacheExists || + // or this entry/node was updated in the last 2 days. + // we don't want older nodes because we only want to create + // node manifests for recently updated/created content. + (entryItem.sys.updatedAt && + Date.now() - new Date(entryItem.sys.updatedAt).getTime() <= + // milliseconds + 1000 * + // seconds + 60 * + // minutes + 60 * + // hours + (Number( + process.env.CONTENT_SYNC_CONTENTFUL_HOURS_SINCE_ENTRY_UPDATE + ) || 48))) + + const manifestId = `${space.sys.id}-${entryItem.sys.id}-${entryItem.sys.updatedAt}` + + if ( + process.env.CONTENTFUL_DEBUG_NODE_MANIFEST === `true` && + numberOfContentSyncDebugLogs <= maxContentSyncDebugLogTimes + ) { + numberOfContentSyncDebugLogs++ + + console.info( + JSON.stringify({ + cacheExists, + isPreview, + createNodeManifestIsSupported, + shouldCreateNodeManifest, + manifestId, + entryItemSysUpdatedAt: entryItem.sys.updatedAt, + }) + ) + } + + if (shouldCreateNodeManifest) { + console.info(`Contentful: Creating node manifest with id ${manifestId}`) + + unstable_createNodeManifest({ + manifestId, + node: entryNode, + }) + } else if (isPreview && !createNodeManifestIsSupported) { + console.warn( + `Contentful: Your version of Gatsby core doesn't support Content Sync (via the unstable_createNodeManifest action). Please upgrade to the latest version to use Content Sync in your site.` + ) + } +} + export const createNodesForContentType = ({ contentTypeItem, restrictedNodeFields, conflictFieldPrefix, entries, + unstable_createNodeManifest, createNode, createNodeId, getNode, @@ -234,6 +312,7 @@ export const createNodesForContentType = ({ locales, space, useNameForId, + syncToken, pluginConfig, }) => { // Establish identifier for content type @@ -419,6 +498,15 @@ export const createNodesForContentType = ({ }, } + contentfulCreateNodeManifest({ + pluginConfig, + syncToken, + entryItem, + entryNode, + space, + unstable_createNodeManifest, + }) + // Revision applies to entries, assets, and content types if (entryItem.sys.revision) { entryNode.sys.revision = entryItem.sys.revision diff --git a/packages/gatsby-source-contentful/src/source-nodes.js b/packages/gatsby-source-contentful/src/source-nodes.js index 2228a018a2cfa..7cb6e7f79b1b8 100644 --- a/packages/gatsby-source-contentful/src/source-nodes.js +++ b/packages/gatsby-source-contentful/src/source-nodes.js @@ -54,7 +54,8 @@ export async function sourceNodes( }, pluginOptions ) { - const { createNode, touchNode, deleteNode } = actions + const { createNode, touchNode, deleteNode, unstable_createNodeManifest } = + actions const online = await isOnline() if ( @@ -427,6 +428,8 @@ export async function sourceNodes( space, useNameForId: pluginConfig.get(`useNameForId`), pluginConfig, + syncToken, + unstable_createNodeManifest, }) ) }