@contentful/experience-design-system-cli 2.17.2-dev-build-ebba024.0 → 2.17.2-dev-build-ebf31d1.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 +1 -2
- package/dist/package.json +2 -1
- package/dist/src/apply/api-client.d.ts +2 -5
- package/dist/src/apply/api-client.js +80 -67
- package/dist/src/apply/command.js +5 -19
- package/dist/src/import/command.js +1 -6
- package/dist/src/import/orchestrator.d.ts +0 -1
- package/dist/src/import/orchestrator.js +0 -2
- package/dist/src/import/tui/WizardApp.d.ts +1 -2
- package/dist/src/import/tui/WizardApp.js +2 -2
- package/dist/src/lib/command-options.d.ts +0 -1
- package/dist/src/lib/command-options.js +0 -3
- package/dist/src/runs/modify-launcher.d.ts +0 -2
- package/dist/src/runs/modify-launcher.js +0 -2
- package/dist/src/runs/push-helpers.d.ts +0 -1
- package/dist/src/runs/push-helpers.js +0 -3
- package/dist/src/runs/replay-helpers.d.ts +0 -4
- package/dist/src/runs/replay-helpers.js +0 -3
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -214,7 +214,6 @@ 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`. |
|
|
218
217
|
| `--dry-run` | _(deprecated)_ | Deprecated alias for `--print-prompt`. Emits a stderr deprecation notice; prompt-print semantics will be removed in a future release. |
|
|
219
218
|
|
|
220
219
|
### Run-picker at wizard start
|
|
@@ -419,7 +418,7 @@ experiences apply select --space-id <id> --environment-id <env> --session <id>
|
|
|
419
418
|
experiences apply push --space-id <id> --environment-id <env> --session <id> [--yes]
|
|
420
419
|
```
|
|
421
420
|
|
|
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
|
|
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`.
|
|
423
422
|
|
|
424
423
|
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.
|
|
425
424
|
|
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-
|
|
3
|
+
"version": "2.17.2-dev-build-ebf31d1.0",
|
|
4
4
|
"description": "Contentful Experiences design system import CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"lint:fix": "nx lint:fix experience-design-system-cli"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
+
"@contentful/experience-design-system-client": "workspace:*",
|
|
41
42
|
"@contentful/experience-design-system-extraction": "workspace:*",
|
|
42
43
|
"@contentful/experience-design-system-types": "workspace:*",
|
|
43
44
|
"commander": "^13.1.0",
|
|
@@ -48,13 +48,10 @@ export declare class ImportApiClient {
|
|
|
48
48
|
constructor(opts: ApiClientOptions);
|
|
49
49
|
private base;
|
|
50
50
|
private headers;
|
|
51
|
-
private
|
|
51
|
+
private requestWithRetry;
|
|
52
52
|
validateToken(): Promise<void>;
|
|
53
53
|
previewImport(manifest: ManifestPayload): Promise<ServerPreviewResponse>;
|
|
54
|
-
applyImport(manifest: ManifestPayload,
|
|
55
|
-
acknowledgeBreakingChanges: boolean;
|
|
56
|
-
allowDeletions?: boolean;
|
|
57
|
-
}): Promise<ApplyOperationResponse>;
|
|
54
|
+
applyImport(manifest: ManifestPayload, acknowledgeBreakingChanges: boolean): Promise<ApplyOperationResponse>;
|
|
58
55
|
pollOperation(operationId: string, opts?: {
|
|
59
56
|
intervalMs?: number;
|
|
60
57
|
maxIntervalMs?: number;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { designSystemImportSourcelessPreview, designSystemImportApply, designSystemImportGetOperation, } from '@contentful/experience-design-system-client';
|
|
1
2
|
import { DEFAULT_API_HOST, toApiHost } from '../host-utils.js';
|
|
2
3
|
import { getDebugLogger } from '../lib/debug-logger.js';
|
|
3
4
|
import { buildUserAgent } from '../lib/user-agent.js';
|
|
@@ -32,6 +33,14 @@ function retryAfterMs(response) {
|
|
|
32
33
|
function errorMessage(error) {
|
|
33
34
|
return error instanceof Error && error.message ? error.message : String(error);
|
|
34
35
|
}
|
|
36
|
+
// The generated client parses non-2xx bodies to JSON internally (unlike a raw
|
|
37
|
+
// fetch(), which hands back the raw body string). Re-serializing here keeps
|
|
38
|
+
// ApiError's `body: string` contract and parsePreviewValidationErrors'
|
|
39
|
+
// `JSON.parse` unchanged for callers, at the cost of a harmless double-parse
|
|
40
|
+
// on error paths only.
|
|
41
|
+
function stringifyError(error) {
|
|
42
|
+
return typeof error === 'string' ? error : JSON.stringify(error ?? {});
|
|
43
|
+
}
|
|
35
44
|
// Cap on the body slice appended to ApiError.message. Bumped from 1000 →
|
|
36
45
|
// 16384 so realistic 422 ValidationFailed reports (which list every
|
|
37
46
|
// offending component, ~100 chars per error, easily exceeds 1KB once you
|
|
@@ -182,45 +191,15 @@ export class ImportApiClient {
|
|
|
182
191
|
'X-Contentful-User-Agent': buildUserAgent(),
|
|
183
192
|
};
|
|
184
193
|
}
|
|
185
|
-
async
|
|
194
|
+
async requestWithRetry(phase, errorPrefix, makeCall, context = {}) {
|
|
186
195
|
const debug = getDebugLogger();
|
|
187
|
-
const errorPrefix = phase === 'preview' ? PREVIEW_ERROR_PREFIX : 'poll failed:';
|
|
188
196
|
const startedAt = Date.now();
|
|
189
197
|
for (let attempt = 1; attempt <= this.retry.maxAttempts; attempt++) {
|
|
198
|
+
let result;
|
|
190
199
|
try {
|
|
191
|
-
|
|
192
|
-
if (!isTransientStatus(response.status))
|
|
193
|
-
return response;
|
|
194
|
-
const body = await response.text();
|
|
195
|
-
if (attempt === this.retry.maxAttempts) {
|
|
196
|
-
const guidance = `The ${phase} request failed after ${attempt} attempts because the service remained unavailable. ` +
|
|
197
|
-
'Wait a moment and try again.';
|
|
198
|
-
debug.event('apply', `${phase}.error`, {
|
|
199
|
-
...context,
|
|
200
|
-
attempt,
|
|
201
|
-
maxAttempts: this.retry.maxAttempts,
|
|
202
|
-
status: response.status,
|
|
203
|
-
reason: 'retry_exhausted',
|
|
204
|
-
durationMs: Date.now() - startedAt,
|
|
205
|
-
bodyHead: body.slice(0, 2000),
|
|
206
|
-
});
|
|
207
|
-
throw new ApiError(`${errorPrefix} ${response.status}`, response.status, body, guidance);
|
|
208
|
-
}
|
|
209
|
-
const backoffMs = Math.min(this.retry.initialDelayMs * 2 ** (attempt - 1), this.retry.maxDelayMs);
|
|
210
|
-
const delayMs = retryAfterMs(response) ?? backoffMs;
|
|
211
|
-
debug.event('apply', `${phase}.retry`, {
|
|
212
|
-
...context,
|
|
213
|
-
attempt,
|
|
214
|
-
maxAttempts: this.retry.maxAttempts,
|
|
215
|
-
status: response.status,
|
|
216
|
-
reason: 'http_5xx',
|
|
217
|
-
delayMs,
|
|
218
|
-
});
|
|
219
|
-
await this.retry.sleep(delayMs);
|
|
200
|
+
result = await makeCall();
|
|
220
201
|
}
|
|
221
202
|
catch (error) {
|
|
222
|
-
if (error instanceof ApiError)
|
|
223
|
-
throw error;
|
|
224
203
|
if (attempt === this.retry.maxAttempts) {
|
|
225
204
|
const body = `The request failed after ${attempt} attempts because of a network error: ${errorMessage(error)}. ` +
|
|
226
205
|
'Check your connection and try again.';
|
|
@@ -244,7 +223,36 @@ export class ImportApiClient {
|
|
|
244
223
|
delayMs,
|
|
245
224
|
});
|
|
246
225
|
await this.retry.sleep(delayMs);
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (!isTransientStatus(result.response.status))
|
|
229
|
+
return result;
|
|
230
|
+
if (attempt === this.retry.maxAttempts) {
|
|
231
|
+
const body = stringifyError(result.error);
|
|
232
|
+
const guidance = `The ${phase} request failed after ${attempt} attempts because the service remained unavailable. ` +
|
|
233
|
+
'Wait a moment and try again.';
|
|
234
|
+
debug.event('apply', `${phase}.error`, {
|
|
235
|
+
...context,
|
|
236
|
+
attempt,
|
|
237
|
+
maxAttempts: this.retry.maxAttempts,
|
|
238
|
+
status: result.response.status,
|
|
239
|
+
reason: 'retry_exhausted',
|
|
240
|
+
durationMs: Date.now() - startedAt,
|
|
241
|
+
bodyHead: body.slice(0, 2000),
|
|
242
|
+
});
|
|
243
|
+
throw new ApiError(`${errorPrefix} ${result.response.status}`, result.response.status, body, guidance);
|
|
247
244
|
}
|
|
245
|
+
const backoffMs = Math.min(this.retry.initialDelayMs * 2 ** (attempt - 1), this.retry.maxDelayMs);
|
|
246
|
+
const delayMs = retryAfterMs(result.response) ?? backoffMs;
|
|
247
|
+
debug.event('apply', `${phase}.retry`, {
|
|
248
|
+
...context,
|
|
249
|
+
attempt,
|
|
250
|
+
maxAttempts: this.retry.maxAttempts,
|
|
251
|
+
status: result.response.status,
|
|
252
|
+
reason: 'http_5xx',
|
|
253
|
+
delayMs,
|
|
254
|
+
});
|
|
255
|
+
await this.retry.sleep(delayMs);
|
|
248
256
|
}
|
|
249
257
|
throw new Error('Retry attempts exhausted');
|
|
250
258
|
}
|
|
@@ -261,44 +269,48 @@ export class ImportApiClient {
|
|
|
261
269
|
}
|
|
262
270
|
}
|
|
263
271
|
async previewImport(manifest) {
|
|
264
|
-
const url = `${this.base()}/design_systems/imports/preview`;
|
|
265
272
|
const debug = getDebugLogger();
|
|
266
273
|
const startedAt = Date.now();
|
|
267
274
|
debug.event('apply', 'preview.request', {
|
|
268
|
-
url
|
|
275
|
+
url: `${this.base()}/design_systems/imports/preview`,
|
|
269
276
|
componentCount: manifest.components?.length ?? 0,
|
|
270
277
|
tokenCount: manifest.designTokens?.length ?? 0,
|
|
271
278
|
});
|
|
272
|
-
const
|
|
273
|
-
|
|
279
|
+
const result = await this.requestWithRetry('preview', PREVIEW_ERROR_PREFIX, () => designSystemImportSourcelessPreview({
|
|
280
|
+
baseUrl: this.host,
|
|
274
281
|
headers: this.headers(),
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
282
|
+
path: { spaceId: this.spaceId, environmentId: this.environmentId },
|
|
283
|
+
body: manifest,
|
|
284
|
+
parseAs: 'json',
|
|
285
|
+
}));
|
|
286
|
+
if (!result.response.ok) {
|
|
287
|
+
const body = stringifyError(result.error);
|
|
279
288
|
debug.event('apply', 'preview.error', {
|
|
280
|
-
status:
|
|
289
|
+
status: result.response.status,
|
|
281
290
|
durationMs: Date.now() - startedAt,
|
|
282
291
|
bodyHead: body.slice(0, 2000),
|
|
283
292
|
});
|
|
284
|
-
throw new ApiError(`${PREVIEW_ERROR_PREFIX} ${
|
|
293
|
+
throw new ApiError(`${PREVIEW_ERROR_PREFIX} ${result.response.status}`, result.response.status, body);
|
|
285
294
|
}
|
|
286
|
-
const parsed =
|
|
287
|
-
debug.event('apply', 'preview.ok', { status:
|
|
295
|
+
const parsed = result.data;
|
|
296
|
+
debug.event('apply', 'preview.ok', { status: result.response.status, durationMs: Date.now() - startedAt });
|
|
288
297
|
return sanitizePreviewResponse(parsed);
|
|
289
298
|
}
|
|
290
|
-
async applyImport(manifest,
|
|
291
|
-
const { acknowledgeBreakingChanges, allowDeletions = false } = options;
|
|
292
|
-
const url = `${this.base()}/design_systems/imports/apply`;
|
|
299
|
+
async applyImport(manifest, acknowledgeBreakingChanges) {
|
|
293
300
|
const debug = getDebugLogger();
|
|
294
301
|
const startedAt = Date.now();
|
|
295
|
-
debug.event('apply', 'apply.request', {
|
|
296
|
-
|
|
302
|
+
debug.event('apply', 'apply.request', {
|
|
303
|
+
url: `${this.base()}/design_systems/imports/apply`,
|
|
304
|
+
acknowledgeBreakingChanges,
|
|
305
|
+
});
|
|
306
|
+
let result;
|
|
297
307
|
try {
|
|
298
|
-
|
|
299
|
-
|
|
308
|
+
result = await designSystemImportApply({
|
|
309
|
+
baseUrl: this.host,
|
|
300
310
|
headers: this.headers(),
|
|
301
|
-
|
|
311
|
+
path: { spaceId: this.spaceId, environmentId: this.environmentId },
|
|
312
|
+
body: { ...manifest, acknowledgeBreakingChanges },
|
|
313
|
+
parseAs: 'json',
|
|
302
314
|
});
|
|
303
315
|
}
|
|
304
316
|
catch (error) {
|
|
@@ -311,21 +323,21 @@ export class ImportApiClient {
|
|
|
311
323
|
});
|
|
312
324
|
throw new ApiError(`${APPLY_ERROR_PREFIX} 0`, 0, body);
|
|
313
325
|
}
|
|
314
|
-
if (!
|
|
315
|
-
const body =
|
|
316
|
-
const guidance = isTransientStatus(
|
|
326
|
+
if (!result.response.ok) {
|
|
327
|
+
const body = stringifyError(result.error);
|
|
328
|
+
const guidance = isTransientStatus(result.response.status)
|
|
317
329
|
? 'The apply request was not retried because the server may already have started an operation and retrying could create a duplicate. Check for an existing operation before trying again.'
|
|
318
330
|
: undefined;
|
|
319
331
|
debug.event('apply', 'apply.error', {
|
|
320
|
-
status:
|
|
332
|
+
status: result.response.status,
|
|
321
333
|
durationMs: Date.now() - startedAt,
|
|
322
334
|
bodyHead: body.slice(0, 2000),
|
|
323
335
|
});
|
|
324
|
-
throw new ApiError(`${APPLY_ERROR_PREFIX} ${
|
|
336
|
+
throw new ApiError(`${APPLY_ERROR_PREFIX} ${result.response.status}`, result.response.status, body, guidance);
|
|
325
337
|
}
|
|
326
|
-
const parsed =
|
|
338
|
+
const parsed = result.data;
|
|
327
339
|
debug.event('apply', 'apply.accepted', {
|
|
328
|
-
status:
|
|
340
|
+
status: result.response.status,
|
|
329
341
|
operationId: parsed.sys?.id,
|
|
330
342
|
durationMs: Date.now() - startedAt,
|
|
331
343
|
});
|
|
@@ -337,15 +349,16 @@ export class ImportApiClient {
|
|
|
337
349
|
const maxAttempts = opts.maxAttempts ?? 150;
|
|
338
350
|
const terminalStatuses = new Set(['succeeded', 'partial', 'failed']);
|
|
339
351
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
method: 'GET',
|
|
352
|
+
const result = await this.requestWithRetry('poll', 'poll failed:', () => designSystemImportGetOperation({
|
|
353
|
+
baseUrl: this.host,
|
|
343
354
|
headers: this.headers(),
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
355
|
+
path: { spaceId: this.spaceId, environmentId: this.environmentId, operationId },
|
|
356
|
+
parseAs: 'json',
|
|
357
|
+
}), { operationId });
|
|
358
|
+
if (!result.response.ok) {
|
|
359
|
+
throw new ApiError(`poll failed: ${result.response.status}`, result.response.status, stringifyError(result.error));
|
|
347
360
|
}
|
|
348
|
-
const op =
|
|
361
|
+
const op = result.data;
|
|
349
362
|
opts.onProgress?.(op);
|
|
350
363
|
getDebugLogger().event('apply', 'poll.tick', {
|
|
351
364
|
operationId,
|
|
@@ -12,7 +12,7 @@ import { ServerPreviewApp, ServerPreviewConfirm, ServerApplyProgress, ServerAppl
|
|
|
12
12
|
import { SelectView, makeSelectKey } from './tui/SelectView.js';
|
|
13
13
|
import { buildPostPushUrl } from '../lib/contentful-urls.js';
|
|
14
14
|
import { resolveCompositionMode } from '../lib/composition-mode.js';
|
|
15
|
-
import {
|
|
15
|
+
import { addArtifactInputOptions, addCompositionOptions, addContentfulTargetOptions, addSelectionOptions, } from '../lib/command-options.js';
|
|
16
16
|
import { stripAllowedComponents } from '../import/strip-allowed-components.js';
|
|
17
17
|
import { readExperiencesCredentials } from '../credentials-store.js';
|
|
18
18
|
import { getInteractiveTerminalSupport, requireInteractiveTerminal } from '../lib/terminal-capabilities.js';
|
|
@@ -469,7 +469,6 @@ export function registerApplyCommand(program) {
|
|
|
469
469
|
addArtifactInputOptions(pushCmd);
|
|
470
470
|
addContentfulTargetOptions(pushCmd);
|
|
471
471
|
addCompositionOptions(pushCmd);
|
|
472
|
-
addAllowDeletionsOption(pushCmd);
|
|
473
472
|
pushCmd
|
|
474
473
|
.option('--yes', 'Skip interactive confirmation')
|
|
475
474
|
.option('--verbose', 'Show all entity progress including skipped/unchanged')
|
|
@@ -548,10 +547,7 @@ export function registerApplyCommand(program) {
|
|
|
548
547
|
}
|
|
549
548
|
let operation;
|
|
550
549
|
try {
|
|
551
|
-
operation = await client.applyImport(manifest,
|
|
552
|
-
acknowledgeBreakingChanges: breakingWithImpact || opts.force === true,
|
|
553
|
-
allowDeletions: opts.allowDeletions === true,
|
|
554
|
-
});
|
|
550
|
+
operation = await client.applyImport(manifest, breakingWithImpact || opts.force === true);
|
|
555
551
|
}
|
|
556
552
|
catch (e) {
|
|
557
553
|
if (e instanceof ApiError)
|
|
@@ -581,10 +577,7 @@ export function registerApplyCommand(program) {
|
|
|
581
577
|
}));
|
|
582
578
|
let operation;
|
|
583
579
|
try {
|
|
584
|
-
operation = await client.applyImport(manifest,
|
|
585
|
-
acknowledgeBreakingChanges: acknowledge,
|
|
586
|
-
allowDeletions: opts.allowDeletions === true,
|
|
587
|
-
});
|
|
580
|
+
operation = await client.applyImport(manifest, acknowledge);
|
|
588
581
|
}
|
|
589
582
|
catch (e) {
|
|
590
583
|
if (e instanceof ApiError) {
|
|
@@ -647,7 +640,6 @@ export function registerApplyCommand(program) {
|
|
|
647
640
|
addContentfulTargetOptions(selectCmd);
|
|
648
641
|
addCompositionOptions(selectCmd);
|
|
649
642
|
addSelectionOptions(selectCmd);
|
|
650
|
-
addAllowDeletionsOption(selectCmd);
|
|
651
643
|
selectCmd.option('--force', 'Skip confirmation for breaking changes').action(async (opts) => {
|
|
652
644
|
const nonInteractive = opts.selectAll || (opts.select ?? []).length > 0 || (opts.deselect ?? []).length > 0;
|
|
653
645
|
if (!nonInteractive) {
|
|
@@ -715,10 +707,7 @@ export function registerApplyCommand(program) {
|
|
|
715
707
|
}
|
|
716
708
|
let operation;
|
|
717
709
|
try {
|
|
718
|
-
operation = await client.applyImport(filteredManifest,
|
|
719
|
-
acknowledgeBreakingChanges: hasBreaking || opts.force === true,
|
|
720
|
-
allowDeletions: opts.allowDeletions === true,
|
|
721
|
-
});
|
|
710
|
+
operation = await client.applyImport(filteredManifest, hasBreaking || opts.force === true);
|
|
722
711
|
}
|
|
723
712
|
catch (e) {
|
|
724
713
|
if (e instanceof ApiError)
|
|
@@ -760,10 +749,7 @@ export function registerApplyCommand(program) {
|
|
|
760
749
|
}));
|
|
761
750
|
let operation;
|
|
762
751
|
try {
|
|
763
|
-
operation = await client.applyImport(filteredManifest,
|
|
764
|
-
acknowledgeBreakingChanges: hasBreaking,
|
|
765
|
-
allowDeletions: opts.allowDeletions === true,
|
|
766
|
-
});
|
|
752
|
+
operation = await client.applyImport(filteredManifest, hasBreaking);
|
|
767
753
|
}
|
|
768
754
|
catch (e) {
|
|
769
755
|
if (e instanceof ApiError) {
|
|
@@ -4,7 +4,7 @@ import { resolveAutoFilter } from './auto-filter-resolve.js';
|
|
|
4
4
|
import { resolveAgent, resolveModel } from './agent-model-resolve.js';
|
|
5
5
|
import { addAgentModelOptions } from '../lib/agent-model-options.js';
|
|
6
6
|
import { resolveCompositionMode } from '../lib/composition-mode.js';
|
|
7
|
-
import {
|
|
7
|
+
import { addCompositionOptions } from '../lib/command-options.js';
|
|
8
8
|
import { isConflictMode } from '../runs/save-path-resolver.js';
|
|
9
9
|
import { readExperiencesCredentials } from '../credentials-store.js';
|
|
10
10
|
import { DEFAULT_CONFIGURED_HOST, toConfiguredHost } from '../host-utils.js';
|
|
@@ -46,7 +46,6 @@ export function registerImportCommand(program) {
|
|
|
46
46
|
.option('--print-prompt', 'Print the generate components prompt without invoking the agent. Replaces the legacy --dry-run prompt-print behaviour on this command.')
|
|
47
47
|
.option('--auto-accept-scope', 'Accept all extracted components without prompting (for scripted/non-TTY callers)');
|
|
48
48
|
addCompositionOptions(cmd);
|
|
49
|
-
addAllowDeletionsOption(cmd);
|
|
50
49
|
cmd
|
|
51
50
|
.option('--composition-map <path>', 'Consume a hand-authored parent→children interchange map (implies --composite)')
|
|
52
51
|
.option('--composition-agent', 'Opt into agentic mapping resolution when deterministic sources find no groups (implies --composite)')
|
|
@@ -137,7 +136,6 @@ export function registerImportCommand(program) {
|
|
|
137
136
|
...(opts.host ? { host: opts.host } : {}),
|
|
138
137
|
interactive: interactiveTerminalSupported,
|
|
139
138
|
...(opts.force ? { force: true } : {}),
|
|
140
|
-
...(opts.allowDeletions ? { allowDeletions: true } : {}),
|
|
141
139
|
});
|
|
142
140
|
return;
|
|
143
141
|
}
|
|
@@ -168,7 +166,6 @@ export function registerImportCommand(program) {
|
|
|
168
166
|
...(opts.saveAsNew ? { saveAsNew: true } : {}),
|
|
169
167
|
...(opts.outDir ? { outDir: opts.outDir } : {}),
|
|
170
168
|
...(opts.force ? { force: true } : {}),
|
|
171
|
-
...(opts.allowDeletions ? { allowDeletions: true } : {}),
|
|
172
169
|
});
|
|
173
170
|
return;
|
|
174
171
|
}
|
|
@@ -300,7 +297,6 @@ export function registerImportCommand(program) {
|
|
|
300
297
|
selectPromptPath: opts.selectPromptPath ?? creds.selectPromptPath,
|
|
301
298
|
generatePromptPath: opts.generatePromptPath ?? creds.generatePromptPath,
|
|
302
299
|
...(opts.rawTokens ? { initialRawTokensPath: resolve(opts.rawTokens) } : {}),
|
|
303
|
-
allowDeletions: opts.allowDeletions === true,
|
|
304
300
|
...pickerProps,
|
|
305
301
|
}));
|
|
306
302
|
unmountInk = unmount;
|
|
@@ -361,7 +357,6 @@ export function registerImportCommand(program) {
|
|
|
361
357
|
dryRun: dryRunForward,
|
|
362
358
|
selectPromptPath: opts.selectPromptPath,
|
|
363
359
|
autoRejectCycles: opts.autoRejectCycles ?? false,
|
|
364
|
-
allowDeletions: opts.allowDeletions ?? false,
|
|
365
360
|
compositionMode: headlessCompositionMode,
|
|
366
361
|
...(opts.compositionMap ? { compositionMap: opts.compositionMap } : {}),
|
|
367
362
|
...(opts.compositionAgent ? { compositionAgent: true } : {}),
|
|
@@ -26,7 +26,6 @@ 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;
|
|
30
29
|
compositionMode?: CompositionMode;
|
|
31
30
|
compositionMap?: string;
|
|
32
31
|
compositionAgent?: boolean;
|
|
@@ -418,8 +418,6 @@ 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');
|
|
423
421
|
pushArgs.push('--yes');
|
|
424
422
|
const pushStepId = createStep(db, sessionId, 'apply push', {
|
|
425
423
|
components: componentsPath,
|
|
@@ -66,6 +66,5 @@ export type WizardAppProps = {
|
|
|
66
66
|
initialRawTokensPath?: string;
|
|
67
67
|
initialRuns?: RunRecord[];
|
|
68
68
|
onRunPicked?: (selection: RunPickerSelection) => void;
|
|
69
|
-
allowDeletions?: boolean;
|
|
70
69
|
};
|
|
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,
|
|
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;
|
|
@@ -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, } = {}) {
|
|
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,
|
|
985
|
+
let operation = await client.applyImport(manifest, acknowledgeBreakingChanges);
|
|
986
986
|
try {
|
|
987
987
|
logStep({
|
|
988
988
|
applyResponse: {
|
|
@@ -3,4 +3,3 @@ export declare function addArtifactInputOptions(cmd: Command): Command;
|
|
|
3
3
|
export declare function addContentfulTargetOptions(cmd: Command): Command;
|
|
4
4
|
export declare function addCompositionOptions(cmd: Command): Command;
|
|
5
5
|
export declare function addSelectionOptions(cmd: Command): Command;
|
|
6
|
-
export declare function addAllowDeletionsOption(cmd: Command): Command;
|
|
@@ -25,6 +25,3 @@ export function addSelectionOptions(cmd) {
|
|
|
25
25
|
.option('--select <pattern>', 'Select entities by ID pattern (repeatable)', collectOptionValue, [])
|
|
26
26
|
.option('--deselect <pattern>', 'Deselect entities by ID pattern (repeatable)', collectOptionValue, []);
|
|
27
27
|
}
|
|
28
|
-
export function addAllowDeletionsOption(cmd) {
|
|
29
|
-
return cmd.option('--allow-deletions', 'Allow the push to delete remote ComponentTypes/DesignTokens missing from the manifest (default: skip them)');
|
|
30
|
-
}
|
|
@@ -26,7 +26,5 @@ 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;
|
|
31
29
|
};
|
|
32
30
|
export declare function launchModifyWizard(input: ModifyLauncherInput): Promise<void>;
|
|
@@ -35,8 +35,6 @@ 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;
|
|
40
38
|
const { waitUntilExit } = render(createElement(WizardApp, props));
|
|
41
39
|
await waitUntilExit();
|
|
42
40
|
}
|
|
@@ -16,8 +16,6 @@ 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;
|
|
21
19
|
/**
|
|
22
20
|
* Test seam: replace the interactive prompt with a deterministic resolver.
|
|
23
21
|
* The CLI surface never sets this; only used by tests.
|
|
@@ -59,8 +57,6 @@ export type ModifyRunOptions = {
|
|
|
59
57
|
outDir?: string;
|
|
60
58
|
/** When true, bypass the source/saved-file staleness check. */
|
|
61
59
|
force?: boolean;
|
|
62
|
-
/** From `--allow-deletions` flag. Forwarded through the modify wizard's push step. */
|
|
63
|
-
allowDeletions?: boolean;
|
|
64
60
|
};
|
|
65
61
|
/**
|
|
66
62
|
* Re-open the wizard with a prior run's extract/generate session pre-populated
|
|
@@ -83,7 +83,6 @@ export async function replayRun(opts) {
|
|
|
83
83
|
environmentId,
|
|
84
84
|
cmaToken,
|
|
85
85
|
...(host ? { host } : {}),
|
|
86
|
-
...(opts.allowDeletions ? { allowDeletions: true } : {}),
|
|
87
86
|
});
|
|
88
87
|
if (!result.ok) {
|
|
89
88
|
throw new Error(result.error);
|
|
@@ -99,7 +98,6 @@ export async function replayRun(opts) {
|
|
|
99
98
|
environmentId,
|
|
100
99
|
cmaToken,
|
|
101
100
|
...(host ? { host } : {}),
|
|
102
|
-
...(opts.allowDeletions ? { allowDeletions: true } : {}),
|
|
103
101
|
});
|
|
104
102
|
if (!tokenResult.ok) {
|
|
105
103
|
throw new Error(tokenResult.error);
|
|
@@ -159,6 +157,5 @@ export async function modifyRun(opts) {
|
|
|
159
157
|
...(mergedEnvironmentId ? { initialEnvironmentId: mergedEnvironmentId } : {}),
|
|
160
158
|
...(mergedHost ? { initialHost: mergedHost } : {}),
|
|
161
159
|
...(mergedCmaToken ? { initialCmaToken: mergedCmaToken } : {}),
|
|
162
|
-
...(opts.allowDeletions !== undefined ? { allowDeletions: opts.allowDeletions } : {}),
|
|
163
160
|
});
|
|
164
161
|
}
|
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-
|
|
3
|
+
"version": "2.17.2-dev-build-ebf31d1.0",
|
|
4
4
|
"description": "Contentful Experiences design system import CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -34,8 +34,9 @@
|
|
|
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-
|
|
38
|
-
"@contentful/experience-design-system-
|
|
37
|
+
"@contentful/experience-design-system-client": "2.17.2-dev-build-ebf31d1.0",
|
|
38
|
+
"@contentful/experience-design-system-extraction": "2.17.2-dev-build-ebf31d1.0",
|
|
39
|
+
"@contentful/experience-design-system-types": "2.17.2-dev-build-ebf31d1.0"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@tsconfig/node24": "^24.0.3",
|