contentful-import 10.5.0 → 10.5.2

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.
Files changed (3) hide show
  1. package/dist/index.js +196 -56
  2. package/dist/index.mjs +196 -56
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4861,7 +4861,7 @@ var startCase_default = startCase;
4861
4861
 
4862
4862
  // lib/index.ts
4863
4863
  var import_p_queue = __toESM(require("p-queue"));
4864
- var import_logging14 = __toESM(require_logging());
4864
+ var import_logging15 = __toESM(require_logging());
4865
4865
  var import_listr4 = __toESM(require_listr());
4866
4866
 
4867
4867
  // lib/tasks/init-client.ts
@@ -5984,6 +5984,29 @@ var PARENT_FOLDER_GROUP_IDS = {
5984
5984
  fragment: "contentful.folder-group-fragment",
5985
5985
  experience: "contentful.folder-group-experience"
5986
5986
  };
5987
+ var VERSION_CONFLICT_MAX_ATTEMPTS = 5;
5988
+ var VERSION_CONFLICT_RETRY_DELAY_MS = 250;
5989
+ var MissingExoFolderGroupSchemesError = class extends Error {
5990
+ constructor(missingSchemeIds) {
5991
+ super(`Missing ExO folder-group concept scheme(s) in the destination organization: ${missingSchemeIds.join(", ")}`);
5992
+ this.name = "MissingExoFolderGroupSchemesError";
5993
+ this.missingSchemeIds = missingSchemeIds;
5994
+ }
5995
+ };
5996
+ var SourceExoFolderConceptReadError = class extends Error {
5997
+ constructor(sourceConceptId, error) {
5998
+ const reason = error instanceof Error ? error.message : String(error);
5999
+ super(`Unable to read source ExO folder concept ${sourceConceptId}: ${reason}`);
6000
+ this.name = "SourceExoFolderConceptReadError";
6001
+ this.sourceConceptId = sourceConceptId;
6002
+ }
6003
+ };
6004
+ var SourceOrganizationResolutionError = class extends Error {
6005
+ constructor(message) {
6006
+ super(message);
6007
+ this.name = "SourceOrganizationResolutionError";
6008
+ }
6009
+ };
5987
6010
  var ENTITY_TYPE_TO_PARENT_GROUP_ID = {
5988
6011
  designTokens: PARENT_FOLDER_GROUP_IDS.designToken,
5989
6012
  components: PARENT_FOLDER_GROUP_IDS.componentType,
@@ -6000,19 +6023,44 @@ function getSourceSpaceId(sourceEntities) {
6000
6023
  }
6001
6024
  return void 0;
6002
6025
  }
