@contentful/experience-design-system-cli 2.23.2-dev-build-8b2cfc9.0 → 2.23.2-dev-build-09d87bb.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 +2 -24
- package/dist/package.json +1 -2
- package/dist/src/analyze/command.js +0 -4
- package/dist/src/analyze/select/tui/App.js +4 -1
- package/dist/src/apply/api-client.d.ts +5 -5
- package/dist/src/apply/api-client.js +8 -18
- package/dist/src/apply/command.js +32 -32
- package/dist/src/apply/preview-utils.d.ts +5 -1
- package/dist/src/apply/preview-utils.js +5 -1
- package/dist/src/apply/tui/ServerApplyView.d.ts +6 -3
- package/dist/src/apply/tui/ServerApplyView.js +15 -6
- package/dist/src/apply/tui/ServerPreviewView.d.ts +2 -1
- package/dist/src/apply/tui/ServerPreviewView.js +3 -3
- package/dist/src/import/command.js +6 -1
- package/dist/src/import/orchestrator.d.ts +1 -0
- package/dist/src/import/orchestrator.js +3 -6
- package/dist/src/import/tui/WizardApp.d.ts +2 -1
- package/dist/src/import/tui/WizardApp.js +8 -8
- package/dist/src/import/tui/final-review-host.d.ts +2 -1
- package/dist/src/import/tui/final-review-host.js +2 -2
- package/dist/src/import/tui/runLivePreview.d.ts +3 -0
- package/dist/src/import/tui/runLivePreview.js +4 -1
- package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +2 -1
- package/dist/src/import/tui/steps/GenerateReviewStep.js +3 -3
- package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +6 -2
- package/dist/src/import/tui/steps/WizardPreviewStep.js +12 -3
- package/dist/src/import/tui/useFinalizePreview.d.ts +2 -0
- package/dist/src/import/tui/useFinalizePreview.js +0 -0
- package/dist/src/import/tui/useLivePreview.d.ts +2 -0
- package/dist/src/import/tui/useLivePreview.js +1 -0
- package/dist/src/index.js +1 -5
- package/dist/src/lib/command-options.d.ts +1 -0
- package/dist/src/lib/command-options.js +3 -0
- package/dist/src/program.js +1 -8
- package/dist/src/runs/modify-launcher.d.ts +2 -0
- package/dist/src/runs/modify-launcher.js +2 -0
- package/dist/src/runs/push-helpers.d.ts +1 -0
- package/dist/src/runs/push-helpers.js +3 -0
- package/dist/src/runs/replay-helpers.d.ts +4 -0
- package/dist/src/runs/replay-helpers.js +3 -0
- package/package.json +5 -6
- package/dist/src/analytics/apply.d.ts +0 -6
- package/dist/src/analytics/apply.js +0 -30
- package/dist/src/analytics/client.d.ts +0 -3
- package/dist/src/analytics/client.js +0 -39
- package/dist/src/analytics/index.d.ts +0 -6
- package/dist/src/analytics/index.js +0 -5
- package/dist/src/analytics/normalize.d.ts +0 -3
- package/dist/src/analytics/normalize.js +0 -17
- package/dist/src/analytics/os.d.ts +0 -2
- package/dist/src/analytics/os.js +0 -13
- package/dist/src/analytics/tracker.d.ts +0 -19
- package/dist/src/analytics/tracker.js +0 -157
- package/dist/src/analytics/types.d.ts +0 -29
- package/dist/src/analytics/types.js +0 -1
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. Without this flag, preview responses suppress the removed-entity list and return a count instead; interactive confirm screens show an opt-out toggle (never opt-in) only when the flag is passed. 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
|
|
|
@@ -450,29 +451,6 @@ Wizard run history is separate: `~/.config/experiences/runs.json`.
|
|
|
450
451
|
|
|
451
452
|
---
|
|
452
453
|
|
|
453
|
-
## Usage data
|
|
454
|
-
|
|
455
|
-
The CLI collects **anonymous usage data** to help us understand which commands are used and where the import workflow succeeds or fails. This data does **not** include your source code, file paths, credentials, prompts, or any content you author.
|
|
456
|
-
|
|
457
|
-
What may be included:
|
|
458
|
-
|
|
459
|
-
- Command name and duration
|
|
460
|
-
- CLI, Node.js, and operating-system version
|
|
461
|
-
- Anonymous session identifiers that link steps within a single import run
|
|
462
|
-
- Structural counts (for example, how many components were extracted or accepted)
|
|
463
|
-
- Space and environment IDs you pass on the command line
|
|
464
|
-
- Contentful request IDs from API responses (to correlate failures with server logs)
|
|
465
|
-
|
|
466
|
-
You can turn this off at any time:
|
|
467
|
-
|
|
468
|
-
```bash
|
|
469
|
-
DISABLE_ANALYTICS=1 experiences import --project ./my-app
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
Setting `DISABLE_ANALYTICS` to any value disables collection for that invocation.
|
|
473
|
-
|
|
474
|
-
---
|
|
475
|
-
|
|
476
454
|
## Development
|
|
477
455
|
|
|
478
456
|
```bash
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/experience-design-system-cli",
|
|
3
|
-
"version": "2.23.2-dev-build-
|
|
3
|
+
"version": "2.23.2-dev-build-09d87bb.0",
|
|
4
4
|
"description": "Contentful Experiences design system import CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,7 +41,6 @@
|
|
|
41
41
|
"@contentful/experience-design-system-extraction": "workspace:*",
|
|
42
42
|
"@contentful/experience-design-system-generation": "workspace:*",
|
|
43
43
|
"@contentful/experience-design-system-types": "workspace:*",
|
|
44
|
-
"@segment/analytics-node": "^3.0.0",
|
|
45
44
|
"commander": "^13.1.0",
|
|
46
45
|
"ink": "^4.4.1",
|
|
47
46
|
"react": "^18.3.1",
|
|
@@ -24,7 +24,6 @@ import { DEFAULT_AGENT_NAME, isAgentName, runAgent, } from '@contentful/experien
|
|
|
24
24
|
import { readExperiencesCredentials } from '../credentials-store.js';
|
|
25
25
|
import { buildAnalyzeViewRows, partitionGlobalWarnings } from './build-analyze-view-rows.js';
|
|
26
26
|
import { getInteractiveTerminalSupport } from '../lib/terminal-capabilities.js';
|
|
27
|
-
import { bindAnalyticsSession, emitSessionStarted, enrichCommandResult } from '../analytics/index.js';
|
|
28
27
|
import { getDebugLogger } from '../lib/debug-logger.js';
|
|
29
28
|
const SCANNED_FILE_EXTENSIONS = new Set(['.astro', '.js', '.jsx', '.svelte', '.ts', '.tsx', '.vue']);
|
|
30
29
|
/**
|
|
@@ -265,8 +264,6 @@ export function registerAnalyzeCommand(program) {
|
|
|
265
264
|
inputPath: projectRoot,
|
|
266
265
|
outDir,
|
|
267
266
|
});
|
|
268
|
-
await bindAnalyticsSession(sessionId);
|
|
269
|
-
await emitSessionStarted('analyze_extract');
|
|
270
267
|
const stepId = createStep(db, sessionId, 'analyze extract', {
|
|
271
268
|
project: projectRoot,
|
|
272
269
|
});
|
|
@@ -540,7 +537,6 @@ export function registerAnalyzeCommand(program) {
|
|
|
540
537
|
storeSlotCycles(db, sessionId, withBreaks);
|
|
541
538
|
storeScannedFiles(db, sessionId, sourceFiles.map((f) => relative(projectRoot, f)));
|
|
542
539
|
updateStep(db, stepId, 'complete', { sessionId });
|
|
543
|
-
enrichCommandResult({ extracted_component_count: validatedComponents.length });
|
|
544
540
|
db.close();
|
|
545
541
|
const allWarnings = [...extraction.warnings, ...filterWarnings];
|
|
546
542
|
const { rows: componentRows, totalErrors } = buildAnalyzeViewRows(filteredComponents, validatedComponents, allWarnings);
|
|
@@ -80,7 +80,10 @@ export function App({ sessionId, artifactsRoot, reviewRoot }) {
|
|
|
80
80
|
if (!manifest.componentsManifest)
|
|
81
81
|
manifest.componentsManifest = {};
|
|
82
82
|
const client = new ImportApiClient({ cmaToken, spaceId, environmentId });
|
|
83
|
-
|
|
83
|
+
// This preview is display-only (component-picker annotations); it never
|
|
84
|
+
// triggers an apply, so always request the full diff to keep the
|
|
85
|
+
// existing "removed" annotation working.
|
|
86
|
+
const preview = await client.previewImport(manifest, true);
|
|
84
87
|
const annotations = {};
|
|
85
88
|
for (const item of preview.components.new) {
|
|
86
89
|
const name = item.name ?? '';
|
|
@@ -45,17 +45,17 @@ export declare class ImportApiClient {
|
|
|
45
45
|
private spaceId;
|
|
46
46
|
private environmentId;
|
|
47
47
|
private retry;
|
|
48
|
-
private lastRequestId?;
|
|
49
|
-
getLastRequestId(): string | undefined;
|
|
50
|
-
private noteRequestId;
|
|
51
48
|
constructor(opts: ApiClientOptions);
|
|
52
49
|
private base;
|
|
53
50
|
private headers;
|
|
54
51
|
private requestWithRetry;
|
|
55
52
|
validateToken(): Promise<void>;
|
|
56
53
|
checkPreflight(): Promise<void>;
|
|
57
|
-
previewImport(manifest: ManifestPayload): Promise<ServerPreviewResponse>;
|
|
58
|
-
applyImport(manifest: ManifestPayload,
|
|
54
|
+
previewImport(manifest: ManifestPayload, allowDeletions?: boolean): Promise<ServerPreviewResponse>;
|
|
55
|
+
applyImport(manifest: ManifestPayload, options: {
|
|
56
|
+
acknowledgeBreakingChanges: boolean;
|
|
57
|
+
allowDeletions?: boolean;
|
|
58
|
+
}): Promise<ApplyOperationResponse>;
|
|
59
59
|
pollOperation(operationId: string, opts?: {
|
|
60
60
|
intervalMs?: number;
|
|
61
61
|
maxIntervalMs?: number;
|
|
@@ -180,15 +180,6 @@ export class ImportApiClient {
|
|
|
180
180
|
spaceId;
|
|
181
181
|
environmentId;
|
|
182
182
|
retry;
|
|
183
|
-
lastRequestId;
|
|
184
|
-
getLastRequestId() {
|
|
185
|
-
return this.lastRequestId;
|
|
186
|
-
}
|
|
187
|
-
noteRequestId(response) {
|
|
188
|
-
const requestId = response.headers.get('x-contentful-request-id');
|
|
189
|
-
if (requestId)
|
|
190
|
-
this.lastRequestId = requestId;
|
|
191
|
-
}
|
|
192
183
|
constructor(opts) {
|
|
193
184
|
this.host = toApiHost(opts.host);
|
|
194
185
|
this.token = opts.cmaToken;
|
|
@@ -246,10 +237,8 @@ export class ImportApiClient {
|
|
|
246
237
|
await this.retry.sleep(delayMs);
|
|
247
238
|
continue;
|
|
248
239
|
}
|
|
249
|
-
if (!isTransientStatus(result.response.status))
|
|
250
|
-
this.noteRequestId(result.response);
|
|
240
|
+
if (!isTransientStatus(result.response.status))
|
|
251
241
|
return result;
|
|
252
|
-
}
|
|
253
242
|
if (attempt === this.retry.maxAttempts) {
|
|
254
243
|
const body = stringifyError(result.error);
|
|
255
244
|
const guidance = `The ${phase} request failed after ${attempt} attempts because the service remained unavailable. ` +
|
|
@@ -284,7 +273,6 @@ export class ImportApiClient {
|
|
|
284
273
|
// false positives that don't apply to the design-systems API authorization path.
|
|
285
274
|
const url = `${this.host}/users/me`;
|
|
286
275
|
const res = await request(url, { token: this.token });
|
|
287
|
-
this.noteRequestId(res);
|
|
288
276
|
if (res.status === 401) {
|
|
289
277
|
throw new ApiError('CMA token is invalid or revoked', res.status, await res.text());
|
|
290
278
|
}
|
|
@@ -310,7 +298,6 @@ export class ImportApiClient {
|
|
|
310
298
|
catch {
|
|
311
299
|
return; // network error — don't block; the real call will surface it
|
|
312
300
|
}
|
|
313
|
-
this.noteRequestId(res);
|
|
314
301
|
if (res.ok)
|
|
315
302
|
return;
|
|
316
303
|
if (res.status >= 500)
|
|
@@ -320,19 +307,20 @@ export class ImportApiClient {
|
|
|
320
307
|
return; // legacy backend without the endpoint
|
|
321
308
|
throw new ApiError(`preflight failed: ${res.status}`, res.status, body);
|
|
322
309
|
}
|
|
323
|
-
async previewImport(manifest) {
|
|
310
|
+
async previewImport(manifest, allowDeletions = false) {
|
|
324
311
|
const debug = getDebugLogger();
|
|
325
312
|
const startedAt = Date.now();
|
|
326
313
|
debug.event('apply', 'preview.request', {
|
|
327
314
|
url: `${this.base()}/design_systems/imports/preview`,
|
|
328
315
|
componentCount: manifest.components?.length ?? 0,
|
|
329
316
|
tokenCount: manifest.designTokens?.length ?? 0,
|
|
317
|
+
allowDeletions,
|
|
330
318
|
});
|
|
331
319
|
const result = await this.requestWithRetry('preview', PREVIEW_ERROR_PREFIX, () => designSystemImportSourcelessPreview({
|
|
332
320
|
baseUrl: this.host,
|
|
333
321
|
headers: this.headers(),
|
|
334
322
|
path: { spaceId: this.spaceId, environmentId: this.environmentId },
|
|
335
|
-
body: manifest,
|
|
323
|
+
body: { ...manifest, allowDeletions },
|
|
336
324
|
parseAs: 'json',
|
|
337
325
|
}));
|
|
338
326
|
if (!result.response.ok) {
|
|
@@ -348,12 +336,14 @@ export class ImportApiClient {
|
|
|
348
336
|
debug.event('apply', 'preview.ok', { status: result.response.status, durationMs: Date.now() - startedAt });
|
|
349
337
|
return sanitizePreviewResponse(parsed);
|
|
350
338
|
}
|
|
351
|
-
async applyImport(manifest,
|
|
339
|
+
async applyImport(manifest, options) {
|
|
340
|
+
const { acknowledgeBreakingChanges, allowDeletions = false } = options;
|
|
352
341
|
const debug = getDebugLogger();
|
|
353
342
|
const startedAt = Date.now();
|
|
354
343
|
debug.event('apply', 'apply.request', {
|
|
355
344
|
url: `${this.base()}/design_systems/imports/apply`,
|
|
356
345
|
acknowledgeBreakingChanges,
|
|
346
|
+
allowDeletions,
|
|
357
347
|
});
|
|
358
348
|
let result;
|
|
359
349
|
try {
|
|
@@ -361,7 +351,7 @@ export class ImportApiClient {
|
|
|
361
351
|
baseUrl: this.host,
|
|
362
352
|
headers: this.headers(),
|
|
363
353
|
path: { spaceId: this.spaceId, environmentId: this.environmentId },
|
|
364
|
-
body: { ...manifest, acknowledgeBreakingChanges },
|
|
354
|
+
body: { ...manifest, acknowledgeBreakingChanges, allowDeletions },
|
|
365
355
|
parseAs: 'json',
|
|
366
356
|
});
|
|
367
357
|
}
|
|
@@ -12,13 +12,11 @@ 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 { addArtifactInputOptions, addCompositionOptions, addContentfulTargetOptions, addSelectionOptions, } from '../lib/command-options.js';
|
|
15
|
+
import { addAllowDeletionsOption, 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';
|
|
19
|
-
import { bindAnalyticsSessionId, completeActiveCommand, failActiveCommand, recordApplyOutcome, recordContentfulContext, } from '../analytics/index.js';
|
|
20
19
|
function die(message) {
|
|
21
|
-
void failActiveCommand({ exit_code: 1 });
|
|
22
20
|
process.stderr.write(`${message}\n`);
|
|
23
21
|
process.exit(1);
|
|
24
22
|
}
|
|
@@ -433,12 +431,6 @@ export function registerApplyCommand(program) {
|
|
|
433
431
|
throw e;
|
|
434
432
|
}
|
|
435
433
|
const { components, tokens, client } = inputs;
|
|
436
|
-
const spaceId = opts.spaceId;
|
|
437
|
-
const environmentId = opts.environmentId;
|
|
438
|
-
await bindAnalyticsSessionId(opts.session, {
|
|
439
|
-
space_key: spaceId,
|
|
440
|
-
environment_key: environmentId,
|
|
441
|
-
});
|
|
442
434
|
try {
|
|
443
435
|
await client.validateToken();
|
|
444
436
|
}
|
|
@@ -458,12 +450,14 @@ export function registerApplyCommand(program) {
|
|
|
458
450
|
die(`Error: ${formatApiError(e)}`);
|
|
459
451
|
throw e;
|
|
460
452
|
}
|
|
461
|
-
|
|
453
|
+
const spaceId = opts.spaceId;
|
|
454
|
+
const environmentId = opts.environmentId;
|
|
462
455
|
if (getInteractiveTerminalSupport().supported) {
|
|
463
456
|
const { waitUntilExit } = render(createElement(ServerPreviewApp, {
|
|
464
457
|
preview,
|
|
465
458
|
spaceId,
|
|
466
459
|
environmentId,
|
|
460
|
+
allowDeletions: false,
|
|
467
461
|
}));
|
|
468
462
|
await waitUntilExit();
|
|
469
463
|
}
|
|
@@ -476,6 +470,7 @@ export function registerApplyCommand(program) {
|
|
|
476
470
|
addArtifactInputOptions(pushCmd);
|
|
477
471
|
addContentfulTargetOptions(pushCmd);
|
|
478
472
|
addCompositionOptions(pushCmd);
|
|
473
|
+
addAllowDeletionsOption(pushCmd);
|
|
479
474
|
pushCmd
|
|
480
475
|
.option('--yes', 'Skip interactive confirmation')
|
|
481
476
|
.option('--verbose', 'Show all entity progress including skipped/unchanged')
|
|
@@ -497,12 +492,6 @@ export function registerApplyCommand(program) {
|
|
|
497
492
|
throw e;
|
|
498
493
|
}
|
|
499
494
|
const { components, tokens, client } = inputs;
|
|
500
|
-
const spaceId = opts.spaceId;
|
|
501
|
-
const environmentId = opts.environmentId;
|
|
502
|
-
await bindAnalyticsSessionId(opts.session, {
|
|
503
|
-
space_key: spaceId,
|
|
504
|
-
environment_key: environmentId,
|
|
505
|
-
});
|
|
506
495
|
assertNoSlotCycles(components);
|
|
507
496
|
try {
|
|
508
497
|
await client.validateToken();
|
|
@@ -515,19 +504,22 @@ export function registerApplyCommand(program) {
|
|
|
515
504
|
const manifest = buildManifest(components, tokens);
|
|
516
505
|
let preview;
|
|
517
506
|
try {
|
|
518
|
-
preview = await client.previewImport(manifest);
|
|
507
|
+
preview = await client.previewImport(manifest, opts.allowDeletions === true);
|
|
519
508
|
}
|
|
520
509
|
catch (e) {
|
|
521
510
|
if (e instanceof ApiError)
|
|
522
511
|
die(`Error: ${formatApiError(e, opts.verbose)}`);
|
|
523
512
|
throw e;
|
|
524
513
|
}
|
|
514
|
+
const spaceId = opts.spaceId;
|
|
515
|
+
const environmentId = opts.environmentId;
|
|
525
516
|
if (opts.dryRun) {
|
|
526
517
|
if (isTTY) {
|
|
527
518
|
const { waitUntilExit } = render(createElement(ServerPreviewApp, {
|
|
528
519
|
preview,
|
|
529
520
|
spaceId,
|
|
530
521
|
environmentId,
|
|
522
|
+
allowDeletions: opts.allowDeletions === true,
|
|
531
523
|
}));
|
|
532
524
|
await waitUntilExit();
|
|
533
525
|
}
|
|
@@ -558,7 +550,10 @@ export function registerApplyCommand(program) {
|
|
|
558
550
|
}
|
|
559
551
|
let operation;
|
|
560
552
|
try {
|
|
561
|
-
operation = await client.applyImport(manifest,
|
|
553
|
+
operation = await client.applyImport(manifest, {
|
|
554
|
+
acknowledgeBreakingChanges: breakingWithImpact || opts.force === true,
|
|
555
|
+
allowDeletions: opts.allowDeletions === true,
|
|
556
|
+
});
|
|
562
557
|
}
|
|
563
558
|
catch (e) {
|
|
564
559
|
if (e instanceof ApiError)
|
|
@@ -575,18 +570,12 @@ export function registerApplyCommand(program) {
|
|
|
575
570
|
throw e;
|
|
576
571
|
}
|
|
577
572
|
const summary = buildApplyOutput(operation, spaceId, environmentId, opts.host);
|
|
578
|
-
recordApplyOutcome(client, spaceId, environmentId, operation);
|
|
579
573
|
process.stdout.write(JSON.stringify(summary, null, 2) + '\n');
|
|
580
|
-
|
|
581
|
-
if (exitCode === 0)
|
|
582
|
-
await completeActiveCommand();
|
|
583
|
-
else
|
|
584
|
-
await failActiveCommand({ exit_code: exitCode });
|
|
585
|
-
process.exit(exitCode);
|
|
574
|
+
process.exit(operation.sys.status === 'succeeded' ? 0 : 1);
|
|
586
575
|
return;
|
|
587
576
|
}
|
|
588
577
|
await new Promise((resolvePromise) => {
|
|
589
|
-
const runApply = async (acknowledge) => {
|
|
578
|
+
const runApply = async (acknowledge, applyDeletions) => {
|
|
590
579
|
instance.rerender(createElement(ServerApplyProgress, {
|
|
591
580
|
spaceId,
|
|
592
581
|
environmentId,
|
|
@@ -594,7 +583,10 @@ export function registerApplyCommand(program) {
|
|
|
594
583
|
}));
|
|
595
584
|
let operation;
|
|
596
585
|
try {
|
|
597
|
-
operation = await client.applyImport(manifest,
|
|
586
|
+
operation = await client.applyImport(manifest, {
|
|
587
|
+
acknowledgeBreakingChanges: acknowledge,
|
|
588
|
+
allowDeletions: applyDeletions,
|
|
589
|
+
});
|
|
598
590
|
}
|
|
599
591
|
catch (e) {
|
|
600
592
|
if (e instanceof ApiError) {
|
|
@@ -642,8 +634,9 @@ export function registerApplyCommand(program) {
|
|
|
642
634
|
spaceId,
|
|
643
635
|
environmentId,
|
|
644
636
|
breakingWithImpact,
|
|
645
|
-
|
|
646
|
-
|
|
637
|
+
allowDeletions: opts.allowDeletions === true,
|
|
638
|
+
onConfirm: (acknowledge, applyDeletions) => {
|
|
639
|
+
void runApply(acknowledge, applyDeletions);
|
|
647
640
|
},
|
|
648
641
|
onCancel: () => {
|
|
649
642
|
process.exit(0);
|
|
@@ -657,6 +650,7 @@ export function registerApplyCommand(program) {
|
|
|
657
650
|
addContentfulTargetOptions(selectCmd);
|
|
658
651
|
addCompositionOptions(selectCmd);
|
|
659
652
|
addSelectionOptions(selectCmd);
|
|
653
|
+
addAllowDeletionsOption(selectCmd);
|
|
660
654
|
selectCmd.option('--force', 'Skip confirmation for breaking changes').action(async (opts) => {
|
|
661
655
|
const nonInteractive = opts.selectAll || (opts.select ?? []).length > 0 || (opts.deselect ?? []).length > 0;
|
|
662
656
|
if (!nonInteractive) {
|
|
@@ -686,7 +680,7 @@ export function registerApplyCommand(program) {
|
|
|
686
680
|
const fullManifest = buildManifest(components, tokens);
|
|
687
681
|
let preview;
|
|
688
682
|
try {
|
|
689
|
-
preview = await client.previewImport(fullManifest);
|
|
683
|
+
preview = await client.previewImport(fullManifest, opts.allowDeletions === true);
|
|
690
684
|
}
|
|
691
685
|
catch (e) {
|
|
692
686
|
if (e instanceof ApiError)
|
|
@@ -724,7 +718,10 @@ export function registerApplyCommand(program) {
|
|
|
724
718
|
}
|
|
725
719
|
let operation;
|
|
726
720
|
try {
|
|
727
|
-
operation = await client.applyImport(filteredManifest,
|
|
721
|
+
operation = await client.applyImport(filteredManifest, {
|
|
722
|
+
acknowledgeBreakingChanges: hasBreaking || opts.force === true,
|
|
723
|
+
allowDeletions: opts.allowDeletions === true,
|
|
724
|
+
});
|
|
728
725
|
}
|
|
729
726
|
catch (e) {
|
|
730
727
|
if (e instanceof ApiError)
|
|
@@ -766,7 +763,10 @@ export function registerApplyCommand(program) {
|
|
|
766
763
|
}));
|
|
767
764
|
let operation;
|
|
768
765
|
try {
|
|
769
|
-
operation = await client.applyImport(filteredManifest,
|
|
766
|
+
operation = await client.applyImport(filteredManifest, {
|
|
767
|
+
acknowledgeBreakingChanges: hasBreaking,
|
|
768
|
+
allowDeletions: opts.allowDeletions === true,
|
|
769
|
+
});
|
|
770
770
|
}
|
|
771
771
|
catch (e) {
|
|
772
772
|
if (e instanceof ApiError) {
|
|
@@ -7,6 +7,10 @@ import type { ServerPreviewResponse } from '@contentful/experience-design-system
|
|
|
7
7
|
* would be a pure no-op (INTEG-4411 refined guard).
|
|
8
8
|
*
|
|
9
9
|
* A push that produces ANY entry in ANY bucket — including a rejection that
|
|
10
|
-
* removes a server-side component — is NOT empty.
|
|
10
|
+
* removes a server-side component — is NOT empty. Note the server hides
|
|
11
|
+
* removals entirely (empty removed[]) unless the preview was fetched with
|
|
12
|
+
* allowDeletions: true, so "empty" here also correctly describes a preview
|
|
13
|
+
* with pending-but-hidden deletions: pushing without --allow-deletions is a
|
|
14
|
+
* genuine no-op in that case too, since the apply gate hides them the same way.
|
|
11
15
|
*/
|
|
12
16
|
export declare function isEmptyPreview(preview: ServerPreviewResponse): boolean;
|
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
* would be a pure no-op (INTEG-4411 refined guard).
|
|
7
7
|
*
|
|
8
8
|
* A push that produces ANY entry in ANY bucket — including a rejection that
|
|
9
|
-
* removes a server-side component — is NOT empty.
|
|
9
|
+
* removes a server-side component — is NOT empty. Note the server hides
|
|
10
|
+
* removals entirely (empty removed[]) unless the preview was fetched with
|
|
11
|
+
* allowDeletions: true, so "empty" here also correctly describes a preview
|
|
12
|
+
* with pending-but-hidden deletions: pushing without --allow-deletions is a
|
|
13
|
+
* genuine no-op in that case too, since the apply gate hides them the same way.
|
|
10
14
|
*/
|
|
11
15
|
export function isEmptyPreview(preview) {
|
|
12
16
|
const { components, tokens, taxonomies } = preview;
|
|
@@ -5,16 +5,19 @@ interface ServerPreviewConfirmProps {
|
|
|
5
5
|
spaceId: string;
|
|
6
6
|
environmentId: string;
|
|
7
7
|
breakingWithImpact: boolean;
|
|
8
|
-
|
|
8
|
+
/** The value the preview was actually fetched with. */
|
|
9
|
+
allowDeletions: boolean;
|
|
10
|
+
onConfirm: (acknowledge: boolean, allowDeletions: boolean) => void;
|
|
9
11
|
onCancel: () => void;
|
|
10
12
|
}
|
|
11
|
-
export declare function ServerPreviewConfirm({ preview, spaceId, environmentId, breakingWithImpact, onConfirm, onCancel, }: ServerPreviewConfirmProps): React.ReactElement;
|
|
13
|
+
export declare function ServerPreviewConfirm({ preview, spaceId, environmentId, breakingWithImpact, allowDeletions: fetchedAllowDeletions, onConfirm, onCancel, }: ServerPreviewConfirmProps): React.ReactElement;
|
|
12
14
|
interface ServerPreviewAppProps {
|
|
13
15
|
preview: ServerPreviewResponse;
|
|
14
16
|
spaceId: string;
|
|
15
17
|
environmentId: string;
|
|
18
|
+
allowDeletions: boolean;
|
|
16
19
|
}
|
|
17
|
-
export declare function ServerPreviewApp({ preview, spaceId, environmentId }: ServerPreviewAppProps): React.ReactElement;
|
|
20
|
+
export declare function ServerPreviewApp({ preview, spaceId, environmentId, allowDeletions, }: ServerPreviewAppProps): React.ReactElement;
|
|
18
21
|
interface ServerApplyProgressProps {
|
|
19
22
|
spaceId: string;
|
|
20
23
|
environmentId: string;
|
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
2
3
|
import { Box, Text, useInput } from 'ink';
|
|
3
4
|
import { ServerPreviewView } from './ServerPreviewView.js';
|
|
4
5
|
import { buildPostPushUrl } from '../../lib/contentful-urls.js';
|
|
5
6
|
import { formatEdsiError } from '../../lib/error-parser.js';
|
|
6
|
-
export function ServerPreviewConfirm({ preview, spaceId, environmentId, breakingWithImpact, onConfirm, onCancel, }) {
|
|
7
|
+
export function ServerPreviewConfirm({ preview, spaceId, environmentId, breakingWithImpact, allowDeletions: fetchedAllowDeletions, onConfirm, onCancel, }) {
|
|
8
|
+
const [allowDeletions, setAllowDeletions] = useState(fetchedAllowDeletions);
|
|
9
|
+
const removedCount = preview.components.removed.length + preview.tokens.removed.length;
|
|
7
10
|
useInput((input, key) => {
|
|
8
|
-
if (key.return)
|
|
9
|
-
onConfirm(breakingWithImpact);
|
|
11
|
+
if (key.return) {
|
|
12
|
+
onConfirm(breakingWithImpact, allowDeletions);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if ((input === 'x' || input === 'X') && fetchedAllowDeletions && removedCount > 0) {
|
|
16
|
+
setAllowDeletions((prev) => !prev);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
10
19
|
if (key.escape || input === 'q')
|
|
11
20
|
onCancel();
|
|
12
21
|
});
|
|
13
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(ServerPreviewView, { preview: preview, spaceId: spaceId, environmentId: environmentId }), _jsxs(Box, { paddingX: 2, flexDirection: "column", children: [breakingWithImpact && (_jsxs(Text, { color: "red", bold: true, children: [' ', "\u26A0 Breaking changes will affect downstream entities. Press Enter to acknowledge and apply."] })), _jsxs(Text, { children: [' ', "Press ", _jsx(Text, { bold: true, children: "Enter" }), " to apply, ", _jsx(Text, { bold: true, children: "Esc" }), " to cancel"] })] })] }));
|
|
22
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(ServerPreviewView, { preview: preview, spaceId: spaceId, environmentId: environmentId, allowDeletions: allowDeletions }), _jsxs(Box, { paddingX: 2, flexDirection: "column", children: [breakingWithImpact && (_jsxs(Text, { color: "red", bold: true, children: [' ', "\u26A0 Breaking changes will affect downstream entities. Press Enter to acknowledge and apply."] })), allowDeletions && removedCount > 0 && (_jsxs(Text, { color: "red", bold: true, children: [' ', "\u26A0 ", removedCount, " missing ", removedCount === 1 ? 'entity' : 'entities', " will be permanently deleted. Press Enter to confirm."] })), fetchedAllowDeletions && removedCount > 0 && (_jsxs(Text, { dimColor: true, children: [" [x] ", allowDeletions ? '[✓]' : '[ ]', " Allow deletions"] })), _jsxs(Text, { children: [' ', "Press ", _jsx(Text, { bold: true, children: "Enter" }), " to apply, ", _jsx(Text, { bold: true, children: "Esc" }), " to cancel"] })] })] }));
|
|
14
23
|
}
|
|
15
|
-
export function ServerPreviewApp({ preview, spaceId, environmentId }) {
|
|
24
|
+
export function ServerPreviewApp({ preview, spaceId, environmentId, allowDeletions, }) {
|
|
16
25
|
useInput((input, key) => {
|
|
17
26
|
if (key.escape || input === 'q')
|
|
18
27
|
process.exit(0);
|
|
19
28
|
});
|
|
20
|
-
return _jsx(ServerPreviewView, { preview: preview, spaceId: spaceId, environmentId: environmentId });
|
|
29
|
+
return (_jsx(ServerPreviewView, { preview: preview, spaceId: spaceId, environmentId: environmentId, allowDeletions: allowDeletions }));
|
|
21
30
|
}
|
|
22
31
|
export function ServerApplyProgress({ spaceId, environmentId, status, operationId, error, }) {
|
|
23
32
|
useInput((_input, key) => {
|
|
@@ -4,6 +4,7 @@ interface ServerPreviewViewProps {
|
|
|
4
4
|
preview: ServerPreviewResponse;
|
|
5
5
|
spaceId: string;
|
|
6
6
|
environmentId: string;
|
|
7
|
+
allowDeletions: boolean;
|
|
7
8
|
}
|
|
8
|
-
export declare function ServerPreviewView({ preview, spaceId, environmentId }: ServerPreviewViewProps): React.ReactElement;
|
|
9
|
+
export declare function ServerPreviewView({ preview, spaceId, environmentId, allowDeletions, }: ServerPreviewViewProps): React.ReactElement;
|
|
9
10
|
export {};
|
|
@@ -13,11 +13,11 @@ function DraftWarning({ hasDraft }) {
|
|
|
13
13
|
return null;
|
|
14
14
|
return _jsx(Text, { color: "yellow", children: " \u26A1 has pending draft changes" });
|
|
15
15
|
}
|
|
16
|
-
export function ServerPreviewView({ preview, spaceId, environmentId }) {
|
|
16
|
+
export function ServerPreviewView({ preview, spaceId, environmentId, allowDeletions, }) {
|
|
17
17
|
const { components, tokens } = preview;
|
|
18
18
|
const totalComponents = components.new.length + components.changed.length + components.unchanged.length + components.removed.length;
|
|
19
19
|
const totalTokens = tokens.new.length + tokens.changed.length + tokens.unchanged.length + tokens.removed.length;
|
|
20
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsxs(Text, { bold: true, children: ["Preview \u2014 ", environmentId, " @ ", spaceId] }), _jsx(Text, { children: " " }), totalComponents > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { bold: true, children: [" Component Types (", totalComponents, " total)"] }), _jsxs(Text, { color: "green", children: [" \u2746 ", components.new.length, " to create"] }), _jsxs(Text, { color: "yellow", children: [" ~ ", components.changed.length, " to update"] }), _jsxs(Text, { color:
|
|
20
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsxs(Text, { bold: true, children: ["Preview \u2014 ", environmentId, " @ ", spaceId] }), _jsx(Text, { children: " " }), totalComponents > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { bold: true, children: [" Component Types (", totalComponents, " total)"] }), _jsxs(Text, { color: "green", children: [" \u2746 ", components.new.length, " to create"] }), _jsxs(Text, { color: "yellow", children: [" ~ ", components.changed.length, " to update"] }), _jsxs(Text, { color: allowDeletions ? 'red' : 'yellow', children: [' ', allowDeletions ? '✗' : '⊘', " ", components.removed.length, " to ", allowDeletions ? 'delete' : 'skip'] }), _jsxs(Text, { dimColor: true, children: [" \u00B7 ", components.unchanged.length, " unchanged"] }), components.changed.map((item, i) => (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { flexDirection: "row", children: [_jsxs(Text, { color: "yellow", children: [" ~ ", item.current.name] }), _jsx(DraftWarning, { hasDraft: item.hasPendingDraftChanges })] }), _jsx(BreakingBadge, { item: item })] }, i))), _jsx(Text, { children: " " })] })), totalTokens > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { bold: true, children: [" Design Tokens (", totalTokens, " total)"] }), _jsxs(Text, { color: "green", children: [" \u2746 ", tokens.new.length, " to create"] }), _jsxs(Text, { color: "yellow", children: [" ~ ", tokens.changed.length, " to update"] }), _jsxs(Text, { color: allowDeletions ? 'red' : 'yellow', children: [' ', allowDeletions ? '✗' : '⊘', " ", tokens.removed.length, " to ", allowDeletions ? 'delete' : 'skip'] }), _jsxs(Text, { dimColor: true, children: [" \u00B7 ", tokens.unchanged.length, " unchanged"] }), tokens.changed
|
|
21
21
|
.filter((t) => t.hasPendingDraftChanges)
|
|
22
|
-
.map((item, i) => (_jsxs(Box, { flexDirection: "row", children: [_jsxs(Text, { color: "yellow", children: [" ~ ", item.current.name] }), _jsx(DraftWarning, { hasDraft: true })] }, i))), _jsx(Text, { children: " " })] })), _jsx(Text, { dimColor: true, children: " Press Q to exit." })] }));
|
|
22
|
+
.map((item, i) => (_jsxs(Box, { flexDirection: "row", children: [_jsxs(Text, { color: "yellow", children: [" ~ ", item.current.name] }), _jsx(DraftWarning, { hasDraft: true })] }, i))), _jsx(Text, { children: " " })] })), !allowDeletions && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "yellow", children: " \u2298 Deletions are hidden by default \u2014 rerun with --allow-deletions to see them." }) })), _jsx(Text, { dimColor: true, children: " Press Q to exit." })] }));
|
|
23
23
|
}
|
|
@@ -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 { addCompositionOptions } from '../lib/command-options.js';
|
|
7
|
+
import { addAllowDeletionsOption, 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,6 +46,7 @@ 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);
|
|
49
50
|
cmd
|
|
50
51
|
.option('--composition-map <path>', 'Consume a hand-authored parent→children interchange map (implies --composite)')
|
|
51
52
|
.option('--composition-agent', 'Opt into agentic mapping resolution when deterministic sources find no groups (implies --composite)')
|
|
@@ -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;
|
|
@@ -7,7 +7,6 @@ import { detectSlotCycles, formatSlotCycleReport } from '../apply/command.js';
|
|
|
7
7
|
import { PREVIEW_ERROR_PREFIX, VALIDATION_FAILED_CODE, parsePreviewValidationErrors } from '../apply/api-client.js';
|
|
8
8
|
import { buildPostPushUrl } from '../lib/contentful-urls.js';
|
|
9
9
|
import { getDebugLogger, debugEnvForSubprocess } from '../lib/debug-logger.js';
|
|
10
|
-
import { bindAnalyticsSession, emitSessionStarted } from '../analytics/index.js';
|
|
11
10
|
function findCliPath() {
|
|
12
11
|
return join(fileURLToPath(import.meta.url), '..', '..', '..', '..', 'bin', 'cli.js');
|
|
13
12
|
}
|
|
@@ -17,7 +16,7 @@ async function runStep(args, cliPath, env = {}, streamStderr = false) {
|
|
|
17
16
|
debug.event('import', 'subprocess.spawn', { cliPath, args });
|
|
18
17
|
return new Promise((res) => {
|
|
19
18
|
const child = execFile('node', [cliPath, ...args], {
|
|
20
|
-
env: debugEnvForSubprocess({ ...process.env, ...env
|
|
19
|
+
env: debugEnvForSubprocess({ ...process.env, ...env }),
|
|
21
20
|
});
|
|
22
21
|
let stdout = '';
|
|
23
22
|
let stderr = '';
|
|
@@ -109,10 +108,6 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
|
|
|
109
108
|
inputPath: projectRoot,
|
|
110
109
|
outDir,
|
|
111
110
|
});
|
|
112
|
-
await bindAnalyticsSession(sessionId, {
|
|
113
|
-
...(opts.spaceId ? { space_key: opts.spaceId, environment_key: opts.environmentId } : {}),
|
|
114
|
-
});
|
|
115
|
-
await emitSessionStarted('import');
|
|
116
111
|
progressWriter(`Experience Design System CLI — Pipeline Import`);
|
|
117
112
|
progressWriter(`Project: ${projectRoot}`);
|
|
118
113
|
progressWriter(`Output: ${outDir}`);
|
|
@@ -423,6 +418,8 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
|
|
|
423
418
|
pushArgs.push('--host', opts.host);
|
|
424
419
|
if (opts.verbose)
|
|
425
420
|
pushArgs.push('--verbose');
|
|
421
|
+
if (opts.allowDeletions)
|
|
422
|
+
pushArgs.push('--allow-deletions');
|
|
426
423
|
pushArgs.push('--yes');
|
|
427
424
|
const pushStepId = createStep(db, sessionId, 'apply push', {
|
|
428
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;
|