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.
- package/dist/index.js +196 -56
- package/dist/index.mjs +196 -56
- 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
|
|
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
|
-
|
|
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
|
|
6010
|
-
if (
|
|
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) =>
|
|
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,
|
|
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({
|
|
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,
|
|
6151
|
+
async function linkChildConceptsToParentGroups(client, destinationOrganizationId, childConceptMap, parentGroups) {
|
|
6083
6152
|
for (const [, { destConceptId, parentGroupId }] of childConceptMap) {
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
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
|
-
|
|
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(
|
|
6130
|
-
|
|
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
|
-
|
|
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 (!
|
|
7122
|
-
|
|
7215
|
+
if (tagsEnabled || !entity.metadata) {
|
|
7216
|
+
return entity;
|
|
7123
7217
|
}
|
|
7124
|
-
|
|
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
|
|
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
|
-
...
|
|
7371
|
-
...
|
|
7372
|
-
...
|
|
7373
|
-
...
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
|
5977
|
-
if (
|
|
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) =>
|
|
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,
|
|
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({
|
|
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,
|
|
6118
|
+
async function linkChildConceptsToParentGroups(client, destinationOrganizationId, childConceptMap, parentGroups) {
|
|
6050
6119
|
for (const [, { destConceptId, parentGroupId }] of childConceptMap) {
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
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
|
-
|
|
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(
|
|
6097
|
-
|
|
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
|
-
|
|
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 (!
|
|
7089
|
-
|
|
7182
|
+
if (tagsEnabled || !entity.metadata) {
|
|
7183
|
+
return entity;
|
|
7090
7184
|
}
|
|
7091
|
-
|
|
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
|
|
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
|
-
...
|
|
7338
|
-
...
|
|
7339
|
-
...
|
|
7340
|
-
...
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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;
|