UNPKG

@amplience/dc-cli

Version:
255 lines (254 loc) 12.8 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.processContentTypes = exports.synchronizeContentTypeRepositories = exports.doSync = exports.doUpdate = exports.doCreate = exports.filterContentTypesById = exports.validateNoDuplicateContentTypeUris = exports.storedContentTypeMapper = exports.ContentTypeWithRepositoryAssignments = exports.builder = exports.LOG_FILENAME = exports.desc = exports.command = void 0; const dynamic_content_client_factory_1 = __importDefault(require("../../services/dynamic-content-client-factory")); const paginator_1 = __importDefault(require("../../common/dc-management-sdk-js/paginator")); const dc_management_sdk_js_1 = require("dc-management-sdk-js"); const lodash_1 = require("lodash"); const table_1 = require("table"); const chalk_1 = __importDefault(require("chalk")); const import_service_1 = require("../../services/import.service"); const table_consts_1 = require("../../common/table/table.consts"); const log_helpers_1 = require("../../common/log-helpers"); const progress_bar_1 = require("../../common/progress-bar/progress-bar"); exports.command = 'import <dir>'; exports.desc = 'Import Content Types'; const LOG_FILENAME = (platform = process.platform) => (0, log_helpers_1.getDefaultLogPath)('type', 'import', platform); exports.LOG_FILENAME = LOG_FILENAME; let notFoundRepositories = []; const builder = (yargs) => { yargs.positional('dir', { describe: 'Path to Content Type definitions', type: 'string' }); yargs.option('sync', { describe: 'Automatically sync Content Type schema', type: 'boolean', default: false }); 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('skipAssign', { describe: 'Skip assigning content types to repositories.', type: 'boolean', default: false }); }; exports.builder = builder; class ContentTypeWithRepositoryAssignments extends dc_management_sdk_js_1.ContentType { } exports.ContentTypeWithRepositoryAssignments = ContentTypeWithRepositoryAssignments; const storedContentTypeMapper = (contentType, storedContentTypes) => { const found = storedContentTypes.find(storedContentType => storedContentType.contentTypeUri === contentType.contentTypeUri); const mutatedContentType = found ? { ...contentType, id: found.id } : contentType; return new ContentTypeWithRepositoryAssignments(mutatedContentType); }; exports.storedContentTypeMapper = storedContentTypeMapper; const validateNoDuplicateContentTypeUris = (importedContentTypes) => { const uriToFilenameMap = new Map(); for (const [filename, contentType] of Object.entries(importedContentTypes)) { if (contentType.contentTypeUri) { const otherFilenames = uriToFilenameMap.get(contentType.contentTypeUri) || []; if (filename) { uriToFilenameMap.set(contentType.contentTypeUri, [...otherFilenames, filename]); } } } const uniqueDuplicateUris = []; uriToFilenameMap.forEach((filenames, uri) => { if (filenames.length > 1) { uniqueDuplicateUris.push([uri, filenames]); } }); if (uniqueDuplicateUris.length > 0) { throw new Error(`Content Types must have unique uri values. Duplicate values found:-\n${uniqueDuplicateUris .map(([uri, filenames]) => ` uri: '${uri}' in files: [${filenames.map(f => `'${f}'`).join(', ')}]`) .join('\n')}`); } }; exports.validateNoDuplicateContentTypeUris = validateNoDuplicateContentTypeUris; const filterContentTypesById = (idFilter, importedContentTypes) => { for (const [filename, contentType] of Object.entries(importedContentTypes)) { if (contentType.contentTypeUri) { if (idFilter.indexOf(contentType.id) === -1) { delete importedContentTypes[filename]; } } } }; exports.filterContentTypesById = filterContentTypesById; const doCreate = async (hub, contentType, log) => { try { const result = await hub.related.contentTypes.register(new dc_management_sdk_js_1.ContentType(contentType)); log.addAction('CREATE', `${result.id}`); return result; } catch (err) { throw new Error(`Error registering content type ${contentType.contentTypeUri}: ${err.message || err}`); } }; exports.doCreate = doCreate; const equals = (a, b) => a.id === b.id && a.contentTypeUri === b.contentTypeUri && (0, lodash_1.isEqual)(a.settings, b.settings); const doUpdate = async (client, contentType, log) => { let retrievedContentType; try { retrievedContentType = await client.contentTypes.get(contentType.id || ''); } catch (err) { throw new Error(`Error unable to get content type ${contentType.id}: ${err.message}`); } if (retrievedContentType.status === dc_management_sdk_js_1.Status.ARCHIVED) { try { retrievedContentType = await retrievedContentType.related.unarchive(); } catch (err) { throw new Error(`Error unable unarchive content type ${contentType.id}: ${err.message}`); } } contentType.settings = { ...retrievedContentType.settings, ...contentType.settings }; let updatedContentType; if (equals(retrievedContentType, contentType)) { return { contentType: retrievedContentType, updateStatus: import_service_1.UpdateStatus.SKIPPED }; } try { updatedContentType = await retrievedContentType.related.update(contentType); log.addAction('UPDATE', `${contentType.id}`); return { contentType: updatedContentType, updateStatus: import_service_1.UpdateStatus.UPDATED }; } catch (err) { throw new Error(`Error updating content type ${contentType.id}: ${err.message || err}`); } }; exports.doUpdate = doUpdate; const doSync = async (client, contentType) => { let retrievedContentType; try { retrievedContentType = await client.contentTypes.get(contentType.id || ''); } catch (err) { throw new Error(`Error unable to get content type ${contentType.id}: ${err.message}`); } try { await retrievedContentType.related.contentTypeSchema.update(); return { contentType: retrievedContentType, updateStatus: import_service_1.UpdateStatus.UPDATED }; } catch (err) { throw new Error(`Error updating the content type schema of the content type ${contentType.id}: ${err.message}`); } }; exports.doSync = doSync; const validateRepositories = (repositories) => Array.isArray(repositories) && repositories.every(repo => typeof repo === 'string'); const synchronizeContentTypeRepositories = async (contentType, namedRepositories) => { if (!validateRepositories(contentType.repositories)) { throw new Error('Invalid format supplied for repositories. Please provide an array of repository names'); } const assignedRepositories = new Map(); namedRepositories.forEach(contentRepository => { const contentRepositoryContentTypes = contentRepository.contentTypes || []; contentRepositoryContentTypes.forEach(assignedContentTypes => { if (assignedContentTypes.hubContentTypeId === contentType.id) { assignedRepositories.set(contentRepository.name || '', contentRepository); } }); }); const contentTypeId = contentType.id || ''; const definedContentRepository = (0, lodash_1.intersection)(contentType.repositories || [], [...namedRepositories.keys()]).filter((value, index, array) => array.indexOf(value) === index); notFoundRepositories = notFoundRepositories.concat((0, lodash_1.difference)(contentType.repositories, [...namedRepositories.keys()])); let changedAssignment = false; for (const repo of definedContentRepository) { if (!assignedRepositories.has(repo)) { const contentRepository = namedRepositories.get(repo); if (!contentRepository) { throw new Error(`Unable to find a Content Repository named: ${repo}`); } await contentRepository.related.contentTypes.assign(contentTypeId); changedAssignment = true; } else { assignedRepositories.delete(repo); } } for (const assignedRepository of assignedRepositories.values()) { await assignedRepository.related.contentTypes.unassign(contentTypeId); changedAssignment = true; } return changedAssignment; }; exports.synchronizeContentTypeRepositories = synchronizeContentTypeRepositories; const processContentTypes = async (contentTypes, client, hub, sync, log, skipAssign = false) => { const contentRepositoryList = await (0, paginator_1.default)(hub.related.contentRepositories.list, {}); const namedRepositories = new Map(contentRepositoryList.map(value => [value.name || '', value])); const progress = (0, progress_bar_1.progressBar)(contentTypes.length, 0, { title: 'Importing content types' }); const data = [[chalk_1.default.bold('ID'), chalk_1.default.bold('Schema ID'), chalk_1.default.bold('Result')]]; for (const contentType of contentTypes) { let status; let contentTypeResult; if (contentType.id) { status = 'UP-TO-DATE'; const result = await (0, exports.doUpdate)(client, contentType, log); if (result.updateStatus === import_service_1.UpdateStatus.UPDATED) { status = 'UPDATED'; } contentTypeResult = result.contentType; if (sync) { const syncResult = await (0, exports.doSync)(client, contentType); if (syncResult.updateStatus === import_service_1.UpdateStatus.UPDATED) { status = 'UPDATED'; } } } else { contentTypeResult = await (0, exports.doCreate)(hub, contentType, log); status = 'CREATED'; } if (contentType.repositories && !skipAssign && (await (0, exports.synchronizeContentTypeRepositories)(new ContentTypeWithRepositoryAssignments({ ...contentType, ...contentTypeResult }), namedRepositories))) { status = contentType.id ? 'UPDATED' : 'CREATED'; } progress.increment(); data.push([contentTypeResult.id || 'UNKNOWN', contentType.contentTypeUri || '', status]); } progress.stop(); log.appendLine((0, table_1.table)(data, table_consts_1.streamTableOptions)); if (!skipAssign && notFoundRepositories.length) { log.appendLine('\nThe following Repositories were not found in destination Hub:'); (0, lodash_1.uniq)(notFoundRepositories).map(name => log.appendLine(` ${name}`)); } else if (skipAssign) { log.appendLine('\nContent types were not automatically registered to the repositories because of --skipAssign argument.'); } }; exports.processContentTypes = processContentTypes; const handler = async (argv, idFilter) => { const { dir, sync, logFile, skipAssign } = argv; const log = logFile.open(); const importedContentTypes = (0, import_service_1.loadJsonFromDirectory)(dir, ContentTypeWithRepositoryAssignments); if (Object.keys(importedContentTypes).length === 0) { log.appendLine(`No content types found in ${dir}`); await log.close(); return; } (0, exports.validateNoDuplicateContentTypeUris)(importedContentTypes); if (idFilter) { (0, exports.filterContentTypesById)(idFilter, importedContentTypes); } const client = (0, dynamic_content_client_factory_1.default)(argv); const hub = await client.hubs.get(argv.hubId); const activeContentTypes = await (0, paginator_1.default)(hub.related.contentTypes.list, { status: dc_management_sdk_js_1.Status.ACTIVE }); const archivedContentTypes = await (0, paginator_1.default)(hub.related.contentTypes.list, { status: dc_management_sdk_js_1.Status.ARCHIVED }); const storedContentTypes = [...activeContentTypes, ...archivedContentTypes]; for (const [filename, importedContentType] of Object.entries(importedContentTypes)) { importedContentTypes[filename] = (0, exports.storedContentTypeMapper)(importedContentType, storedContentTypes); } await (0, exports.processContentTypes)(Object.values(importedContentTypes), client, hub, sync, log, skipAssign); await log.close(); }; exports.handler = handler;