contentful-export
Version:
this tool allows you to export a space to a JSON dump
250 lines (246 loc) • 8.65 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = getFullSourceSpace;
var _bluebird = _interopRequireDefault(require("bluebird"));
var _contentfulBatchLibs = require("contentful-batch-libs");
var _listr = _interopRequireDefault(require("listr"));
var _listrVerboseRenderer = _interopRequireDefault(require("listr-verbose-renderer"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const MAX_ALLOWED_LIMIT = 1000;
let pageLimit = MAX_ALLOWED_LIMIT;
/**
* Gets all the content from a space via the management API. This includes
* content in draft state.
*/
function getFullSourceSpace({
client,
cdaClient,
spaceId,
environmentId = 'master',
skipContentModel,
skipContent,
skipWebhooks,
skipRoles,
skipEditorInterfaces,
skipTags,
stripTags,
includeDrafts,
includeArchived,
maxAllowedLimit,
listrOptions,
queryEntries,
queryAssets
}) {
pageLimit = maxAllowedLimit || MAX_ALLOWED_LIMIT;
listrOptions = listrOptions || {
renderer: _listrVerboseRenderer.default
};
return new _listr.default([{
title: 'Connecting to space',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
return client.getSpace(spaceId).then(space => {
ctx.space = space;
return space.getEnvironment(environmentId);
}).then(environment => {
ctx.environment = environment;
});
})
}, {
title: 'Fetching content types data',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
return pagedGet({
source: ctx.environment,
method: 'getContentTypes'
}).then(extractItems).then(items => {
ctx.data.contentTypes = items;
});
}),
skip: () => skipContentModel
}, {
title: 'Fetching tags data',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
return pagedGet({
source: ctx.environment,
method: 'getTags'
}).then(extractItems).then(items => {
ctx.data.tags = items;
}).catch(() => {
ctx.data.tags = [];
});
}),
skip: () => skipTags
}, {
title: 'Fetching editor interfaces data',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
return getEditorInterfaces(ctx.data.contentTypes).then(editorInterfaces => {
ctx.data.editorInterfaces = editorInterfaces.filter(editorInterface => {
return editorInterface !== null;
});
});
}),
skip: ctx => skipContentModel || skipEditorInterfaces || ctx.data.contentTypes.length === 0 && 'Skipped since no content types downloaded'
}, {
title: 'Fetching content entries data',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
const source = (cdaClient === null || cdaClient === void 0 ? void 0 : cdaClient.withAllLocales) || ctx.environment;
if (cdaClient) {
// let's not fetch children when using Content Delivery API
queryEntries = queryEntries || {};
queryEntries.include = 0;
}
return pagedGet({
source,
method: 'getEntries',
query: queryEntries
}).then(extractItems).then(items => filterDrafts(items, includeDrafts, cdaClient)).then(items => filterArchived(items, includeArchived)).then(items => removeTags(items, stripTags)).then(items => {
ctx.data.entries = items;
});
}),
skip: () => skipContent
}, {
title: 'Fetching assets data',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
const source = (cdaClient === null || cdaClient === void 0 ? void 0 : cdaClient.withAllLocales) || ctx.environment;
queryAssets = queryAssets || {};
return pagedGet({
source,
method: 'getAssets',
query: queryAssets
}).then(extractItems).then(items => filterDrafts(items, includeDrafts, cdaClient)).then(items => filterArchived(items, includeArchived)).then(items => removeTags(items, stripTags)).then(items => {
ctx.data.assets = items;
});
}),
skip: () => skipContent
}, {
title: 'Fetching locales data',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
return pagedGet({
source: ctx.environment,
method: 'getLocales'
}).then(extractItems).then(items => {
ctx.data.locales = items;
});
}),
skip: () => skipContentModel
}, {
title: 'Fetching webhooks data',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
return pagedGet({
source: ctx.space,
method: 'getWebhooks'
}).then(extractItems).then(items => {
ctx.data.webhooks = items;
});
}),
skip: () => skipWebhooks || environmentId !== 'master' && 'Webhooks can only be exported from master environment'
}, {
title: 'Fetching roles data',
task: (0, _contentfulBatchLibs.wrapTask)(ctx => {
return pagedGet({
source: ctx.space,
method: 'getRoles'
}).then(extractItems).then(items => {
ctx.data.roles = items;
});
}),
skip: () => skipRoles || environmentId !== 'master' && 'Roles can only be exported from master environment'
}], listrOptions);
}
function getEditorInterfaces(contentTypes) {
return _bluebird.default.map(contentTypes, contentType => {
return contentType.getEditorInterface().then(editorInterface => {
_contentfulBatchLibs.logEmitter.emit('info', `Fetched editor interface for ${contentType.name}`);
return editorInterface;
}).catch(() => {
// old contentTypes may not have an editor interface but we'll handle in a later stage
// but it should not stop getting the data process
_contentfulBatchLibs.logEmitter.emit('warning', `No editor interface found for ${contentType}`);
return _bluebird.default.resolve(null);
});
}, {
concurrency: 6
});
}
/**
* Gets all the existing entities based on pagination parameters.
* The first call will have no aggregated response. Subsequent calls will
* concatenate the new responses to the original one.
*/
function pagedGet({
source,
method,
skip = 0,
aggregatedResponse = null,
query = null
}) {
const userQueryLimit = query && query.limit;
const fetchedTotal = aggregatedResponse && aggregatedResponse.items.length;
const limit = userQueryLimit ? Math.min(pageLimit, userQueryLimit - fetchedTotal) : pageLimit;
const requestQuery = Object.assign({}, {
skip,
order: 'sys.createdAt,sys.id'
}, query, {
limit
});
return source[method](requestQuery).then(response => {
if (!aggregatedResponse) {
aggregatedResponse = response;
} else {
aggregatedResponse.items = aggregatedResponse.items.concat(response.items);
}
const totalItemsLength = aggregatedResponse.items.length;
const total = response.total;
logPagingStatus(response, requestQuery, userQueryLimit);
const gotAllQueryLimitedItems = userQueryLimit && totalItemsLength >= userQueryLimit;
const gotAllItems = totalItemsLength >= total;
const gotNoItems = totalItemsLength <= 0;
if (gotAllQueryLimitedItems || gotAllItems || gotNoItems) {
return aggregatedResponse;
}
return pagedGet({
source,
method,
skip: skip + response.items.length,
aggregatedResponse,
query
});
});
}
function logPagingStatus(response, requestQuery, userLimit) {
const {
total,
limit,
items
} = response;
const pagedItemsLength = items.length;
// sometimes our pageLimit or queryLimit of 1000 is overridden by the API (like in locales)
const imposedLimit = limit || requestQuery.limit;
const limitedTotal = userLimit ? Math.min(userLimit, total) : total;
const page = Math.ceil(requestQuery.skip / imposedLimit) + 1;
const pages = Math.ceil(limitedTotal / imposedLimit);
_contentfulBatchLibs.logEmitter.emit('info', `Fetched ${pagedItemsLength} of ${total} items (Page ${page}/${pages})`);
}
function extractItems(response) {
return response.items;
}
function filterDrafts(items, includeDrafts, cdaClient) {
// CDA filters drafts based on host, no need to do filtering here
return includeDrafts || cdaClient ? items : items.filter(item => !!item.sys.publishedVersion || !!item.sys.archivedVersion);
}
function filterArchived(items, includeArchived) {
return includeArchived ? items : items.filter(item => !item.sys.archivedVersion);
}
function removeTags(items, stripTags) {
if (stripTags) {
items.forEach(item => {
var _item$metadata;
if ((_item$metadata = item.metadata) !== null && _item$metadata !== void 0 && _item$metadata.tags) {
item.metadata.tags = [];
}
});
}
return items;
}
module.exports = exports.default;