contentful-import 10.3.0 → 10.4.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/README.md +18 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +213 -17
- package/dist/index.mjs +210 -14
- package/dist/usageParams.d.mts +4 -0
- package/dist/usageParams.d.ts +4 -0
- package/dist/usageParams.js +4 -0
- package/dist/usageParams.mjs +4 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -227,6 +227,10 @@ Path to a JSON file with the configuration options. This file will be merged wit
|
|
|
227
227
|
|
|
228
228
|
Flag controlling whether Experience Orchestration (ExO) entities — Design Tokens, Components, Experience Templates, Experience Fragments, Data Assemblies, and Experiences — are imported when present in the source content. Requires the `exoM1` entitlement on the destination space's organization. Set to `false` to opt out. See the "Experience Orchestration (ExO) entities" section below for what happens when the destination isn't entitled.
|
|
229
229
|
|
|
230
|
+
#### `skipExoVariants` [boolean] [default: false]
|
|
231
|
+
|
|
232
|
+
Skip importing nested Experience and Experience Fragment Optimization Variants. This can be useful when re-importing the same export because the upstream API generates new variant IDs on every create and cannot upsert by the source variant ID.
|
|
233
|
+
|
|
230
234
|
## :rescue_worker_helmet: Troubleshooting
|
|
231
235
|
|
|
232
236
|
### Proxy
|
|
@@ -292,6 +296,8 @@ The `designTokens`, `components`, `experienceTemplates`, `dataAssemblies`, `expe
|
|
|
292
296
|
|
|
293
297
|
ExO import is on by default (`includeExperienceOrchestration: true`) — for the CLI and the module API alike. Pass `includeExperienceOrchestration: false` (`--include-experience-orchestration=false` on the CLI) to opt out.
|
|
294
298
|
|
|
299
|
+
Optimization Variant import is on automatically when the source contains nested variants. Pass `skipExoVariants: true` (or `--skip-exo-variants`) to leave them out of the import. When variants are imported, a warning is logged because each run creates fresh destination variant IDs and re-importing can create duplicates.
|
|
300
|
+
|
|
295
301
|
```javascript
|
|
296
302
|
import contentfulImport from 'contentful-import'
|
|
297
303
|
|
|
@@ -322,10 +328,21 @@ ExO entities are created and published in dependency order, then unpublished in
|
|
|
322
328
|
4. Experience Templates — create, then publish
|
|
323
329
|
5. Experience Fragments — create, then publish
|
|
324
330
|
6. Experiences — create, then publish
|
|
325
|
-
7.
|
|
331
|
+
7. Experience Optimization Variants — create, then publish/archive (only if the source has any; see below)
|
|
332
|
+
8. Experience Fragment Optimization Variants — create, then publish/archive (only if the source has any; see below)
|
|
333
|
+
9. Unpublish pass, in reverse: Experiences → Experience Fragments → Experience Templates → Components → Data Assemblies
|
|
326
334
|
|
|
327
335
|
An entity that's published in the source is published in the destination on import. An entity that's unpublished (or removed) in the source but still published in the destination is unpublished on re-import — this propagates in both directions, so reverting a published ExO entity back to draft in the source and re-running the import will unpublish it in the destination too.
|
|
328
336
|
|
|
337
|
+
### Optimization Variants
|
|
338
|
+
|
|
339
|
+
Experiences and Experience Fragments each support **Optimization Variants** — alternate personalization versions nested onto their parent (`experience.optimizationVariants` / `experienceFragment.optimizationVariants`), not a flat top-level array like the other six ExO entity types. A variant's `sys.id` is borrowed from its parent rather than being globally unique — see the export tool's own doc ([contentful-export's ExO doc](https://github.com/contentful/contentful-export/blob/main/docs/exo-export.md#optimization-variants)) for the full rationale.
|
|
340
|
+
|
|
341
|
+
Two behaviors are worth calling out explicitly because they differ from every other ExO entity type:
|
|
342
|
+
|
|
343
|
+
- **No ID preservation.** Every other ExO entity is created via upsert-with-known-ID. Variants can't be: the upstream API's create endpoint always server-generates a fresh ID, and its update endpoint 404s on an unknown ID instead of creating one. Every import run creates brand-new destination variants — re-running an import with variants in the source data creates additional variants rather than updating existing ones.
|
|
344
|
+
- **The API's synthetic "default" entry is filtered out.** The upstream list endpoint always leads with an entry representing the parent's own base view (`sys.variantType: 'default'`) — not a real variant. `contentful-export` already excludes it; `contentful-import` filters it again defensively for older export files.
|
|
345
|
+
|
|
329
346
|
### URN rewriting / backward compatibility
|
|
330
347
|
|
|
331
348
|
- Export files taken before the ExO entity rename (`ComponentType` → `Component`, `Fragment` → `ExperienceFragment`, `Template` → `ExperienceTemplate`) are upgraded automatically on import, including the corresponding resource-link `linkType`s and URN path segments. This upgrade is upgrade-only (there's no downgrade path) and idempotent, so it's safe to run against already-upgraded data.
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -263,7 +263,7 @@ var require_logging = __commonJS({
|
|
|
263
263
|
throw new Error("Unable to extract API error data");
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
|
-
function
|
|
266
|
+
function formatLogMessageOneLine2(logMessage) {
|
|
267
267
|
const { level } = logMessage;
|
|
268
268
|
if (!level) {
|
|
269
269
|
return logMessage.toString().replace(/\s+/g, " ");
|
|
@@ -299,7 +299,7 @@ var require_logging = __commonJS({
|
|
|
299
299
|
return logMessage.error.toString().replace(/\s+/g, " ");
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
|
-
exports2.formatLogMessageOneLine =
|
|
302
|
+
exports2.formatLogMessageOneLine = formatLogMessageOneLine2;
|
|
303
303
|
function formatLogMessageLogfile(logMessage) {
|
|
304
304
|
const { level } = logMessage;
|
|
305
305
|
if (level === "info" || level === "warning") {
|
|
@@ -338,7 +338,7 @@ var require_logging = __commonJS({
|
|
|
338
338
|
|
|
339
339
|
The following ${count.errors} errors and ${count.warnings} warnings occurred:
|
|
340
340
|
`);
|
|
341
|
-
errorLog.map((logMessage) => `${(0, format_1.default)((0, parseISO_1.default)(logMessage.ts), "HH:mm:ss")} - ${
|
|
341
|
+
errorLog.map((logMessage) => `${(0, format_1.default)((0, parseISO_1.default)(logMessage.ts), "HH:mm:ss")} - ${formatLogMessageOneLine2(logMessage)}`).map((logMessage) => console.log(logMessage));
|
|
342
342
|
return;
|
|
343
343
|
}
|
|
344
344
|
console.log("No errors or warnings occurred");
|
|
@@ -385,7 +385,7 @@ The following ${count.errors} errors and ${count.warnings} warnings occurred:
|
|
|
385
385
|
exports2.setupLogging = setupLogging2;
|
|
386
386
|
function logToTaskOutput(task) {
|
|
387
387
|
function logToTask(logMessage) {
|
|
388
|
-
const content =
|
|
388
|
+
const content = formatLogMessageOneLine2(logMessage);
|
|
389
389
|
const symbols = {
|
|
390
390
|
info: figures_1.default.tick,
|
|
391
391
|
warning: figures_1.default.warning,
|
|
@@ -598,12 +598,12 @@ var require_common = __commonJS({
|
|
|
598
598
|
args.unshift("%O");
|
|
599
599
|
}
|
|
600
600
|
let index = 0;
|
|
601
|
-
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match,
|
|
601
|
+
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format3) => {
|
|
602
602
|
if (match === "%%") {
|
|
603
603
|
return "%";
|
|
604
604
|
}
|
|
605
605
|
index++;
|
|
606
|
-
const formatter = createDebug.formatters[
|
|
606
|
+
const formatter = createDebug.formatters[format3];
|
|
607
607
|
if (typeof formatter === "function") {
|
|
608
608
|
const val = args[index];
|
|
609
609
|
match = formatter.call(self2, val);
|
|
@@ -2047,7 +2047,7 @@ __export(index_exports, {
|
|
|
2047
2047
|
});
|
|
2048
2048
|
module.exports = __toCommonJS(index_exports);
|
|
2049
2049
|
var import_cli_table3 = __toESM(require("cli-table3"));
|
|
2050
|
-
var
|
|
2050
|
+
var import_date_fns3 = require("date-fns");
|
|
2051
2051
|
var import_listr3 = __toESM(require("listr"));
|
|
2052
2052
|
var import_listr_update_renderer = __toESM(require("listr-update-renderer"));
|
|
2053
2053
|
var import_listr_verbose_renderer2 = __toESM(require("listr-verbose-renderer"));
|
|
@@ -4889,7 +4889,7 @@ var startCase_default = startCase;
|
|
|
4889
4889
|
|
|
4890
4890
|
// lib/index.ts
|
|
4891
4891
|
var import_p_queue = __toESM(require("p-queue"));
|
|
4892
|
-
var
|
|
4892
|
+
var import_logging13 = __toESM(require_logging());
|
|
4893
4893
|
var import_listr4 = __toESM(require_listr());
|
|
4894
4894
|
|
|
4895
4895
|
// lib/tasks/init-client.ts
|
|
@@ -4955,6 +4955,34 @@ async function unpublishExoEntity(type, entity, unpublish) {
|
|
|
4955
4955
|
return null;
|
|
4956
4956
|
}
|
|
4957
4957
|
}
|
|
4958
|
+
function filterVariantsToPublish(variants) {
|
|
4959
|
+
return variants.filter((v) => v.sys.publishedVersion);
|
|
4960
|
+
}
|
|
4961
|
+
function filterVariantsToArchive(variants) {
|
|
4962
|
+
return variants.filter((v) => v.sys.archivedVersion && !v.sys.publishedVersion);
|
|
4963
|
+
}
|
|
4964
|
+
async function publishVariant(type, entity, publish) {
|
|
4965
|
+
try {
|
|
4966
|
+
const result = await publish();
|
|
4967
|
+
import_logging2.logEmitter.emit("info", `PUBLISH ${type} ${entity.sys.variant}`);
|
|
4968
|
+
return result;
|
|
4969
|
+
} catch (err) {
|
|
4970
|
+
err.entity = entity;
|
|
4971
|
+
import_logging2.logEmitter.emit("error", err);
|
|
4972
|
+
return null;
|
|
4973
|
+
}
|
|
4974
|
+
}
|
|
4975
|
+
async function archiveVariant(type, entity, archive) {
|
|
4976
|
+
try {
|
|
4977
|
+
const result = await archive();
|
|
4978
|
+
import_logging2.logEmitter.emit("info", `ARCHIVE ${type} ${entity.sys.variant}`);
|
|
4979
|
+
return result;
|
|
4980
|
+
} catch (err) {
|
|
4981
|
+
err.entity = entity;
|
|
4982
|
+
import_logging2.logEmitter.emit("error", err);
|
|
4983
|
+
return null;
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4958
4986
|
function isExoEntitlementError(err) {
|
|
4959
4987
|
if (!(err instanceof Error)) {
|
|
4960
4988
|
return false;
|
|
@@ -6165,6 +6193,7 @@ function pushToSpace({
|
|
|
6165
6193
|
spaceId,
|
|
6166
6194
|
environmentId,
|
|
6167
6195
|
includeExperienceOrchestration,
|
|
6196
|
+
skipExoVariants,
|
|
6168
6197
|
contentModelOnly,
|
|
6169
6198
|
skipContentModel,
|
|
6170
6199
|
skipContentUpdates,
|
|
@@ -6187,6 +6216,13 @@ function pushToSpace({
|
|
|
6187
6216
|
...DEFAULT_CONTENT_STRUCTURE,
|
|
6188
6217
|
...destinationData
|
|
6189
6218
|
};
|
|
6219
|
+
const hasOptimizationVariants = [
|
|
6220
|
+
...sourceData.experiences || [],
|
|
6221
|
+
...sourceData.experienceFragments || []
|
|
6222
|
+
].some((parent2) => (parent2.optimizationVariants || []).some(isRealOptimizationVariant));
|
|
6223
|
+
if (includeExperienceOrchestration && !skipExoVariants && hasOptimizationVariants) {
|
|
6224
|
+
import_logging11.logEmitter.emit("warning", "Optimization Variants are imported with new destination IDs and can be duplicated by re-imports. Set skipExoVariants to true to skip them.");
|
|
6225
|
+
}
|
|
6190
6226
|
listrOptions = listrOptions || {
|
|
6191
6227
|
renderer: import_listr_verbose_renderer.default
|
|
6192
6228
|
};
|
|
@@ -6651,12 +6687,12 @@ function pushToSpace({
|
|
|
6651
6687
|
try {
|
|
6652
6688
|
const existing = destinationDataById.experienceFragments?.get(entity.sys.id);
|
|
6653
6689
|
if (existing) {
|
|
6654
|
-
const payload = { ...entity, sys: { id: entity.sys.id, type: "ExperienceFragment", version: existing.sys.version } };
|
|
6690
|
+
const payload = { ...omitSysAndOptimizationVariants(entity), sys: { id: entity.sys.id, type: "ExperienceFragment", version: existing.sys.version } };
|
|
6655
6691
|
const result = await client.experienceFragment.upsert({ spaceId, environmentId, experienceFragmentId: entity.sys.id }, payload);
|
|
6656
6692
|
import_logging11.logEmitter.emit("info", `UPDATE ExperienceFragment ${entity.sys.id}`);
|
|
6657
6693
|
results.push(result);
|
|
6658
6694
|
} else {
|
|
6659
|
-
const payload = { ...
|
|
6695
|
+
const payload = { ...omitSysAndOptimizationVariants(entity), component: entity.sys.component, sys: { id: entity.sys.id, type: "ExperienceFragment" } };
|
|
6660
6696
|
const result = await client.experienceFragment.upsert({ spaceId, environmentId, experienceFragmentId: entity.sys.id }, payload);
|
|
6661
6697
|
import_logging11.logEmitter.emit("info", `CREATE ExperienceFragment ${entity.sys.id}`);
|
|
6662
6698
|
results.push(result);
|
|
@@ -6693,12 +6729,12 @@ function pushToSpace({
|
|
|
6693
6729
|
try {
|
|
6694
6730
|
const existing = destinationDataById.experiences?.get(entity.sys.id);
|
|
6695
6731
|
if (existing) {
|
|
6696
|
-
const payload = { ...entity, sys: { id: entity.sys.id, type: "Experience", version: existing.sys.version } };
|
|
6732
|
+
const payload = { ...omitSysAndOptimizationVariants(entity), sys: { id: entity.sys.id, type: "Experience", version: existing.sys.version } };
|
|
6697
6733
|
const result = await client.experience.upsert({ spaceId, environmentId, experienceId: entity.sys.id }, payload);
|
|
6698
6734
|
import_logging11.logEmitter.emit("info", `UPDATE Experience ${entity.sys.id}`);
|
|
6699
6735
|
return result;
|
|
6700
6736
|
} else {
|
|
6701
|
-
const payload = { ...
|
|
6737
|
+
const payload = { ...omitSysAndOptimizationVariants(entity), experienceTemplate: entity.sys.experienceTemplate, sys: { id: entity.sys.id, type: "Experience" } };
|
|
6702
6738
|
const result = await client.experience.upsert({ spaceId, environmentId, experienceId: entity.sys.id }, payload);
|
|
6703
6739
|
import_logging11.logEmitter.emit("info", `CREATE Experience ${entity.sys.id}`);
|
|
6704
6740
|
return result;
|
|
@@ -6726,6 +6762,85 @@ function pushToSpace({
|
|
|
6726
6762
|
}),
|
|
6727
6763
|
skip: () => !includeExperienceOrchestration || skipContentPublishing || !(sourceData.experiences || []).length
|
|
6728
6764
|
},
|
|
6765
|
+
// Optimization Variants are sub-resources nested on their parent Experience/ExperienceFragment
|
|
6766
|
+
// (sourceData.experiences[].optimizationVariants), not a flat top-level array. A variant's
|
|
6767
|
+
// sys.id is borrowed from its parent, not unique, so variant creation/publish/archive is
|
|
6768
|
+
// handled by new, self-contained functions (importVariantsForParents, filterVariantsToPublish,
|
|
6769
|
+
// filterVariantsToArchive, publishVariant, archiveVariant) rather than by generalizing
|
|
6770
|
+
// destinationDataById / filterExoEntitiesToPublish / filterExoEntitiesToUnpublish, which all
|
|
6771
|
+
// assume sys.id uniqueness.
|
|
6772
|
+
//
|
|
6773
|
+
// Unlike the base Experience/Fragment create/update, there is no upsert-by-known-ID for
|
|
6774
|
+
// variants: the upstream API's create endpoint always server-generates a fresh variantId
|
|
6775
|
+
// (crypto.randomUUID()) and its update endpoint 404s on an unknown variantId rather than
|
|
6776
|
+
// creating one. So every import run creates fresh destination variants via POST rather than
|
|
6777
|
+
// matching against any existing destination variant.
|
|
6778
|
+
{
|
|
6779
|
+
title: "Importing Experience Optimization Variants",
|
|
6780
|
+
task: (0, import_listr2.wrapTask)(async (ctx) => {
|
|
6781
|
+
const results = await importVariantsForParents({
|
|
6782
|
+
parents: ctx.data.experiences || [],
|
|
6783
|
+
sourceParents: sourceData.experiences || [],
|
|
6784
|
+
client,
|
|
6785
|
+
spaceId,
|
|
6786
|
+
environmentId,
|
|
6787
|
+
kind: "experience"
|
|
6788
|
+
});
|
|
6789
|
+
ctx.data.experienceVariants = results.flatMap((r) => r.created);
|
|
6790
|
+
}),
|
|
6791
|
+
skip: () => !includeExperienceOrchestration || skipExoVariants || !(sourceData.experiences || []).some((e) => (e.optimizationVariants || []).some(isRealOptimizationVariant))
|
|
6792
|
+
},
|
|
6793
|
+
{
|
|
6794
|
+
title: "Publishing Experience Optimization Variants",
|
|
6795
|
+
task: (0, import_listr2.wrapTask)(async (ctx) => {
|
|
6796
|
+
const toPublish = filterVariantsToPublish(ctx.data.experienceVariants || []);
|
|
6797
|
+
await Promise.all(toPublish.map(
|
|
6798
|
+
(v) => publishVariant("ExperienceVariant", v, () => client.experienceVariant.publish(
|
|
6799
|
+
{ spaceId, environmentId, experienceId: v.sys.id, variantId: v.sys.variant, version: v.sys.version }
|
|
6800
|
+
))
|
|
6801
|
+
));
|
|
6802
|
+
const toArchive = filterVariantsToArchive(ctx.data.experienceVariants || []);
|
|
6803
|
+
await Promise.all(toArchive.map(
|
|
6804
|
+
(v) => archiveVariant("ExperienceVariant", v, () => client.experienceVariant.archive(
|
|
6805
|
+
{ spaceId, environmentId, experienceId: v.sys.id, variantId: v.sys.variant, version: v.sys.version }
|
|
6806
|
+
))
|
|
6807
|
+
));
|
|
6808
|
+
}),
|
|
6809
|
+
skip: () => !includeExperienceOrchestration || skipExoVariants || skipContentPublishing || !(sourceData.experiences || []).some((e) => (e.optimizationVariants || []).some(isRealOptimizationVariant))
|
|
6810
|
+
},
|
|
6811
|
+
{
|
|
6812
|
+
title: "Importing Experience Fragment Optimization Variants",
|
|
6813
|
+
task: (0, import_listr2.wrapTask)(async (ctx) => {
|
|
6814
|
+
const results = await importVariantsForParents({
|
|
6815
|
+
parents: ctx.data.experienceFragments || [],
|
|
6816
|
+
sourceParents: sourceData.experienceFragments || [],
|
|
6817
|
+
client,
|
|
6818
|
+
spaceId,
|
|
6819
|
+
environmentId,
|
|
6820
|
+
kind: "experienceFragment"
|
|
6821
|
+
});
|
|
6822
|
+
ctx.data.experienceFragmentVariants = results.flatMap((r) => r.created);
|
|
6823
|
+
}),
|
|
6824
|
+
skip: () => !includeExperienceOrchestration || skipExoVariants || !(sourceData.experienceFragments || []).some((f) => (f.optimizationVariants || []).some(isRealOptimizationVariant))
|
|
6825
|
+
},
|
|
6826
|
+
{
|
|
6827
|
+
title: "Publishing Experience Fragment Optimization Variants",
|
|
6828
|
+
task: (0, import_listr2.wrapTask)(async (ctx) => {
|
|
6829
|
+
const toPublish = filterVariantsToPublish(ctx.data.experienceFragmentVariants || []);
|
|
6830
|
+
await Promise.all(toPublish.map(
|
|
6831
|
+
(v) => publishVariant("ExperienceFragmentVariant", v, () => client.experienceFragmentVariant.publish(
|
|
6832
|
+
{ spaceId, environmentId, experienceFragmentId: v.sys.id, variantId: v.sys.variant, version: v.sys.version }
|
|
6833
|
+
))
|
|
6834
|
+
));
|
|
6835
|
+
const toArchive = filterVariantsToArchive(ctx.data.experienceFragmentVariants || []);
|
|
6836
|
+
await Promise.all(toArchive.map(
|
|
6837
|
+
(v) => archiveVariant("ExperienceFragmentVariant", v, () => client.experienceFragmentVariant.archive(
|
|
6838
|
+
{ spaceId, environmentId, experienceFragmentId: v.sys.id, variantId: v.sys.variant, version: v.sys.version }
|
|
6839
|
+
))
|
|
6840
|
+
));
|
|
6841
|
+
}),
|
|
6842
|
+
skip: () => !includeExperienceOrchestration || skipExoVariants || skipContentPublishing || !(sourceData.experienceFragments || []).some((f) => (f.optimizationVariants || []).some(isRealOptimizationVariant))
|
|
6843
|
+
},
|
|
6729
6844
|
// Unpublishing runs after all Importing/Publishing tasks, in reverse dependency order
|
|
6730
6845
|
// (Experience first, DataAssembly last) - the API rejects unpublishing an entity that a
|
|
6731
6846
|
// still-published parent references, so parents must unpublish before the children they embed.
|
|
@@ -6797,6 +6912,48 @@ function omitSys(entity) {
|
|
|
6797
6912
|
const { sys: _sys, ...rest } = entity;
|
|
6798
6913
|
return rest;
|
|
6799
6914
|
}
|
|
6915
|
+
function omitSysAndOptimizationVariants(entity) {
|
|
6916
|
+
const { sys: _sys, optimizationVariants: _variants, ...rest } = entity;
|
|
6917
|
+
return rest;
|
|
6918
|
+
}
|
|
6919
|
+
function omitVariantSys(variant) {
|
|
6920
|
+
const { sys: _sys, ...rest } = variant;
|
|
6921
|
+
return rest;
|
|
6922
|
+
}
|
|
6923
|
+
function isRealOptimizationVariant(variant) {
|
|
6924
|
+
return Boolean(variant?.sys) && variant.sys.variantType !== "default";
|
|
6925
|
+
}
|
|
6926
|
+
async function importVariantsForParents({
|
|
6927
|
+
parents,
|
|
6928
|
+
sourceParents,
|
|
6929
|
+
client,
|
|
6930
|
+
spaceId,
|
|
6931
|
+
environmentId,
|
|
6932
|
+
kind
|
|
6933
|
+
}) {
|
|
6934
|
+
const ns = kind === "experience" ? client.experienceVariant : client.experienceFragmentVariant;
|
|
6935
|
+
const idParam = kind === "experience" ? "experienceId" : "experienceFragmentId";
|
|
6936
|
+
const label = kind === "experience" ? "ExperienceVariant" : "ExperienceFragmentVariant";
|
|
6937
|
+
const parentRefField = kind === "experience" ? "experienceTemplate" : "component";
|
|
6938
|
+
const sourceParentsById = new Map(sourceParents.map((sourceParent) => [sourceParent.sys.id, sourceParent]));
|
|
6939
|
+
return Promise.all(parents.map(async (parent2) => {
|
|
6940
|
+
const sourceParent = sourceParentsById.get(parent2.sys.id);
|
|
6941
|
+
const sourceVariants = (sourceParent?.optimizationVariants ?? []).filter(isRealOptimizationVariant);
|
|
6942
|
+
const created = [];
|
|
6943
|
+
for (const variant of sourceVariants) {
|
|
6944
|
+
try {
|
|
6945
|
+
const payload = { ...omitVariantSys(variant), [parentRefField]: variant.sys[parentRefField] };
|
|
6946
|
+
const result = await ns.create({ spaceId, environmentId, [idParam]: parent2.sys.id }, payload);
|
|
6947
|
+
import_logging11.logEmitter.emit("info", `CREATE ${label} ${result.sys.variant} (parent ${parent2.sys.id})`);
|
|
6948
|
+
created.push({ ...result, sys: { ...result.sys, publishedVersion: variant.sys.publishedVersion, archivedVersion: variant.sys.archivedVersion } });
|
|
6949
|
+
} catch (err) {
|
|
6950
|
+
err.entity = variant;
|
|
6951
|
+
import_logging11.logEmitter.emit("error", err);
|
|
6952
|
+
}
|
|
6953
|
+
}
|
|
6954
|
+
return { parentId: parent2.sys.id, created };
|
|
6955
|
+
}));
|
|
6956
|
+
}
|
|
6800
6957
|
function archiveEntities2({ entities, sourceEntities, client, spaceId, environmentId, requestQueue }) {
|
|
6801
6958
|
const entityIdsToArchive = sourceEntities.filter(({ original }) => original.sys.archivedVersion).map(({ original }) => original.sys.id);
|
|
6802
6959
|
const entitiesToArchive = entities.filter((entity) => entityIdsToArchive.indexOf(entity.sys.id) !== -1);
|
|
@@ -7385,6 +7542,7 @@ async function parseOptions(params) {
|
|
|
7385
7542
|
uploadAssets: false,
|
|
7386
7543
|
rateLimit: 7,
|
|
7387
7544
|
includeExperienceOrchestration: true,
|
|
7545
|
+
skipExoVariants: false,
|
|
7388
7546
|
host: "api.contentful.com"
|
|
7389
7547
|
};
|
|
7390
7548
|
const configFile = params.config ? require((0, import_path2.resolve)(process.cwd(), params.config)) : {};
|
|
@@ -7459,6 +7617,29 @@ async function parseOptions(params) {
|
|
|
7459
7617
|
return options;
|
|
7460
7618
|
}
|
|
7461
7619
|
|
|
7620
|
+
// lib/utils/display-error-log.ts
|
|
7621
|
+
var import_date_fns2 = require("date-fns");
|
|
7622
|
+
var import_logging12 = __toESM(require_logging());
|
|
7623
|
+
function displayErrorLog(errorLog) {
|
|
7624
|
+
if (errorLog.length) {
|
|
7625
|
+
const count = errorLog.reduce((count2, curr) => {
|
|
7626
|
+
if (Object.prototype.hasOwnProperty.call(curr, "warning")) {
|
|
7627
|
+
count2.warnings++;
|
|
7628
|
+
} else if (Object.prototype.hasOwnProperty.call(curr, "error")) {
|
|
7629
|
+
count2.errors++;
|
|
7630
|
+
}
|
|
7631
|
+
return count2;
|
|
7632
|
+
}, { warnings: 0, errors: 0 });
|
|
7633
|
+
console.log(`
|
|
7634
|
+
|
|
7635
|
+
The following ${count.errors} errors and ${count.warnings} warnings occurred:
|
|
7636
|
+
`);
|
|
7637
|
+
errorLog.map((logMessage) => `${(0, import_date_fns2.format)((0, import_date_fns2.parseISO)(logMessage.ts), "HH:mm:ss")} - ${(0, import_logging12.formatLogMessageOneLine)(logMessage)}`).map((logMessage) => console.log(logMessage));
|
|
7638
|
+
return;
|
|
7639
|
+
}
|
|
7640
|
+
console.log("No errors or warnings occurred");
|
|
7641
|
+
}
|
|
7642
|
+
|
|
7462
7643
|
// lib/index.ts
|
|
7463
7644
|
var ONE_SECOND = 1e3;
|
|
7464
7645
|
var tableOptions = {
|
|
@@ -7485,7 +7666,7 @@ async function runContentfulImport(params) {
|
|
|
7485
7666
|
intervalCap: options.rateLimit,
|
|
7486
7667
|
carryoverConcurrencyCount: true
|
|
7487
7668
|
});
|
|
7488
|
-
(0,
|
|
7669
|
+
(0, import_logging13.setupLogging)(log);
|
|
7489
7670
|
const infoTable = new import_cli_table3.default(tableOptions);
|
|
7490
7671
|
infoTable.push([{ colSpan: 2, content: "The following entities are going to be imported:" }]);
|
|
7491
7672
|
Object.keys(options.content).forEach((type) => {
|
|
@@ -7500,6 +7681,20 @@ async function runContentfulImport(params) {
|
|
|
7500
7681
|
}
|
|
7501
7682
|
infoTable.push([startCase_default(type), options.content[type].length]);
|
|
7502
7683
|
});
|
|
7684
|
+
const experienceVariantCount = (options.content.experiences || []).reduce(
|
|
7685
|
+
(sum, e) => sum + (e.optimizationVariants?.length ?? 0),
|
|
7686
|
+
0
|
|
7687
|
+
);
|
|
7688
|
+
if (!options.skipExoVariants && experienceVariantCount > 0) {
|
|
7689
|
+
infoTable.push(["Experience Optimization Variants", experienceVariantCount]);
|
|
7690
|
+
}
|
|
7691
|
+
const experienceFragmentVariantCount = (options.content.experienceFragments || []).reduce(
|
|
7692
|
+
(sum, f) => sum + (f.optimizationVariants?.length ?? 0),
|
|
7693
|
+
0
|
|
7694
|
+
);
|
|
7695
|
+
if (!options.skipExoVariants && experienceFragmentVariantCount > 0) {
|
|
7696
|
+
infoTable.push(["Experience Fragment Optimization Variants", experienceFragmentVariantCount]);
|
|
7697
|
+
}
|
|
7503
7698
|
console.log(infoTable.toString());
|
|
7504
7699
|
const tasks = new import_listr3.default([
|
|
7505
7700
|
{
|
|
@@ -7548,6 +7743,7 @@ async function runContentfulImport(params) {
|
|
|
7548
7743
|
client: ctx.client,
|
|
7549
7744
|
spaceId: options.spaceId,
|
|
7550
7745
|
includeExperienceOrchestration: options.includeExperienceOrchestration,
|
|
7746
|
+
skipExoVariants: options.skipExoVariants,
|
|
7551
7747
|
environmentId: options.environmentId,
|
|
7552
7748
|
contentModelOnly: options.contentModelOnly,
|
|
7553
7749
|
skipLocales: options.skipLocales,
|
|
@@ -7582,8 +7778,8 @@ async function runContentfulImport(params) {
|
|
|
7582
7778
|
console.log("No data was imported");
|
|
7583
7779
|
}
|
|
7584
7780
|
const endTime = /* @__PURE__ */ new Date();
|
|
7585
|
-
const durationHuman = (0,
|
|
7586
|
-
const durationSeconds = (0,
|
|
7781
|
+
const durationHuman = (0, import_date_fns3.formatDistance)(endTime, options.startTime);
|
|
7782
|
+
const durationSeconds = (0, import_date_fns3.differenceInSeconds)(endTime, options.startTime);
|
|
7587
7783
|
console.log(`The import took ${durationHuman} (${durationSeconds}s)`);
|
|
7588
7784
|
return ctx.data;
|
|
7589
7785
|
}).catch((err) => {
|
|
@@ -7595,9 +7791,9 @@ async function runContentfulImport(params) {
|
|
|
7595
7791
|
}).then((data) => {
|
|
7596
7792
|
const errorLog = log.filter((logMessage) => logMessage.level !== "info" && logMessage.level !== "warning");
|
|
7597
7793
|
const displayLog = log.filter((logMessage) => logMessage.level !== "info");
|
|
7598
|
-
|
|
7794
|
+
displayErrorLog(displayLog);
|
|
7599
7795
|
if (errorLog.length) {
|
|
7600
|
-
return (0,
|
|
7796
|
+
return (0, import_logging13.writeErrorLogFile)(options.errorLogFile, errorLog).then(() => {
|
|
7601
7797
|
const multiError = new ContentfulMultiError("Errors occurred");
|
|
7602
7798
|
multiError.name = "ContentfulMultiError";
|
|
7603
7799
|
multiError.errors = errorLog;
|
package/dist/index.mjs
CHANGED
|
@@ -235,7 +235,7 @@ var require_logging = __commonJS({
|
|
|
235
235
|
throw new Error("Unable to extract API error data");
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
|
-
function
|
|
238
|
+
function formatLogMessageOneLine2(logMessage) {
|
|
239
239
|
const { level } = logMessage;
|
|
240
240
|
if (!level) {
|
|
241
241
|
return logMessage.toString().replace(/\s+/g, " ");
|
|
@@ -271,7 +271,7 @@ var require_logging = __commonJS({
|
|
|
271
271
|
return logMessage.error.toString().replace(/\s+/g, " ");
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
|
-
exports2.formatLogMessageOneLine =
|
|
274
|
+
exports2.formatLogMessageOneLine = formatLogMessageOneLine2;
|
|
275
275
|
function formatLogMessageLogfile(logMessage) {
|
|
276
276
|
const { level } = logMessage;
|
|
277
277
|
if (level === "info" || level === "warning") {
|
|
@@ -310,7 +310,7 @@ var require_logging = __commonJS({
|
|
|
310
310
|
|
|
311
311
|
The following ${count.errors} errors and ${count.warnings} warnings occurred:
|
|
312
312
|
`);
|
|
313
|
-
errorLog.map((logMessage) => `${(0, format_1.default)((0, parseISO_1.default)(logMessage.ts), "HH:mm:ss")} - ${
|
|
313
|
+
errorLog.map((logMessage) => `${(0, format_1.default)((0, parseISO_1.default)(logMessage.ts), "HH:mm:ss")} - ${formatLogMessageOneLine2(logMessage)}`).map((logMessage) => console.log(logMessage));
|
|
314
314
|
return;
|
|
315
315
|
}
|
|
316
316
|
console.log("No errors or warnings occurred");
|
|
@@ -357,7 +357,7 @@ The following ${count.errors} errors and ${count.warnings} warnings occurred:
|
|
|
357
357
|
exports2.setupLogging = setupLogging2;
|
|
358
358
|
function logToTaskOutput(task) {
|
|
359
359
|
function logToTask(logMessage) {
|
|
360
|
-
const content =
|
|
360
|
+
const content = formatLogMessageOneLine2(logMessage);
|
|
361
361
|
const symbols = {
|
|
362
362
|
info: figures_1.default.tick,
|
|
363
363
|
warning: figures_1.default.warning,
|
|
@@ -570,12 +570,12 @@ var require_common = __commonJS({
|
|
|
570
570
|
args.unshift("%O");
|
|
571
571
|
}
|
|
572
572
|
let index = 0;
|
|
573
|
-
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match,
|
|
573
|
+
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format3) => {
|
|
574
574
|
if (match === "%%") {
|
|
575
575
|
return "%";
|
|
576
576
|
}
|
|
577
577
|
index++;
|
|
578
|
-
const formatter = createDebug.formatters[
|
|
578
|
+
const formatter = createDebug.formatters[format3];
|
|
579
579
|
if (typeof formatter === "function") {
|
|
580
580
|
const val = args[index];
|
|
581
581
|
match = formatter.call(self2, val);
|
|
@@ -4855,7 +4855,7 @@ var startCase = createCompounder_default(function(result, word, index) {
|
|
|
4855
4855
|
var startCase_default = startCase;
|
|
4856
4856
|
|
|
4857
4857
|
// lib/index.ts
|
|
4858
|
-
var
|
|
4858
|
+
var import_logging13 = __toESM(require_logging());
|
|
4859
4859
|
var import_listr4 = __toESM(require_listr());
|
|
4860
4860
|
import PQueue from "p-queue";
|
|
4861
4861
|
|
|
@@ -4922,6 +4922,34 @@ async function unpublishExoEntity(type, entity, unpublish) {
|
|
|
4922
4922
|
return null;
|
|
4923
4923
|
}
|
|
4924
4924
|
}
|
|
4925
|
+
function filterVariantsToPublish(variants) {
|
|
4926
|
+
return variants.filter((v) => v.sys.publishedVersion);
|
|
4927
|
+
}
|
|
4928
|
+
function filterVariantsToArchive(variants) {
|
|
4929
|
+
return variants.filter((v) => v.sys.archivedVersion && !v.sys.publishedVersion);
|
|
4930
|
+
}
|
|
4931
|
+
async function publishVariant(type, entity, publish) {
|
|
4932
|
+
try {
|
|
4933
|
+
const result = await publish();
|
|
4934
|
+
import_logging2.logEmitter.emit("info", `PUBLISH ${type} ${entity.sys.variant}`);
|
|
4935
|
+
return result;
|
|
4936
|
+
} catch (err) {
|
|
4937
|
+
err.entity = entity;
|
|
4938
|
+
import_logging2.logEmitter.emit("error", err);
|
|
4939
|
+
return null;
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
4942
|
+
async function archiveVariant(type, entity, archive) {
|
|
4943
|
+
try {
|
|
4944
|
+
const result = await archive();
|
|
4945
|
+
import_logging2.logEmitter.emit("info", `ARCHIVE ${type} ${entity.sys.variant}`);
|
|
4946
|
+
return result;
|
|
4947
|
+
} catch (err) {
|
|
4948
|
+
err.entity = entity;
|
|
4949
|
+
import_logging2.logEmitter.emit("error", err);
|
|
4950
|
+
return null;
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4925
4953
|
function isExoEntitlementError(err) {
|
|
4926
4954
|
if (!(err instanceof Error)) {
|
|
4927
4955
|
return false;
|
|
@@ -6132,6 +6160,7 @@ function pushToSpace({
|
|
|
6132
6160
|
spaceId,
|
|
6133
6161
|
environmentId,
|
|
6134
6162
|
includeExperienceOrchestration,
|
|
6163
|
+
skipExoVariants,
|
|
6135
6164
|
contentModelOnly,
|
|
6136
6165
|
skipContentModel,
|
|
6137
6166
|
skipContentUpdates,
|
|
@@ -6154,6 +6183,13 @@ function pushToSpace({
|
|
|
6154
6183
|
...DEFAULT_CONTENT_STRUCTURE,
|
|
6155
6184
|
...destinationData
|
|
6156
6185
|
};
|
|
6186
|
+
const hasOptimizationVariants = [
|
|
6187
|
+
...sourceData.experiences || [],
|
|
6188
|
+
...sourceData.experienceFragments || []
|
|
6189
|
+
].some((parent2) => (parent2.optimizationVariants || []).some(isRealOptimizationVariant));
|
|
6190
|
+
if (includeExperienceOrchestration && !skipExoVariants && hasOptimizationVariants) {
|
|
6191
|
+
import_logging11.logEmitter.emit("warning", "Optimization Variants are imported with new destination IDs and can be duplicated by re-imports. Set skipExoVariants to true to skip them.");
|
|
6192
|
+
}
|
|
6157
6193
|
listrOptions = listrOptions || {
|
|
6158
6194
|
renderer: verboseRenderer
|
|
6159
6195
|
};
|
|
@@ -6618,12 +6654,12 @@ function pushToSpace({
|
|
|
6618
6654
|
try {
|
|
6619
6655
|
const existing = destinationDataById.experienceFragments?.get(entity.sys.id);
|
|
6620
6656
|
if (existing) {
|
|
6621
|
-
const payload = { ...entity, sys: { id: entity.sys.id, type: "ExperienceFragment", version: existing.sys.version } };
|
|
6657
|
+
const payload = { ...omitSysAndOptimizationVariants(entity), sys: { id: entity.sys.id, type: "ExperienceFragment", version: existing.sys.version } };
|
|
6622
6658
|
const result = await client.experienceFragment.upsert({ spaceId, environmentId, experienceFragmentId: entity.sys.id }, payload);
|
|
6623
6659
|
import_logging11.logEmitter.emit("info", `UPDATE ExperienceFragment ${entity.sys.id}`);
|
|
6624
6660
|
results.push(result);
|
|
6625
6661
|
} else {
|
|
6626
|
-
const payload = { ...
|
|
6662
|
+
const payload = { ...omitSysAndOptimizationVariants(entity), component: entity.sys.component, sys: { id: entity.sys.id, type: "ExperienceFragment" } };
|
|
6627
6663
|
const result = await client.experienceFragment.upsert({ spaceId, environmentId, experienceFragmentId: entity.sys.id }, payload);
|
|
6628
6664
|
import_logging11.logEmitter.emit("info", `CREATE ExperienceFragment ${entity.sys.id}`);
|
|
6629
6665
|
results.push(result);
|
|
@@ -6660,12 +6696,12 @@ function pushToSpace({
|
|
|
6660
6696
|
try {
|
|
6661
6697
|
const existing = destinationDataById.experiences?.get(entity.sys.id);
|
|
6662
6698
|
if (existing) {
|
|
6663
|
-
const payload = { ...entity, sys: { id: entity.sys.id, type: "Experience", version: existing.sys.version } };
|
|
6699
|
+
const payload = { ...omitSysAndOptimizationVariants(entity), sys: { id: entity.sys.id, type: "Experience", version: existing.sys.version } };
|
|
6664
6700
|
const result = await client.experience.upsert({ spaceId, environmentId, experienceId: entity.sys.id }, payload);
|
|
6665
6701
|
import_logging11.logEmitter.emit("info", `UPDATE Experience ${entity.sys.id}`);
|
|
6666
6702
|
return result;
|
|
6667
6703
|
} else {
|
|
6668
|
-
const payload = { ...
|
|
6704
|
+
const payload = { ...omitSysAndOptimizationVariants(entity), experienceTemplate: entity.sys.experienceTemplate, sys: { id: entity.sys.id, type: "Experience" } };
|
|
6669
6705
|
const result = await client.experience.upsert({ spaceId, environmentId, experienceId: entity.sys.id }, payload);
|
|
6670
6706
|
import_logging11.logEmitter.emit("info", `CREATE Experience ${entity.sys.id}`);
|
|
6671
6707
|
return result;
|
|
@@ -6693,6 +6729,85 @@ function pushToSpace({
|
|
|
6693
6729
|
}),
|
|
6694
6730
|
skip: () => !includeExperienceOrchestration || skipContentPublishing || !(sourceData.experiences || []).length
|
|
6695
6731
|
},
|
|
6732
|
+
// Optimization Variants are sub-resources nested on their parent Experience/ExperienceFragment
|
|
6733
|
+
// (sourceData.experiences[].optimizationVariants), not a flat top-level array. A variant's
|
|
6734
|
+
// sys.id is borrowed from its parent, not unique, so variant creation/publish/archive is
|
|
6735
|
+
// handled by new, self-contained functions (importVariantsForParents, filterVariantsToPublish,
|
|
6736
|
+
// filterVariantsToArchive, publishVariant, archiveVariant) rather than by generalizing
|
|
6737
|
+
// destinationDataById / filterExoEntitiesToPublish / filterExoEntitiesToUnpublish, which all
|
|
6738
|
+
// assume sys.id uniqueness.
|
|
6739
|
+
//
|
|
6740
|
+
// Unlike the base Experience/Fragment create/update, there is no upsert-by-known-ID for
|
|
6741
|
+
// variants: the upstream API's create endpoint always server-generates a fresh variantId
|
|
6742
|
+
// (crypto.randomUUID()) and its update endpoint 404s on an unknown variantId rather than
|
|
6743
|
+
// creating one. So every import run creates fresh destination variants via POST rather than
|
|
6744
|
+
// matching against any existing destination variant.
|
|
6745
|
+
{
|
|
6746
|
+
title: "Importing Experience Optimization Variants",
|
|
6747
|
+
task: (0, import_listr2.wrapTask)(async (ctx) => {
|
|
6748
|
+
const results = await importVariantsForParents({
|
|
6749
|
+
parents: ctx.data.experiences || [],
|
|
6750
|
+
sourceParents: sourceData.experiences || [],
|
|
6751
|
+
client,
|
|
6752
|
+
spaceId,
|
|
6753
|
+
environmentId,
|
|
6754
|
+
kind: "experience"
|
|
6755
|
+
});
|
|
6756
|
+
ctx.data.experienceVariants = results.flatMap((r) => r.created);
|
|
6757
|
+
}),
|
|
6758
|
+
skip: () => !includeExperienceOrchestration || skipExoVariants || !(sourceData.experiences || []).some((e) => (e.optimizationVariants || []).some(isRealOptimizationVariant))
|
|
6759
|
+
},
|
|
6760
|
+
{
|
|
6761
|
+
title: "Publishing Experience Optimization Variants",
|
|
6762
|
+
task: (0, import_listr2.wrapTask)(async (ctx) => {
|
|
6763
|
+
const toPublish = filterVariantsToPublish(ctx.data.experienceVariants || []);
|
|
6764
|
+
await Promise.all(toPublish.map(
|
|
6765
|
+
(v) => publishVariant("ExperienceVariant", v, () => client.experienceVariant.publish(
|
|
6766
|
+
{ spaceId, environmentId, experienceId: v.sys.id, variantId: v.sys.variant, version: v.sys.version }
|
|
6767
|
+
))
|
|
6768
|
+
));
|
|
6769
|
+
const toArchive = filterVariantsToArchive(ctx.data.experienceVariants || []);
|
|
6770
|
+
await Promise.all(toArchive.map(
|
|
6771
|
+
(v) => archiveVariant("ExperienceVariant", v, () => client.experienceVariant.archive(
|
|
6772
|
+
{ spaceId, environmentId, experienceId: v.sys.id, variantId: v.sys.variant, version: v.sys.version }
|
|
6773
|
+
))
|
|
6774
|
+
));
|
|
6775
|
+
}),
|
|
6776
|
+
skip: () => !includeExperienceOrchestration || skipExoVariants || skipContentPublishing || !(sourceData.experiences || []).some((e) => (e.optimizationVariants || []).some(isRealOptimizationVariant))
|
|
6777
|
+
},
|
|
6778
|
+
{
|
|
6779
|
+
title: "Importing Experience Fragment Optimization Variants",
|
|
6780
|
+
task: (0, import_listr2.wrapTask)(async (ctx) => {
|
|
6781
|
+
const results = await importVariantsForParents({
|
|
6782
|
+
parents: ctx.data.experienceFragments || [],
|
|
6783
|
+
sourceParents: sourceData.experienceFragments || [],
|
|
6784
|
+
client,
|
|
6785
|
+
spaceId,
|
|
6786
|
+
environmentId,
|
|
6787
|
+
kind: "experienceFragment"
|
|
6788
|
+
});
|
|
6789
|
+
ctx.data.experienceFragmentVariants = results.flatMap((r) => r.created);
|
|
6790
|
+
}),
|
|
6791
|
+
skip: () => !includeExperienceOrchestration || skipExoVariants || !(sourceData.experienceFragments || []).some((f) => (f.optimizationVariants || []).some(isRealOptimizationVariant))
|
|
6792
|
+
},
|
|
6793
|
+
{
|
|
6794
|
+
title: "Publishing Experience Fragment Optimization Variants",
|
|
6795
|
+
task: (0, import_listr2.wrapTask)(async (ctx) => {
|
|
6796
|
+
const toPublish = filterVariantsToPublish(ctx.data.experienceFragmentVariants || []);
|
|
6797
|
+
await Promise.all(toPublish.map(
|
|
6798
|
+
(v) => publishVariant("ExperienceFragmentVariant", v, () => client.experienceFragmentVariant.publish(
|
|
6799
|
+
{ spaceId, environmentId, experienceFragmentId: v.sys.id, variantId: v.sys.variant, version: v.sys.version }
|
|
6800
|
+
))
|
|
6801
|
+
));
|
|
6802
|
+
const toArchive = filterVariantsToArchive(ctx.data.experienceFragmentVariants || []);
|
|
6803
|
+
await Promise.all(toArchive.map(
|
|
6804
|
+
(v) => archiveVariant("ExperienceFragmentVariant", v, () => client.experienceFragmentVariant.archive(
|
|
6805
|
+
{ spaceId, environmentId, experienceFragmentId: v.sys.id, variantId: v.sys.variant, version: v.sys.version }
|
|
6806
|
+
))
|
|
6807
|
+
));
|
|
6808
|
+
}),
|
|
6809
|
+
skip: () => !includeExperienceOrchestration || skipExoVariants || skipContentPublishing || !(sourceData.experienceFragments || []).some((f) => (f.optimizationVariants || []).some(isRealOptimizationVariant))
|
|
6810
|
+
},
|
|
6696
6811
|
// Unpublishing runs after all Importing/Publishing tasks, in reverse dependency order
|
|
6697
6812
|
// (Experience first, DataAssembly last) - the API rejects unpublishing an entity that a
|
|
6698
6813
|
// still-published parent references, so parents must unpublish before the children they embed.
|
|
@@ -6764,6 +6879,48 @@ function omitSys(entity) {
|
|
|
6764
6879
|
const { sys: _sys, ...rest } = entity;
|
|
6765
6880
|
return rest;
|
|
6766
6881
|
}
|
|
6882
|
+
function omitSysAndOptimizationVariants(entity) {
|
|
6883
|
+
const { sys: _sys, optimizationVariants: _variants, ...rest } = entity;
|
|
6884
|
+
return rest;
|
|
6885
|
+
}
|
|
6886
|
+
function omitVariantSys(variant) {
|
|
6887
|
+
const { sys: _sys, ...rest } = variant;
|
|
6888
|
+
return rest;
|
|
6889
|
+
}
|
|
6890
|
+
function isRealOptimizationVariant(variant) {
|
|
6891
|
+
return Boolean(variant?.sys) && variant.sys.variantType !== "default";
|
|
6892
|
+
}
|
|
6893
|
+
async function importVariantsForParents({
|
|
6894
|
+
parents,
|
|
6895
|
+
sourceParents,
|
|
6896
|
+
client,
|
|
6897
|
+
spaceId,
|
|
6898
|
+
environmentId,
|
|
6899
|
+
kind
|
|
6900
|
+
}) {
|
|
6901
|
+
const ns = kind === "experience" ? client.experienceVariant : client.experienceFragmentVariant;
|
|
6902
|
+
const idParam = kind === "experience" ? "experienceId" : "experienceFragmentId";
|
|
6903
|
+
const label = kind === "experience" ? "ExperienceVariant" : "ExperienceFragmentVariant";
|
|
6904
|
+
const parentRefField = kind === "experience" ? "experienceTemplate" : "component";
|
|
6905
|
+
const sourceParentsById = new Map(sourceParents.map((sourceParent) => [sourceParent.sys.id, sourceParent]));
|
|
6906
|
+
return Promise.all(parents.map(async (parent2) => {
|
|
6907
|
+
const sourceParent = sourceParentsById.get(parent2.sys.id);
|
|
6908
|
+
const sourceVariants = (sourceParent?.optimizationVariants ?? []).filter(isRealOptimizationVariant);
|
|
6909
|
+
const created = [];
|
|
6910
|
+
for (const variant of sourceVariants) {
|
|
6911
|
+
try {
|
|
6912
|
+
const payload = { ...omitVariantSys(variant), [parentRefField]: variant.sys[parentRefField] };
|
|
6913
|
+
const result = await ns.create({ spaceId, environmentId, [idParam]: parent2.sys.id }, payload);
|
|
6914
|
+
import_logging11.logEmitter.emit("info", `CREATE ${label} ${result.sys.variant} (parent ${parent2.sys.id})`);
|
|
6915
|
+
created.push({ ...result, sys: { ...result.sys, publishedVersion: variant.sys.publishedVersion, archivedVersion: variant.sys.archivedVersion } });
|
|
6916
|
+
} catch (err) {
|
|
6917
|
+
err.entity = variant;
|
|
6918
|
+
import_logging11.logEmitter.emit("error", err);
|
|
6919
|
+
}
|
|
6920
|
+
}
|
|
6921
|
+
return { parentId: parent2.sys.id, created };
|
|
6922
|
+
}));
|
|
6923
|
+
}
|
|
6767
6924
|
function archiveEntities2({ entities, sourceEntities, client, spaceId, environmentId, requestQueue }) {
|
|
6768
6925
|
const entityIdsToArchive = sourceEntities.filter(({ original }) => original.sys.archivedVersion).map(({ original }) => original.sys.id);
|
|
6769
6926
|
const entitiesToArchive = entities.filter((entity) => entityIdsToArchive.indexOf(entity.sys.id) !== -1);
|
|
@@ -7349,6 +7506,7 @@ async function parseOptions(params) {
|
|
|
7349
7506
|
uploadAssets: false,
|
|
7350
7507
|
rateLimit: 7,
|
|
7351
7508
|
includeExperienceOrchestration: true,
|
|
7509
|
+
skipExoVariants: false,
|
|
7352
7510
|
host: "api.contentful.com"
|
|
7353
7511
|
};
|
|
7354
7512
|
const configFile = params.config ? __require(resolve(process.cwd(), params.config)) : {};
|
|
@@ -7423,6 +7581,29 @@ async function parseOptions(params) {
|
|
|
7423
7581
|
return options;
|
|
7424
7582
|
}
|
|
7425
7583
|
|
|
7584
|
+
// lib/utils/display-error-log.ts
|
|
7585
|
+
var import_logging12 = __toESM(require_logging());
|
|
7586
|
+
import { format as format2, parseISO } from "date-fns";
|
|
7587
|
+
function displayErrorLog(errorLog) {
|
|
7588
|
+
if (errorLog.length) {
|
|
7589
|
+
const count = errorLog.reduce((count2, curr) => {
|
|
7590
|
+
if (Object.prototype.hasOwnProperty.call(curr, "warning")) {
|
|
7591
|
+
count2.warnings++;
|
|
7592
|
+
} else if (Object.prototype.hasOwnProperty.call(curr, "error")) {
|
|
7593
|
+
count2.errors++;
|
|
7594
|
+
}
|
|
7595
|
+
return count2;
|
|
7596
|
+
}, { warnings: 0, errors: 0 });
|
|
7597
|
+
console.log(`
|
|
7598
|
+
|
|
7599
|
+
The following ${count.errors} errors and ${count.warnings} warnings occurred:
|
|
7600
|
+
`);
|
|
7601
|
+
errorLog.map((logMessage) => `${format2(parseISO(logMessage.ts), "HH:mm:ss")} - ${(0, import_logging12.formatLogMessageOneLine)(logMessage)}`).map((logMessage) => console.log(logMessage));
|
|
7602
|
+
return;
|
|
7603
|
+
}
|
|
7604
|
+
console.log("No errors or warnings occurred");
|
|
7605
|
+
}
|
|
7606
|
+
|
|
7426
7607
|
// lib/index.ts
|
|
7427
7608
|
var ONE_SECOND = 1e3;
|
|
7428
7609
|
var tableOptions = {
|
|
@@ -7449,7 +7630,7 @@ async function runContentfulImport(params) {
|
|
|
7449
7630
|
intervalCap: options.rateLimit,
|
|
7450
7631
|
carryoverConcurrencyCount: true
|
|
7451
7632
|
});
|
|
7452
|
-
(0,
|
|
7633
|
+
(0, import_logging13.setupLogging)(log);
|
|
7453
7634
|
const infoTable = new Table(tableOptions);
|
|
7454
7635
|
infoTable.push([{ colSpan: 2, content: "The following entities are going to be imported:" }]);
|
|
7455
7636
|
Object.keys(options.content).forEach((type) => {
|
|
@@ -7464,6 +7645,20 @@ async function runContentfulImport(params) {
|
|
|
7464
7645
|
}
|
|
7465
7646
|
infoTable.push([startCase_default(type), options.content[type].length]);
|
|
7466
7647
|
});
|
|
7648
|
+
const experienceVariantCount = (options.content.experiences || []).reduce(
|
|
7649
|
+
(sum, e) => sum + (e.optimizationVariants?.length ?? 0),
|
|
7650
|
+
0
|
|
7651
|
+
);
|
|
7652
|
+
if (!options.skipExoVariants && experienceVariantCount > 0) {
|
|
7653
|
+
infoTable.push(["Experience Optimization Variants", experienceVariantCount]);
|
|
7654
|
+
}
|
|
7655
|
+
const experienceFragmentVariantCount = (options.content.experienceFragments || []).reduce(
|
|
7656
|
+
(sum, f) => sum + (f.optimizationVariants?.length ?? 0),
|
|
7657
|
+
0
|
|
7658
|
+
);
|
|
7659
|
+
if (!options.skipExoVariants && experienceFragmentVariantCount > 0) {
|
|
7660
|
+
infoTable.push(["Experience Fragment Optimization Variants", experienceFragmentVariantCount]);
|
|
7661
|
+
}
|
|
7467
7662
|
console.log(infoTable.toString());
|
|
7468
7663
|
const tasks = new Listr2([
|
|
7469
7664
|
{
|
|
@@ -7512,6 +7707,7 @@ async function runContentfulImport(params) {
|
|
|
7512
7707
|
client: ctx.client,
|
|
7513
7708
|
spaceId: options.spaceId,
|
|
7514
7709
|
includeExperienceOrchestration: options.includeExperienceOrchestration,
|
|
7710
|
+
skipExoVariants: options.skipExoVariants,
|
|
7515
7711
|
environmentId: options.environmentId,
|
|
7516
7712
|
contentModelOnly: options.contentModelOnly,
|
|
7517
7713
|
skipLocales: options.skipLocales,
|
|
@@ -7559,9 +7755,9 @@ async function runContentfulImport(params) {
|
|
|
7559
7755
|
}).then((data) => {
|
|
7560
7756
|
const errorLog = log.filter((logMessage) => logMessage.level !== "info" && logMessage.level !== "warning");
|
|
7561
7757
|
const displayLog = log.filter((logMessage) => logMessage.level !== "info");
|
|
7562
|
-
|
|
7758
|
+
displayErrorLog(displayLog);
|
|
7563
7759
|
if (errorLog.length) {
|
|
7564
|
-
return (0,
|
|
7760
|
+
return (0, import_logging13.writeErrorLogFile)(options.errorLogFile, errorLog).then(() => {
|
|
7565
7761
|
const multiError = new ContentfulMultiError("Errors occurred");
|
|
7566
7762
|
multiError.name = "ContentfulMultiError";
|
|
7567
7763
|
multiError.errors = errorLog;
|
package/dist/usageParams.d.mts
CHANGED
|
@@ -36,6 +36,8 @@ declare const _default: {
|
|
|
36
36
|
header: string | undefined;
|
|
37
37
|
"include-experience-orchestration": boolean;
|
|
38
38
|
includeExperienceOrchestration: boolean;
|
|
39
|
+
"skip-exo-variants": boolean;
|
|
40
|
+
skipExoVariants: boolean;
|
|
39
41
|
_: (string | number)[];
|
|
40
42
|
$0: string;
|
|
41
43
|
} | Promise<{
|
|
@@ -76,6 +78,8 @@ declare const _default: {
|
|
|
76
78
|
header: string | undefined;
|
|
77
79
|
"include-experience-orchestration": boolean;
|
|
78
80
|
includeExperienceOrchestration: boolean;
|
|
81
|
+
"skip-exo-variants": boolean;
|
|
82
|
+
skipExoVariants: boolean;
|
|
79
83
|
_: (string | number)[];
|
|
80
84
|
$0: string;
|
|
81
85
|
}>;
|
package/dist/usageParams.d.ts
CHANGED
|
@@ -36,6 +36,8 @@ declare const _default: {
|
|
|
36
36
|
header: string | undefined;
|
|
37
37
|
"include-experience-orchestration": boolean;
|
|
38
38
|
includeExperienceOrchestration: boolean;
|
|
39
|
+
"skip-exo-variants": boolean;
|
|
40
|
+
skipExoVariants: boolean;
|
|
39
41
|
_: (string | number)[];
|
|
40
42
|
$0: string;
|
|
41
43
|
} | Promise<{
|
|
@@ -76,6 +78,8 @@ declare const _default: {
|
|
|
76
78
|
header: string | undefined;
|
|
77
79
|
"include-experience-orchestration": boolean;
|
|
78
80
|
includeExperienceOrchestration: boolean;
|
|
81
|
+
"skip-exo-variants": boolean;
|
|
82
|
+
skipExoVariants: boolean;
|
|
79
83
|
_: (string | number)[];
|
|
80
84
|
$0: string;
|
|
81
85
|
}>;
|
package/dist/usageParams.js
CHANGED
|
@@ -118,5 +118,9 @@ var usageParams_default = import_yargs.default.version(version || "Version only
|
|
|
118
118
|
describe: "Import Experience Orchestration entities (designTokens, components, experienceTemplates, experienceFragments, dataAssemblies, experiences). Requires a space with ExO enabled.",
|
|
119
119
|
type: "boolean",
|
|
120
120
|
default: true
|
|
121
|
+
}).option("skip-exo-variants", {
|
|
122
|
+
describe: "Skip importing Experience and Experience Fragment Optimization Variants",
|
|
123
|
+
type: "boolean",
|
|
124
|
+
default: false
|
|
121
125
|
}).config("config", "An optional configuration JSON file containing all the options for a single run").argv;
|
|
122
126
|
module.exports = module.exports.default || module.exports;
|
package/dist/usageParams.mjs
CHANGED
|
@@ -80,6 +80,10 @@ var usageParams_default = yargs.version(version || "Version only available on in
|
|
|
80
80
|
describe: "Import Experience Orchestration entities (designTokens, components, experienceTemplates, experienceFragments, dataAssemblies, experiences). Requires a space with ExO enabled.",
|
|
81
81
|
type: "boolean",
|
|
82
82
|
default: true
|
|
83
|
+
}).option("skip-exo-variants", {
|
|
84
|
+
describe: "Skip importing Experience and Experience Fragment Optimization Variants",
|
|
85
|
+
type: "boolean",
|
|
86
|
+
default: false
|
|
83
87
|
}).config("config", "An optional configuration JSON file containing all the options for a single run").argv;
|
|
84
88
|
export {
|
|
85
89
|
usageParams_default as default
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contentful-import",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.4.0",
|
|
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",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"bluebird": "^3.7.2",
|
|
65
65
|
"cli-table3": "^0.6.5",
|
|
66
66
|
"contentful-batch-libs": "^9.7.0",
|
|
67
|
-
"contentful-management": "^12.
|
|
67
|
+
"contentful-management": "^12.17.0",
|
|
68
68
|
"date-fns": "^4.4.0",
|
|
69
69
|
"joi": "^18.2.3",
|
|
70
70
|
"listr": "^0.14.3",
|