contentful-import 10.3.0 → 10.5.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 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
@@ -278,7 +282,8 @@ The data to import should be structured like this:
278
282
  "experienceTemplates": [],
279
283
  "dataAssemblies": [],
280
284
  "experienceFragments": [],
281
- "experiences": []
285
+ "experiences": [],
286
+ "releases": []
282
287
  }
283
288
  ```
284
289
 
@@ -286,12 +291,16 @@ Note: `tags` are not available for all users. If you do not have access to this
286
291
 
287
292
  The `designTokens`, `components`, `experienceTemplates`, `dataAssemblies`, `experienceFragments`, and `experiences` keys are Experience Orchestration (ExO) entities — see the "Experience Orchestration (ExO) entities" section below.
288
293
 
294
+ The `releases` key is subject to the [Releases](https://www.contentful.com/help/releases/) feature — see the "Releases" section below.
295
+
289
296
  ## :test_tube: Experience Orchestration (ExO) entities
290
297
 
291
298
  > **Experimental:** ExO entities (`designTokens`, `components`, `experienceTemplates`, `dataAssemblies`, `experienceFragments`, `experiences`) are `@internal` and considered experimental. Their shape and import behavior are subject to change without notice.
292
299
 
293
300
  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
301
 
302
+ 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.
303
+
295
304
  ```javascript
296
305
  import contentfulImport from 'contentful-import'
297
306
 
@@ -322,15 +331,38 @@ ExO entities are created and published in dependency order, then unpublished in
322
331
  4. Experience Templates — create, then publish
323
332
  5. Experience Fragments — create, then publish
324
333
  6. Experiences — create, then publish
325
- 7. Unpublish pass, in reverse: Experiences Experience Fragments Experience Templates Components Data Assemblies
334
+ 7. Experience Optimization Variants create, then publish/archive (only if the source has any; see below)
335
+ 8. Experience Fragment Optimization Variants — create, then publish/archive (only if the source has any; see below)
336
+ 9. Unpublish pass, in reverse: Experiences → Experience Fragments → Experience Templates → Components → Data Assemblies
326
337
 
327
338
  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
339
 
340
+ ### Optimization Variants
341
+
342
+ 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.
343
+
344
+ Two behaviors are worth calling out explicitly because they differ from every other ExO entity type:
345
+
346
+ - **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.
347
+ - **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.
348
+
329
349
  ### URN rewriting / backward compatibility
330
350
 
331
351
  - 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.
332
352
  - Export files that predate ExO entirely (no ExO keys, or empty ExO arrays) import unchanged — no extra configuration is needed to import older export files.
333
353
 
354
+ ## :package: Releases
355
+
356
+ > **Only `Release.v2` ("Releases") is supported. `Release.v1` ("Launch") is not supported.**
357
+ >
358
+ > **The destination space's organization must have the [Releases](https://www.contentful.com/help/releases/) entitlement enabled.** Releases is a premium/paid feature — if the destination isn't entitled, importing releases will fail.
359
+
360
+ If your source content includes a `releases` key, each entry is checked for `sys.schemaVersion`. Only releases with `sys.schemaVersion: "Release.v2"` are imported; any `Release.v1` (Launch) release is skipped and logged as an error, since its payload shape isn't compatible with the `Release.v2` create/update API.
361
+
362
+ A release that already exists in the destination space at the source's exact `sys.id` is updated; otherwise one is created. There is no separate publish/unpublish step for releases — a release's own `entities` collection already carries the per-entity `publish`/`unpublish` action to take when the release itself is applied.
363
+
364
+ **Releases have no ID-preserving create, unlike every other importable entity.** The Releases API always server-generates a release's `sys.id` on create — there is no way to request a specific ID. So the update path above only fires if a release already exists in the destination at the source's exact ID (for example, an environment cloned from the source) — which an import run can never produce on its own. Practically: re-importing the same source data creates additional releases rather than updating the ones from a prior run. If you need to re-run an import that includes releases, delete or archive the previously-imported ones first to avoid duplicates.
365
+
334
366
  ## :bulb: Importing to a space with existing content
335
367
 
336
368
  - Both source space and destination space must share the same content model structure. In order to achieve that, please use [contentful-migration](https://www.npmjs.com/package/contentful-migration).
@@ -351,6 +383,7 @@ An entity that's published in the source is published in the destination on impo
351
383
  - Imported webhooks with credentials will be imported as normal webhooks. Credentials should be added manually afterwards.
352
384
  - Imported webhooks with secret headers will be imported without these headers. Secret headers should be added manuall afterwards.
353
385
  - If you have custom UI extensions, you need to reinstall them manually in the new space.
386
+ - `Release.v1` ("Launch") releases are not supported for import — only `Release.v2` ("Releases") releases are imported; see the "Releases" section above.
354
387
  - Per-locale publish state is restored, with three caveats:
355
388
  - The destination has to support [locale-based publishing](https://www.contentful.com/help/localization/locale-based-publishing/), which means two things: the organization is entitled to it (it is not on every plan), and the destination environment has "Locale-based (un)publishing" selected under **Settings > Locales > Publishing options** — the default is "Publish all locales". The import checks the entitlement up front and detects an environment that publishes whole entities anyway, and in either case logs a warning and falls back to publishing every locale, exactly as it did before this feature. The import itself does not fail.
356
389
  - A locale that was `changed` in the source space (published, with newer draft edits on top) is imported as `published`. Reconstructing `changed` needs two separate writes, which an import cannot express.
package/dist/index.d.mts CHANGED
@@ -21,6 +21,7 @@ type RunContentfulImportParams = {
21
21
  errorLogFile?: string;
22
22
  useVerboseRenderer?: boolean;
23
23
  includeExperienceOrchestration?: boolean;
24
+ skipExoVariants?: boolean;
24
25
  timeout?: number;
25
26
  retryLimit?: number;
26
27
  config?: string;
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ type RunContentfulImportParams = {
21
21
  errorLogFile?: string;
22
22
  useVerboseRenderer?: boolean;
23
23
  includeExperienceOrchestration?: boolean;
24
+ skipExoVariants?: boolean;
24
25
  timeout?: number;
25
26
  retryLimit?: number;
26
27
  config?: string;