6003
- async function ensureParentFolderGroupsExist(client, organizationId) {
6026
+ function isVersionMismatchError(err) {
6027
+ return err?.error?.sys?.id === "VersionMismatch";
6028
+ }
6029
+ async function waitForVersionConflictRetry(attempt) {
6030
+ await new Promise((resolve2) => setTimeout(resolve2, VERSION_CONFLICT_RETRY_DELAY_MS * attempt));
6031
+ }
6032
+ async function resolveSourceOrganizationId(client, sourceSpaceId) {
6033
+ if (!sourceSpaceId) {
6034
+ throw new SourceOrganizationResolutionError(
6035
+ "Unable to resolve the source organization because the exported ExO entity does not include a source space ID"
6036
+ );
6037
+ }
6038
+ try {
6039
+ const sourceSpace = await client.space.get({ spaceId: sourceSpaceId });
6040
+ const sourceOrganizationId = sourceSpace?.sys?.organization?.sys?.id;
6041
+ if (!sourceOrganizationId) {
6042
+ throw new Error(`source space ${sourceSpaceId} has no organization link`);
6043
+ }
6044
+ return sourceOrganizationId;
6045
+ } catch (err) {
6046
+ if (err instanceof SourceOrganizationResolutionError) throw err;
6047
+ const reason = err instanceof Error ? err.message : String(err);
6048
+ throw new SourceOrganizationResolutionError(
6049
+ `Unable to resolve the source organization for space ${sourceSpaceId}: ${reason}`
6050
+ );
6051
+ }
6052
+ }
6053
+ async function ensureParentFolderGroupsExist(client, destinationOrganizationId, requiredParentGroupIds) {
6054
+ if (requiredParentGroupIds.size === 0) return /* @__PURE__ */ new Map();
6004
6055
  const { items } = await client.conceptScheme.getMany({
6005
- organizationId,
6056
+ organizationId: destinationOrganizationId,
6006
6057
  query: { purpose: "internal" }
6007
6058
  });
6008
6059
  const existingIds = new Set(items.map((s) => s.sys.id));
6009
- const allParentFolderGroupsExist = Object.values(PARENT_FOLDER_GROUP_IDS).every((id) => existingIds.has(id));
6010
- if (!allParentFolderGroupsExist) {
6011
- return /* @__PURE__ */ new Map();
6012
- }
6013
- const parentGroupIdSet = new Set(Object.values(PARENT_FOLDER_GROUP_IDS));
6060
+ const missingSchemeIds = [...requiredParentGroupIds].filter((id) => !existingIds.has(id));
6061
+ if (missingSchemeIds.length > 0) throw new MissingExoFolderGroupSchemesError(missingSchemeIds);
6014
6062
  return new Map(
6015
- items.filter((s) => parentGroupIdSet.has(s.sys.id)).map((s) => [s.sys.id, s])
6063
+ items.filter((s) => requiredParentGroupIds.has(s.sys.id)).map((s) => [s.sys.id, s])
6016
6064
  );
6017
6065
  }
6018
6066
  function deriveChildConceptMap(sourceEntities, destinationSpaceId) {
@@ -6031,27 +6079,48 @@ function deriveChildConceptMap(sourceEntities, destinationSpaceId) {
6031
6079
  }
6032
6080
  return childConceptMap;
6033
6081
  }
6034
- async function createOrPatchChildConcepts(client, organizationId, destinationSpaceId, childConceptMap) {
6082
+ async function createOrPatchChildConcepts(client, sourceOrganizationId, destinationOrganizationId, destinationSpaceId, childConceptMap) {
6035
6083
  const spaceLink = { sys: { type: "Link", linkType: "Space", id: destinationSpaceId } };
6084
+ const existingDestinationConcepts = /* @__PURE__ */ new Map();
6036
6085
  for (const [sourceConceptId, { destConceptId }] of childConceptMap) {
6037
- let prefLabel = { "en-US": destConceptId };
6038
- try {
6039
- const sourceConcept = await client.concept.get({ organizationId, conceptId: sourceConceptId });
6040
- if (sourceConcept?.prefLabel) prefLabel = sourceConcept.prefLabel;
6041
- } catch {
6042
- }
6043
6086
  let existing = null;
6044
6087
  try {
6045
- existing = await client.concept.get({ organizationId, conceptId: destConceptId });
6088
+ existing = await client.concept.get({
6089
+ organizationId: destinationOrganizationId,
6090
+ conceptId: destConceptId
6091
+ });
6046
6092
  } catch (err) {
6047
6093
  if (err?.name !== "NotFound") {
6048
6094
  import_logging10.logEmitter.emit("warning", `Could not fetch destination child concept ${destConceptId}: ${err?.message ?? err}`);
6049
6095
  }
6050
6096
  }
6097
+ existingDestinationConcepts.set(sourceConceptId, existing);
6098
+ }
6099
+ const sourceConceptLabels = /* @__PURE__ */ new Map();
6100
+ for (const [sourceConceptId] of childConceptMap) {
6101
+ if (existingDestinationConcepts.get(sourceConceptId)) {
6102
+ continue;
6103
+ }
6104
+ try {
6105
+ const sourceConcept = await client.concept.get({
6106
+ organizationId: sourceOrganizationId,
6107
+ conceptId: sourceConceptId
6108
+ });
6109
+ if (!sourceConcept?.prefLabel) {
6110
+ throw new Error("source concept has no prefLabel");
6111
+ }
6112
+ sourceConceptLabels.set(sourceConceptId, sourceConcept.prefLabel);
6113
+ } catch (err) {
6114
+ throw new SourceExoFolderConceptReadError(sourceConceptId, err);
6115
+ }
6116
+ }
6117
+ for (const [sourceConceptId, { destConceptId }] of childConceptMap) {
6118
+ const existing = existingDestinationConcepts.get(sourceConceptId);
6051
6119
  if (!existing) {
6120
+ const prefLabel = sourceConceptLabels.get(sourceConceptId);
6052
6121
  try {
6053
6122
  await client.concept.createWithId(
6054
- { organizationId, conceptId: destConceptId },
6123
+ { organizationId: destinationOrganizationId, conceptId: destConceptId },
6055
6124
  // @ts-expect-error - CMA.js type needs to be updated to be aware of purpose: 'internal'
6056
6125
  { purpose: "internal", prefLabel, metadata: { spaces: [spaceLink] } }
6057
6126
  );
@@ -6068,7 +6137,7 @@ async function createOrPatchChildConcepts(client, organizationId, destinationSpa
6068
6137
  if (patches.length > 0) {
6069
6138
  try {
6070
6139
  await client.concept.patch(
6071
- { organizationId, conceptId: destConceptId, version: existing.sys.version },
6140
+ { organizationId: destinationOrganizationId, conceptId: destConceptId, version: existing.sys.version },
6072
6141
  patches
6073
6142
  );
6074
6143
  import_logging10.logEmitter.emit("info", `Patched child folder concept ${destConceptId} (${patches.map((p) => p.path).join(", ")})`);
@@ -6079,21 +6148,33 @@ async function createOrPatchChildConcepts(client, organizationId, destinationSpa
6079
6148
  }
6080
6149
  }
6081
6150
  }
6082
- async function linkChildConceptsToParentGroups(client, organizationId, childConceptMap, parentGroups) {
6151
+ async function linkChildConceptsToParentGroups(client, destinationOrganizationId, childConceptMap, parentGroups) {
6083
6152
  for (const [, { destConceptId, parentGroupId }] of childConceptMap) {
6084
- const parentGroup = parentGroups.get(parentGroupId);
6085
- if (!parentGroup) continue;
6086
- const alreadyLinked = (parentGroup.concepts ?? []).some((c) => c.sys.id === destConceptId);
6087
- if (alreadyLinked) continue;
6088
- try {
6089
- const updated = await client.conceptScheme.patch(
6090
- { organizationId, conceptSchemeId: parentGroupId, version: parentGroup.sys.version },
6091
- [{ op: "add", path: "/concepts/-", value: { sys: { type: "Link", linkType: "TaxonomyConcept", id: destConceptId } } }]
6092
- );
6093
- parentGroups.set(parentGroupId, updated);
6094
- import_logging10.logEmitter.emit("info", `Linked child concept ${destConceptId} to parent group ${parentGroupId}`);
6095
- } catch (err) {
6096
- import_logging10.logEmitter.emit("error", `Failed to link child concept ${destConceptId} to parent group ${parentGroupId}: ${err?.message ?? err}`);
6153
+ let parentGroup = parentGroups.get(parentGroupId);
6154
+ for (let attempt = 1; parentGroup && attempt <= VERSION_CONFLICT_MAX_ATTEMPTS; attempt++) {
6155
+ const alreadyLinked = (parentGroup.concepts ?? []).some((c) => c.sys.id === destConceptId);
6156
+ if (alreadyLinked) break;
6157
+ try {
6158
+ const updated = await client.conceptScheme.patch(
6159
+ { organizationId: destinationOrganizationId, conceptSchemeId: parentGroupId, version: parentGroup.sys.version },
6160
+ [{ op: "add", path: "/concepts/-", value: { sys: { type: "Link", linkType: "TaxonomyConcept", id: destConceptId } } }]
6161
+ );
6162
+ parentGroups.set(parentGroupId, updated);
6163
+ import_logging10.logEmitter.emit("info", `Linked child concept ${destConceptId} to parent group ${parentGroupId}`);
6164
+ break;
6165
+ } catch (err) {
6166
+ if (!isVersionMismatchError(err) || attempt === VERSION_CONFLICT_MAX_ATTEMPTS) {
6167
+ import_logging10.logEmitter.emit("error", `Failed to link child concept ${destConceptId} to parent group ${parentGroupId}: ${err?.message ?? err}`);
6168
+ break;
6169
+ }
6170
+ import_logging10.logEmitter.emit("warning", `Version mismatch linking child concept ${destConceptId} to parent group ${parentGroupId}; retrying`);
6171
+ await waitForVersionConflictRetry(attempt);
6172
+ parentGroup = await client.conceptScheme.get({
6173
+ organizationId: destinationOrganizationId,
6174
+ conceptSchemeId: parentGroupId
6175
+ });
6176
+ parentGroups.set(parentGroupId, parentGroup);
6177
+ }
6097
6178
  }
6098
6179
  }
6099
6180
  }
@@ -6109,7 +6190,7 @@ function rewriteEntityFolderConcepts(entities2, childConceptMap) {
6109
6190
  }
6110
6191
  async function importExoFolders({
6111
6192
  client,
6112
- organizationId,
6193
+ destinationOrganizationId,
6113
6194
  destinationSpaceId,
6114
6195
  sourceEntities
6115
6196
  }) {
@@ -6118,16 +6199,22 @@ async function importExoFolders({
6118
6199
  import_logging10.logEmitter.emit("info", "Source and destination space are the same \u2014 skipping ExO folder import");
6119
6200
  return;
6120
6201
  }
6121
- const parentGroups = await ensureParentFolderGroupsExist(client, organizationId);
6122
- if (parentGroups.size === 0) {
6123
- import_logging10.logEmitter.emit("warn", "One or more Experience Orchestration folder group concept schemes are missing in the destination organization. Please create them before importing.");
6124
- return;
6125
- }
6126
6202
  const childConceptMap = deriveChildConceptMap(sourceEntities, destinationSpaceId);
6127
6203
  if (childConceptMap.size === 0) return;
6204
+ const requiredParentGroupIds = new Set(
6205
+ [...childConceptMap.values()].map(({ parentGroupId }) => parentGroupId)
6206
+ );
6207
+ const sourceOrganizationId = await resolveSourceOrganizationId(client, sourceSpaceId);
6208
+ const parentGroups = await ensureParentFolderGroupsExist(client, destinationOrganizationId, requiredParentGroupIds);
6128
6209
  import_logging10.logEmitter.emit("info", `Importing ${childConceptMap.size} ExO folder concept(s) into destination space ${destinationSpaceId}`);
6129
- await createOrPatchChildConcepts(client, organizationId, destinationSpaceId, childConceptMap);
6130
- await linkChildConceptsToParentGroups(client, organizationId, childConceptMap, parentGroups);
6210
+ await createOrPatchChildConcepts(
6211
+ client,
6212
+ sourceOrganizationId,
6213
+ destinationOrganizationId,
6214
+ destinationSpaceId,
6215
+ childConceptMap
6216
+ );
6217
+ await linkChildConceptsToParentGroups(client, destinationOrganizationId, childConceptMap, parentGroups);
6131
6218
  const allEntities = [
6132
6219
  ...sourceEntities.designTokens ?? [],
6133
6220
  ...sourceEntities.components ?? [],
@@ -6557,7 +6644,7 @@ function pushToSpace({
6557
6644
  const space = await client.space.get({ spaceId });
6558
6645
  await importExoFolders({
6559
6646
  client,
6560
- organizationId: space.sys.organization.sys.id,
6647
+ destinationOrganizationId: space.sys.organization.sys.id,
6561
6648
  destinationSpaceId: spaceId,
6562
6649
  sourceEntities: {
6563
6650
  designTokens: sourceData.designTokens,
@@ -6568,6 +6655,9 @@ function pushToSpace({
6568
6655
  }
6569
6656
  });
6570
6657
  } catch (error) {
6658
+ if (error instanceof MissingExoFolderGroupSchemesError || error instanceof SourceOrganizationResolutionError || error instanceof SourceExoFolderConceptReadError) {
6659
+ throw error;
6660
+ }
6571
6661
  import_logging12.logEmitter.emit("warning", `Unable to create Experience Orchestration (ExO) folders, error: ${error}`);
6572
6662
  }
6573
6663
  }),
@@ -7060,6 +7150,9 @@ async function publishEntities2({ entities: entities2, sourceEntities, client, s
7060
7150
  });
7061
7151
  }
7062
7152
 
7153
+ // lib/transform/transform-space.ts
7154
+ var import_logging13 = __toESM(require_logging());
7155
+
7063
7156
  // lib/transform/transformers.ts
7064
7157
  var transformers_exports = {};
7065
7158
  __export(transformers_exports, {
@@ -7068,6 +7161,7 @@ __export(transformers_exports, {
7068
7161
  entries: () => entries,
7069
7162
  locales: () => locales,
7070
7163
  releases: () => releases,
7164
+ removeMetadataTags: () => removeMetadataTags,
7071
7165
  tags: () => tags,
7072
7166
  webhooks: () => webhooks
7073
7167
  });
@@ -7118,10 +7212,14 @@ function locales(locale, destinationLocales) {
7118
7212
  return transformedLocale;
7119
7213
  }
7120
7214
  function removeMetadataTags(entity, tagsEnabled = false) {
7121
- if (!tagsEnabled) {
7122
- delete entity.metadata;
7215
+ if (tagsEnabled || !entity.metadata) {
7216
+ return entity;
7123
7217
  }
7124
- return entity;
7218
+ const restMetadata = omit_default(entity.metadata, "tags");
7219
+ return {
7220
+ ...omit_default(entity, "metadata"),
7221
+ ...Object.keys(restMetadata).length > 0 ? { metadata: restMetadata } : {}
7222
+ };
7125
7223
  }
7126
7224
  function releases(release) {
7127
7225
  return release;
@@ -7363,14 +7461,20 @@ function upgradeExperience(entity) {
7363
7461
  ...entity.slots !== void 0 ? { slots: upgradeNodeMap(entity.slots) } : {}
7364
7462
  };
7365
7463
  }
7366
- function upgradeExoResources(resources) {
7464
+ function upgradeEntityArray(key, resources, upgrade, tagsEnabled) {
7465
+ const items = resources[key];
7466
+ if (!Array.isArray(items)) return {};
7467
+ const upgraded = items.map((entity) => removeMetadataTags(upgrade(entity), tagsEnabled));
7468
+ return { [key]: upgraded };
7469
+ }
7470
+ function upgradeExoResources(resources, tagsEnabled = false) {
7367
7471
  if (!resources) return resources;
7368
7472
  return {
7369
7473
  ...resources,
7370
- ...Array.isArray(resources.components) ? { components: resources.components.map(upgradeComponent) } : {},
7371
- ...Array.isArray(resources.experienceTemplates) ? { experienceTemplates: resources.experienceTemplates.map(upgradeExperienceTemplate) } : {},
7372
- ...Array.isArray(resources.experienceFragments) ? { experienceFragments: resources.experienceFragments.map(upgradeExperienceFragment) } : {},
7373
- ...Array.isArray(resources.experiences) ? { experiences: resources.experiences.map(upgradeExperience) } : {}
7474
+ ...upgradeEntityArray("components", resources, upgradeComponent, tagsEnabled),
7475
+ ...upgradeEntityArray("experienceTemplates", resources, upgradeExperienceTemplate, tagsEnabled),
7476
+ ...upgradeEntityArray("experienceFragments", resources, upgradeExperienceFragment, tagsEnabled),
7477
+ ...upgradeEntityArray("experiences", resources, upgradeExperience, tagsEnabled)
7374
7478
  };
7375
7479
  }
7376
7480
 
@@ -7384,10 +7488,46 @@ var entities = [
7384
7488
  "tags",
7385
7489
  "releases"
7386
7490
  ];
7491
+ var TAG_SCRUBBED_ENTITY_TYPES = [
7492
+ "entries",
7493
+ "assets",
7494
+ "components",
7495
+ "experienceTemplates",
7496
+ "experienceFragments",
7497
+ "experiences",
7498
+ "dataAssemblies",
7499
+ "designTokens"
7500
+ ];
7501
+ function countEntitiesWithTags(sourceData) {
7502
+ return TAG_SCRUBBED_ENTITY_TYPES.reduce((count, type) => {
7503
+ const entitiesOfType = sourceData[type] ?? [];
7504
+ return count + entitiesOfType.filter((entity) => entity.metadata?.tags?.length).length;
7505
+ }, 0);
7506
+ }
7507
+ function warnIfTagsWillBeStripped(sourceData, tagsEnabled) {
7508
+ if (tagsEnabled) return;
7509
+ const strippedCount = countEntitiesWithTags(sourceData);
7510
+ if (strippedCount === 0) return;
7511
+ import_logging13.logEmitter.emit("warning", `The destination space/environment does not have access to the Tags feature. metadata.tags was removed from ${strippedCount} ${strippedCount === 1 ? "entity" : "entities"} during import.`);
7512
+ }
7513
+ function stripTagsFromDataAssembliesAndDesignTokens(spaceData, tagsEnabled) {
7514
+ if (tagsEnabled) return;
7515
+ if (Array.isArray(spaceData.dataAssemblies)) {
7516
+ spaceData.dataAssemblies = spaceData.dataAssemblies.map((entity) => ({
7517
+ ...entity,
7518
+ metadata: { ...entity.metadata, tags: [] }
7519
+ }));
7520
+ }
7521
+ if (Array.isArray(spaceData.designTokens)) {
7522
+ spaceData.designTokens = spaceData.designTokens.map((entity) => removeMetadataTags(entity, false));
7523
+ }
7524
+ }
7387
7525
  function transform_space_default(sourceData, destinationData) {
7388
- const baseSpaceData = upgradeExoResources(omit_default(sourceData, ...entities));
7389
- sourceData.locales = sortLocales(sourceData.locales);
7390
7526
  const tagsEnabled = !!destinationData.tags;
7527
+ warnIfTagsWillBeStripped(sourceData, tagsEnabled);
7528
+ const baseSpaceData = upgradeExoResources(omit_default(sourceData, ...entities), tagsEnabled);
7529
+ stripTagsFromDataAssembliesAndDesignTokens(baseSpaceData, tagsEnabled);
7530
+ sourceData.locales = sortLocales(sourceData.locales);
7391
7531
  return entities.reduce((transformedSpaceData, type) => {
7392
7532
  const sortedEntities = type === "tags" || type === "releases" ? sourceData[type] ?? [] : sortEntries(sourceData[type] ?? []);
7393
7533
  const transformedEntities = sortedEntities.map((entity) => ({
@@ -7688,7 +7828,7 @@ async function parseOptions(params) {
7688
7828
 
7689
7829
  // lib/utils/display-error-log.ts
7690
7830
  var import_date_fns2 = require("date-fns");
7691
- var import_logging13 = __toESM(require_logging());
7831
+ var import_logging14 = __toESM(require_logging());
7692
7832
  function displayErrorLog(errorLog) {
7693
7833
  if (errorLog.length) {
7694
7834
  const count = errorLog.reduce((count2, curr) => {
@@ -7703,7 +7843,7 @@ function displayErrorLog(errorLog) {
7703
7843
 
7704
7844
  The following ${count.errors} errors and ${count.warnings} warnings occurred:
7705
7845
  `);
7706
- errorLog.map((logMessage) => `${(0, import_date_fns2.format)((0, import_date_fns2.parseISO)(logMessage.ts), "HH:mm:ss")} - ${(0, import_logging13.formatLogMessageOneLine)(logMessage)}`).map((logMessage) => console.log(logMessage));
7846
+ errorLog.map((logMessage) => `${(0, import_date_fns2.format)((0, import_date_fns2.parseISO)(logMessage.ts), "HH:mm:ss")} - ${(0, import_logging14.formatLogMessageOneLine)(logMessage)}`).map((logMessage) => console.log(logMessage));
7707
7847
  return;
7708
7848
  }
7709
7849
  console.log("No errors or warnings occurred");
@@ -7735,7 +7875,7 @@ async function runContentfulImport(params) {
7735
7875
  intervalCap: options.rateLimit,
7736
7876
  carryoverConcurrencyCount: true
7737
7877
  });
7738
- (0, import_logging14.setupLogging)(log);
7878
+ (0, import_logging15.setupLogging)(log);
7739
7879
  const infoTable = new import_cli_table3.default(tableOptions);
7740
7880
  infoTable.push([{ colSpan: 2, content: "The following entities are going to be imported:" }]);
7741
7881
  Object.keys(options.content).forEach((type) => {
@@ -7862,7 +8002,7 @@ async function runContentfulImport(params) {
7862
8002
  const displayLog = log.filter((logMessage) => logMessage.level !== "info");
7863
8003
  displayErrorLog(displayLog);
7864
8004
  if (errorLog.length) {
7865
- return (0, import_logging14.writeErrorLogFile)(options.errorLogFile, errorLog).then(() => {
8005
+ return (0, import_logging15.writeErrorLogFile)(options.errorLogFile, errorLog).then(() => {
7866
8006
  const multiError = new ContentfulMultiError("Errors occurred");
7867
8007
  multiError.name = "ContentfulMultiError";
7868
8008
  multiError.errors = errorLog;
package/dist/index.mjs CHANGED
@@ -4827,7 +4827,7 @@ var startCase = createCompounder_default(function(result, word, index) {
4827
4827
  var startCase_default = startCase;
4828
4828
 
4829
4829
  // lib/index.ts
4830
- var import_logging14 = __toESM(require_logging());
4830
+ var import_logging15 = __toESM(require_logging());
4831
4831
  var import_listr4 = __toESM(require_listr());
4832
4832
  import PQueue from "p-queue";
4833
4833
 
@@ -5951,6 +5951,29 @@ var PARENT_FOLDER_GROUP_IDS = {
5951
5951
  fragment: "contentful.folder-group-fragment",
5952
5952
  experience: "contentful.folder-group-experience"
5953
5953
  };
5954
+ var VERSION_CONFLICT_MAX_ATTEMPTS = 5;
5955
+ var VERSION_CONFLICT_RETRY_DELAY_MS = 250;
5956
+ var MissingExoFolderGroupSchemesError = class extends Error {
5957
+ constructor(missingSchemeIds) {
5958
+ super(`Missing ExO folder-group concept scheme(s) in the destination organization: ${missingSchemeIds.join(", ")}`);
5959
+ this.name = "MissingExoFolderGroupSchemesError";
5960
+ this.missingSchemeIds = missingSchemeIds;
5961
+ }
5962
+ };
5963
+ var SourceExoFolderConceptReadError = class extends Error {
5964
+ constructor(sourceConceptId, error) {
5965
+ const reason = error instanceof Error ? error.message : String(error);
5966
+ super(`Unable to read source ExO folder concept ${sourceConceptId}: ${reason}`);
5967
+ this.name = "SourceExoFolderConceptReadError";
5968
+ this.sourceConceptId = sourceConceptId;
5969
+ }
5970
+ };
5971
+ var SourceOrganizationResolutionError = class extends Error {
5972
+ constructor(message) {
5973
+ super(message);
5974
+ this.name = "SourceOrganizationResolutionError";
5975
+ }
5976
+ };
5954
5977
  var ENTITY_TYPE_TO_PARENT_GROUP_ID = {
5955
5978
  designTokens: PARENT_FOLDER_GROUP_IDS.designToken,
5956
5979
  components: PARENT_FOLDER_GROUP_IDS.componentType,
@@ -5967,19 +5990,44 @@ function getSourceSpaceId(sourceEntities) {
5967
5990
  }
5968
5991
  return void 0;
5969
5992
  }
5970
- async function ensureParentFolderGroupsExist(client, organizationId) {
5993
+ function isVersionMismatchError(err) {
5994
+ return err?.error?.sys?.id === "VersionMismatch";
5995
+ }
5996
+ async function waitForVersionConflictRetry(attempt) {
5997
+ await new Promise((resolve2) => setTimeout(resolve2, VERSION_CONFLICT_RETRY_DELAY_MS * attempt));
5998
+ }
5999
+ async function resolveSourceOrganizationId(client, sourceSpaceId) {
6000
+ if (!sourceSpaceId) {
6001
+ throw new SourceOrganizationResolutionError(
6002
+ "Unable to resolve the source organization because the exported ExO entity does not include a source space ID"
6003
+ );
6004
+ }
6005
+ try {
6006
+ const sourceSpace = await client.space.get({ spaceId: sourceSpaceId });
6007
+ const sourceOrganizationId = sourceSpace?.sys?.organization?.sys?.id;
6008
+ if (!sourceOrganizationId) {
6009
+ throw new Error(`source space ${sourceSpaceId} has no organization link`);
6010
+ }
6011
+ return sourceOrganizationId;
6012
+ } catch (err) {
6013
+ if (err instanceof SourceOrganizationResolutionError) throw err;
6014
+ const reason = err instanceof Error ? err.message : String(err);
6015
+ throw new SourceOrganizationResolutionError(
6016
+ `Unable to resolve the source organization for space ${sourceSpaceId}: ${reason}`
6017
+ );
6018
+ }
6019
+ }
6020
+ async function ensureParentFolderGroupsExist(client, destinationOrganizationId, requiredParentGroupIds) {
6021
+ if (requiredParentGroupIds.size === 0) return /* @__PURE__ */ new Map();
5971
6022
  const { items } = await client.conceptScheme.getMany({
5972
- organizationId,
6023
+ organizationId: destinationOrganizationId,
5973
6024
  query: { purpose: "internal" }
5974
6025
  });
5975
6026
  const existingIds = new Set(items.map((s) => s.sys.id));
5976
- const allParentFolderGroupsExist = Object.values(PARENT_FOLDER_GROUP_IDS).every((id) => existingIds.has(id));
5977
- if (!allParentFolderGroupsExist) {
5978
- return /* @__PURE__ */ new Map();
5979
- }
5980
- const parentGroupIdSet = new Set(Object.values(PARENT_FOLDER_GROUP_IDS));
6027
+ const missingSchemeIds = [...requiredParentGroupIds].filter((id) => !existingIds.has(id));
6028
+ if (missingSchemeIds.length > 0) throw new MissingExoFolderGroupSchemesError(missingSchemeIds);
5981
6029
  return new Map(
5982
- items.filter((s) => parentGroupIdSet.has(s.sys.id)).map((s) => [s.sys.id, s])
6030
+ items.filter((s) => requiredParentGroupIds.has(s.sys.id)).map((s) => [s.sys.id, s])
5983
6031
  );
5984
6032
  }
5985
6033
  function deriveChildConceptMap(sourceEntities, destinationSpaceId) {
@@ -5998,27 +6046,48 @@ function deriveChildConceptMap(sourceEntities, destinationSpaceId) {
5998
6046
  }
5999
6047
  return childConceptMap;
6000
6048
  }
6001
- async function createOrPatchChildConcepts(client, organizationId, destinationSpaceId, childConceptMap) {
6049
+ async function createOrPatchChildConcepts(client, sourceOrganizationId, destinationOrganizationId, destinationSpaceId, childConceptMap) {
6002
6050
  const spaceLink = { sys: { type: "Link", linkType: "Space", id: destinationSpaceId } };
6051
+ const existingDestinationConcepts = /* @__PURE__ */ new Map();
6003
6052
  for (const [sourceConceptId, { destConceptId }] of childConceptMap) {
6004
- let prefLabel = { "en-US": destConceptId };
6005
- try {
6006
- const sourceConcept = await client.concept.get({ organizationId, conceptId: sourceConceptId });
6007
- if (sourceConcept?.prefLabel) prefLabel = sourceConcept.prefLabel;
6008
- } catch {
6009
- }
6010
6053
  let existing = null;
6011
6054
  try {
6012
- existing = await client.concept.get({ organizationId, conceptId: destConceptId });
6055
+ existing = await client.concept.get({
6056
+ organizationId: destinationOrganizationId,
6057
+ conceptId: destConceptId
6058
+ });
6013
6059
  } catch (err) {
6014
6060
  if (err?.name !== "NotFound") {
6015
6061
  import_logging10.logEmitter.emit("warning", `Could not fetch destination child concept ${destConceptId}: ${err?.message ?? err}`);
6016
6062
  }
6017
6063
  }
6064
+ existingDestinationConcepts.set(sourceConceptId, existing);
6065
+ }
6066
+ const sourceConceptLabels = /* @__PURE__ */ new Map();
6067
+ for (const [sourceConceptId] of childConceptMap) {
6068
+ if (existingDestinationConcepts.get(sourceConceptId)) {
6069
+ continue;
6070
+ }
6071
+ try {
6072
+ const sourceConcept = await client.concept.get({
6073
+ organizationId: sourceOrganizationId,
6074
+ conceptId: sourceConceptId
6075
+ });
6076
+ if (!sourceConcept?.prefLabel) {
6077
+ throw new Error("source concept has no prefLabel");
6078
+ }
6079
+ sourceConceptLabels.set(sourceConceptId, sourceConcept.prefLabel);
6080
+ } catch (err) {
6081
+ throw new SourceExoFolderConceptReadError(sourceConceptId, err);
6082
+ }
6083
+ }
6084
+ for (const [sourceConceptId, { destConceptId }] of childConceptMap) {
6085
+ const existing = existingDestinationConcepts.get(sourceConceptId);
6018
6086
  if (!existing) {
6087
+ const prefLabel = sourceConceptLabels.get(sourceConceptId);
6019
6088
  try {
6020
6089
  await client.concept.createWithId(
6021
- { organizationId, conceptId: destConceptId },
6090
+ { organizationId: destinationOrganizationId, conceptId: destConceptId },
6022
6091
  // @ts-expect-error - CMA.js type needs to be updated to be aware of purpose: 'internal'
6023
6092
  { purpose: "internal", prefLabel, metadata: { spaces: [spaceLink] } }
6024
6093
  );
@@ -6035,7 +6104,7 @@ async function createOrPatchChildConcepts(client, organizationId, destinationSpa
6035
6104
  if (patches.length > 0) {
6036
6105
  try {
6037
6106
  await client.concept.patch(
6038
- { organizationId, conceptId: destConceptId, version: existing.sys.version },
6107
+ { organizationId: destinationOrganizationId, conceptId: destConceptId, version: existing.sys.version },
6039
6108
  patches
6040
6109
  );
6041
6110
  import_logging10.logEmitter.emit("info", `Patched child folder concept ${destConceptId} (${patches.map((p) => p.path).join(", ")})`);
@@ -6046,21 +6115,33 @@ async function createOrPatchChildConcepts(client, organizationId, destinationSpa
6046
6115
  }
6047
6116
  }
6048
6117
  }
6049
- async function linkChildConceptsToParentGroups(client, organizationId, childConceptMap, parentGroups) {
6118
+ async function linkChildConceptsToParentGroups(client, destinationOrganizationId, childConceptMap, parentGroups) {
6050
6119
  for (const [, { destConceptId, parentGroupId }] of childConceptMap) {
6051
- const parentGroup = parentGroups.get(parentGroupId);
6052
- if (!parentGroup) continue;
6053
- const alreadyLinked = (parentGroup.concepts ?? []).some((c) => c.sys.id === destConceptId);
6054
- if (alreadyLinked) continue;
6055
- try {
6056
- const updated = await client.conceptScheme.patch(
6057
- { organizationId, conceptSchemeId: parentGroupId, version: parentGroup.sys.version },
6058
- [{ op: "add", path: "/concepts/-", value: { sys: { type: "Link", linkType: "TaxonomyConcept", id: destConceptId } } }]
6059
- );
6060
- parentGroups.set(parentGroupId, updated);
6061
- import_logging10.logEmitter.emit("info", `Linked child concept ${destConceptId} to parent group ${parentGroupId}`);
6062
- } catch (err) {
6063
- import_logging10.logEmitter.emit("error", `Failed to link child concept ${destConceptId} to parent group ${parentGroupId}: ${err?.message ?? err}`);
6120
+ let parentGroup = parentGroups.get(parentGroupId);
6121
+ for (let attempt = 1; parentGroup && attempt <= VERSION_CONFLICT_MAX_ATTEMPTS; attempt++) {
6122
+ const alreadyLinked = (parentGroup.concepts ?? []).some((c) => c.sys.id === destConceptId);
6123
+ if (alreadyLinked) break;
6124
+ try {
6125
+ const updated = await client.conceptScheme.patch(
6126
+ { organizationId: destinationOrganizationId, conceptSchemeId: parentGroupId, version: parentGroup.sys.version },
6127
+ [{ op: "add", path: "/concepts/-", value: { sys: { type: "Link", linkType: "TaxonomyConcept", id: destConceptId } } }]
6128
+ );
6129
+ parentGroups.set(parentGroupId, updated);
6130
+ import_logging10.logEmitter.emit("info", `Linked child concept ${destConceptId} to parent group ${parentGroupId}`);
6131
+ break;
6132
+ } catch (err) {
6133
+ if (!isVersionMismatchError(err) || attempt === VERSION_CONFLICT_MAX_ATTEMPTS) {
6134
+ import_logging10.logEmitter.emit("error", `Failed to link child concept ${destConceptId} to parent group ${parentGroupId}: ${err?.message ?? err}`);
6135
+ break;
6136
+ }
6137
+ import_logging10.logEmitter.emit("warning", `Version mismatch linking child concept ${destConceptId} to parent group ${parentGroupId}; retrying`);
6138
+ await waitForVersionConflictRetry(attempt);
6139
+ parentGroup = await client.conceptScheme.get({
6140
+ organizationId: destinationOrganizationId,
6141
+ conceptSchemeId: parentGroupId
6142
+ });
6143
+ parentGroups.set(parentGroupId, parentGroup);
6144
+ }
6064
6145
  }
6065
6146
  }
6066
6147
  }
@@ -6076,7 +6157,7 @@ function rewriteEntityFolderConcepts(entities2, childConceptMap) {
6076
6157
  }
6077
6158
  async function importExoFolders({
6078
6159
  client,
6079
- organizationId,
6160
+ destinationOrganizationId,
6080
6161
  destinationSpaceId,
6081
6162
  sourceEntities
6082
6163
  }) {
@@ -6085,16 +6166,22 @@ async function importExoFolders({
6085
6166
  import_logging10.logEmitter.emit("info", "Source and destination space are the same \u2014 skipping ExO folder import");
6086
6167
  return;
6087
6168
  }
6088
- const parentGroups = await ensureParentFolderGroupsExist(client, organizationId);
6089
- if (parentGroups.size === 0) {
6090
- import_logging10.logEmitter.emit("warn", "One or more Experience Orchestration folder group concept schemes are missing in the destination organization. Please create them before importing.");
6091
- return;
6092
- }
6093
6169
  const childConceptMap = deriveChildConceptMap(sourceEntities, destinationSpaceId);
6094
6170
  if (childConceptMap.size === 0) return;
6171
+ const requiredParentGroupIds = new Set(
6172
+ [...childConceptMap.values()].map(({ parentGroupId }) => parentGroupId)
6173
+ );
6174
+ const sourceOrganizationId = await resolveSourceOrganizationId(client, sourceSpaceId);
6175
+ const parentGroups = await ensureParentFolderGroupsExist(client, destinationOrganizationId, requiredParentGroupIds);
6095
6176
  import_logging10.logEmitter.emit("info", `Importing ${childConceptMap.size} ExO folder concept(s) into destination space ${destinationSpaceId}`);
6096
- await createOrPatchChildConcepts(client, organizationId, destinationSpaceId, childConceptMap);
6097
- await linkChildConceptsToParentGroups(client, organizationId, childConceptMap, parentGroups);
6177
+ await createOrPatchChildConcepts(
6178
+ client,
6179
+ sourceOrganizationId,
6180
+ destinationOrganizationId,
6181
+ destinationSpaceId,
6182
+ childConceptMap
6183
+ );
6184
+ await linkChildConceptsToParentGroups(client, destinationOrganizationId, childConceptMap, parentGroups);
6098
6185
  const allEntities = [
6099
6186
  ...sourceEntities.designTokens ?? [],
6100
6187
  ...sourceEntities.components ?? [],
@@ -6524,7 +6611,7 @@ function pushToSpace({
6524
6611
  const space = await client.space.get({ spaceId });
6525
6612
  await importExoFolders({
6526
6613
  client,
6527
- organizationId: space.sys.organization.sys.id,
6614
+ destinationOrganizationId: space.sys.organization.sys.id,
6528
6615
  destinationSpaceId: spaceId,
6529
6616
  sourceEntities: {
6530
6617
  designTokens: sourceData.designTokens,
@@ -6535,6 +6622,9 @@ function pushToSpace({
6535
6622
  }
6536
6623
  });
6537
6624
  } catch (error) {
6625
+ if (error instanceof MissingExoFolderGroupSchemesError || error instanceof SourceOrganizationResolutionError || error instanceof SourceExoFolderConceptReadError) {
6626
+ throw error;
6627
+ }
6538
6628
  import_logging12.logEmitter.emit("warning", `Unable to create Experience Orchestration (ExO) folders, error: ${error}`);
6539
6629
  }
6540
6630
  }),
@@ -7027,6 +7117,9 @@ async function publishEntities2({ entities: entities2, sourceEntities, client, s
7027
7117
  });
7028
7118
  }
7029
7119
 
7120
+ // lib/transform/transform-space.ts
7121
+ var import_logging13 = __toESM(require_logging());
7122
+
7030
7123
  // lib/transform/transformers.ts
7031
7124
  var transformers_exports = {};
7032
7125
  __export(transformers_exports, {
@@ -7035,6 +7128,7 @@ __export(transformers_exports, {
7035
7128
  entries: () => entries,
7036
7129
  locales: () => locales,
7037
7130
  releases: () => releases,
7131
+ removeMetadataTags: () => removeMetadataTags,
7038
7132
  tags: () => tags,
7039
7133
  webhooks: () => webhooks
7040
7134
  });
@@ -7085,10 +7179,14 @@ function locales(locale, destinationLocales) {
7085
7179
  return transformedLocale;
7086
7180
  }
7087
7181
  function removeMetadataTags(entity, tagsEnabled = false) {
7088
- if (!tagsEnabled) {
7089
- delete entity.metadata;
7182
+ if (tagsEnabled || !entity.metadata) {
7183
+ return entity;
7090
7184
  }
7091
- return entity;
7185
+ const restMetadata = omit_default(entity.metadata, "tags");
7186
+ return {
7187
+ ...omit_default(entity, "metadata"),
7188
+ ...Object.keys(restMetadata).length > 0 ? { metadata: restMetadata } : {}
7189
+ };
7092
7190
  }
7093
7191
  function releases(release) {
7094
7192
  return release;
@@ -7330,14 +7428,20 @@ function upgradeExperience(entity) {
7330
7428
  ...entity.slots !== void 0 ? { slots: upgradeNodeMap(entity.slots) } : {}
7331
7429
  };
7332
7430
  }
7333
- function upgradeExoResources(resources) {
7431
+ function upgradeEntityArray(key, resources, upgrade, tagsEnabled) {
7432
+ const items = resources[key];
7433
+ if (!Array.isArray(items)) return {};
7434
+ const upgraded = items.map((entity) => removeMetadataTags(upgrade(entity), tagsEnabled));
7435
+ return { [key]: upgraded };
7436
+ }
7437
+ function upgradeExoResources(resources, tagsEnabled = false) {
7334
7438
  if (!resources) return resources;
7335
7439
  return {
7336
7440
  ...resources,
7337
- ...Array.isArray(resources.components) ? { components: resources.components.map(upgradeComponent) } : {},
7338
- ...Array.isArray(resources.experienceTemplates) ? { experienceTemplates: resources.experienceTemplates.map(upgradeExperienceTemplate) } : {},
7339
- ...Array.isArray(resources.experienceFragments) ? { experienceFragments: resources.experienceFragments.map(upgradeExperienceFragment) } : {},
7340
- ...Array.isArray(resources.experiences) ? { experiences: resources.experiences.map(upgradeExperience) } : {}
7441
+ ...upgradeEntityArray("components", resources, upgradeComponent, tagsEnabled),
7442
+ ...upgradeEntityArray("experienceTemplates", resources, upgradeExperienceTemplate, tagsEnabled),
7443
+ ...upgradeEntityArray("experienceFragments", resources, upgradeExperienceFragment, tagsEnabled),
7444
+ ...upgradeEntityArray("experiences", resources, upgradeExperience, tagsEnabled)
7341
7445
  };
7342
7446
  }
7343
7447
 
@@ -7351,10 +7455,46 @@ var entities = [
7351
7455
  "tags",
7352
7456
  "releases"
7353
7457
  ];
7458
+ var TAG_SCRUBBED_ENTITY_TYPES = [
7459
+ "entries",
7460
+ "assets",
7461
+ "components",
7462
+ "experienceTemplates",
7463
+ "experienceFragments",
7464
+ "experiences",
7465
+ "dataAssemblies",
7466
+ "designTokens"
7467
+ ];
7468
+ function countEntitiesWithTags(sourceData) {
7469
+ return TAG_SCRUBBED_ENTITY_TYPES.reduce((count, type) => {
7470
+ const entitiesOfType = sourceData[type] ?? [];
7471
+ return count + entitiesOfType.filter((entity) => entity.metadata?.tags?.length).length;
7472
+ }, 0);
7473
+ }
7474
+ function warnIfTagsWillBeStripped(sourceData, tagsEnabled) {
7475
+ if (tagsEnabled) return;
7476
+ const strippedCount = countEntitiesWithTags(sourceData);
7477
+ if (strippedCount === 0) return;
7478
+ import_logging13.logEmitter.emit("warning", `The destination space/environment does not have access to the Tags feature. metadata.tags was removed from ${strippedCount} ${strippedCount === 1 ? "entity" : "entities"} during import.`);
7479
+ }
7480
+ function stripTagsFromDataAssembliesAndDesignTokens(spaceData, tagsEnabled) {
7481
+ if (tagsEnabled) return;
7482
+ if (Array.isArray(spaceData.dataAssemblies)) {
7483
+ spaceData.dataAssemblies = spaceData.dataAssemblies.map((entity) => ({
7484
+ ...entity,
7485
+ metadata: { ...entity.metadata, tags: [] }
7486
+ }));
7487
+ }
7488
+ if (Array.isArray(spaceData.designTokens)) {
7489
+ spaceData.designTokens = spaceData.designTokens.map((entity) => removeMetadataTags(entity, false));
7490
+ }
7491
+ }
7354
7492
  function transform_space_default(sourceData, destinationData) {
7355
- const baseSpaceData = upgradeExoResources(omit_default(sourceData, ...entities));
7356
- sourceData.locales = sortLocales(sourceData.locales);
7357
7493
  const tagsEnabled = !!destinationData.tags;
7494
+ warnIfTagsWillBeStripped(sourceData, tagsEnabled);
7495
+ const baseSpaceData = upgradeExoResources(omit_default(sourceData, ...entities), tagsEnabled);
7496
+ stripTagsFromDataAssembliesAndDesignTokens(baseSpaceData, tagsEnabled);
7497
+ sourceData.locales = sortLocales(sourceData.locales);
7358
7498
  return entities.reduce((transformedSpaceData, type) => {
7359
7499
  const sortedEntities = type === "tags" || type === "releases" ? sourceData[type] ?? [] : sortEntries(sourceData[type] ?? []);
7360
7500
  const transformedEntities = sortedEntities.map((entity) => ({
@@ -7651,7 +7791,7 @@ async function parseOptions(params) {
7651
7791
  }
7652
7792
 
7653
7793
  // lib/utils/display-error-log.ts
7654
- var import_logging13 = __toESM(require_logging());
7794
+ var import_logging14 = __toESM(require_logging());
7655
7795
  import { format as format2, parseISO } from "date-fns";
7656
7796
  function displayErrorLog(errorLog) {
7657
7797
  if (errorLog.length) {
@@ -7667,7 +7807,7 @@ function displayErrorLog(errorLog) {
7667
7807
 
7668
7808
  The following ${count.errors} errors and ${count.warnings} warnings occurred:
7669
7809
  `);
7670
- errorLog.map((logMessage) => `${format2(parseISO(logMessage.ts), "HH:mm:ss")} - ${(0, import_logging13.formatLogMessageOneLine)(logMessage)}`).map((logMessage) => console.log(logMessage));
7810
+ errorLog.map((logMessage) => `${format2(parseISO(logMessage.ts), "HH:mm:ss")} - ${(0, import_logging14.formatLogMessageOneLine)(logMessage)}`).map((logMessage) => console.log(logMessage));
7671
7811
  return;
7672
7812
  }
7673
7813
  console.log("No errors or warnings occurred");
@@ -7699,7 +7839,7 @@ async function runContentfulImport(params) {
7699
7839
  intervalCap: options.rateLimit,
7700
7840
  carryoverConcurrencyCount: true
7701
7841
  });
7702
- (0, import_logging14.setupLogging)(log);
7842
+ (0, import_logging15.setupLogging)(log);
7703
7843
  const infoTable = new Table(tableOptions);
7704
7844
  infoTable.push([{ colSpan: 2, content: "The following entities are going to be imported:" }]);
7705
7845
  Object.keys(options.content).forEach((type) => {
@@ -7826,7 +7966,7 @@ async function runContentfulImport(params) {
7826
7966
  const displayLog = log.filter((logMessage) => logMessage.level !== "info");
7827
7967
  displayErrorLog(displayLog);
7828
7968
  if (errorLog.length) {
7829
- return (0, import_logging14.writeErrorLogFile)(options.errorLogFile, errorLog).then(() => {
7969
+ return (0, import_logging15.writeErrorLogFile)(options.errorLogFile, errorLog).then(() => {
7830
7970
  const multiError = new ContentfulMultiError("Errors occurred");
7831
7971
  multiError.name = "ContentfulMultiError";
7832
7972
  multiError.errors = errorLog;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contentful-import",
3
- "version": "10.5.0",
3
+ "version": "10.5.2",
4
4
  "description": "this tool allows you to import JSON dump exported by contentful-export",
5
5
  "main": "dist/index.mjs",
6
6
  "typings": "dist/index.d.ts",