@dlillyatx/dc-cli
Version:
Dynamic Content CLI Tool
290 lines (289 loc) • 14.3 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.separateReplicas = exports.processWebhooks = exports.filterWebhooks = exports.processIndexes = exports.getIndexExports = exports.getExportedWebhooks = exports.getExportRecordForIndex = exports.enrichIndex = exports.enrichReplica = exports.registerWebhook = exports.filterIndexesById = exports.EnrichedSearchIndex = exports.EnrichedReplica = exports.EnrichedAssignedContentType = exports.equals = exports.ensureSettings = exports.assignedContentTypeEquals = exports.replicaEquals = exports.webhookEquals = 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 AssignedContentType_1 = require("dc-management-sdk-js/build/main/lib/model/AssignedContentType");
const lodash_1 = require("lodash");
const table_1 = require("table");
const paginator_1 = __importDefault(require("../../common/dc-management-sdk-js/paginator"));
const directory_utils_1 = require("../../common/import/directory-utils");
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 export_service_1 = require("../../services/export.service");
const import_service_1 = require("../../services/import.service");
const import_1 = require("./import");
const path_1 = require("path");
exports.command = 'export <dir>';
exports.desc = 'Export Search Indexes';
exports.LOG_FILENAME = (platform = process.platform) => log_helpers_1.getDefaultLogPath('search-index', 'export', platform);
exports.builder = (yargs) => {
yargs
.positional('dir', {
describe: 'Output directory for the exported Search Index definitions',
type: 'string'
})
.option('id', {
type: 'string',
describe: 'The ID of a Search Index to be exported.\nIf no --id option is given, all search indexes for the hub are exported.\nA single --id option may be given to export a single Search Index.\nMultiple --id options may be given to export multiple search indexes at the same time.',
requiresArg: true
})
.alias('f', 'force')
.option('f', {
type: 'boolean',
boolean: true,
describe: 'Overwrite search indexes without asking.'
})
.option('logFile', {
type: 'string',
default: exports.LOG_FILENAME,
describe: 'Path to a log file to write to.',
coerce: log_helpers_1.createLog
});
};
const ensureJSON = (resource) => {
return resource.toJSON != null ? resource.toJSON() : resource;
};
exports.webhookEquals = (a, b) => {
if (a === undefined) {
return b === undefined;
}
else if (b === undefined) {
return false;
}
return (a.method === b.method &&
a.secret === b.secret &&
a.label === b.label &&
a.active === b.active &&
lodash_1.isEqual(a.customPayload, b.customPayload) &&
lodash_1.isEqual(a.events, b.events) &&
lodash_1.isEqual(a.filters, b.filters) &&
lodash_1.isEqual(a.handlers, b.handlers) &&
lodash_1.isEqual(a.headers, b.headers));
};
exports.replicaEquals = (a, b, keys) => a.label === b.label &&
(!keys || lodash_1.isEqual(ensureJSON(a.keys), ensureJSON(b.keys))) &&
lodash_1.isEqual(ensureJSON(a.settings), ensureJSON(b.settings));
exports.assignedContentTypeEquals = (a, b, aWebhooks, bWebhooks) => !(aWebhooks && bWebhooks) ||
(exports.webhookEquals(aWebhooks.get(a.webhook), bWebhooks.get(b.webhook)) &&
exports.webhookEquals(aWebhooks.get(a.activeContentWebhook), bWebhooks.get(b.activeContentWebhook)) &&
exports.webhookEquals(aWebhooks.get(a.archivedContentWebhook), bWebhooks.get(b.archivedContentWebhook)));
exports.ensureSettings = (settings) => {
const result = ensureJSON(settings);
result.replicas = result.replicas || [];
return result;
};
exports.equals = (a, b, keys = true, aWebhooks, bWebhooks) => a.label === b.label &&
a.assignedContentTypes
.map((x, i) => exports.assignedContentTypeEquals(x, b.assignedContentTypes[i], aWebhooks, bWebhooks))
.reduce((a, b) => a && b, true) &&
a.replicas.length == b.replicas.length &&
a.replicas.map((x, i) => exports.replicaEquals(x, b.replicas[i], keys)).reduce((a, b) => a && b, true) &&
(!keys || lodash_1.isEqual(ensureJSON(a.keys), ensureJSON(b.keys))) &&
lodash_1.isEqual(exports.ensureSettings(a.settings), exports.ensureSettings(b.settings));
const searchIndexList = (hub, parentId, projection) => {
return (options) => hub.related.searchIndexes.list(parentId, projection, options);
};
class EnrichedAssignedContentType extends AssignedContentType_1.AssignedContentType {
}
exports.EnrichedAssignedContentType = EnrichedAssignedContentType;
class EnrichedReplica extends dc_management_sdk_js_1.SearchIndex {
}
exports.EnrichedReplica = EnrichedReplica;
class EnrichedSearchIndex extends dc_management_sdk_js_1.SearchIndex {
toJSON() {
const result = super.toJSON();
result.assignedContentTypes = result.assignedContentTypes.map((type) => type.toJSON());
return result;
}
}
exports.EnrichedSearchIndex = EnrichedSearchIndex;
exports.filterIndexesById = (listToFilter, indexIdList) => {
if (indexIdList.length === 0) {
return listToFilter;
}
const unmatchedIndexUriList = indexIdList.filter(id => !listToFilter.some(index => index.id === id));
if (unmatchedIndexUriList.length > 0) {
throw new Error(`The following ID(s) could not be found: [${unmatchedIndexUriList
.map(u => `'${u}'`)
.join(', ')}].\nNothing was exported, exiting.`);
}
return listToFilter.filter(index => indexIdList.some(id => index.id === id));
};
exports.registerWebhook = (mapping, webhook) => {
mapping.set(webhook.id, webhook);
return webhook.id;
};
exports.enrichReplica = async (replica) => {
const enrichedReplica = new EnrichedReplica(replica);
enrichedReplica.settings = await replica.related.settings.get();
enrichedReplica.keys = await replica.related.keys.get();
return enrichedReplica;
};
exports.enrichIndex = async (webhooks, allReplicas, index) => {
const enrichedIndex = new EnrichedSearchIndex(index);
enrichedIndex.settings = await index.related.settings.get();
const types = await paginator_1.default(index.related.assignedContentTypes.list);
enrichedIndex.keys = await index.related.keys.get();
const replicas = allReplicas.get(index.id);
if (replicas) {
enrichedIndex.replicas = await Promise.all(replicas.map(exports.enrichReplica));
}
else {
enrichedIndex.replicas = [];
}
const enrichedTypes = [];
for (const type of types) {
const enriched = new EnrichedAssignedContentType(type);
enriched.webhook = exports.registerWebhook(webhooks, await type.related.webhook());
enriched.activeContentWebhook = exports.registerWebhook(webhooks, await type.related.activeContentWebhook());
enriched.archivedContentWebhook = exports.registerWebhook(webhooks, await type.related.archivedContentWebhook());
enrichedTypes.push(enriched);
}
enrichedIndex.assignedContentTypes = enrichedTypes;
return enrichedIndex;
};
exports.getExportRecordForIndex = (index, outputDir, previouslyExportedIndexes, previouslyExportedWebhooks, webhooksBeingExported) => {
const indexOfExportedIndex = Object.values(previouslyExportedIndexes).findIndex(c => c.name === index.name);
if (indexOfExportedIndex < 0) {
const filename = export_service_1.uniqueFilenamePath(outputDir, index.name, 'json', Object.keys(previouslyExportedIndexes));
previouslyExportedIndexes[filename] = index;
return {
filename: filename,
status: 'CREATED',
index
};
}
const filename = Object.keys(previouslyExportedIndexes)[indexOfExportedIndex];
const previouslyExportedIndex = Object.values(previouslyExportedIndexes)[indexOfExportedIndex];
if (exports.equals(previouslyExportedIndex, index, true, previouslyExportedWebhooks, webhooksBeingExported)) {
return { filename, status: 'UP-TO-DATE', index };
}
return {
filename,
status: 'UPDATED',
index
};
};
exports.getExportedWebhooks = (outputDir) => {
const exportedWebhooks = import_service_1.loadJsonFromDirectory(path_1.join(outputDir, 'webhooks'), dc_management_sdk_js_1.Webhook);
const webhookList = Object.values(exportedWebhooks);
const webhooks = new Map();
for (const webhook of webhookList) {
if (webhook.id) {
webhooks.set(webhook.id, webhook);
}
}
return webhooks;
};
exports.getIndexExports = (outputDir, previouslyExportedIndexes, indexesBeingExported, webhooksBeingExported) => {
const allExports = [];
const updatedExportsMap = [];
const previouslyExportedWebhooks = exports.getExportedWebhooks(outputDir);
for (const index of indexesBeingExported) {
if (!index.name) {
continue;
}
const exportRecord = exports.getExportRecordForIndex(index, outputDir, previouslyExportedIndexes, previouslyExportedWebhooks, webhooksBeingExported);
allExports.push(exportRecord);
if (exportRecord.status === 'UPDATED') {
updatedExportsMap.push({ uri: index.name, filename: exportRecord.filename });
}
}
return [allExports, updatedExportsMap];
};
exports.processIndexes = async (outputDir, previouslyExportedIndexes, indexesBeingExported, webhooksBeingExported, log, force) => {
if (indexesBeingExported.length === 0) {
export_service_1.nothingExportedExit(log, 'No search indexes to export from this hub, exiting.');
return;
}
const [allExports, updatedExportsMap] = exports.getIndexExports(outputDir, previouslyExportedIndexes, indexesBeingExported, webhooksBeingExported);
if (allExports.length === 0 ||
(Object.keys(updatedExportsMap).length > 0 && !(force || (await export_service_1.promptToOverwriteExports(updatedExportsMap, log))))) {
export_service_1.nothingExportedExit(log);
return;
}
await directory_utils_1.ensureDirectoryExists(outputDir);
const data = [];
data.push([chalk_1.default.bold('File'), chalk_1.default.bold('Name'), chalk_1.default.bold('Result')]);
for (const { filename, status, index } of allExports) {
if (status !== 'UP-TO-DATE') {
delete index.id;
export_service_1.writeJsonToFile(filename, index);
}
else {
indexesBeingExported.splice(indexesBeingExported.indexOf(index), 1);
}
data.push([filename, index.name, status]);
}
log.appendLine(table_1.table(data, table_consts_1.streamTableOptions));
};
exports.filterWebhooks = (webhooks, filteredIndexes) => {
const filtered = new Map();
for (const index of filteredIndexes) {
for (const type of index.assignedContentTypes) {
filtered.set(type.webhook, webhooks.get(type.webhook));
filtered.set(type.activeContentWebhook, webhooks.get(type.activeContentWebhook));
filtered.set(type.archivedContentWebhook, webhooks.get(type.archivedContentWebhook));
}
}
return filtered;
};
exports.processWebhooks = async (outputDir, webhooksBeingExported, log) => {
if (webhooksBeingExported.length === 0) {
return;
}
log.appendLine('Exporting Webhooks...');
const previouslyExportedWebhooks = {};
const base = path_1.join(outputDir, 'webhooks');
await directory_utils_1.ensureDirectoryExists(base);
const data = [];
data.push([chalk_1.default.bold('File'), chalk_1.default.bold('Label'), chalk_1.default.bold('Result')]);
for (const webhook of webhooksBeingExported) {
const filename = export_service_1.uniqueFilenamePath(base, webhook.label, 'json', Object.keys(previouslyExportedWebhooks));
previouslyExportedWebhooks[filename] = webhook;
export_service_1.writeJsonToFile(filename, webhook);
data.push([filename, webhook.label, 'UPDATED']);
}
log.appendLine(table_1.table(data, table_consts_1.streamTableOptions));
};
exports.separateReplicas = (allIndexes) => {
const storedIndexes = [];
const allReplicas = new Map();
for (const index of allIndexes) {
if (index.parentId == null) {
storedIndexes.push(index);
}
else {
let list = allReplicas.get(index.parentId);
if (list == null) {
list = [];
allReplicas.set(index.parentId, list);
}
list.push(index);
}
}
return { storedIndexes, allReplicas };
};
exports.handler = async (argv) => {
const { dir, id, logFile, force } = argv;
const client = dynamic_content_client_factory_1.default(argv);
const hub = await client.hubs.get(argv.hubId);
const log = logFile.open();
const previouslyExportedIndexes = import_service_1.loadJsonFromDirectory(dir, EnrichedSearchIndex);
import_1.validateNoDuplicateIndexNames(previouslyExportedIndexes);
const allStoredIndexes = await paginator_1.default(searchIndexList(hub));
const { storedIndexes, allReplicas } = exports.separateReplicas(allStoredIndexes);
const idArray = id ? (Array.isArray(id) ? id : [id]) : [];
const filteredIndexes = exports.filterIndexesById(storedIndexes, idArray);
const webhooks = new Map();
const enrichedIndexes = await Promise.all(filteredIndexes.map(index => exports.enrichIndex(webhooks, allReplicas, index)));
await exports.processIndexes(dir, previouslyExportedIndexes, enrichedIndexes, webhooks, log, force || false);
const filteredWebhooks = exports.filterWebhooks(webhooks, enrichedIndexes);
await exports.processWebhooks(dir, Array.from(filteredWebhooks.values()), log);
await log.close();
};