contentful-import 9.1.0 → 9.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1315 -157
- package/dist/index.mjs +1308 -0
- package/package.json +26 -6
- package/dist/parseOptions.js +0 -97
- package/dist/tasks/get-destination-data.js +0 -122
- package/dist/tasks/init-client.js +0 -19
- package/dist/tasks/push-to-space/assets.js +0 -75
- package/dist/tasks/push-to-space/creation.js +0 -178
- package/dist/tasks/push-to-space/publishing.js +0 -100
- package/dist/tasks/push-to-space/push-to-space.js +0 -329
- package/dist/transform/transform-space.js +0 -56
- package/dist/transform/transformers.js +0 -70
- package/dist/usageParams.js +0 -115
- package/dist/utils/headers.js +0 -38
- package/dist/utils/schema.js +0 -87
- package/dist/utils/sort-entries.js +0 -116
- package/dist/utils/sort-locales.js +0 -37
- package/dist/utils/validations.js +0 -54
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1308 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined")
|
|
6
|
+
return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// lib/index.ts
|
|
15
|
+
import Table from "cli-table3";
|
|
16
|
+
import differenceInSeconds from "date-fns/differenceInSeconds";
|
|
17
|
+
import formatDistance from "date-fns/formatDistance";
|
|
18
|
+
import Listr2 from "listr";
|
|
19
|
+
import UpdateRenderer from "listr-update-renderer";
|
|
20
|
+
import VerboseRenderer from "listr-verbose-renderer";
|
|
21
|
+
import { startCase } from "lodash";
|
|
22
|
+
import PQueue from "p-queue";
|
|
23
|
+
import { displayErrorLog, setupLogging, writeErrorLogFile } from "contentful-batch-libs/dist/logging";
|
|
24
|
+
import { wrapTask as wrapTask2 } from "contentful-batch-libs/dist/listr";
|
|
25
|
+
|
|
26
|
+
// lib/tasks/init-client.js
|
|
27
|
+
import { createClient } from "contentful-management";
|
|
28
|
+
import { logEmitter } from "contentful-batch-libs/dist/logging";
|
|
29
|
+
function logHandler(level, data) {
|
|
30
|
+
logEmitter.emit(level, data);
|
|
31
|
+
}
|
|
32
|
+
function initClient(opts) {
|
|
33
|
+
const defaultOpts = {
|
|
34
|
+
timeout: 3e4,
|
|
35
|
+
logHandler
|
|
36
|
+
};
|
|
37
|
+
const config = {
|
|
38
|
+
...defaultOpts,
|
|
39
|
+
...opts
|
|
40
|
+
};
|
|
41
|
+
return createClient(config);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// lib/tasks/get-destination-data.js
|
|
45
|
+
import Promise2 from "bluebird";
|
|
46
|
+
import { logEmitter as logEmitter2 } from "contentful-batch-libs/dist/logging";
|
|
47
|
+
var BATCH_CHAR_LIMIT = 1990;
|
|
48
|
+
var BATCH_SIZE_LIMIT = 100;
|
|
49
|
+
var METHODS = {
|
|
50
|
+
contentTypes: { name: "content types", method: "getContentTypes" },
|
|
51
|
+
locales: { name: "locales", method: "getLocales" },
|
|
52
|
+
entries: { name: "entries", method: "getEntries" },
|
|
53
|
+
assets: { name: "assets", method: "getAssets" }
|
|
54
|
+
};
|
|
55
|
+
async function batchedIdQuery({ environment, type, ids, requestQueue }) {
|
|
56
|
+
const method = METHODS[type].method;
|
|
57
|
+
const entityTypeName = METHODS[type].name;
|
|
58
|
+
const batches = getIdBatches(ids);
|
|
59
|
+
let totalFetched = 0;
|
|
60
|
+
const allPendingResponses = batches.map((idBatch) => {
|
|
61
|
+
return requestQueue.add(async () => {
|
|
62
|
+
const response = await environment[method]({
|
|
63
|
+
"sys.id[in]": idBatch,
|
|
64
|
+
limit: idBatch.split(",").length
|
|
65
|
+
});
|
|
66
|
+
totalFetched = totalFetched + response.items.length;
|
|
67
|
+
logEmitter2.emit("info", `Fetched ${totalFetched} of ${response.total} ${entityTypeName}`);
|
|
68
|
+
return response.items;
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
const responses = await Promise2.all(allPendingResponses);
|
|
72
|
+
return responses.flat();
|
|
73
|
+
}
|
|
74
|
+
function getIdBatches(ids) {
|
|
75
|
+
const batches = [];
|
|
76
|
+
let currentBatch = "";
|
|
77
|
+
let currentSize = 0;
|
|
78
|
+
while (ids.length > 0) {
|
|
79
|
+
const id = ids.splice(0, 1);
|
|
80
|
+
currentBatch += id;
|
|
81
|
+
currentSize = currentSize + 1;
|
|
82
|
+
if (currentSize === BATCH_SIZE_LIMIT || currentBatch.length > BATCH_CHAR_LIMIT || ids.length === 0) {
|
|
83
|
+
batches.push(currentBatch);
|
|
84
|
+
currentBatch = "";
|
|
85
|
+
currentSize = 0;
|
|
86
|
+
} else {
|
|
87
|
+
currentBatch += ",";
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return batches;
|
|
91
|
+
}
|
|
92
|
+
async function getDestinationData({
|
|
93
|
+
client,
|
|
94
|
+
spaceId,
|
|
95
|
+
environmentId,
|
|
96
|
+
sourceData,
|
|
97
|
+
contentModelOnly,
|
|
98
|
+
skipLocales,
|
|
99
|
+
skipContentModel,
|
|
100
|
+
requestQueue
|
|
101
|
+
}) {
|
|
102
|
+
const space = await client.getSpace(spaceId);
|
|
103
|
+
const environment = await space.getEnvironment(environmentId);
|
|
104
|
+
const result = {
|
|
105
|
+
contentTypes: [],
|
|
106
|
+
tags: [],
|
|
107
|
+
locales: [],
|
|
108
|
+
entries: [],
|
|
109
|
+
assets: []
|
|
110
|
+
};
|
|
111
|
+
sourceData = {
|
|
112
|
+
...result,
|
|
113
|
+
...sourceData
|
|
114
|
+
};
|
|
115
|
+
if (!skipContentModel) {
|
|
116
|
+
const contentTypeIds = sourceData.contentTypes.map((e) => e.sys.id);
|
|
117
|
+
result.contentTypes = batchedIdQuery({
|
|
118
|
+
environment,
|
|
119
|
+
type: "contentTypes",
|
|
120
|
+
ids: contentTypeIds,
|
|
121
|
+
requestQueue
|
|
122
|
+
});
|
|
123
|
+
if (!skipLocales) {
|
|
124
|
+
const localeIds = sourceData.locales.map((e) => e.sys.id);
|
|
125
|
+
result.locales = batchedIdQuery({
|
|
126
|
+
environment,
|
|
127
|
+
type: "locales",
|
|
128
|
+
ids: localeIds,
|
|
129
|
+
requestQueue
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
result.tags = environment.getTags().then((response) => response.items).catch((e) => {
|
|
134
|
+
delete result.tags;
|
|
135
|
+
});
|
|
136
|
+
if (contentModelOnly) {
|
|
137
|
+
return Promise2.props(result);
|
|
138
|
+
}
|
|
139
|
+
const entryIds = sourceData.entries.map((e) => e.sys.id);
|
|
140
|
+
const assetIds = sourceData.assets.map((e) => e.sys.id);
|
|
141
|
+
result.entries = batchedIdQuery({
|
|
142
|
+
environment,
|
|
143
|
+
type: "entries",
|
|
144
|
+
ids: entryIds,
|
|
145
|
+
requestQueue
|
|
146
|
+
});
|
|
147
|
+
result.assets = batchedIdQuery({
|
|
148
|
+
environment,
|
|
149
|
+
type: "assets",
|
|
150
|
+
ids: assetIds,
|
|
151
|
+
requestQueue
|
|
152
|
+
});
|
|
153
|
+
result.webhooks = [];
|
|
154
|
+
return Promise2.props(result);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// lib/tasks/push-to-space/push-to-space.js
|
|
158
|
+
import Listr from "listr";
|
|
159
|
+
import verboseRenderer from "listr-verbose-renderer";
|
|
160
|
+
import { logEmitter as logEmitter6 } from "contentful-batch-libs/dist/logging";
|
|
161
|
+
import { wrapTask } from "contentful-batch-libs/dist/listr";
|
|
162
|
+
|
|
163
|
+
// lib/tasks/push-to-space/assets.js
|
|
164
|
+
import fs from "fs";
|
|
165
|
+
import { join } from "path";
|
|
166
|
+
import { promisify } from "util";
|
|
167
|
+
import getEntityName from "contentful-batch-libs/dist/get-entity-name";
|
|
168
|
+
import { logEmitter as logEmitter3 } from "contentful-batch-libs/dist/logging";
|
|
169
|
+
var stat = promisify(fs.stat);
|
|
170
|
+
async function getAssetStreamForURL(url, assetsDirectory) {
|
|
171
|
+
const [, assetPath] = url.split("//");
|
|
172
|
+
const filePath = join(assetsDirectory, assetPath);
|
|
173
|
+
try {
|
|
174
|
+
await stat(filePath);
|
|
175
|
+
return fs.createReadStream(filePath);
|
|
176
|
+
} catch (err) {
|
|
177
|
+
const error = new Error("Cannot open asset from filesystem");
|
|
178
|
+
error.filePath = filePath;
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async function processAssetForLocale(locale, asset, processingOptions) {
|
|
183
|
+
try {
|
|
184
|
+
return await asset.processForLocale(locale, processingOptions);
|
|
185
|
+
} catch (err) {
|
|
186
|
+
err.entity = asset;
|
|
187
|
+
logEmitter3.emit("error", err);
|
|
188
|
+
throw err;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function lastResult(promises) {
|
|
192
|
+
if (!promises.length)
|
|
193
|
+
throw new RangeError("No last result from no promises");
|
|
194
|
+
const results = [];
|
|
195
|
+
await Promise.all(
|
|
196
|
+
promises.map(
|
|
197
|
+
(p) => p.then((v) => {
|
|
198
|
+
results.push(v);
|
|
199
|
+
})
|
|
200
|
+
)
|
|
201
|
+
);
|
|
202
|
+
return results[results.length - 1];
|
|
203
|
+
}
|
|
204
|
+
async function processAssets({
|
|
205
|
+
assets: assets2,
|
|
206
|
+
timeout,
|
|
207
|
+
retryLimit,
|
|
208
|
+
requestQueue
|
|
209
|
+
}) {
|
|
210
|
+
const processingOptions = Object.assign(
|
|
211
|
+
{},
|
|
212
|
+
timeout && { processingCheckWait: timeout },
|
|
213
|
+
retryLimit && { processingCheckRetry: retryLimit }
|
|
214
|
+
);
|
|
215
|
+
const pendingProcessingAssets = assets2.map(async (asset) => {
|
|
216
|
+
logEmitter3.emit("info", `Processing Asset ${getEntityName(asset)}`);
|
|
217
|
+
const locales2 = Object.keys(asset.fields.file || {});
|
|
218
|
+
let latestAssetVersion = asset;
|
|
219
|
+
try {
|
|
220
|
+
latestAssetVersion = await lastResult(
|
|
221
|
+
locales2.map((locale) => {
|
|
222
|
+
return requestQueue.add(
|
|
223
|
+
() => processAssetForLocale(locale, asset, processingOptions)
|
|
224
|
+
);
|
|
225
|
+
})
|
|
226
|
+
);
|
|
227
|
+
} catch (err) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
return latestAssetVersion;
|
|
231
|
+
});
|
|
232
|
+
const potentiallyProcessedAssets = await Promise.all(pendingProcessingAssets);
|
|
233
|
+
return potentiallyProcessedAssets.filter((asset) => asset);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// lib/tasks/push-to-space/creation.js
|
|
237
|
+
import { find } from "lodash/collection";
|
|
238
|
+
import { assign, get, omitBy, omit } from "lodash/object";
|
|
239
|
+
import getEntityName2 from "contentful-batch-libs/dist/get-entity-name";
|
|
240
|
+
import { logEmitter as logEmitter4 } from "contentful-batch-libs/dist/logging";
|
|
241
|
+
function createEntities({ context, entities, destinationEntitiesById, requestQueue }) {
|
|
242
|
+
return createEntitiesWithConcurrency({ context, entities, destinationEntitiesById, requestQueue });
|
|
243
|
+
}
|
|
244
|
+
function createLocales({ context, entities, destinationEntitiesById, requestQueue }) {
|
|
245
|
+
return createEntitiesInSequence({ context, entities, destinationEntitiesById, requestQueue });
|
|
246
|
+
}
|
|
247
|
+
async function createEntitiesWithConcurrency({ context, entities, destinationEntitiesById, requestQueue }) {
|
|
248
|
+
const pendingCreatedEntities = entities.map((entity) => {
|
|
249
|
+
const destinationEntity = getDestinationEntityForSourceEntity(destinationEntitiesById, entity.transformed);
|
|
250
|
+
const operation = destinationEntity ? "update" : "create";
|
|
251
|
+
return requestQueue.add(async () => {
|
|
252
|
+
try {
|
|
253
|
+
const createdEntity = await (destinationEntity ? updateDestinationWithSourceData(destinationEntity, entity.transformed) : createInDestination(context, entity.transformed));
|
|
254
|
+
creationSuccessNotifier(operation, createdEntity);
|
|
255
|
+
return createdEntity;
|
|
256
|
+
} catch (err) {
|
|
257
|
+
return handleCreationErrors(entity, err);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
const createdEntities = await Promise.all(pendingCreatedEntities);
|
|
262
|
+
return createdEntities.filter((entity) => entity);
|
|
263
|
+
}
|
|
264
|
+
async function createEntitiesInSequence({ context, entities, destinationEntitiesById, requestQueue }) {
|
|
265
|
+
const createdEntities = [];
|
|
266
|
+
for (const entity of entities) {
|
|
267
|
+
const destinationEntity = getDestinationEntityForSourceEntity(destinationEntitiesById, entity.transformed);
|
|
268
|
+
const operation = destinationEntity ? "update" : "create";
|
|
269
|
+
try {
|
|
270
|
+
const createdEntity = await requestQueue.add(async () => {
|
|
271
|
+
const createdOrUpdatedEntity = await (destinationEntity ? updateDestinationWithSourceData(destinationEntity, entity.transformed) : createInDestination(context, entity.transformed));
|
|
272
|
+
return createdOrUpdatedEntity;
|
|
273
|
+
});
|
|
274
|
+
creationSuccessNotifier(operation, createdEntity);
|
|
275
|
+
createdEntities.push(createdEntity);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
const maybeSubstituteEntity = handleCreationErrors(entity, err);
|
|
278
|
+
if (maybeSubstituteEntity) {
|
|
279
|
+
createdEntities.push(maybeSubstituteEntity);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return createdEntities;
|
|
284
|
+
}
|
|
285
|
+
async function createEntries({ context, entities, destinationEntitiesById, requestQueue }) {
|
|
286
|
+
const createdEntries = await Promise.all(entities.map((entry) => {
|
|
287
|
+
return createEntry({ entry, target: context.target, skipContentModel: context.skipContentModel, destinationEntitiesById, requestQueue });
|
|
288
|
+
}));
|
|
289
|
+
return createdEntries.filter((entry) => entry);
|
|
290
|
+
}
|
|
291
|
+
async function createEntry({ entry, target, skipContentModel, destinationEntitiesById, requestQueue }) {
|
|
292
|
+
const contentTypeId = entry.original.sys.contentType.sys.id;
|
|
293
|
+
const destinationEntry = getDestinationEntityForSourceEntity(
|
|
294
|
+
destinationEntitiesById,
|
|
295
|
+
entry.transformed
|
|
296
|
+
);
|
|
297
|
+
const operation = destinationEntry ? "update" : "create";
|
|
298
|
+
try {
|
|
299
|
+
const createdOrUpdatedEntry = await requestQueue.add(() => {
|
|
300
|
+
return destinationEntry ? updateDestinationWithSourceData(destinationEntry, entry.transformed) : createEntryInDestination(target, contentTypeId, entry.transformed);
|
|
301
|
+
});
|
|
302
|
+
creationSuccessNotifier(operation, createdOrUpdatedEntry);
|
|
303
|
+
return createdOrUpdatedEntry;
|
|
304
|
+
} catch (err) {
|
|
305
|
+
if (skipContentModel && err.name === "UnknownField") {
|
|
306
|
+
const errors = get(JSON.parse(err.message), "details.errors");
|
|
307
|
+
entry.transformed.fields = cleanupUnknownFields(entry.transformed.fields, errors);
|
|
308
|
+
return createEntry({ entry, target, skipContentModel, destinationEntitiesById, requestQueue });
|
|
309
|
+
}
|
|
310
|
+
err.entity = entry;
|
|
311
|
+
logEmitter4.emit("error", err);
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function updateDestinationWithSourceData(destinationEntity, sourceEntity) {
|
|
316
|
+
const plainData = getPlainData(sourceEntity);
|
|
317
|
+
assign(destinationEntity, plainData);
|
|
318
|
+
return destinationEntity.update();
|
|
319
|
+
}
|
|
320
|
+
function createInDestination(context, sourceEntity) {
|
|
321
|
+
const { type, target } = context;
|
|
322
|
+
if (type === "Tag") {
|
|
323
|
+
return createTagInDestination(context, sourceEntity);
|
|
324
|
+
}
|
|
325
|
+
const id = get(sourceEntity, "sys.id");
|
|
326
|
+
const plainData = getPlainData(sourceEntity);
|
|
327
|
+
return id ? target[`create${type}WithId`](id, plainData) : target[`create${type}`](plainData);
|
|
328
|
+
}
|
|
329
|
+
function createEntryInDestination(space, contentTypeId, sourceEntity) {
|
|
330
|
+
const id = sourceEntity.sys.id;
|
|
331
|
+
const plainData = getPlainData(sourceEntity);
|
|
332
|
+
return id ? space.createEntryWithId(contentTypeId, id, plainData) : space.createEntry(contentTypeId, plainData);
|
|
333
|
+
}
|
|
334
|
+
function createTagInDestination(context, sourceEntity) {
|
|
335
|
+
const id = sourceEntity.sys.id;
|
|
336
|
+
const visibility = sourceEntity.sys.visibility || "private";
|
|
337
|
+
const name = sourceEntity.name;
|
|
338
|
+
return context.target.createTag(id, name, visibility);
|
|
339
|
+
}
|
|
340
|
+
function handleCreationErrors(entity, err) {
|
|
341
|
+
if (get(err, "error.sys.id") === "ValidationFailed") {
|
|
342
|
+
const errors = get(err, "error.details.errors");
|
|
343
|
+
if (errors && errors.length > 0 && errors[0].name === "taken") {
|
|
344
|
+
return entity;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
err.entity = entity.original;
|
|
348
|
+
logEmitter4.emit("error", err);
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
function cleanupUnknownFields(fields, errors) {
|
|
352
|
+
return omitBy(fields, (field, fieldId) => {
|
|
353
|
+
return find(errors, (error) => {
|
|
354
|
+
const [, errorFieldId] = error.path;
|
|
355
|
+
return error.name === "unknown" && errorFieldId === fieldId;
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
function getDestinationEntityForSourceEntity(destinationEntitiesById, sourceEntity) {
|
|
360
|
+
return destinationEntitiesById.get(get(sourceEntity, "sys.id")) || null;
|
|
361
|
+
}
|
|
362
|
+
function creationSuccessNotifier(method, createdEntity) {
|
|
363
|
+
const verb = method[0].toUpperCase() + method.substr(1, method.length) + "d";
|
|
364
|
+
logEmitter4.emit("info", `${verb} ${createdEntity.sys.type} ${getEntityName2(createdEntity)}`);
|
|
365
|
+
return createdEntity;
|
|
366
|
+
}
|
|
367
|
+
function getPlainData(entity) {
|
|
368
|
+
const data = entity.toPlainObject ? entity.toPlainObject() : entity;
|
|
369
|
+
return omit(data, "sys");
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// lib/tasks/push-to-space/publishing.js
|
|
373
|
+
import getEntityName3 from "contentful-batch-libs/dist/get-entity-name";
|
|
374
|
+
import { logEmitter as logEmitter5 } from "contentful-batch-libs/dist/logging";
|
|
375
|
+
async function publishEntities({ entities, requestQueue }) {
|
|
376
|
+
const entitiesToPublish = entities.filter((entity2) => {
|
|
377
|
+
if (!entity2 || !entity2.publish) {
|
|
378
|
+
logEmitter5.emit("warning", `Unable to publish ${getEntityName3(entity2)}`);
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
return true;
|
|
382
|
+
});
|
|
383
|
+
if (entitiesToPublish.length === 0) {
|
|
384
|
+
logEmitter5.emit("info", "Skipping publishing since zero valid entities passed");
|
|
385
|
+
return [];
|
|
386
|
+
}
|
|
387
|
+
const entity = entities[0].original || entities[0];
|
|
388
|
+
const type = entity.sys.type || "unknown type";
|
|
389
|
+
logEmitter5.emit("info", `Publishing ${entities.length} ${type}s`);
|
|
390
|
+
const result = await runQueue(entitiesToPublish, [], requestQueue);
|
|
391
|
+
logEmitter5.emit("info", `Successfully published ${result.length} ${type}s`);
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
async function archiveEntities({ entities, requestQueue }) {
|
|
395
|
+
const entitiesToArchive = entities.filter((entity2) => {
|
|
396
|
+
if (!entity2 || !entity2.archive) {
|
|
397
|
+
logEmitter5.emit("warning", `Unable to archive ${getEntityName3(entity2)}`);
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
return true;
|
|
401
|
+
});
|
|
402
|
+
if (entitiesToArchive.length === 0) {
|
|
403
|
+
logEmitter5.emit("info", "Skipping archiving since zero valid entities passed");
|
|
404
|
+
return [];
|
|
405
|
+
}
|
|
406
|
+
const entity = entities[0].original || entities[0];
|
|
407
|
+
const type = entity.sys.type || "unknown type";
|
|
408
|
+
logEmitter5.emit("info", `Archiving ${entities.length} ${type}s`);
|
|
409
|
+
const pendingArchivedEntities = entitiesToArchive.map((entity2) => {
|
|
410
|
+
return requestQueue.add(async () => {
|
|
411
|
+
try {
|
|
412
|
+
const archivedEntity = await entity2.archive();
|
|
413
|
+
return archivedEntity;
|
|
414
|
+
} catch (err) {
|
|
415
|
+
err.entity = entity2;
|
|
416
|
+
logEmitter5.emit("error", err);
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
const allPossiblyArchivedEntities = await Promise.all(pendingArchivedEntities);
|
|
422
|
+
const allArchivedEntities = allPossiblyArchivedEntities.filter((entity2) => entity2);
|
|
423
|
+
logEmitter5.emit("info", `Successfully archived ${allArchivedEntities.length} ${type}s`);
|
|
424
|
+
return allArchivedEntities;
|
|
425
|
+
}
|
|
426
|
+
async function runQueue(queue, result = [], requestQueue) {
|
|
427
|
+
const publishedEntities = [];
|
|
428
|
+
for (const entity of queue) {
|
|
429
|
+
logEmitter5.emit("info", `Publishing ${entity.sys.type} ${getEntityName3(entity)}`);
|
|
430
|
+
try {
|
|
431
|
+
const publishedEntity = await requestQueue.add(() => entity.publish());
|
|
432
|
+
publishedEntities.push(publishedEntity);
|
|
433
|
+
} catch (err) {
|
|
434
|
+
err.entity = entity;
|
|
435
|
+
logEmitter5.emit("error", err);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
result = [
|
|
439
|
+
...result,
|
|
440
|
+
...publishedEntities
|
|
441
|
+
];
|
|
442
|
+
const publishedEntityIds = new Set(publishedEntities.map((entity) => entity.sys.id));
|
|
443
|
+
const unpublishedEntities = queue.filter((entity) => !publishedEntityIds.has(entity.sys.id));
|
|
444
|
+
if (unpublishedEntities.length > 0) {
|
|
445
|
+
if (queue.length === unpublishedEntities.length) {
|
|
446
|
+
const unpublishedEntityNames = unpublishedEntities.map(getEntityName3).join(", ");
|
|
447
|
+
logEmitter5.emit("error", `Could not publish the following entities: ${unpublishedEntityNames}`);
|
|
448
|
+
} else {
|
|
449
|
+
return runQueue(unpublishedEntities, result, requestQueue);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return result;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// lib/tasks/push-to-space/push-to-space.js
|
|
456
|
+
var DEFAULT_CONTENT_STRUCTURE = {
|
|
457
|
+
entries: [],
|
|
458
|
+
assets: [],
|
|
459
|
+
contentTypes: [],
|
|
460
|
+
tags: [],
|
|
461
|
+
locales: [],
|
|
462
|
+
webhooks: [],
|
|
463
|
+
editorInterfaces: []
|
|
464
|
+
};
|
|
465
|
+
function pushToSpace({
|
|
466
|
+
sourceData,
|
|
467
|
+
destinationData = {},
|
|
468
|
+
client,
|
|
469
|
+
spaceId,
|
|
470
|
+
environmentId,
|
|
471
|
+
contentModelOnly,
|
|
472
|
+
skipContentModel,
|
|
473
|
+
skipLocales,
|
|
474
|
+
skipContentPublishing,
|
|
475
|
+
timeout,
|
|
476
|
+
retryLimit,
|
|
477
|
+
listrOptions,
|
|
478
|
+
uploadAssets,
|
|
479
|
+
assetsDirectory,
|
|
480
|
+
requestQueue
|
|
481
|
+
}) {
|
|
482
|
+
sourceData = {
|
|
483
|
+
...DEFAULT_CONTENT_STRUCTURE,
|
|
484
|
+
...sourceData
|
|
485
|
+
};
|
|
486
|
+
destinationData = {
|
|
487
|
+
...DEFAULT_CONTENT_STRUCTURE,
|
|
488
|
+
...destinationData
|
|
489
|
+
};
|
|
490
|
+
listrOptions = listrOptions || {
|
|
491
|
+
renderer: verboseRenderer
|
|
492
|
+
};
|
|
493
|
+
const destinationDataById = {};
|
|
494
|
+
for (const [entityType, entities] of Object.entries(destinationData)) {
|
|
495
|
+
const entitiesById = /* @__PURE__ */ new Map();
|
|
496
|
+
for (const entity of entities) {
|
|
497
|
+
entitiesById.set(entity.sys.id, entity);
|
|
498
|
+
}
|
|
499
|
+
destinationDataById[entityType] = entitiesById;
|
|
500
|
+
}
|
|
501
|
+
return new Listr([
|
|
502
|
+
{
|
|
503
|
+
title: "Connecting to space",
|
|
504
|
+
task: wrapTask(async (ctx, task) => {
|
|
505
|
+
const space = await client.getSpace(spaceId);
|
|
506
|
+
const environment = await space.getEnvironment(environmentId);
|
|
507
|
+
ctx.space = space;
|
|
508
|
+
ctx.environment = environment;
|
|
509
|
+
})
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
title: "Importing Locales",
|
|
513
|
+
task: wrapTask(async (ctx, task) => {
|
|
514
|
+
const locales2 = await createLocales({
|
|
515
|
+
context: { target: ctx.environment, type: "Locale" },
|
|
516
|
+
entities: sourceData.locales,
|
|
517
|
+
destinationEntitiesById: destinationDataById.locales,
|
|
518
|
+
requestQueue
|
|
519
|
+
});
|
|
520
|
+
ctx.data.locales = locales2;
|
|
521
|
+
}),
|
|
522
|
+
skip: () => skipContentModel || skipLocales
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
title: "Importing Content Types",
|
|
526
|
+
task: wrapTask(async (ctx, task) => {
|
|
527
|
+
const contentTypes2 = await createEntities({
|
|
528
|
+
context: { target: ctx.environment, type: "ContentType" },
|
|
529
|
+
entities: sourceData.contentTypes,
|
|
530
|
+
destinationEntitiesById: destinationDataById.contentTypes,
|
|
531
|
+
requestQueue
|
|
532
|
+
});
|
|
533
|
+
ctx.data.contentTypes = contentTypes2;
|
|
534
|
+
}),
|
|
535
|
+
skip: () => skipContentModel
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
title: "Publishing Content Types",
|
|
539
|
+
task: wrapTask(async (ctx, task) => {
|
|
540
|
+
const publishedContentTypes = await publishEntities2({
|
|
541
|
+
entities: ctx.data.contentTypes,
|
|
542
|
+
sourceEntities: sourceData.contentTypes,
|
|
543
|
+
requestQueue
|
|
544
|
+
});
|
|
545
|
+
ctx.data.contentTypes = publishedContentTypes;
|
|
546
|
+
}),
|
|
547
|
+
skip: (ctx) => skipContentModel
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
title: "Importing Tags",
|
|
551
|
+
task: wrapTask(async (ctx, task) => {
|
|
552
|
+
const tags2 = await createEntities({
|
|
553
|
+
context: { target: ctx.environment, type: "Tag" },
|
|
554
|
+
entities: sourceData.tags,
|
|
555
|
+
destinationEntitiesById: destinationDataById.tags,
|
|
556
|
+
requestQueue
|
|
557
|
+
});
|
|
558
|
+
ctx.data.tags = tags2;
|
|
559
|
+
}),
|
|
560
|
+
// we remove `tags` from destination data if an error was thrown trying to access them
|
|
561
|
+
// this means the user doesn't have access to this feature, skip importing tags
|
|
562
|
+
skip: () => !destinationDataById.tags
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
title: "Importing Editor Interfaces",
|
|
566
|
+
task: wrapTask(async (ctx, task) => {
|
|
567
|
+
const allEditorInterfacesBeingFetched = ctx.data.contentTypes.map(async (contentType) => {
|
|
568
|
+
const editorInterface = sourceData.editorInterfaces.find((editorInterface2) => {
|
|
569
|
+
return editorInterface2.sys.contentType.sys.id === contentType.sys.id;
|
|
570
|
+
});
|
|
571
|
+
if (!editorInterface) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
try {
|
|
575
|
+
const ctEditorInterface = await requestQueue.add(() => ctx.environment.getEditorInterfaceForContentType(contentType.sys.id));
|
|
576
|
+
logEmitter6.emit("info", `Fetched editor interface for ${contentType.name}`);
|
|
577
|
+
ctEditorInterface.controls = editorInterface.controls;
|
|
578
|
+
ctEditorInterface.groupControls = editorInterface.groupControls;
|
|
579
|
+
ctEditorInterface.editorLayout = editorInterface.editorLayout;
|
|
580
|
+
const updatedEditorInterface = await requestQueue.add(() => ctEditorInterface.update());
|
|
581
|
+
return updatedEditorInterface;
|
|
582
|
+
} catch (err) {
|
|
583
|
+
err.entity = editorInterface;
|
|
584
|
+
throw err;
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
const allEditorInterfaces = await Promise.all(allEditorInterfacesBeingFetched);
|
|
588
|
+
const editorInterfaces = allEditorInterfaces.filter((editorInterface) => editorInterface);
|
|
589
|
+
ctx.data.editorInterfaces = editorInterfaces;
|
|
590
|
+
}),
|
|
591
|
+
skip: (ctx) => skipContentModel || ctx.data.contentTypes.length === 0
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
title: "Uploading Assets",
|
|
595
|
+
task: wrapTask(async (ctx, task) => {
|
|
596
|
+
const allPendingUploads = [];
|
|
597
|
+
for (const asset of sourceData.assets) {
|
|
598
|
+
for (const file of Object.values(asset.transformed.fields.file)) {
|
|
599
|
+
allPendingUploads.push(requestQueue.add(async () => {
|
|
600
|
+
try {
|
|
601
|
+
logEmitter6.emit("info", `Uploading Asset file ${file.upload}`);
|
|
602
|
+
const assetStream = await getAssetStreamForURL(file.upload, assetsDirectory);
|
|
603
|
+
const upload = await ctx.environment.createUpload({
|
|
604
|
+
fileName: asset.transformed.sys.id,
|
|
605
|
+
file: assetStream
|
|
606
|
+
});
|
|
607
|
+
delete file.upload;
|
|
608
|
+
file.uploadFrom = {
|
|
609
|
+
sys: {
|
|
610
|
+
type: "Link",
|
|
611
|
+
linkType: "Upload",
|
|
612
|
+
id: upload.sys.id
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
return upload;
|
|
616
|
+
} catch (err) {
|
|
617
|
+
logEmitter6.emit("error", err);
|
|
618
|
+
}
|
|
619
|
+
}));
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
const uploads = await Promise.all(allPendingUploads);
|
|
623
|
+
ctx.data.uploadedAssetFiles = uploads;
|
|
624
|
+
}),
|
|
625
|
+
skip: (ctx) => !uploadAssets || !sourceData.assets.length
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
title: "Importing Assets",
|
|
629
|
+
task: wrapTask(async (ctx, task) => {
|
|
630
|
+
const assetsToProcess = await createEntities({
|
|
631
|
+
context: { target: ctx.environment, type: "Asset" },
|
|
632
|
+
entities: sourceData.assets,
|
|
633
|
+
destinationEntitiesById: destinationDataById.assets,
|
|
634
|
+
requestQueue
|
|
635
|
+
});
|
|
636
|
+
const processedAssets = await processAssets({
|
|
637
|
+
assets: assetsToProcess,
|
|
638
|
+
timeout,
|
|
639
|
+
retryLimit,
|
|
640
|
+
requestQueue
|
|
641
|
+
});
|
|
642
|
+
ctx.data.assets = processedAssets;
|
|
643
|
+
}),
|
|
644
|
+
skip: (ctx) => contentModelOnly
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
title: "Publishing Assets",
|
|
648
|
+
task: wrapTask(async (ctx, task) => {
|
|
649
|
+
const publishedAssets = await publishEntities2({
|
|
650
|
+
entities: ctx.data.assets,
|
|
651
|
+
sourceEntities: sourceData.assets,
|
|
652
|
+
requestQueue
|
|
653
|
+
});
|
|
654
|
+
ctx.data.publishedAssets = publishedAssets;
|
|
655
|
+
}),
|
|
656
|
+
skip: (ctx) => contentModelOnly || skipContentPublishing
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
title: "Archiving Assets",
|
|
660
|
+
task: wrapTask(async (ctx, task) => {
|
|
661
|
+
const archivedAssets = await archiveEntities2({
|
|
662
|
+
entities: ctx.data.assets,
|
|
663
|
+
sourceEntities: sourceData.assets,
|
|
664
|
+
requestQueue
|
|
665
|
+
});
|
|
666
|
+
ctx.data.archivedAssets = archivedAssets;
|
|
667
|
+
}),
|
|
668
|
+
skip: (ctx) => contentModelOnly || skipContentPublishing
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
title: "Importing Content Entries",
|
|
672
|
+
task: wrapTask(async (ctx, task) => {
|
|
673
|
+
const entries2 = await createEntries({
|
|
674
|
+
context: { target: ctx.environment, skipContentModel },
|
|
675
|
+
entities: sourceData.entries,
|
|
676
|
+
destinationEntitiesById: destinationDataById.entries,
|
|
677
|
+
requestQueue
|
|
678
|
+
});
|
|
679
|
+
ctx.data.entries = entries2;
|
|
680
|
+
}),
|
|
681
|
+
skip: (ctx) => contentModelOnly
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
title: "Publishing Content Entries",
|
|
685
|
+
task: wrapTask(async (ctx, task) => {
|
|
686
|
+
const publishedEntries = await publishEntities2({
|
|
687
|
+
entities: ctx.data.entries,
|
|
688
|
+
sourceEntities: sourceData.entries,
|
|
689
|
+
requestQueue
|
|
690
|
+
});
|
|
691
|
+
ctx.data.publishedEntries = publishedEntries;
|
|
692
|
+
}),
|
|
693
|
+
skip: (ctx) => contentModelOnly || skipContentPublishing
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
title: "Archiving Entries",
|
|
697
|
+
task: wrapTask(async (ctx, task) => {
|
|
698
|
+
const archivedEntries = await archiveEntities2({
|
|
699
|
+
entities: ctx.data.entries,
|
|
700
|
+
sourceEntities: sourceData.entries,
|
|
701
|
+
requestQueue
|
|
702
|
+
});
|
|
703
|
+
ctx.data.archivedEntries = archivedEntries;
|
|
704
|
+
}),
|
|
705
|
+
skip: (ctx) => contentModelOnly || skipContentPublishing
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
title: "Creating Web Hooks",
|
|
709
|
+
task: wrapTask(async (ctx, task) => {
|
|
710
|
+
const webhooks2 = await createEntities({
|
|
711
|
+
context: { target: ctx.space, type: "Webhook" },
|
|
712
|
+
entities: sourceData.webhooks,
|
|
713
|
+
destinationEntitiesById: destinationDataById.webhooks,
|
|
714
|
+
requestQueue
|
|
715
|
+
});
|
|
716
|
+
ctx.data.webhooks = webhooks2;
|
|
717
|
+
}),
|
|
718
|
+
skip: (ctx) => contentModelOnly || environmentId !== "master" && "Webhooks can only be imported in master environment"
|
|
719
|
+
}
|
|
720
|
+
], listrOptions);
|
|
721
|
+
}
|
|
722
|
+
function archiveEntities2({ entities, sourceEntities, requestQueue }) {
|
|
723
|
+
const entityIdsToArchive = sourceEntities.filter(({ original }) => original.sys.archivedVersion).map(({ original }) => original.sys.id);
|
|
724
|
+
const entitiesToArchive = entities.filter((entity) => entityIdsToArchive.indexOf(entity.sys.id) !== -1);
|
|
725
|
+
return archiveEntities({ entities: entitiesToArchive, requestQueue });
|
|
726
|
+
}
|
|
727
|
+
function publishEntities2({ entities, sourceEntities, requestQueue }) {
|
|
728
|
+
const entityIdsToPublish = sourceEntities.filter(({ original }) => original.sys.publishedVersion).map(({ original }) => original.sys.id);
|
|
729
|
+
const entitiesToPublish = entities.filter((entity) => entityIdsToPublish.indexOf(entity.sys.id) !== -1);
|
|
730
|
+
return publishEntities({ entities: entitiesToPublish, requestQueue });
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// lib/transform/transform-space.js
|
|
734
|
+
import { omit as omit3, defaults } from "lodash/object";
|
|
735
|
+
|
|
736
|
+
// lib/transform/transformers.js
|
|
737
|
+
var transformers_exports = {};
|
|
738
|
+
__export(transformers_exports, {
|
|
739
|
+
assets: () => assets,
|
|
740
|
+
contentTypes: () => contentTypes,
|
|
741
|
+
entries: () => entries,
|
|
742
|
+
locales: () => locales,
|
|
743
|
+
tags: () => tags,
|
|
744
|
+
webhooks: () => webhooks
|
|
745
|
+
});
|
|
746
|
+
import { omit as omit2, pick } from "lodash/object";
|
|
747
|
+
import { find as find2, reduce } from "lodash/collection";
|
|
748
|
+
function contentTypes(contentType) {
|
|
749
|
+
return contentType;
|
|
750
|
+
}
|
|
751
|
+
function tags(tag) {
|
|
752
|
+
return tag;
|
|
753
|
+
}
|
|
754
|
+
function entries(entry, _, tagsEnabled = false) {
|
|
755
|
+
return removeMetadataTags(entry, tagsEnabled);
|
|
756
|
+
}
|
|
757
|
+
function webhooks(webhook) {
|
|
758
|
+
if (webhook.httpBasicUsername) {
|
|
759
|
+
delete webhook.httpBasicUsername;
|
|
760
|
+
}
|
|
761
|
+
if (webhook.headers) {
|
|
762
|
+
webhook.headers = webhook.headers.filter((header) => !header.secret);
|
|
763
|
+
}
|
|
764
|
+
return webhook;
|
|
765
|
+
}
|
|
766
|
+
function assets(asset, _, tagsEnabled = false) {
|
|
767
|
+
const transformedAsset = omit2(asset, "sys");
|
|
768
|
+
transformedAsset.sys = pick(asset.sys, "id");
|
|
769
|
+
transformedAsset.fields = pick(asset.fields, "title", "description");
|
|
770
|
+
transformedAsset.fields.file = reduce(
|
|
771
|
+
asset.fields.file,
|
|
772
|
+
(newFile, localizedFile, locale) => {
|
|
773
|
+
newFile[locale] = pick(localizedFile, "contentType", "fileName");
|
|
774
|
+
if (!localizedFile.uploadFrom) {
|
|
775
|
+
const assetUrl = localizedFile.url || localizedFile.upload;
|
|
776
|
+
newFile[locale].upload = `${/^(http|https):\/\//i.test(assetUrl) ? "" : "https:"}${assetUrl}`;
|
|
777
|
+
} else {
|
|
778
|
+
newFile[locale].uploadFrom = localizedFile.uploadFrom;
|
|
779
|
+
}
|
|
780
|
+
return newFile;
|
|
781
|
+
},
|
|
782
|
+
{}
|
|
783
|
+
);
|
|
784
|
+
return removeMetadataTags(transformedAsset, tagsEnabled);
|
|
785
|
+
}
|
|
786
|
+
function locales(locale, destinationLocales) {
|
|
787
|
+
const transformedLocale = pick(locale, "code", "name", "contentManagementApi", "contentDeliveryApi", "fallbackCode", "optional");
|
|
788
|
+
const destinationLocale = find2(destinationLocales, { code: locale.code });
|
|
789
|
+
if (destinationLocale) {
|
|
790
|
+
transformedLocale.sys = pick(destinationLocale.sys, "id");
|
|
791
|
+
}
|
|
792
|
+
return transformedLocale;
|
|
793
|
+
}
|
|
794
|
+
function removeMetadataTags(entity, tagsEnabled = false) {
|
|
795
|
+
if (!tagsEnabled) {
|
|
796
|
+
delete entity.metadata;
|
|
797
|
+
}
|
|
798
|
+
return entity;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// lib/utils/sort-entries.js
|
|
802
|
+
import { some, filter, map } from "lodash/collection";
|
|
803
|
+
import * as _o from "lodash/object";
|
|
804
|
+
import { flatten } from "lodash/array";
|
|
805
|
+
function sortEntries(entries2) {
|
|
806
|
+
const linkedEntries = getLinkedEntries(entries2);
|
|
807
|
+
const mergedLinkedEntries = mergeSort(linkedEntries, (a) => {
|
|
808
|
+
return hasLinkedIndexesInFront(a);
|
|
809
|
+
});
|
|
810
|
+
return map(mergedLinkedEntries, (linkInfo) => entries2[linkInfo.index]);
|
|
811
|
+
function hasLinkedIndexesInFront(item) {
|
|
812
|
+
if (hasLinkedIndexes(item)) {
|
|
813
|
+
return some(item.linkIndexes, (index) => index > item.index) ? 1 : -1;
|
|
814
|
+
}
|
|
815
|
+
return 0;
|
|
816
|
+
}
|
|
817
|
+
function hasLinkedIndexes(item) {
|
|
818
|
+
return item.linkIndexes.length > 0;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
function getLinkedEntries(entries2) {
|
|
822
|
+
return map(entries2, function(entry) {
|
|
823
|
+
const entryIndex = entries2.indexOf(entry);
|
|
824
|
+
const rawLinks = map(entry.fields, (field) => {
|
|
825
|
+
field = _o.values(field)[0];
|
|
826
|
+
if (isEntryLink(field)) {
|
|
827
|
+
return getFieldEntriesIndex(field, entries2);
|
|
828
|
+
} else if (isEntityArray(field) && isEntryLink(field[0])) {
|
|
829
|
+
return map(field, (item) => getFieldEntriesIndex(item, entries2));
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
return {
|
|
833
|
+
index: entryIndex,
|
|
834
|
+
linkIndexes: filter(flatten(rawLinks), (index) => index >= 0)
|
|
835
|
+
};
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
function getFieldEntriesIndex(field, entries2) {
|
|
839
|
+
const id = _o.get(field, "sys.id");
|
|
840
|
+
return entries2.findIndex((entry) => entry.sys.id === id);
|
|
841
|
+
}
|
|
842
|
+
function isEntryLink(item) {
|
|
843
|
+
return _o.get(item, "sys.type") === "Entry" || _o.get(item, "sys.linkType") === "Entry";
|
|
844
|
+
}
|
|
845
|
+
function isEntityArray(item) {
|
|
846
|
+
return Array.isArray(item) && item.length > 0 && _o.has(item[0], "sys");
|
|
847
|
+
}
|
|
848
|
+
function mergeSort(arr, compareFn) {
|
|
849
|
+
if (arr.length < 2)
|
|
850
|
+
return arr;
|
|
851
|
+
if (compareFn == null)
|
|
852
|
+
compareFn = defaultCompare;
|
|
853
|
+
const mid = ~~(arr.length / 2);
|
|
854
|
+
const left = mergeSort(arr.slice(0, mid), compareFn);
|
|
855
|
+
const right = mergeSort(arr.slice(mid, arr.length), compareFn);
|
|
856
|
+
return merge(left, right, compareFn);
|
|
857
|
+
}
|
|
858
|
+
function defaultCompare(a, b) {
|
|
859
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
860
|
+
}
|
|
861
|
+
function merge(left, right, compareFn) {
|
|
862
|
+
const result = [];
|
|
863
|
+
while (left.length && right.length) {
|
|
864
|
+
if (compareFn(left[0], right[0]) <= 0) {
|
|
865
|
+
result.push(left.shift());
|
|
866
|
+
} else {
|
|
867
|
+
result.push(right.shift());
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
if (left.length)
|
|
871
|
+
result.push.apply(result, left);
|
|
872
|
+
if (right.length)
|
|
873
|
+
result.push.apply(result, right);
|
|
874
|
+
return result;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// lib/utils/sort-locales.js
|
|
878
|
+
function sortLocales(locales2) {
|
|
879
|
+
const localeByFallback = {};
|
|
880
|
+
locales2.forEach((locale) => {
|
|
881
|
+
if (locale.fallbackCode === null) {
|
|
882
|
+
locale.fallbackCode = void 0;
|
|
883
|
+
}
|
|
884
|
+
if (!localeByFallback[locale.fallbackCode]) {
|
|
885
|
+
localeByFallback[locale.fallbackCode] = [];
|
|
886
|
+
}
|
|
887
|
+
localeByFallback[locale.fallbackCode].push(locale);
|
|
888
|
+
});
|
|
889
|
+
return sortByFallbackKey(localeByFallback);
|
|
890
|
+
}
|
|
891
|
+
function sortByFallbackKey(localeByFallback, key) {
|
|
892
|
+
if (!localeByFallback[key]) {
|
|
893
|
+
return [];
|
|
894
|
+
}
|
|
895
|
+
const sortedLocales = localeByFallback[key];
|
|
896
|
+
sortedLocales.forEach((locale) => {
|
|
897
|
+
sortByFallbackKey(localeByFallback, locale.code).forEach((x) => sortedLocales.push(x));
|
|
898
|
+
});
|
|
899
|
+
sortedLocales.forEach((locale) => {
|
|
900
|
+
if (!locale.fallbackCode) {
|
|
901
|
+
locale.fallbackCode = null;
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
return sortedLocales;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// lib/transform/transform-space.js
|
|
908
|
+
var spaceEntities = [
|
|
909
|
+
"contentTypes",
|
|
910
|
+
"entries",
|
|
911
|
+
"assets",
|
|
912
|
+
"locales",
|
|
913
|
+
"webhooks",
|
|
914
|
+
"tags"
|
|
915
|
+
];
|
|
916
|
+
function transform_space_default(sourceData, destinationData, customTransformers, entities = spaceEntities) {
|
|
917
|
+
const transformers = defaults(customTransformers, transformers_exports);
|
|
918
|
+
const baseSpaceData = omit3(sourceData, ...entities);
|
|
919
|
+
sourceData.locales = sortLocales(sourceData.locales);
|
|
920
|
+
const tagsEnabled = !!destinationData.tags;
|
|
921
|
+
return entities.reduce((transformedSpaceData, type) => {
|
|
922
|
+
const sortedEntities = type === "tags" ? sourceData[type] : sortEntries(sourceData[type]);
|
|
923
|
+
const transformedEntities = sortedEntities.map((entity) => ({
|
|
924
|
+
original: entity,
|
|
925
|
+
transformed: transformers[type](entity, destinationData[type], tagsEnabled)
|
|
926
|
+
}));
|
|
927
|
+
transformedSpaceData[type] = transformedEntities;
|
|
928
|
+
return transformedSpaceData;
|
|
929
|
+
}, baseSpaceData);
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
// lib/utils/schema.js
|
|
933
|
+
import Joi from "joi";
|
|
934
|
+
var entrySchema = {
|
|
935
|
+
sys: Joi.object(),
|
|
936
|
+
fields: Joi.object()
|
|
937
|
+
};
|
|
938
|
+
var tagSchema = {
|
|
939
|
+
name: Joi.string().required(),
|
|
940
|
+
sys: Joi.object()
|
|
941
|
+
};
|
|
942
|
+
var contentTypeSchema = {
|
|
943
|
+
sys: Joi.object(),
|
|
944
|
+
fields: Joi.array().required().items(Joi.object().keys({
|
|
945
|
+
id: Joi.string().required(),
|
|
946
|
+
name: Joi.string().required(),
|
|
947
|
+
type: Joi.string().required().regex(/^Symbol|Text|Integer|Number|Date|Object|Boolean|Array|Link|Location$/),
|
|
948
|
+
validations: Joi.array(),
|
|
949
|
+
disabled: Joi.boolean(),
|
|
950
|
+
omitted: Joi.boolean(),
|
|
951
|
+
required: Joi.boolean(),
|
|
952
|
+
localized: Joi.boolean(),
|
|
953
|
+
linkType: Joi.string().when("type", { is: "Link", then: Joi.string().regex(/^Asset|Entry$/), otherwise: Joi.forbidden() })
|
|
954
|
+
}))
|
|
955
|
+
};
|
|
956
|
+
var assetSchema = {
|
|
957
|
+
sys: Joi.object(),
|
|
958
|
+
fields: Joi.object({
|
|
959
|
+
file: Joi.object().pattern(/.+/, Joi.object({
|
|
960
|
+
url: Joi.string().required(),
|
|
961
|
+
details: Joi.object({
|
|
962
|
+
size: Joi.number(),
|
|
963
|
+
image: Joi.object({
|
|
964
|
+
width: Joi.number(),
|
|
965
|
+
height: Joi.number()
|
|
966
|
+
})
|
|
967
|
+
}),
|
|
968
|
+
fileName: Joi.string().required(),
|
|
969
|
+
contentType: Joi.string().required()
|
|
970
|
+
}))
|
|
971
|
+
}).required()
|
|
972
|
+
};
|
|
973
|
+
var editorInterfaceSchema = {
|
|
974
|
+
sys: Joi.object(),
|
|
975
|
+
controls: Joi.array().items({ fieldId: Joi.string(), widgetId: Joi.string() })
|
|
976
|
+
};
|
|
977
|
+
var localeSchema = {
|
|
978
|
+
name: Joi.string().required(),
|
|
979
|
+
internal_code: Joi.string(),
|
|
980
|
+
code: Joi.string().required(),
|
|
981
|
+
fallbackCode: Joi.string().allow(null),
|
|
982
|
+
default: Joi.boolean(),
|
|
983
|
+
contentManagementApi: Joi.boolean(),
|
|
984
|
+
contentDeliveryApi: Joi.boolean(),
|
|
985
|
+
optional: Joi.boolean(),
|
|
986
|
+
sys: Joi.object()
|
|
987
|
+
};
|
|
988
|
+
var webhookSchema = {
|
|
989
|
+
name: Joi.string(),
|
|
990
|
+
url: Joi.string().replace(/{[^}{]+?}/g, "x").regex(/^https?:\/\/[^ /}{][^ }{]*$/i).required(),
|
|
991
|
+
topics: Joi.array().required(),
|
|
992
|
+
httpBasicUsername: Joi.string().allow("", null)
|
|
993
|
+
};
|
|
994
|
+
var payloadSchema = Joi.object({
|
|
995
|
+
entries: Joi.array().items(entrySchema),
|
|
996
|
+
contentTypes: Joi.array().items(contentTypeSchema),
|
|
997
|
+
tags: Joi.array().items(tagSchema),
|
|
998
|
+
assets: Joi.array().items(assetSchema),
|
|
999
|
+
locales: Joi.array().items(localeSchema),
|
|
1000
|
+
editorInterfaces: Joi.array().items(editorInterfaceSchema),
|
|
1001
|
+
webhooks: Joi.array().items(webhookSchema)
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
// lib/utils/validations.js
|
|
1005
|
+
import getEntityName4 from "contentful-batch-libs/dist/get-entity-name";
|
|
1006
|
+
var attachEntityName = (details, payload) => {
|
|
1007
|
+
details.map((detail) => {
|
|
1008
|
+
if (detail.path.length >= 2) {
|
|
1009
|
+
detail.entity = getEntityName4(payload[detail.path[0]][detail.path[1]]);
|
|
1010
|
+
}
|
|
1011
|
+
return detail;
|
|
1012
|
+
});
|
|
1013
|
+
};
|
|
1014
|
+
var countInvalidEntities = (validationData) => {
|
|
1015
|
+
const entityCount = validationData.reduce((entities, currentDetail) => {
|
|
1016
|
+
if (!entities[currentDetail.path[0]]) {
|
|
1017
|
+
entities[currentDetail.path[0]] = 1;
|
|
1018
|
+
} else {
|
|
1019
|
+
entities[currentDetail.path[0]]++;
|
|
1020
|
+
}
|
|
1021
|
+
return entities;
|
|
1022
|
+
}, {});
|
|
1023
|
+
return Object.keys(entityCount).map((key) => `${key}:${entityCount[key]}`);
|
|
1024
|
+
};
|
|
1025
|
+
var assertPayload = (payload) => {
|
|
1026
|
+
const result = payloadSchema.validate(payload, { allowUnknown: true, abortEarly: false });
|
|
1027
|
+
if (result.error) {
|
|
1028
|
+
attachEntityName(result.error.details, payload);
|
|
1029
|
+
const invalidEntityCount = countInvalidEntities(result.error.details).join(", ");
|
|
1030
|
+
result.error.message = `${invalidEntityCount} - Get further details in the error log file`;
|
|
1031
|
+
delete result.error._object;
|
|
1032
|
+
throw result.error;
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
var assertDefaultLocale = (source, destination) => {
|
|
1036
|
+
const sourceDefaultLocale = source.locales.find((locale) => locale.default === true);
|
|
1037
|
+
const destinationDefaultLocale = destination.locales.find((locale) => locale.default === true);
|
|
1038
|
+
if (!sourceDefaultLocale || !destinationDefaultLocale) {
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
if (sourceDefaultLocale.code !== destinationDefaultLocale.code) {
|
|
1042
|
+
throw new Error(`
|
|
1043
|
+
Please make sure the destination space have the same default locale as the source
|
|
1044
|
+
|
|
1045
|
+
Default locale for source space : ${sourceDefaultLocale.code}
|
|
1046
|
+
|
|
1047
|
+
Default locale for destination space: ${destinationDefaultLocale.code}
|
|
1048
|
+
|
|
1049
|
+
`);
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1053
|
+
// lib/parseOptions.js
|
|
1054
|
+
import fs2 from "fs";
|
|
1055
|
+
import { resolve } from "path";
|
|
1056
|
+
import format from "date-fns/format";
|
|
1057
|
+
|
|
1058
|
+
// package.json
|
|
1059
|
+
var version = "0.0.0-determined-by-semantic-release";
|
|
1060
|
+
|
|
1061
|
+
// lib/utils/headers.js
|
|
1062
|
+
function getHeadersConfig(value) {
|
|
1063
|
+
if (!value) {
|
|
1064
|
+
return {};
|
|
1065
|
+
}
|
|
1066
|
+
const values2 = Array.isArray(value) ? value : [value];
|
|
1067
|
+
return values2.reduce((headers, value2) => {
|
|
1068
|
+
value2 = value2.trim();
|
|
1069
|
+
const separatorIndex = value2.indexOf(":");
|
|
1070
|
+
if (separatorIndex === -1) {
|
|
1071
|
+
return headers;
|
|
1072
|
+
}
|
|
1073
|
+
const headerKey = value2.slice(0, separatorIndex).trim();
|
|
1074
|
+
const headerValue = value2.slice(separatorIndex + 1).trim();
|
|
1075
|
+
return {
|
|
1076
|
+
...headers,
|
|
1077
|
+
[headerKey]: headerValue
|
|
1078
|
+
};
|
|
1079
|
+
}, {});
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
// lib/parseOptions.js
|
|
1083
|
+
import { proxyStringToObject, agentFromProxy } from "contentful-batch-libs/dist/proxy";
|
|
1084
|
+
import addSequenceHeader from "contentful-batch-libs/dist/add-sequence-header";
|
|
1085
|
+
import { parseChunked } from "@discoveryjs/json-ext";
|
|
1086
|
+
var SUPPORTED_ENTITY_TYPES = [
|
|
1087
|
+
"contentTypes",
|
|
1088
|
+
"tags",
|
|
1089
|
+
"entries",
|
|
1090
|
+
"assets",
|
|
1091
|
+
"locales",
|
|
1092
|
+
"webhooks",
|
|
1093
|
+
"editorInterfaces"
|
|
1094
|
+
];
|
|
1095
|
+
async function parseOptions(params) {
|
|
1096
|
+
const defaultOptions = {
|
|
1097
|
+
skipContentModel: false,
|
|
1098
|
+
skipLocales: false,
|
|
1099
|
+
skipContentPublishing: false,
|
|
1100
|
+
useVerboseRenderer: false,
|
|
1101
|
+
environmentId: "master",
|
|
1102
|
+
rawProxy: false,
|
|
1103
|
+
uploadAssets: false,
|
|
1104
|
+
rateLimit: 7
|
|
1105
|
+
};
|
|
1106
|
+
const configFile = params.config ? __require(resolve(process.cwd(), params.config)) : {};
|
|
1107
|
+
const options = {
|
|
1108
|
+
...defaultOptions,
|
|
1109
|
+
...configFile,
|
|
1110
|
+
...params,
|
|
1111
|
+
headers: addSequenceHeader(params.headers || getHeadersConfig(params.header))
|
|
1112
|
+
};
|
|
1113
|
+
if (!options.spaceId) {
|
|
1114
|
+
throw new Error("The `spaceId` option is required.");
|
|
1115
|
+
}
|
|
1116
|
+
if (!options.managementToken) {
|
|
1117
|
+
throw new Error("The `managementToken` option is required.");
|
|
1118
|
+
}
|
|
1119
|
+
if (!options.contentFile && !options.content) {
|
|
1120
|
+
throw new Error("Either the `contentFile` or `content` option are required.");
|
|
1121
|
+
}
|
|
1122
|
+
if (options.contentModelOnly && options.skipContentModel) {
|
|
1123
|
+
throw new Error("`contentModelOnly` and `skipContentModel` cannot be used together");
|
|
1124
|
+
}
|
|
1125
|
+
if (options.skipLocales && !options.contentModelOnly) {
|
|
1126
|
+
throw new Error("`skipLocales` can only be used together with `contentModelOnly`");
|
|
1127
|
+
}
|
|
1128
|
+
const proxySimpleExp = /.+:\d+/;
|
|
1129
|
+
const proxyAuthExp = /.+:.+@.+:\d+/;
|
|
1130
|
+
if (typeof options.proxy === "string" && options.proxy && !(proxySimpleExp.test(options.proxy) || proxyAuthExp.test(options.proxy))) {
|
|
1131
|
+
throw new Error("Please provide the proxy config in the following format:\nhost:port or user:password@host:port");
|
|
1132
|
+
}
|
|
1133
|
+
options.startTime = /* @__PURE__ */ new Date();
|
|
1134
|
+
if (!options.errorLogFile) {
|
|
1135
|
+
options.errorLogFile = resolve(process.cwd(), `contentful-import-error-log-${options.spaceId}-${format(options.startTime, "yyyy-MM-dd'T'HH-mm-ss")}.json`);
|
|
1136
|
+
} else {
|
|
1137
|
+
options.errorLogFile = resolve(process.cwd(), options.errorLogFile);
|
|
1138
|
+
}
|
|
1139
|
+
options.accessToken = options.managementToken;
|
|
1140
|
+
if (!options.content) {
|
|
1141
|
+
const fileStream = fs2.createReadStream(options.contentFile, { encoding: "utf8" });
|
|
1142
|
+
options.content = await parseChunked(fileStream);
|
|
1143
|
+
}
|
|
1144
|
+
Object.keys(options.content).forEach((type) => {
|
|
1145
|
+
if (SUPPORTED_ENTITY_TYPES.indexOf(type) === -1) {
|
|
1146
|
+
delete options.content[type];
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
SUPPORTED_ENTITY_TYPES.forEach((type) => {
|
|
1150
|
+
options.content[type] = options.content[type] || [];
|
|
1151
|
+
});
|
|
1152
|
+
if (typeof options.proxy === "string") {
|
|
1153
|
+
options.proxy = proxyStringToObject(options.proxy);
|
|
1154
|
+
}
|
|
1155
|
+
if (!options.rawProxy && options.proxy) {
|
|
1156
|
+
options.httpsAgent = agentFromProxy(options.proxy);
|
|
1157
|
+
delete options.proxy;
|
|
1158
|
+
}
|
|
1159
|
+
options.application = options.managementApplication || `contentful.import/${version}`;
|
|
1160
|
+
options.feature = options.managementFeature || "library-import";
|
|
1161
|
+
return options;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// lib/index.ts
|
|
1165
|
+
var ONE_SECOND = 1e3;
|
|
1166
|
+
function createListrOptions(options) {
|
|
1167
|
+
if (options.useVerboseRenderer) {
|
|
1168
|
+
return {
|
|
1169
|
+
renderer: VerboseRenderer
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
return {
|
|
1173
|
+
renderer: UpdateRenderer,
|
|
1174
|
+
collapse: false
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
async function runContentfulImport(params) {
|
|
1178
|
+
const log = [];
|
|
1179
|
+
const options = await parseOptions(params);
|
|
1180
|
+
const listrOptions = createListrOptions(options);
|
|
1181
|
+
const requestQueue = new PQueue({
|
|
1182
|
+
interval: ONE_SECOND,
|
|
1183
|
+
intervalCap: options.rateLimit,
|
|
1184
|
+
carryoverConcurrencyCount: true
|
|
1185
|
+
});
|
|
1186
|
+
setupLogging(log);
|
|
1187
|
+
const infoTable = new Table();
|
|
1188
|
+
infoTable.push([{ colSpan: 2, content: "The following entities are going to be imported:" }]);
|
|
1189
|
+
Object.keys(options.content).forEach((type) => {
|
|
1190
|
+
if (options.skipLocales && type === "locales") {
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
if (options.skipContentModel && ["contentTypes", "editorInterfaces"].indexOf(type) >= 0) {
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
if (options.contentModelOnly && !(["contentTypes", "editorInterfaces", "locales"].indexOf(type) >= 0)) {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
infoTable.push([startCase(type), options.content[type].length]);
|
|
1200
|
+
});
|
|
1201
|
+
console.log(infoTable.toString());
|
|
1202
|
+
const tasks = new Listr2([
|
|
1203
|
+
{
|
|
1204
|
+
title: "Validating content-file",
|
|
1205
|
+
task: (ctx) => {
|
|
1206
|
+
assertPayload(options.content);
|
|
1207
|
+
}
|
|
1208
|
+
},
|
|
1209
|
+
{
|
|
1210
|
+
title: "Initialize client",
|
|
1211
|
+
task: wrapTask2(async (ctx) => {
|
|
1212
|
+
ctx.client = initClient({ ...options, content: void 0 });
|
|
1213
|
+
})
|
|
1214
|
+
},
|
|
1215
|
+
{
|
|
1216
|
+
title: "Checking if destination space already has any content and retrieving it",
|
|
1217
|
+
task: wrapTask2(async (ctx, task) => {
|
|
1218
|
+
const destinationData = await getDestinationData({
|
|
1219
|
+
client: ctx.client,
|
|
1220
|
+
spaceId: options.spaceId,
|
|
1221
|
+
environmentId: options.environmentId,
|
|
1222
|
+
sourceData: options.content,
|
|
1223
|
+
skipLocales: options.skipLocales,
|
|
1224
|
+
skipContentModel: options.skipContentModel,
|
|
1225
|
+
requestQueue
|
|
1226
|
+
});
|
|
1227
|
+
ctx.sourceDataUntransformed = options.content;
|
|
1228
|
+
ctx.destinationData = destinationData;
|
|
1229
|
+
assertDefaultLocale(ctx.sourceDataUntransformed, ctx.destinationData);
|
|
1230
|
+
})
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
title: "Apply transformations to source data",
|
|
1234
|
+
task: wrapTask2(async (ctx) => {
|
|
1235
|
+
const transformedSourceData = transform_space_default(ctx.sourceDataUntransformed, ctx.destinationData);
|
|
1236
|
+
ctx.sourceData = transformedSourceData;
|
|
1237
|
+
})
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
title: "Push content to destination space",
|
|
1241
|
+
task: (ctx, task) => {
|
|
1242
|
+
return pushToSpace({
|
|
1243
|
+
sourceData: ctx.sourceData,
|
|
1244
|
+
destinationData: ctx.destinationData,
|
|
1245
|
+
client: ctx.client,
|
|
1246
|
+
spaceId: options.spaceId,
|
|
1247
|
+
environmentId: options.environmentId,
|
|
1248
|
+
contentModelOnly: options.contentModelOnly,
|
|
1249
|
+
skipLocales: options.skipLocales,
|
|
1250
|
+
skipContentModel: options.skipContentModel,
|
|
1251
|
+
skipContentPublishing: options.skipContentPublishing,
|
|
1252
|
+
timeout: options.timeout,
|
|
1253
|
+
retryLimit: options.retryLimit,
|
|
1254
|
+
uploadAssets: options.uploadAssets,
|
|
1255
|
+
assetsDirectory: options.assetsDirectory,
|
|
1256
|
+
listrOptions,
|
|
1257
|
+
requestQueue
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
], listrOptions);
|
|
1262
|
+
return tasks.run({
|
|
1263
|
+
data: {}
|
|
1264
|
+
}).then((ctx) => {
|
|
1265
|
+
console.log("Finished importing all data");
|
|
1266
|
+
const resultTypes = Object.keys(ctx.data);
|
|
1267
|
+
if (resultTypes.length) {
|
|
1268
|
+
const resultTable = new Table();
|
|
1269
|
+
resultTable.push([{ colSpan: 2, content: "Imported entities" }]);
|
|
1270
|
+
resultTypes.forEach((type) => {
|
|
1271
|
+
resultTable.push([startCase(type), ctx.data[type].length]);
|
|
1272
|
+
});
|
|
1273
|
+
console.log(resultTable.toString());
|
|
1274
|
+
} else {
|
|
1275
|
+
console.log("No data was imported");
|
|
1276
|
+
}
|
|
1277
|
+
const endTime = /* @__PURE__ */ new Date();
|
|
1278
|
+
const durationHuman = formatDistance(endTime, options.startTime);
|
|
1279
|
+
const durationSeconds = differenceInSeconds(endTime, options.startTime);
|
|
1280
|
+
console.log(`The import took ${durationHuman} (${durationSeconds}s)`);
|
|
1281
|
+
return ctx.data;
|
|
1282
|
+
}).catch((err) => {
|
|
1283
|
+
log.push({
|
|
1284
|
+
ts: (/* @__PURE__ */ new Date()).toJSON(),
|
|
1285
|
+
level: "error",
|
|
1286
|
+
error: err
|
|
1287
|
+
});
|
|
1288
|
+
}).then((data) => {
|
|
1289
|
+
const errorLog = log.filter((logMessage) => logMessage.level !== "info" && logMessage.level !== "warning");
|
|
1290
|
+
const displayLog = log.filter((logMessage) => logMessage.level !== "info");
|
|
1291
|
+
displayErrorLog(displayLog);
|
|
1292
|
+
if (errorLog.length) {
|
|
1293
|
+
return writeErrorLogFile(options.errorLogFile, errorLog).then(() => {
|
|
1294
|
+
const multiError = new Error("Errors occurred");
|
|
1295
|
+
multiError.name = "ContentfulMultiError";
|
|
1296
|
+
multiError.errors = errorLog;
|
|
1297
|
+
throw multiError;
|
|
1298
|
+
});
|
|
1299
|
+
}
|
|
1300
|
+
console.log("The import was successful.");
|
|
1301
|
+
return data;
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
var lib_default = runContentfulImport;
|
|
1305
|
+
module.exports = runContentfulImport;
|
|
1306
|
+
export {
|
|
1307
|
+
lib_default as default
|
|
1308
|
+
};
|