UNPKG

@amplience/dc-cli

Version:
270 lines (269 loc) 12.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.handler = exports.processIndexes = exports.loadAndRewriteWebhooks = exports.doUpdate = exports.doCreate = exports.enrichIndex = exports.updateWebhookIfDifferent = exports.getIndexProperties = exports.storedIndexMapper = exports.filterIndexesById = exports.rewriteIndexNames = exports.validateNoDuplicateIndexNames = exports.replicaList = exports.builder = exports.LOG_FILENAME = exports.desc = exports.command = void 0; const chalk_1 = __importDefault(require("chalk")); const dc_management_sdk_js_1 = require("dc-management-sdk-js"); const path_1 = require("path"); const table_1 = require("table"); const paginator_1 = __importDefault(require("../../common/dc-management-sdk-js/paginator")); const log_helpers_1 = require("../../common/log-helpers"); const table_consts_1 = require("../../common/table/table.consts"); const dynamic_content_client_factory_1 = __importDefault(require("../../services/dynamic-content-client-factory")); const import_service_1 = require("../../services/import.service"); const export_1 = require("./export"); const webhook_rewriter_1 = require("./webhook-rewriter"); exports.command = 'import <dir>'; exports.desc = 'Import Search Index'; const LOG_FILENAME = (platform = process.platform) => (0, log_helpers_1.getDefaultLogPath)('search-index', 'import', platform); exports.LOG_FILENAME = LOG_FILENAME; const builder = (yargs) => { yargs.positional('dir', { describe: 'Directory containing Search Indexes', type: 'string' }); yargs.option('logFile', { type: 'string', default: exports.LOG_FILENAME, describe: 'Path to a log file to write to.', coerce: log_helpers_1.createLog }); yargs.option('webhooks', { type: 'boolean', describe: 'Import webhooks as well. The command will attempt to rewrite account names and staging environments in the webhook body to match the destination.', boolean: true }); }; exports.builder = builder; const searchIndexList = (hub, parentId, projection) => { return (options) => hub.related.searchIndexes.list(parentId, projection, options); }; const replicaList = (index, projection) => { return (options) => index.related.replicas.list(projection, options); }; exports.replicaList = replicaList; const validateNoDuplicateIndexNames = (importedIndexes) => { const nameToFilenameMap = new Map(); for (const [filename, index] of Object.entries(importedIndexes)) { if (index.name) { const otherFilenames = nameToFilenameMap.get(index.name) || []; if (filename) { nameToFilenameMap.set(index.name, [...otherFilenames, filename]); } } } const uniqueDuplicateNames = []; nameToFilenameMap.forEach((filenames, name) => { if (filenames.length > 1) { uniqueDuplicateNames.push([name, filenames]); } }); if (uniqueDuplicateNames.length > 0) { throw new Error(`Indexes must have unique name values. Duplicate values found:-\n${uniqueDuplicateNames .map(([name, filenames]) => ` name: '${name}' in files: [${filenames.map(f => `'${f}'`).join(', ')}]`) .join('\n')}`); } }; exports.validateNoDuplicateIndexNames = validateNoDuplicateIndexNames; const rewriteIndexName = (hub, index) => { const name = index.name; const firstDot = name.indexOf('.'); if (firstDot == -1) { index.name = `${hub.name}.${name}`; } else { index.name = `${hub.name}${name.substring(firstDot)}`; } }; const rewriteIndexNames = (hub, importedIndexes) => { const toRewrite = [...Object.values(importedIndexes)]; for (const index of Object.values(importedIndexes)) { rewriteIndexName(hub, index); if (index.replicas) { for (const replica of index.replicas) { const name = replica.name; rewriteIndexName(hub, replica); const sReplicas = index.settings.replicas; if (sReplicas) { for (let i = 0; i < sReplicas.length; i++) { if (sReplicas[i] === name) { sReplicas[i] = replica.name; } } } } toRewrite.push(...index.replicas); } } }; exports.rewriteIndexNames = rewriteIndexNames; const filterIndexesById = (idFilter, importedIndexes) => { for (const [filename, index] of Object.entries(importedIndexes)) { if (idFilter.indexOf(index.id) === -1) { delete importedIndexes[filename]; } } }; exports.filterIndexesById = filterIndexesById; const storedIndexMapper = (index, storedIndexes) => { const found = storedIndexes.find(stored => stored.name === index.name); const mutatedIndex = found ? { ...index, id: found.id } : index; return new export_1.EnrichedSearchIndex(mutatedIndex); }; exports.storedIndexMapper = storedIndexMapper; const getIndexProperties = (index) => { return { label: index.label, name: index.name, suffix: index.suffix, type: index.type }; }; exports.getIndexProperties = getIndexProperties; const updateWebhookIfDifferent = async (webhook, newWebhook) => { if (newWebhook === undefined) { return; } await webhook.related.update(newWebhook); }; exports.updateWebhookIfDifferent = updateWebhookIfDifferent; const enrichIndex = async (hub, index, enrichedIndex, webhooks) => { const settings = await index.related.settings.get(); const replicas = new Set(settings.replicas || []); if (enrichedIndex.settings.replicas) { enrichedIndex.settings.replicas.forEach((replica) => { replicas.add(replica); }); } enrichedIndex.settings.replicas = Array.from(replicas); const hasReplicas = replicas.size; await index.related.settings.update(enrichedIndex.settings, false, { waitUntilApplied: hasReplicas ? ['replicas'] : false }); index = await hub.related.searchIndexes.get(index.id); if (hasReplicas) { const listOfReplicas = await (0, paginator_1.default)((0, exports.replicaList)(index)); await Promise.all(enrichedIndex.replicas.map(async (importReplica) => { let replica = listOfReplicas.find(replica => replica.name === importReplica.name); if (replica) { replica = await replica.related.update(new dc_management_sdk_js_1.SearchIndex((0, exports.getIndexProperties)(importReplica))); return replica.related.settings.update(importReplica.settings, false); } })); } const types = await (0, paginator_1.default)(index.related.assignedContentTypes.list); const unassigned = new Set(types); for (const assignment of enrichedIndex.assignedContentTypes) { let existing = types.find(type => type.contentTypeUri === assignment.contentTypeUri); if (!existing) { existing = await index.related.assignedContentTypes.create(assignment); } unassigned.delete(existing); if (webhooks) { await (0, exports.updateWebhookIfDifferent)(await existing.related.webhook(), webhooks.get(assignment.webhook)); await (0, exports.updateWebhookIfDifferent)(await existing.related.activeContentWebhook(), webhooks.get(assignment.activeContentWebhook)); await (0, exports.updateWebhookIfDifferent)(await existing.related.archivedContentWebhook(), webhooks.get(assignment.archivedContentWebhook)); } } for (const toRemove of unassigned) { await toRemove.related.unassign(index.id); } }; exports.enrichIndex = enrichIndex; const doCreate = async (hub, index, webhooks, log) => { try { const assignedContentTypes = index.assignedContentTypes.map(type => ({ contentTypeUri: type.contentTypeUri })); const toCreate = new dc_management_sdk_js_1.SearchIndex({ ...(0, exports.getIndexProperties)(index), assignedContentTypes }); const createdIndex = await hub.related.searchIndexes.create(toCreate); await (0, exports.enrichIndex)(hub, createdIndex, index, webhooks); log.addAction('CREATE', `${createdIndex.id}`); return createdIndex; } catch (err) { throw new Error(`Error creating index ${index.name}: ${err}`); } }; exports.doCreate = doCreate; const doUpdate = async (hub, allReplicas, index, webhooks, log) => { try { const retrievedIndex = await hub.related.searchIndexes.get(index.id); const dstWebhooks = new Map(); const enrichedWebhook = await (0, export_1.enrichIndex)(dstWebhooks, allReplicas, retrievedIndex); if ((0, export_1.equals)(enrichedWebhook, index, false, dstWebhooks, webhooks)) { return { index: retrievedIndex, updateStatus: import_service_1.UpdateStatus.SKIPPED }; } Object.assign(retrievedIndex, (0, exports.getIndexProperties)(index)); const updatedIndex = await retrievedIndex.related.update(retrievedIndex); await (0, exports.enrichIndex)(hub, updatedIndex, index, webhooks); log.addAction('UPDATE', `${retrievedIndex.id}`); return { index: updatedIndex, updateStatus: import_service_1.UpdateStatus.UPDATED }; } catch (err) { throw new Error(`Error updating index ${index.name}: ${err}`); } }; exports.doUpdate = doUpdate; const loadAndRewriteWebhooks = async (hub, dir) => { const webhookList = (0, import_service_1.loadJsonFromDirectory)(dir, dc_management_sdk_js_1.Webhook); const webhooks = new Map(); for (const webhook of Object.values(webhookList)) { webhooks.set(webhook.id, webhook); } const account = hub.name; const settings = hub.settings; const vseObj = settings.virtualStagingEnvironment; const vse = vseObj ? vseObj.hostname : undefined; webhooks.forEach(webhook => { if (webhook.customPayload) { webhook.customPayload.value = (0, webhook_rewriter_1.rewriteDeliveryContentItem)(webhook.customPayload.value, account, vse); } }); return webhooks; }; exports.loadAndRewriteWebhooks = loadAndRewriteWebhooks; const processIndexes = async (indexesToProcess, allReplicas, webhooks, hub, log) => { const data = []; data.push([chalk_1.default.bold('ID'), chalk_1.default.bold('Name'), chalk_1.default.bold('Result')]); for (const entry of indexesToProcess) { let status; let index; if (entry.id) { const result = await (0, exports.doUpdate)(hub, allReplicas, entry, webhooks, log); index = result.index; status = result.updateStatus === import_service_1.UpdateStatus.SKIPPED ? 'UP-TO-DATE' : 'UPDATED'; } else { index = await (0, exports.doCreate)(hub, entry, webhooks, log); status = 'CREATED'; } data.push([index.id, index.name, status]); } log.appendLine((0, table_1.table)(data, table_consts_1.streamTableOptions)); }; exports.processIndexes = processIndexes; const handler = async (argv, idFilter) => { const { dir, logFile } = argv; const client = (0, dynamic_content_client_factory_1.default)(argv); const hub = await client.hubs.get(argv.hubId); const log = logFile.open(); const indexes = (0, import_service_1.loadJsonFromDirectory)(dir, export_1.EnrichedSearchIndex); if (Object.keys(indexes).length === 0) { log.appendLine(`No search indexes found in ${dir}`); await log.close(); return; } (0, exports.validateNoDuplicateIndexNames)(indexes); (0, exports.rewriteIndexNames)(hub, indexes); if (idFilter) { (0, exports.filterIndexesById)(idFilter, indexes); } const allStoredIndexes = await (0, paginator_1.default)(searchIndexList(hub)); const { storedIndexes, allReplicas } = (0, export_1.separateReplicas)(allStoredIndexes); const indexesToProcess = Object.values(indexes).map(index => (0, exports.storedIndexMapper)(index, storedIndexes)); const webhooks = argv.webhooks ? await (0, exports.loadAndRewriteWebhooks)(hub, (0, path_1.join)(dir, 'webhooks')) : undefined; await (0, exports.processIndexes)(indexesToProcess, allReplicas, webhooks, hub, log); await log.close(); }; exports.handler = handler;