@contentful/experience-design-system-cli 2.17.2-dev-build-cade400.0 → 2.17.2-dev-build-90291e8.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
@@ -214,6 +214,7 @@ Pass `--select-prompt-path <path>` and/or `--generate-prompt-path <path>` to swa
214
214
  | `--host <url>` | `https://api.contentful.com` | Override API base URL |
215
215
  | `--on-conflict <mode>` | _(prompt via `<SaveConflictGate>`)_ | Headless conflict resolution when a file already exists at the save path: `overwrite`, `skip`, or `fail`. Bypasses the wizard's interactive save-conflict gate. Mutex with `--no-save`. |
216
216
  | `--print-prompt` | — | Print the generate prompt to stdout and exit. Replaces the prompt-print semantics of `--dry-run`. |
217
+ | `--allow-deletions` | off (non-destructive) | Allow the push to delete remote ComponentTypes/DesignTokens missing from the manifest. Default skips them instead of deleting. Forwarded to headless subprocess pushes and `--push-from-run`. |
217
218
  | `--dry-run` | _(deprecated)_ | Deprecated alias for `--print-prompt`. Emits a stderr deprecation notice; prompt-print semantics will be removed in a future release. |
218
219
 
219
220
  ### Run-picker at wizard start
@@ -418,7 +419,7 @@ experiences apply select --space-id <id> --environment-id <env> --session <id>
418
419
  experiences apply push --space-id <id> --environment-id <env> --session <id> [--yes]
