contentful-import 9.1.0 → 9.2.0

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.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
+ };