UNPKG

@kontent-ai/gatsby-source

Version:
267 lines 15.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.handleIncomingWebhook = void 0; const client = __importStar(require("./client")); const sourceNodes_items_1 = require("./sourceNodes.items"); const naming_1 = require("./naming"); const lodash_1 = __importDefault(require("lodash")); const parseKontentWebhookBody = (api) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r; if (((_b = (_a = api.webhookBody) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.api_name) === "delivery_preview" || ((_d = (_c = api.webhookBody) === null || _c === void 0 ? void 0 : _c.message) === null || _d === void 0 ? void 0 : _d.api_name) === "delivery_production") { const parsedBody = api.webhookBody; const isCorrectStructure = ((_f = (_e = parsedBody === null || parsedBody === void 0 ? void 0 : parsedBody.data) === null || _e === void 0 ? void 0 : _e.items) === null || _f === void 0 ? void 0 : _f.every(item => item.language && item.id)) && ((_g = parsedBody === null || parsedBody === void 0 ? void 0 : parsedBody.message) === null || _g === void 0 ? void 0 : _g.api_name) && ((_h = parsedBody === null || parsedBody === void 0 ? void 0 : parsedBody.message) === null || _h === void 0 ? void 0 : _h.project_id) && ((_j = parsedBody === null || parsedBody === void 0 ? void 0 : parsedBody.message) === null || _j === void 0 ? void 0 : _j.operation) !== null; if (isCorrectStructure) { return parsedBody; } } else if (((_l = (_k = api.webhookBody) === null || _k === void 0 ? void 0 : _k.message) === null || _l === void 0 ? void 0 : _l.api_name) === "content_management") { const parsedBody = api.webhookBody; const isCorrectStructure = ((_o = (_m = parsedBody === null || parsedBody === void 0 ? void 0 : parsedBody.data) === null || _m === void 0 ? void 0 : _m.items) === null || _o === void 0 ? void 0 : _o.every(item => item.language && item.transition_from && item.transition_to && item.item.id)) && ((_p = parsedBody === null || parsedBody === void 0 ? void 0 : parsedBody.message) === null || _p === void 0 ? void 0 : _p.api_name) && ((_q = parsedBody === null || parsedBody === void 0 ? void 0 : parsedBody.message) === null || _q === void 0 ? void 0 : _q.project_id) && ((_r = parsedBody === null || parsedBody === void 0 ? void 0 : parsedBody.message) === null || _r === void 0 ? void 0 : _r.operation) !== null; if (isCorrectStructure) { return parsedBody; } } return null; }; const isKontentSupportedWebhook = (message, pluginConfig) => { var _a; const isCorrectProject = message.project_id === pluginConfig.projectId; const isPreviewWebhook = 'delivery_preview' === message.api_name && ['upsert', 'archive', 'restore'].includes(message.operation); const isBuildWebhook = 'delivery_production' === message.api_name && ['publish', 'unpublish'].includes(message.operation); const isWorkflowWebhook = 'content_management' === message.api_name && message.operation === 'change_workflow_step'; const isCorrectMessageType = message.type == 'content_item_variant'; return isCorrectProject && (isPreviewWebhook || isBuildWebhook || (isWorkflowWebhook && ((_a = pluginConfig === null || pluginConfig === void 0 ? void 0 : pluginConfig.experimental) === null || _a === void 0 ? void 0 : _a.managementApiTriggersUpdate))) && isCorrectMessageType; }; const createNodeFromRawKontentItem = (api, rawKontentItem, includeRawContent, preferredLanguage) => { (0, sourceNodes_items_1.addPreferredLanguageProperty)([rawKontentItem], preferredLanguage); (0, sourceNodes_items_1.alterRichTextElements)([rawKontentItem]); const nodeData = (0, sourceNodes_items_1.getKontentItemLanguageVariantArtifact)(api, rawKontentItem, includeRawContent); api.actions.createNode(nodeData); return nodeData.id; }; const isContentComponent = (data) => { var _a; // Components have substring 01 in its id starting at position 14. // xxxxxxxx-xxxx-01xx-xxxx-xxxxxxxxxxxx const id = (_a = data === null || data === void 0 ? void 0 : data.system) === null || _a === void 0 ? void 0 : _a.id; return id !== null && id.substring(14, 16) === "01"; }; const handleUpsertItem = async (api, pluginConfig, itemId, itemLanguage) => { // TODO - language codename is not provided for management call if (itemLanguage && !pluginConfig.languageCodenames.includes(itemLanguage)) { api.reporter.verbose(`Cant find specified language ${itemLanguage} in plugin configuration`); return []; } // TODO could be optimized to by checking the fallback structure and save some requests // not recreate the ones that has different system.language // be careful on fallback language - verify cz->de->en fallbacks const createdItemsIds = []; for (const lang of pluginConfig.languageCodenames) { const { item: kontentItem, modularKontent } = await client.loadKontentItem(itemId, lang, pluginConfig, true); if (kontentItem === undefined) { api.reporter.verbose(`Item (${itemId}) language variant (${lang}) not found on the kontent.ai delivery API for update`); continue; } const nodeId = createNodeFromRawKontentItem(api, kontentItem, pluginConfig.includeRawContent, lang); createdItemsIds.push(nodeId); for (const key in modularKontent) { if (Object.prototype.hasOwnProperty.call(modularKontent, key)) { const modularKontentItem = modularKontent[key]; const nodeId = createNodeFromRawKontentItem(api, modularKontentItem, pluginConfig.includeRawContent, lang); createdItemsIds.push(nodeId); } } } return createdItemsIds; }; const handleDeleteItem = async (api, pluginConfig) => { var _a, _b, _c; const itemInfo = (_a = api.webhookBody) === null || _a === void 0 ? void 0 : _a.data.items[0]; if (!pluginConfig.languageCodenames.includes(itemInfo.language)) { api.reporter.verbose(`Cant find specified language ${itemInfo.language} in plugin configuration`); return []; } // TODO could be optimized to by checking the fallback structure and save some requests // not recreate the ones that has different system.language // be careful on fallback language - verify cz->de->en fallbacks const touchedItemsIds = []; for (const lang of pluginConfig.languageCodenames) { const { item: kontentItem, modularKontent } = await client.loadKontentItem(itemInfo.id, lang, pluginConfig, true); if (kontentItem === undefined) { //item was deleted (with content components) const idString = (0, naming_1.getKontentItemNodeStringForId)(itemInfo.id, lang); const node = api.getNode(api.createNodeId(idString)); if (!node) { api.reporter.warn(`Node with ${idString} not found - skipping`); continue; } // Remove content components const kontentItemNodes = api.getNodes() .filter((node) => node.internal.type.startsWith((0, naming_1.getKontentItemInterfaceName)())) .map(node => node); const modularItemCodenames = lodash_1.default.flatMap(Object.values(node.elements) .filter(element => element.type === naming_1.RICH_TEXT_ELEMENT_TYPE_NAME) .map(richTextElement => richTextElement.modular_content)); modularItemCodenames.forEach(modularItemCodename => { const candidate = kontentItemNodes.find((candidateNode) => { var _a; return ((_a = candidateNode === null || candidateNode === void 0 ? void 0 : candidateNode.system) === null || _a === void 0 ? void 0 : _a.codename) === modularItemCodename && candidateNode[naming_1.PREFERRED_LANGUAGE_IDENTIFIER] === node[naming_1.PREFERRED_LANGUAGE_IDENTIFIER]; }); if (candidate && isContentComponent(candidate)) { touchedItemsIds.push(candidate.id); api.actions.deleteNode(candidate); } }); if (node) { touchedItemsIds.push(node.id); api.actions.deleteNode(node); } continue; } else { // fallback version still available const nodeId = createNodeFromRawKontentItem(api, kontentItem, pluginConfig.includeRawContent, lang); touchedItemsIds.push(nodeId); for (const key in modularKontent) { if (Object.prototype.hasOwnProperty.call(modularKontent, key)) { const modularKontentItem = modularKontent[key]; const nodeId = createNodeFromRawKontentItem(api, modularKontentItem, pluginConfig.includeRawContent, lang); touchedItemsIds.push(nodeId); } } } } if (((_b = api.webhookBody) === null || _b === void 0 ? void 0 : _b.data.items.length) > 1) { api.reporter.verbose(`Webhook contains more than one item for un-publish operation - upserting all (all but first in webhook) related items.`); for (const relatedItem of (_c = api.webhookBody) === null || _c === void 0 ? void 0 : _c.data.items.slice(1)) { api.reporter.verbose(`Upserting item ${relatedItem.codename} (${relatedItem.codename}) - ${relatedItem.language}`); const processedIds = await handleUpsertItem(api, pluginConfig, relatedItem.id, relatedItem.language); touchedItemsIds.push(...processedIds); } } return touchedItemsIds; }; const handleIncomingWebhook = async (api, pluginConfig, itemTypes) => { var _a; const webhook = parseKontentWebhookBody(api); if (webhook === null) { api.reporter.verbose('Webhook ignored - webhook does not come from Kontent.ai'); return; } if (!isKontentSupportedWebhook(webhook.message, pluginConfig)) { api.reporter.verbose('This Kontent.ai webhook is not handled by the Gatsby source kontent source plugin'); return; } api.reporter.verbose(`Handling ${webhook.message.operation} from ${webhook.message.api_name} API`); if (webhook.data.items.length > 1) { if (webhook.message.operation != 'unpublish') { api.reporter.warn(`Webhook contains more than one item! - contains (${webhook.data.items.length})`); } else { api.reporter.verbose(`Unpublish webhook contains more than one item (${webhook.data.items.length})`); } } const processedItemIds = []; if (webhook.message.api_name === 'delivery_preview') { const item = webhook.data.items[0]; // TODO: Webhook header signature (once headers are available) // use signatureHelper '@kontent-ai/kontent-webhook-helper' // https://github.com/gatsbyjs/gatsby/issues/23593 if (webhook.message.operation === "upsert" || webhook.message.operation === "restore") { const processedIds = await handleUpsertItem(api, pluginConfig, item.id, item.language); processedItemIds.push(...processedIds); } if (webhook.message.operation === "archive") { const processedIds = await handleDeleteItem(api, pluginConfig); processedItemIds.push(...processedIds); } } else if (webhook.message.api_name === 'delivery_production') { const item = webhook.data.items[0]; // TODO: Webhook header signature (once headers are available) // use signatureHelper '@kontent-ai/kontent-webhook-helper' // https://github.com/gatsbyjs/gatsby/issues/23593 if (webhook.message.operation === "publish") { const processedIds = await handleUpsertItem(api, pluginConfig, item.id, item.language); processedItemIds.push(...processedIds); } if (webhook.message.operation === "unpublish") { const processedIds = await handleDeleteItem(api, pluginConfig); processedItemIds.push(...processedIds); } } else if (((_a = pluginConfig === null || pluginConfig === void 0 ? void 0 : pluginConfig.experimental) === null || _a === void 0 ? void 0 : _a.managementApiTriggersUpdate) && webhook.message.api_name === 'content_management') { const item = webhook.data.items[0]; // TODO: Webhook header signature (once headers are available) // use signatureHelper '@kontent-ai/kontent-webhook-helper' // https://github.com/gatsbyjs/gatsby/issues/23593 if (webhook.message.operation === "change_workflow_step") { const processedIds = await handleUpsertItem(api, pluginConfig, item.item.id); processedItemIds.push(...processedIds); } else { api.reporter.verbose(`Operation '${webhook.message.operation}' is not supported yet!`); } } else { api.reporter.verbose(`Webhook is not supported yet!`); api.reporter.verbose(JSON.stringify(webhook, null, 2)); return; } for (const itemType of itemTypes) { const itemsToTouch = api.getNodesByType(itemType); itemsToTouch .filter(item => !processedItemIds.includes(item.id)) .forEach(itemToTouch => api.actions.touchNode(itemToTouch)); } if (pluginConfig.includeTaxonomies) { const taxonomies = api.getNodesByType((0, naming_1.getKontentTaxonomyTypeName)()); for (const taxonomy of taxonomies) { api.actions.touchNode(taxonomy); } } if (pluginConfig.includeTypes) { const types = api.getNodesByType((0, naming_1.getKontentTypeTypeName)()); for (const type of types) { api.actions.touchNode(type); } } }; exports.handleIncomingWebhook = handleIncomingWebhook; //# sourceMappingURL=webhookProcessor.js.map