UNPKG

contentful-import

Version:

this tool allows you to import JSON dump exported by contentful-export

280 lines (243 loc) 10.8 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; exports.default = pushToSpace; var _bluebird = require('bluebird'); var _bluebird2 = _interopRequireDefault(_bluebird); var _listr = require('listr'); var _listr2 = _interopRequireDefault(_listr); var _listrVerboseRenderer = require('listr-verbose-renderer'); var _listrVerboseRenderer2 = _interopRequireDefault(_listrVerboseRenderer); var _logging = require('contentful-batch-libs/dist/logging'); var _listr3 = require('contentful-batch-libs/dist/listr'); var _assets = require('./assets'); var assets = _interopRequireWildcard(_assets); var _creation = require('./creation'); var creation = _interopRequireWildcard(_creation); var _publishing = require('./publishing'); var publishing = _interopRequireWildcard(_publishing); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const DEFAULT_CONTENT_STRUCTURE = { entries: [], assets: [], contentTypes: [], tags: [], locales: [], webhooks: [], editorInterfaces: [] /** * Pushes all changes to a given space. Handles (un)publishing * as well as delays after creation and before publishing. * * Creates everything in the right order so that a content type for a given entry * is there when entry creation for that content type is attempted. * * Allows only content model or only content pushing. * * Options: * - sourceData: see DEFAULT_CONTENT_STRUCTURE * - destinationData: see DEFAULT_CONTENT_STRUCTURE * - client: preconfigured management API client * - spaceId: ID of space content is being copied to * - prePublishDelay: milliseconds wait before publishing * - contentModelOnly: synchronizes only content types and locales * - skipLocales: skips locales when synchronizing the content model * - skipContentModel: synchronizes only entries and assets * - skipContentPublishing: create content but don't publish it */ };function pushToSpace({ sourceData, destinationData = {}, client, spaceId, environmentId, prePublishDelay, contentModelOnly, skipContentModel, skipLocales, skipContentPublishing, timeout, retryLimit, listrOptions }) { sourceData = _extends({}, DEFAULT_CONTENT_STRUCTURE, sourceData); destinationData = _extends({}, DEFAULT_CONTENT_STRUCTURE, destinationData); listrOptions = listrOptions || { renderer: _listrVerboseRenderer2.default }; return new _listr2.default([{ title: 'Connecting to space', task: (0, _listr3.wrapTask)((ctx, task) => { return client.getSpace(spaceId).then(space => { ctx.space = space; return space.getEnvironment(environmentId); }).then(environment => { ctx.environment = environment; }); }) }, { title: 'Importing Locales', task: (0, _listr3.wrapTask)((ctx, task) => { return creation.createLocales({ target: ctx.environment, type: 'Locale' }, sourceData.locales, destinationData.locales).then(locales => { ctx.data.locales = locales; }); }), skip: () => skipContentModel || skipLocales }, { title: 'Importing Content Types', task: (0, _listr3.wrapTask)((ctx, task) => { return creation.createEntities({ target: ctx.environment, type: 'ContentType' }, sourceData.contentTypes, destinationData.contentTypes).then(removeEmptyEntities).then(contentTypes => { ctx.data.contentTypes = contentTypes; if (contentTypes.length < 5) { return _bluebird2.default.delay(prePublishDelay); } }); }), skip: () => skipContentModel }, { title: 'Publishing Content Types', task: (0, _listr3.wrapTask)((ctx, task) => { return publishEntities(ctx, task, ctx.data.contentTypes, sourceData.contentTypes).then(removeEmptyEntities).then(contentTypes => { ctx.data.contentTypes = contentTypes; }); }), skip: ctx => skipContentModel }, { title: 'Importing Tags', task: (0, _listr3.wrapTask)((ctx, task) => { return creation.createEntities({ target: ctx.environment, type: 'Tag' }, sourceData.tags, destinationData.tags).then(removeEmptyEntities).then(tags => { ctx.data.tags = tags; }); }), // we remove `tags` from destination data if an error was thrown trying to access them // this means the user doesn't have access to this feature, skip importing tags skip: () => !destinationData.tags }, { title: 'Importing Editor Interfaces', task: (0, _listr3.wrapTask)((ctx, task) => { let contentTypesWithEditorInterface = ctx.data.contentTypes.map(contentType => { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = sourceData.editorInterfaces[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { let editorInterface = _step.value; if (editorInterface.sys.contentType.sys.id === contentType.sys.id) { return ctx.environment.getEditorInterfaceForContentType(contentType.sys.id).then(ctEditorInterface => { _logging.logEmitter.emit('info', `Fetched editor interface for ${contentType.name}`); ctEditorInterface.controls = editorInterface.controls; return ctEditorInterface.update(); }).catch(err => { err.entity = editorInterface; throw err; }); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return _bluebird2.default.resolve(); }); return _bluebird2.default.all(contentTypesWithEditorInterface).then(removeEmptyEntities).then(editorInterfaces => { ctx.data.editorInterfaces = editorInterfaces; }); }), skip: ctx => skipContentModel || ctx.data.contentTypes.length === 0 }, { title: 'Importing Assets', task: (0, _listr3.wrapTask)((ctx, task) => { return creation.createEntities({ target: ctx.environment, type: 'Asset' }, sourceData.assets, destinationData.assets).then(removeEmptyEntities).then(assetsToProcess => { return assets.processAssets(assetsToProcess, { timeout, retryLimit }); }).then(removeEmptyEntities).then(assets => { ctx.data.assets = assets; if (assets.length < 5) { return _bluebird2.default.delay(prePublishDelay); } }); }), skip: ctx => contentModelOnly }, { title: 'Publishing Assets', task: (0, _listr3.wrapTask)((ctx, task) => { return publishEntities(ctx, task, ctx.data.assets, sourceData.assets).then(removeEmptyEntities).then(assets => { ctx.data.publishedAssets = assets; }); }), skip: ctx => contentModelOnly || skipContentPublishing }, { title: 'Archiving Assets', task: (0, _listr3.wrapTask)((ctx, task) => { return archiveEntities(ctx, task, ctx.data.assets, sourceData.assets).then(removeEmptyEntities).then(assets => { ctx.data.archivedAssets = assets; }); }), skip: ctx => contentModelOnly || skipContentPublishing }, { title: 'Importing Content Entries', task: (0, _listr3.wrapTask)((ctx, task) => { return creation.createEntries({ target: ctx.environment, skipContentModel }, sourceData.entries, destinationData.entries).then(removeEmptyEntities).then(entries => { ctx.data.entries = entries; if (entries.length < 5) { return _bluebird2.default.delay(prePublishDelay); } }); }), skip: ctx => contentModelOnly }, { title: 'Publishing Content Entries', task: (0, _listr3.wrapTask)((ctx, task) => { return publishEntities(ctx, task, ctx.data.entries, sourceData.entries).then(removeEmptyEntities).then(entries => { ctx.data.publishedEntries = entries; }); }), skip: ctx => contentModelOnly || skipContentPublishing }, { title: 'Archiving Entries', task: (0, _listr3.wrapTask)((ctx, task) => { return archiveEntities(ctx, task, ctx.data.entries, sourceData.entries).then(removeEmptyEntities).then(entries => { ctx.data.archivedEntries = entries; }); }), skip: ctx => contentModelOnly || skipContentPublishing }, { title: 'Creating Web Hooks', task: (0, _listr3.wrapTask)((ctx, task) => { return creation.createEntities({ target: ctx.space, type: 'Webhook' }, sourceData.webhooks, destinationData.webhooks).then(removeEmptyEntities).then(webhooks => { ctx.data.webhooks = webhooks; }); }), skip: ctx => contentModelOnly || environmentId !== 'master' && 'Webhooks can only be imported in master environment' }], listrOptions); } // In case some entity throws an error, we null it in the list to avoid further processing. // This functions removes the nulled entities from the lists. function removeEmptyEntities(entityList) { return entityList.filter(entity => !!entity && entity.sys); } function archiveEntities(ctx, task, entities, sourceEntities) { const entityIdsToArchive = sourceEntities.filter(({ original }) => original.sys.archivedVersion).map(({ original }) => original.sys.id); const entitiesToArchive = entities.filter(entity => entityIdsToArchive.indexOf(entity.sys.id) !== -1); return publishing.archiveEntities(entitiesToArchive); } function publishEntities(ctx, task, entities, sourceEntities) { // Find all entities in source content which are published const entityIdsToPublish = sourceEntities.filter(({ original }) => original.sys.publishedVersion).map(({ original }) => original.sys.id); // Filter imported entities and publish only these who got published in the source const entitiesToPublish = entities.filter(entity => entityIdsToPublish.indexOf(entity.sys.id) !== -1); return publishing.publishEntities(entitiesToPublish); } module.exports = exports.default;