@amplience/dc-cli
Version:
Dynamic Content CLI Tool
270 lines (269 loc) • 12.6 kB
JavaScript
;
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;