419
420
  ```
420
421
 
421
- Shared flags: `--components`, `--tokens`, `--session`, `--space-id`, `--environment-id`, `--cma-token`, `--host`, `--viewports`. `apply preview` adds `--include-unchanged`. `apply select` adds `--select-all`, `--select`, `--deselect`, `--force`. `apply push` adds `--yes`, `--verbose`, `--force`, `--dry-run`.
422
+ Shared flags: `--components`, `--tokens`, `--session`, `--space-id`, `--environment-id`, `--cma-token`, `--host`, `--viewports`. `apply preview` adds `--include-unchanged`. `apply select` adds `--select-all`, `--select`, `--deselect`, `--force`, `--allow-deletions`. `apply push` adds `--yes`, `--verbose`, `--force`, `--dry-run`, `--allow-deletions`. By default, remote ComponentTypes and DesignTokens missing from the pushed manifest are skipped, not deleted; pass `--allow-deletions` to restore the prior delete behavior.
422
423
 
423
424
  Design tokens are written first (component types may reference token kinds). Each entity write is recorded in the session database atomically — interrupted pushes resume from where they left off.
424
425
 
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.17.2-dev-build-cade400.0",
3
+ "version": "2.17.2-dev-build-90291e8.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -51,7 +51,10 @@ export declare class ImportApiClient {
51
51
  private fetchWithRetry;
52
52
  validateToken(): Promise<void>;
53
53
  previewImport(manifest: ManifestPayload): Promise<ServerPreviewResponse>;
54
- applyImport(manifest: ManifestPayload, acknowledgeBreakingChanges: boolean): Promise<ApplyOperationResponse>;
54
+ applyImport(manifest: ManifestPayload, options: {
55
+ acknowledgeBreakingChanges: boolean;
56
+ allowDeletions?: boolean;
57
+ }): Promise<ApplyOperationResponse>;
55
58
  pollOperation(operationId: string, opts?: {
56
59
  intervalMs?: number;
57
60
  maxIntervalMs?: number;
@@ -287,17 +287,18 @@ export class ImportApiClient {
287
287
  debug.event('apply', 'preview.ok', { status: res.status, durationMs: Date.now() - startedAt });
288
288
  return sanitizePreviewResponse(parsed);
289
289
  }
290
- async applyImport(manifest, acknowledgeBreakingChanges) {
290
+ async applyImport(manifest, options) {
291
+ const { acknowledgeBreakingChanges, allowDeletions = false } = options;
291
292
  const url = `${this.base()}/design_systems/imports/apply`;
292
293
  const debug = getDebugLogger();
293
294
  const startedAt = Date.now();
294
- debug.event('apply', 'apply.request', { url, acknowledgeBreakingChanges });
295
+ debug.event('apply', 'apply.request', { url, acknowledgeBreakingChanges, allowDeletions });
295
296
  let res;
296
297
  try {
297
298
  res = await fetch(url, {
298
299
  method: 'POST',
299
300
  headers: this.headers(),
300
- body: JSON.stringify({ ...manifest, acknowledgeBreakingChanges }),
301
+ body: JSON.stringify({ ...manifest, acknowledgeBreakingChanges, allowDeletions }),
301
302
  });
302
303
  }
303
304
  catch (error) {
@@ -474,6 +474,7 @@ export function registerApplyCommand(program) {
474
474
  .option('--verbose', 'Show all entity progress including skipped/unchanged')
475
475
  .option('--force', 'Skip confirmation for breaking changes (for CI)')
476
476
  .option('--dry-run', 'Run preview only without applying')
477
+ .option('--allow-deletions', 'Allow the push to delete remote ComponentTypes/DesignTokens missing from the manifest (default: skip them)')
477
478
  .action(async (opts) => {
478
479
  const isTTY = getInteractiveTerminalSupport().supported;
479
480
  if (!isTTY && !opts.yes) {
@@ -547,7 +548,10 @@ export function registerApplyCommand(program) {
547
548
  }
548
549
  let operation;
549
550
  try {
550
- operation = await client.applyImport(manifest, breakingWithImpact || opts.force === true);
551
+ operation = await client.applyImport(manifest, {
552
+ acknowledgeBreakingChanges: breakingWithImpact || opts.force === true,
553
+ allowDeletions: opts.allowDeletions === true,
554
+ });
551
555
  }
552
556
  catch (e) {
553
557
  if (e instanceof ApiError)
@@ -577,7 +581,10 @@ export function registerApplyCommand(program) {
577
581
  }));
578
582
  let operation;
579
583
  try {
580
- operation = await client.applyImport(manifest, acknowledge);
584
+ operation = await client.applyImport(manifest, {
585
+ acknowledgeBreakingChanges: acknowledge,
586
+ allowDeletions: opts.allowDeletions === true,
587
+ });
581
588
  }
582
589
  catch (e) {
583
590
  if (e instanceof ApiError) {
@@ -640,7 +647,10 @@ export function registerApplyCommand(program) {
640
647
  addContentfulTargetOptions(selectCmd);
641
648
  addCompositionOptions(selectCmd);
642
649
  addSelectionOptions(selectCmd);
643
- selectCmd.option('--force', 'Skip confirmation for breaking changes').action(async (opts) => {
650
+ selectCmd
651
+ .option('--force', 'Skip confirmation for breaking changes')
652
+ .option('--allow-deletions', 'Allow the push to delete remote ComponentTypes/DesignTokens missing from the manifest (default: skip them)')
653
+ .action(async (opts) => {
644
654
  const nonInteractive = opts.selectAll || (opts.select ?? []).length > 0 || (opts.deselect ?? []).length > 0;
645
655
  if (!nonInteractive) {
646
656
  requireInteractiveTerminal({
@@ -707,7 +717,10 @@ export function registerApplyCommand(program) {
707
717
  }
708
718
  let operation;
709
719
  try {
710
- operation = await client.applyImport(filteredManifest, hasBreaking || opts.force === true);
720
+ operation = await client.applyImport(filteredManifest, {
721
+ acknowledgeBreakingChanges: hasBreaking || opts.force === true,
722
+ allowDeletions: opts.allowDeletions === true,
723
+ });
711
724
  }
712
725
  catch (e) {
713
726
  if (e instanceof ApiError)
@@ -749,7 +762,10 @@ export function registerApplyCommand(program) {
749
762
  }));
750
763
  let operation;
751
764
  try {
752
- operation = await client.applyImport(filteredManifest, hasBreaking);
765
+ operation = await client.applyImport(filteredManifest, {
766
+ acknowledgeBreakingChanges: hasBreaking,
767
+ allowDeletions: opts.allowDeletions === true,
768
+ });
753
769
  }
754
770
  catch (e) {
755
771
  if (e instanceof ApiError) {
@@ -74,6 +74,7 @@ export function registerImportCommand(program) {
74
74
  .option('--overwrite', "Only valid with --modify: save back to the run's recorded savePath")
75
75
  .option('--save-as-new', 'Only valid with --modify: always save to a new path (prompts for one)')
76
76
  .option('--force', 'Bypass staleness checks when paired with --push-from-run or --modify.')
77
+ .option('--allow-deletions', 'Allow the push to delete remote ComponentTypes/DesignTokens missing from the manifest (default: skip them)')
77
78
  .action(async (opts) => {
78
79
  const interactiveTerminalSupported = getInteractiveTerminalSupport().supported;
79
80
  // --modify and --push-from-run resume a recorded session; the composition
@@ -136,6 +137,7 @@ export function registerImportCommand(program) {
136
137
  ...(opts.host ? { host: opts.host } : {}),
137
138
  interactive: interactiveTerminalSupported,
138
139
  ...(opts.force ? { force: true } : {}),
140
+ ...(opts.allowDeletions ? { allowDeletions: true } : {}),
139
141
  });
140
142
  return;
141
143
  }
@@ -166,6 +168,7 @@ export function registerImportCommand(program) {
166
168
  ...(opts.saveAsNew ? { saveAsNew: true } : {}),
167
169
  ...(opts.outDir ? { outDir: opts.outDir } : {}),
168
170
  ...(opts.force ? { force: true } : {}),
171
+ ...(opts.allowDeletions ? { allowDeletions: true } : {}),
169
172
  });
170
173
  return;
171
174
  }
@@ -297,6 +300,7 @@ export function registerImportCommand(program) {
297
300
  selectPromptPath: opts.selectPromptPath ?? creds.selectPromptPath,
298
301
  generatePromptPath: opts.generatePromptPath ?? creds.generatePromptPath,
299
302
  ...(opts.rawTokens ? { initialRawTokensPath: resolve(opts.rawTokens) } : {}),
303
+ allowDeletions: opts.allowDeletions === true,
300
304
  ...pickerProps,
301
305
  }));
302
306
  unmountInk = unmount;
@@ -357,6 +361,7 @@ export function registerImportCommand(program) {
357
361
  dryRun: dryRunForward,
358
362
  selectPromptPath: opts.selectPromptPath,
359
363
  autoRejectCycles: opts.autoRejectCycles ?? false,
364
+ allowDeletions: opts.allowDeletions ?? false,
360
365
  compositionMode: headlessCompositionMode,
361
366
  ...(opts.compositionMap ? { compositionMap: opts.compositionMap } : {}),
362
367
  ...(opts.compositionAgent ? { compositionAgent: true } : {}),
@@ -26,6 +26,7 @@ export interface PipelineOptions {
26
26
  selectPromptPath?: string;
27
27
  /** When true, auto-reject cycle participants and retry push instead of surfacing an error. */
28
28
  autoRejectCycles?: boolean;
29
+ allowDeletions?: boolean;
29
30
  compositionMode?: CompositionMode;
30
31
  compositionMap?: string;
31
32
  compositionAgent?: boolean;
@@ -418,6 +418,8 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
418
418
  pushArgs.push('--host', opts.host);
419
419
  if (opts.verbose)
420
420
  pushArgs.push('--verbose');
421
+ if (opts.allowDeletions)
422
+ pushArgs.push('--allow-deletions');
421
423
  pushArgs.push('--yes');
422
424
  const pushStepId = createStep(db, sessionId, 'apply push', {
423
425
  components: componentsPath,
@@ -66,5 +66,6 @@ export type WizardAppProps = {
66
66
  initialRawTokensPath?: string;
67
67
  initialRuns?: RunRecord[];
68
68
  onRunPicked?: (selection: RunPickerSelection) => void;
69
+ allowDeletions?: boolean;
69
70
  };
70
- export declare function WizardApp({ initialSpaceId, initialEnvironmentId, initialCmaToken, initialHost, initialAgent, initialModel, initialProjectPath, host, autoAcceptScope, autoRejectCycles, compositionMode, compositionMap, compositionAgent, compositionAgentMode, compositionRefresh, generateMap, promptOverrides, noCache, autoFilter, livePreview, noPush, noSave, outDirOverride, onConflictMode, selectPromptPath, generatePromptPath, seedExtractSessionId, seedGenerateSessionId, seedTokenSessionId, seedTokensPath, initialStep, initialRawTokensPath, initialRuns, onRunPicked, }?: WizardAppProps): React.ReactElement;
71
+ export declare function WizardApp({ initialSpaceId, initialEnvironmentId, initialCmaToken, initialHost, initialAgent, initialModel, initialProjectPath, host, autoAcceptScope, autoRejectCycles, compositionMode, compositionMap, compositionAgent, compositionAgentMode, compositionRefresh, generateMap, promptOverrides, noCache, autoFilter, livePreview, noPush, noSave, outDirOverride, onConflictMode, selectPromptPath, generatePromptPath, seedExtractSessionId, seedGenerateSessionId, seedTokenSessionId, seedTokensPath, initialStep, initialRawTokensPath, initialRuns, onRunPicked, allowDeletions, }?: WizardAppProps): React.ReactElement;
@@ -138,7 +138,7 @@ function logStep(entry) {
138
138
  appendFileSync(WIZARD_LOG, line);
139
139
  getDebugLogger().event('wizard', 'step', entry);
140
140
  }
141
- export function WizardApp({ initialSpaceId = '', initialEnvironmentId = 'master', initialCmaToken = '', initialHost, initialAgent, initialModel, initialProjectPath, host, autoAcceptScope = false, autoRejectCycles = false, compositionMode = 'atomic', compositionMap, compositionAgent = false, compositionAgentMode, compositionRefresh = false, generateMap, promptOverrides, noCache = false, autoFilter = true, livePreview = true, noPush = false, noSave = false, outDirOverride, onConflictMode, selectPromptPath, generatePromptPath, seedExtractSessionId, seedGenerateSessionId, seedTokenSessionId, seedTokensPath, initialStep, initialRawTokensPath, initialRuns, onRunPicked, } = {}) {
141
+ export function WizardApp({ initialSpaceId = '', initialEnvironmentId = 'master', initialCmaToken = '', initialHost, initialAgent, initialModel, initialProjectPath, host, autoAcceptScope = false, autoRejectCycles = false, compositionMode = 'atomic', compositionMap, compositionAgent = false, compositionAgentMode, compositionRefresh = false, generateMap, promptOverrides, noCache = false, autoFilter = true, livePreview = true, noPush = false, noSave = false, outDirOverride, onConflictMode, selectPromptPath, generatePromptPath, seedExtractSessionId, seedGenerateSessionId, seedTokenSessionId, seedTokensPath, initialStep, initialRawTokensPath, initialRuns, onRunPicked, allowDeletions = false, } = {}) {
142
142
  const defaultConfiguredHost = toConfiguredHost(host || process.env['EDS_HOST']) ?? DEFAULT_CONFIGURED_HOST;
143
143
  const resolveWizardHost = (hostValue) => hostValue || defaultConfiguredHost;
144
144
  const { stdout } = useStdout();
@@ -982,7 +982,7 @@ export function WizardApp({ initialSpaceId = '', initialEnvironmentId = 'master'
982
982
  environmentId,
983
983
  host: resolvedHost,
984
984
  });
985
- let operation = await client.applyImport(manifest, acknowledgeBreakingChanges);
985
+ let operation = await client.applyImport(manifest, { acknowledgeBreakingChanges, allowDeletions });
986
986
  try {
987
987
  logStep({
988
988
  applyResponse: {
@@ -26,5 +26,7 @@ export type ModifyLauncherInput = {
26
26
  initialHost?: string;
27
27
  /** Pre-fill CMA token (from credentials.json / env). */
28
28
  initialCmaToken?: string;
29
+ /** From `--allow-deletions` flag. Forwarded to wizard's push step. */
30
+ allowDeletions?: boolean;
29
31
  };
30
32
  export declare function launchModifyWizard(input: ModifyLauncherInput): Promise<void>;
@@ -35,6 +35,8 @@ export async function launchModifyWizard(input) {
35
35
  props.initialHost = input.initialHost;
36
36
  if (input.initialCmaToken)
37
37
  props.initialCmaToken = input.initialCmaToken;
38
+ if (input.allowDeletions !== undefined)
39
+ props.allowDeletions = input.allowDeletions;
38
40
  const { waitUntilExit } = render(createElement(WizardApp, props));
39
41
  await waitUntilExit();
40
42
  }
@@ -15,6 +15,7 @@ export type PushSessionOptions = {
15
15
  environmentId: string;
16
16
  cmaToken: string;
17
17
  host?: string;
18
+ allowDeletions?: boolean;
18
19
  };
19
20
  /**
20
21
  * Push a recorded pipeline.db session's components + tokens to Contentful by
@@ -60,6 +60,9 @@ export async function pushRunSession(opts) {
60
60
  if (opts.host) {
61
61
  args.push('--host', opts.host);
62
62
  }
63
+ if (opts.allowDeletions) {
64
+ args.push('--allow-deletions');
65
+ }
63
66
  const r = await runCli(args);
64
67
  if (r.exitCode === 0)
65
68
  return { ok: true };
@@ -16,6 +16,8 @@ export type ReplayRunOptions = {
16
16
  interactive?: boolean;
17
17
  /** When true, bypass the source/saved-file staleness check. */
18
18
  force?: boolean;
19
+ /** From `--allow-deletions` flag. Forwarded verbatim to the pushed session's apply request. */
20
+ allowDeletions?: boolean;
19
21
  /**
20
22
  * Test seam: replace the interactive prompt with a deterministic resolver.
21
23
  * The CLI surface never sets this; only used by tests.
@@ -57,6 +59,8 @@ export type ModifyRunOptions = {
57
59
  outDir?: string;
58
60
  /** When true, bypass the source/saved-file staleness check. */
59
61
  force?: boolean;
62
+ /** From `--allow-deletions` flag. Forwarded through the modify wizard's push step. */
63
+ allowDeletions?: boolean;
60
64
  };
61
65
  /**
62
66
  * Re-open the wizard with a prior run's extract/generate session pre-populated
@@ -83,6 +83,7 @@ export async function replayRun(opts) {
83
83
  environmentId,
84
84
  cmaToken,
85
85
  ...(host ? { host } : {}),
86
+ ...(opts.allowDeletions ? { allowDeletions: true } : {}),
86
87
  });
87
88
  if (!result.ok) {
88
89
  throw new Error(result.error);
@@ -98,6 +99,7 @@ export async function replayRun(opts) {
98
99
  environmentId,
99
100
  cmaToken,
100
101
  ...(host ? { host } : {}),
102
+ ...(opts.allowDeletions ? { allowDeletions: true } : {}),
101
103
  });
102
104
  if (!tokenResult.ok) {
103
105
  throw new Error(tokenResult.error);
@@ -157,5 +159,6 @@ export async function modifyRun(opts) {
157
159
  ...(mergedEnvironmentId ? { initialEnvironmentId: mergedEnvironmentId } : {}),
158
160
  ...(mergedHost ? { initialHost: mergedHost } : {}),
159
161
  ...(mergedCmaToken ? { initialCmaToken: mergedCmaToken } : {}),
162
+ ...(opts.allowDeletions !== undefined ? { allowDeletions: opts.allowDeletions } : {}),
160
163
  });
161
164
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.17.2-dev-build-cade400.0",
3
+ "version": "2.17.2-dev-build-90291e8.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,8 +34,8 @@
34
34
  "react": "^18.3.1",
35
35
  "react-devtools-core": "^4.19.1",
36
36
  "react-dom": "^18.3.1",
37
- "@contentful/experience-design-system-extraction": "2.17.2-dev-build-cade400.0",
38
- "@contentful/experience-design-system-types": "2.17.2-dev-build-cade400.0"
37
+ "@contentful/experience-design-system-extraction": "2.17.2-dev-build-90291e8.0",
38
+ "@contentful/experience-design-system-types": "2.17.2-dev-build-90291e8.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@tsconfig/node24": "^24.0.3",