@itxch/contentful-import
Version:
This tool allows you to import JSON dump exported by contentful-export
165 lines (164 loc) • 6.16 kB
JavaScript
"use strict";
const Table = require("cli-table3");
const differenceInSeconds = require("date-fns/differenceInSeconds");
const formatDistance = require("date-fns/formatDistance");
const Listr = require("listr");
const UpdateRenderer = require("listr-update-renderer");
const verboseRenderer = require("listr-verbose-renderer");
const lodashEs = require("lodash-es");
const PQueue = require("p-queue");
const logging_js = require("contentful-batch-libs/dist/logging.js");
const listr_js = require("contentful-batch-libs/dist/listr.js");
const initClient = require("./tasks/init-client.cjs");
const getDestinationData = require("./tasks/get-destination-data.cjs");
const pushToSpace = require("./tasks/push-to-space/push-to-space.cjs");
const transformSpace = require("./transform/transform-space.cjs");
const validations = require("./utils/validations.cjs");
const parseOptions = require("./parseOptions.cjs");
const errors = require("./utils/errors.cjs");
const ONE_SECOND = 1e3;
const tableOptions = {
// remove ANSI color codes for better CI/CD compatibility
style: { head: [], border: [] }
};
function createListrOptions(options) {
if (options.useVerboseRenderer) {
return {
renderer: verboseRenderer
};
}
return {
renderer: UpdateRenderer,
collapse: false
};
}
async function runContentfulImport(params) {
const log = [];
const options = await parseOptions(params);
const listrOptions = createListrOptions(options);
const requestQueue = new PQueue.default({
interval: ONE_SECOND,
intervalCap: options.rateLimit,
carryoverConcurrencyCount: true
});
logging_js.setupLogging(log.filter((log2) => log2.level !== "info"));
const infoTable = new Table(tableOptions);
infoTable.push([{ colSpan: 2, content: "The following entities are going to be imported:" }]);
Object.keys(options.content).forEach((type) => {
if (options.skipLocales && type === "locales") {
return;
}
if (options.skipContentModel && ["contentTypes", "editorInterfaces"].indexOf(type) >= 0) {
return;
}
if (options.contentModelOnly && !(["contentTypes", "editorInterfaces", "locales"].indexOf(type) >= 0)) {
return;
}
infoTable.push([lodashEs.startCase(type), options.content[type].length]);
});
console.log(infoTable.toString());
const tasks = new Listr([
{
title: "Validating content-file",
task: () => {
validations.assertPayload(options.content);
}
},
{
title: "Initialize client",
task: listr_js.wrapTask(async (ctx) => {
ctx.client = initClient({ ...options, content: void 0 });
})
},
{
title: "Checking if destination space already has any content and retrieving it",
task: listr_js.wrapTask(async (ctx) => {
const destinationData = await getDestinationData({
client: ctx.client,
spaceId: options.spaceId,
environmentId: options.environmentId,
sourceData: options.content,
skipLocales: options.skipLocales,
skipContentModel: options.skipContentModel,
requestQueue
});
ctx.sourceDataUntransformed = options.content;
ctx.destinationData = destinationData;
validations.assertDefaultLocale(ctx.sourceDataUntransformed, ctx.destinationData);
})
},
{
title: "Apply transformations to source data",
task: listr_js.wrapTask(async (ctx) => {
const transformedSourceData = transformSpace(ctx.sourceDataUntransformed, ctx.destinationData);
ctx.sourceData = transformedSourceData;
})
},
{
title: "Push content to destination space",
task: (ctx) => {
return pushToSpace({
sourceData: ctx.sourceData,
destinationData: ctx.destinationData,
client: ctx.client,
spaceId: options.spaceId,
environmentId: options.environmentId,
contentModelOnly: options.contentModelOnly,
skipLocales: options.skipLocales,
skipContentModel: options.skipContentModel,
skipContentPublishing: options.skipContentPublishing,
skipAssetUpdates: options.skipAssetUpdates,
skipContentUpdates: options.skipContentUpdates,
timeout: options.timeout,
retryLimit: options.retryLimit,
uploadAssets: options.uploadAssets,
assetsDirectory: options.assetsDirectory,
listrOptions,
requestQueue
});
}
}
], listrOptions);
return tasks.run({
data: {}
}).then((ctx) => {
console.log("Finished importing all data");
const resultTypes = Object.keys(ctx.data);
if (resultTypes.length) {
const resultTable = new Table(tableOptions);
resultTable.push([{ colSpan: 2, content: "Imported entities" }]);
resultTypes.forEach((type) => {
resultTable.push([lodashEs.startCase(type), ctx.data[type].length]);
});
console.log(resultTable.toString());
} else {
console.log("No data was imported");
}
const endTime = /* @__PURE__ */ new Date();
const durationHuman = formatDistance(endTime, options.startTime);
const durationSeconds = differenceInSeconds(endTime, options.startTime);
console.log(`The import took ${durationHuman} (${durationSeconds}s)`);
return ctx.data;
}).catch((err) => {
log.push({
ts: (/* @__PURE__ */ new Date()).toJSON(),
level: "error",
error: err
});
}).then((data) => {
const errorLog = log.filter((logMessage) => logMessage.level !== "info" && logMessage.level !== "warning");
const displayLog = log.filter((logMessage) => logMessage.level !== "info");
logging_js.displayErrorLog(displayLog);
if (errorLog.length) {
return logging_js.writeErrorLogFile(options.errorLogFile, errorLog).then(() => {
const multiError = new errors.ContentfulMultiError("Errors occurred");
multiError.name = "ContentfulMultiError";
multiError.errors = errorLog;
throw multiError;
});
}
console.log("The import was successful.");
return data;
});
}
module.exports = runContentfulImport;