@contentful/experience-design-system-cli 2.24.1-dev-build-58e271c.0 → 2.24.1-dev-build-abcd76f.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.
Files changed (38) hide show
  1. package/README.md +0 -23
  2. package/dist/package.json +3 -4
  3. package/dist/src/analyze/command.js +2 -8
  4. package/dist/src/analyze/select/command.js +9 -13
  5. package/dist/src/analyze/select-agent/command.js +11 -14
  6. package/dist/src/apply/api-client.d.ts +0 -3
  7. package/dist/src/apply/api-client.js +1 -14
  8. package/dist/src/apply/command.d.ts +1 -1
  9. package/dist/src/apply/command.js +50 -71
  10. package/dist/src/generate/command.js +9 -15
  11. package/dist/src/generate/edit/command.js +0 -1
  12. package/dist/src/import/orchestrator.js +12 -18
  13. package/dist/src/index.js +1 -6
  14. package/dist/src/print/command.js +13 -16
  15. package/dist/src/program.js +1 -8
  16. package/package.json +7 -8
  17. package/dist/src/analytics/apply.d.ts +0 -6
  18. package/dist/src/analytics/apply.js +0 -30
  19. package/dist/src/analytics/client.d.ts +0 -7
  20. package/dist/src/analytics/client.js +0 -68
  21. package/dist/src/analytics/constants.d.ts +0 -4
  22. package/dist/src/analytics/constants.js +0 -4
  23. package/dist/src/analytics/env.d.ts +0 -4
  24. package/dist/src/analytics/env.js +0 -14
  25. package/dist/src/analytics/exit.d.ts +0 -5
  26. package/dist/src/analytics/exit.js +0 -24
  27. package/dist/src/analytics/index.d.ts +0 -10
  28. package/dist/src/analytics/index.js +0 -9
  29. package/dist/src/analytics/normalize.d.ts +0 -3
  30. package/dist/src/analytics/normalize.js +0 -18
  31. package/dist/src/analytics/os.d.ts +0 -2
  32. package/dist/src/analytics/os.js +0 -13
  33. package/dist/src/analytics/session.d.ts +0 -3
  34. package/dist/src/analytics/session.js +0 -15
  35. package/dist/src/analytics/tracker.d.ts +0 -17
  36. package/dist/src/analytics/tracker.js +0 -126
  37. package/dist/src/analytics/types.d.ts +0 -28
  38. package/dist/src/analytics/types.js +0 -1
@@ -16,10 +16,9 @@ import { addAllowDeletionsOption, addArtifactInputOptions, addCompositionOptions
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, exitWithAnalytics, failureFromApiError, recordApplyOutcome, recordContentfulContext, } from '../analytics/index.js';
20
- async function die(message, fields = {}) {
19
+ function die(message) {
21
20
  process.stderr.write(`${message}\n`);
22
- return exitWithAnalytics(1, fields);
21
+ process.exit(1);
23
22
  }
24
23
  async function pathExists(p) {
25
24
  return access(p)
@@ -28,7 +27,7 @@ async function pathExists(p) {
28
27
  }
29
28
  async function assertFileExists(flag, p) {
30
29
  if (!(await pathExists(p)))
31
- return await die(`Error: file not found: ${p} (from ${flag})`);
30
+ die(`Error: file not found: ${p} (from ${flag})`);
32
31
  }
33
32
  async function readJsonFile(flag, p) {
34
33
  let text;
@@ -36,13 +35,13 @@ async function readJsonFile(flag, p) {
36
35
  text = await readFile(p, 'utf8');
37
36
  }
38
37
  catch {
39
- return await die(`Error: file not found: ${p} (from ${flag})`);
38
+ die(`Error: file not found: ${p} (from ${flag})`);
40
39
  }
41
40
  try {
42
41
  return JSON.parse(text);
43
42
  }
44
43
  catch {
45
- return await die(`Error: ${flag} is not valid JSON: ${p}`);
44
+ die(`Error: ${flag} is not valid JSON: ${p}`);
46
45
  }
47
46
  }
48
47
  const IGNORE_TOKEN_DIRS = new Set(['node_modules', 'dist', 'build', '.next', '.nuxt', '.git']);
@@ -84,12 +83,12 @@ export async function readTokensFromPath(flag, p) {
84
83
  s = await stat(p);
85
84
  }
86
85
  catch {
87
- return await die(`Error: file not found: ${p} (from ${flag})`);
86
+ die(`Error: file not found: ${p} (from ${flag})`);
88
87
  }
89
88
  if (s.isDirectory()) {
90
89
  const files = await collectJsonFiles(p);
91
90
  if (files.length === 0)
92
- return await die(`Error: no .json files found in directory: ${p} (from ${flag})`);
91
+ die(`Error: no .json files found in directory: ${p} (from ${flag})`);
93
92
  const merged = {};
94
93
  for (const file of files.sort()) {
95
94
  let text;
@@ -112,36 +111,36 @@ export async function readTokensFromPath(flag, p) {
112
111
  }
113
112
  const { valid, errors } = validateDTCG(merged);
114
113
  if (!valid)
115
- return await die(`Error: ${flag} contains invalid token types:\n${errors.map((e) => ` ${e.path}: ${e.message}`).join('\n')}`);
114
+ die(`Error: ${flag} contains invalid token types:\n${errors.map((e) => ` ${e.path}: ${e.message}`).join('\n')}`);
116
115
  return flattenDTCG(merged, '');
117
116
  }
118
117
  const raw = await readJsonFile(flag, p);
119
118
  if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
120
- return await die(`Error: ${flag} is not valid JSON: expected an object`);
119
+ die(`Error: ${flag} is not valid JSON: expected an object`);
121
120
  }
122
121
  const { valid, errors } = validateDTCG(raw);
123
122
  if (!valid)
124
- return await die(`Error: ${flag} contains invalid token types:\n${errors.map((e) => ` ${e.path}: ${e.message}`).join('\n')}`);
123
+ die(`Error: ${flag} contains invalid token types:\n${errors.map((e) => ` ${e.path}: ${e.message}`).join('\n')}`);
125
124
  return flattenDTCG(raw, '');
126
125
  }
127
126
  async function resolveSharedInputs(opts) {
128
127
  if (!opts.components && !opts.tokens && !opts.session) {
129
- return await die('Error: at least one of --components, --tokens, or --session is required');
128
+ die('Error: at least one of --components, --tokens, or --session is required');
130
129
  }
131
130
  if (opts.session && opts.components) {
132
- return await die('Error: --session and --components are mutually exclusive');
131
+ die('Error: --session and --components are mutually exclusive');
133
132
  }
134
133
  const spaceId = opts.spaceId ?? process.env.CONTENTFUL_SPACE_ID;
135
134
  const environmentId = opts.environmentId ?? process.env.CONTENTFUL_ENVIRONMENT_ID;
136
135
  if (!spaceId)
137
- return await die('Error: --space-id is required (or set CONTENTFUL_SPACE_ID)');
136
+ die('Error: --space-id is required (or set CONTENTFUL_SPACE_ID)');
138
137
  if (!environmentId)
139
- return await die('Error: --environment-id is required (or set CONTENTFUL_ENVIRONMENT_ID)');
138
+ die('Error: --environment-id is required (or set CONTENTFUL_ENVIRONMENT_ID)');
140
139
  opts.spaceId = spaceId;
141
140
  opts.environmentId = environmentId;
142
141
  const cmaToken = opts.cmaToken ?? process.env.CONTENTFUL_MANAGEMENT_TOKEN;
143
142
  if (!cmaToken) {
144
- return await die('Error: CMA token is required. Pass --cma-token or set CONTENTFUL_MANAGEMENT_TOKEN');
143
+ die('Error: CMA token is required. Pass --cma-token or set CONTENTFUL_MANAGEMENT_TOKEN');
145
144
  }
146
145
  if (opts.components)
147
146
  await assertFileExists('--components', opts.components);
@@ -155,14 +154,14 @@ async function resolveSharedInputs(opts) {
155
154
  db.close();
156
155
  }
157
156
  if (components.length === 0) {
158
- return await die(`Error: session '${opts.session}' has no generated components. Run generate components first.`);
157
+ die(`Error: session '${opts.session}' has no generated components. Run generate components first.`);
159
158
  }
160
159
  }
161
160
  else if (opts.components) {
162
161
  const raw = await readJsonFile('--components', opts.components);
163
162
  const result = validateCDF(raw);
164
163
  if (!result.valid) {
165
- return await die(`Error: --components failed schema validation: ${result.errors.map((e) => e.message).join(', ')}`);
164
+ die(`Error: --components failed schema validation: ${result.errors.map((e) => e.message).join(', ')}`);
166
165
  }
167
166
  components = result.components;
168
167
  }
@@ -214,12 +213,12 @@ export function formatSlotCycleReport(cycles) {
214
213
  }
215
214
  return lines;
216
215
  }
217
- export async function assertNoSlotCycles(components) {
216
+ export function assertNoSlotCycles(components) {
218
217
  const cycles = detectSlotCycles(components);
219
218
  if (cycles.length === 0)
220
219
  return;
221
220
  process.stderr.write(formatSlotCycleReport(cycles).join('\n') + '\n');
222
- await exitWithAnalytics(1);
221
+ process.exit(1);
223
222
  }
224
223
  export function extractComponentsFromManifest(manifest) {
225
224
  const componentsManifest = manifest?.componentsManifest;
@@ -428,24 +427,18 @@ export function registerApplyCommand(program) {
428
427
  }
429
428
  catch (e) {
430
429
  if (e instanceof ApiError)
431
- return await die(`Error: ${formatApiError(e)}`, failureFromApiError(e));
430
+ die(`Error: ${formatApiError(e)}`);
432
431
  throw e;
433
432
  }
434
433
  const { components, tokens, client } = inputs;
435
- const spaceId = opts.spaceId;
436
- const environmentId = opts.environmentId;
437
- await bindAnalyticsSessionId(opts.session, {
438
- space_key: spaceId,
439
- environment_key: environmentId,
440
- });
441
434
  try {
442
435
  await client.validateToken();
443
436
  }
444
437
  catch (e) {
445
438
  if (e instanceof ApiError)
446
- return await die(`Error: ${formatApiError(e)}`, failureFromApiError(e));
439
+ die(`Error: ${formatApiError(e)}`);
447
440
  const cause = e instanceof Error && e.cause instanceof Error ? e.cause.message : '';
448
- return await die(`Error: unable to connect to API host${cause ? `: ${cause}` : ''}`);
441
+ die(`Error: unable to connect to API host${cause ? `: ${cause}` : ''}`);
449
442
  }
450
443
  const manifest = buildManifest(components, tokens);
451
444
  let preview;
@@ -454,10 +447,11 @@ export function registerApplyCommand(program) {
454
447
  }
455
448
  catch (e) {
456
449
  if (e instanceof ApiError)
457
- return await die(`Error: ${formatApiError(e)}`, failureFromApiError(e));
450
+ die(`Error: ${formatApiError(e)}`);
458
451
  throw e;
459
452
  }
460
- recordContentfulContext(client, spaceId, environmentId);
453
+ const spaceId = opts.spaceId;
454
+ const environmentId = opts.environmentId;
461
455
  if (getInteractiveTerminalSupport().supported) {
462
456
  const { waitUntilExit } = render(createElement(ServerPreviewApp, {
463
457
  preview,
@@ -469,7 +463,7 @@ export function registerApplyCommand(program) {
469
463
  }
470
464
  else {
471
465
  process.stdout.write(JSON.stringify(buildPreviewOutput(preview, spaceId, environmentId), null, 2) + '\n');
472
- await exitWithAnalytics(0);
466
+ process.exit(0);
473
467
  }
474
468
  });
475
469
  const pushCmd = applyCmd.command('push').description('Write component types and design tokens to Contentful ExO');
@@ -486,7 +480,7 @@ export function registerApplyCommand(program) {
486
480
  const isTTY = getInteractiveTerminalSupport().supported;
487
481
  if (!isTTY && !opts.yes) {
488
482
  process.stderr.write('Error: apply push requires --yes in non-interactive mode\n');
489
- await exitWithAnalytics(1);
483
+ process.exit(1);
490
484
  }
491
485
  let inputs;
492
486
  try {
@@ -494,23 +488,17 @@ export function registerApplyCommand(program) {
494
488
  }
495
489
  catch (e) {
496
490
  if (e instanceof ApiError)
497
- return await die(`Error: ${formatApiError(e, opts.verbose)}`, failureFromApiError(e));
491
+ die(`Error: ${formatApiError(e, opts.verbose)}`);
498
492
  throw e;
499
493
  }
500
494
  const { components, tokens, client } = inputs;
501
- const spaceId = opts.spaceId;
502
- const environmentId = opts.environmentId;
503
- await bindAnalyticsSessionId(opts.session, {
504
- space_key: spaceId,
505
- environment_key: environmentId,
506
- });
507
- await assertNoSlotCycles(components);
495
+ assertNoSlotCycles(components);
508
496
  try {
509
497
  await client.validateToken();
510
498
  }
511
499
  catch (e) {
512
500
  if (e instanceof ApiError)
513
- return await die(`Error: ${formatApiError(e, opts.verbose)}`, failureFromApiError(e));
501
+ die(`Error: ${formatApiError(e, opts.verbose)}`);
514
502
  throw e;
515
503
  }
516
504
  const manifest = buildManifest(components, tokens);
@@ -520,10 +508,11 @@ export function registerApplyCommand(program) {
520
508
  }
521
509
  catch (e) {
522
510
  if (e instanceof ApiError)
523
- return await die(`Error: ${formatApiError(e, opts.verbose)}`, failureFromApiError(e));
511
+ die(`Error: ${formatApiError(e, opts.verbose)}`);
524
512
  throw e;
525
513
  }
526
- recordContentfulContext(client, spaceId, environmentId);
514
+ const spaceId = opts.spaceId;
515
+ const environmentId = opts.environmentId;
527
516
  if (opts.dryRun) {
528
517
  if (isTTY) {
529
518
  const { waitUntilExit } = render(createElement(ServerPreviewApp, {
@@ -537,7 +526,7 @@ export function registerApplyCommand(program) {
537
526
  else {
538
527
  process.stdout.write(JSON.stringify(buildPreviewOutput(preview, spaceId, environmentId), null, 2) + '\n');
539
528
  }
540
- await exitWithAnalytics(0);
529
+ process.exit(0);
541
530
  }
542
531
  if (isEmptyPreview(preview)) {
543
532
  if (isTTY && !opts.yes) {
@@ -546,14 +535,14 @@ export function registerApplyCommand(program) {
546
535
  else {
547
536
  process.stdout.write(JSON.stringify(buildPreviewOutput(preview, spaceId, environmentId), null, 2) + '\n');
548
537
  }
549
- await exitWithAnalytics(0);
538
+ process.exit(0);
550
539
  }
551
540
  const breakingWithImpact = hasBreakingChangesWithImpact(preview);
552
541
  if (!isTTY || opts.yes) {
553
542
  if (breakingWithImpact && !opts.force) {
554
543
  process.stderr.write('Error: breaking changes with downstream impact detected. Use --force to acknowledge.\n');
555
544
  process.stdout.write(JSON.stringify(buildPreviewOutput(preview, spaceId, environmentId), null, 2) + '\n');
556
- await exitWithAnalytics(1);
545
+ process.exit(1);
557
546
  }
558
547
  const verbose = opts.verbose ?? false;
559
548
  if (verbose) {
@@ -568,7 +557,7 @@ export function registerApplyCommand(program) {
568
557
  }
569
558
  catch (e) {
570
559
  if (e instanceof ApiError)
571
- return await die(`Error: ${formatApiError(e, opts.verbose)}`, failureFromApiError(e));
560
+ die(`Error: ${formatApiError(e, opts.verbose)}`);
572
561
  throw e;
573
562
  }
574
563
  process.stderr.write(`Apply operation started: ${operation.sys.id}\n`);
@@ -577,14 +566,12 @@ export function registerApplyCommand(program) {
577
566
  }
578
567
  catch (e) {
579
568
  if (e instanceof ApiError)
580
- return await die(`Error: ${formatApiError(e, opts.verbose)}`, failureFromApiError(e));
569
+ die(`Error: ${formatApiError(e, opts.verbose)}`);
581
570
  throw e;
582
571
  }
583
572
  const summary = buildApplyOutput(operation, spaceId, environmentId, opts.host);
584
- recordApplyOutcome(client, spaceId, environmentId, operation);
585
573
  process.stdout.write(JSON.stringify(summary, null, 2) + '\n');
586
- const exitCode = operation.sys.status === 'succeeded' ? 0 : 1;
587
- await exitWithAnalytics(exitCode);
574
+ process.exit(operation.sys.status === 'succeeded' ? 0 : 1);
588
575
  return;
589
576
  }
590
577
  await new Promise((resolvePromise) => {
@@ -634,7 +621,6 @@ export function registerApplyCommand(program) {
634
621
  }
635
622
  throw e;
636
623
  }
637
- recordApplyOutcome(client, spaceId, environmentId, operation);
638
624
  instance.rerender(createElement(ServerApplyDone, {
639
625
  operation,
640
626
  spaceId,
@@ -653,7 +639,7 @@ export function registerApplyCommand(program) {
653
639
  void runApply(acknowledge, applyDeletions);
654
640
  },
655
641
  onCancel: () => {
656
- void exitWithAnalytics(0);
642
+ process.exit(0);
657
643
  },
658
644
  }));
659
645
  void instance.waitUntilExit().then(() => resolvePromise());
@@ -678,17 +664,17 @@ export function registerApplyCommand(program) {
678
664
  }
679
665
  catch (e) {
680
666
  if (e instanceof ApiError)
681
- return await die(`Error: ${formatApiError(e)}`, failureFromApiError(e));
667
+ die(`Error: ${formatApiError(e)}`);
682
668
  throw e;
683
669
  }
684
670
  const { components, tokens, client } = inputs;
685
- await assertNoSlotCycles(components);
671
+ assertNoSlotCycles(components);
686
672
  try {
687
673
  await client.validateToken();
688
674
  }
689
675
  catch (e) {
690
676
  if (e instanceof ApiError)
691
- return await die(`Error: ${formatApiError(e)}`, failureFromApiError(e));
677
+ die(`Error: ${formatApiError(e)}`);
692
678
  throw e;
693
679
  }
694
680
  const fullManifest = buildManifest(components, tokens);
@@ -698,26 +684,21 @@ export function registerApplyCommand(program) {
698
684
  }
699
685
  catch (e) {
700
686
  if (e instanceof ApiError)
701
- return await die(`Error: ${formatApiError(e)}`, failureFromApiError(e));
687
+ die(`Error: ${formatApiError(e)}`);
702
688
  throw e;
703
689
  }
704
690
  const spaceId = opts.spaceId;
705
691
  const environmentId = opts.environmentId;
706
- await bindAnalyticsSessionId(opts.session, {
707
- space_key: spaceId,
708
- environment_key: environmentId,
709
- });
710
- recordContentfulContext(client, spaceId, environmentId);
711
692
  const entities = getSelectableEntities(preview);
712
693
  if (entities.length === 0) {
713
694
  process.stderr.write('Nothing to change — design system is up to date.\n');
714
- await exitWithAnalytics(0);
695
+ process.exit(0);
715
696
  }
716
697
  if (nonInteractive) {
717
698
  const selectedKeys = resolveNonInteractiveSelection(entities, opts);
718
699
  if (selectedKeys.size === 0) {
719
700
  process.stderr.write('No entities matched selection criteria.\n');
720
- await exitWithAnalytics(0);
701
+ process.exit(0);
721
702
  }
722
703
  const selectedComponentKeys = new Set();
723
704
  const selectedTokenPaths = new Set();
@@ -733,7 +714,7 @@ export function registerApplyCommand(program) {
733
714
  const hasBreaking = entities.some((e) => e.isBreaking && selectedKeys.has(makeSelectKey(e.kind, e.id)));
734
715
  if (hasBreaking && !opts.force) {
735
716
  process.stderr.write('Error: selection includes breaking changes. Use --force to acknowledge.\n');
736
- await exitWithAnalytics(1);
717
+ process.exit(1);
737
718
  }
738
719
  let operation;
739
720
  try {
@@ -744,7 +725,7 @@ export function registerApplyCommand(program) {
744
725
  }
745
726
  catch (e) {
746
727
  if (e instanceof ApiError)
747
- return await die(`Error: ${formatApiError(e)}`, failureFromApiError(e));
728
+ die(`Error: ${formatApiError(e)}`);
748
729
  throw e;
749
730
  }
750
731
  process.stderr.write(`Apply operation started: ${operation.sys.id}\n`);
@@ -753,13 +734,12 @@ export function registerApplyCommand(program) {
753
734
  }
754
735
  catch (e) {
755
736
  if (e instanceof ApiError)
756
- return await die(`Error: ${formatApiError(e)}`, failureFromApiError(e));
737
+ die(`Error: ${formatApiError(e)}`);
757
738
  throw e;
758
739
  }
759
740
  const summary = buildApplyOutput(operation, spaceId, environmentId, opts.host);
760
- recordApplyOutcome(client, spaceId, environmentId, operation);
761
741
  process.stdout.write(JSON.stringify(summary, null, 2) + '\n');
762
- await exitWithAnalytics(operation.sys.status === 'succeeded' ? 0 : 1);
742
+ process.exit(operation.sys.status === 'succeeded' ? 0 : 1);
763
743
  return;
764
744
  }
765
745
  await new Promise((resolvePromise) => {
@@ -821,7 +801,6 @@ export function registerApplyCommand(program) {
821
801
  }
822
802
  throw e;
823
803
  }
824
- recordApplyOutcome(client, spaceId, environmentId, operation);
825
804
  instance.rerender(createElement(ServerApplyDone, {
826
805
  operation,
827
806
  spaceId,
@@ -14,7 +14,6 @@ import { hashPromptForSkill } from '../session/cache-keys.js';
14
14
  import { getRefineArtifactsRoot, getRefineSessionPaths } from '../analyze/select/persistence.js';
15
15
  import { readExperiencesCredentials } from '../credentials-store.js';
16
16
  import { addAgentModelOptions } from '../lib/agent-model-options.js';
17
- import { bindAnalyticsSessionId, exitWithAnalytics } from '../analytics/index.js';
18
17
  const execFileAsync = promisify(execFile);
19
18
  const DEFAULT_TIMEOUT_MS = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 3 * 60 * 1000);
20
19
  const DEFAULT_COMPONENT_CONCURRENCY = 10;
@@ -24,8 +23,7 @@ const invoker = createLocalCliAgentInvoker({
24
23
  });
25
24
  function die(message) {
26
25
  process.stderr.write(`${message}\n`);
27
- void exitWithAnalytics(1);
28
- throw new Error('exit');
26
+ process.exit(1);
29
27
  }
30
28
  async function pathExists(p) {
31
29
  return access(p)
@@ -278,8 +276,7 @@ function resolveSessionId(sessionFlag) {
278
276
  .get();
279
277
  if (!row) {
280
278
  process.stderr.write('Error: no completed analyze extract session found. Run analyze extract first, or pass --session <id>.\n');
281
- void exitWithAnalytics(1);
282
- throw new Error('exit');
279
+ process.exit(1);
283
280
  }
284
281
  return row.id;
285
282
  }
@@ -343,7 +340,6 @@ async function runGenerateSkill(skill, opts, verbose = false) {
343
340
  let allComponents;
344
341
  if (skill === 'components') {
345
342
  sessionId = resolveSessionId(opts.session);
346
- await bindAnalyticsSessionId(sessionId);
347
343
  const acceptedNames = await loadAcceptedNames(sessionId);
348
344
  const db = openPipelineDb();
349
345
  try {
@@ -400,7 +396,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
400
396
  skillPathOverride: generatePromptPath,
401
397
  });
402
398
  process.stdout.write(prompt + '\n');
403
- await exitWithAnalytics(0);
399
+ process.exit(0);
404
400
  }
405
401
  const binary = resolveBinary(agent);
406
402
  if (!(await assertBinaryInPath(binary))) {
@@ -409,7 +405,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
409
405
  skill,
410
406
  sessionId: sessionId ?? '',
411
407
  });
412
- await exitWithAnalytics(1);
408
+ process.exit(1);
413
409
  }
414
410
  if (skill === 'components' && allComponents && sessionId) {
415
411
  const db = openPipelineDb();
@@ -475,8 +471,6 @@ async function runGenerateSkill(skill, opts, verbose = false) {
475
471
  resolvedSessionId = newId;
476
472
  }
477
473
  }
478
- sessionId = resolvedSessionId;
479
- await bindAnalyticsSessionId(resolvedSessionId);
480
474
  const tokenPromptHash = await hashPromptForSkill('tokens');
481
475
  // Check cache before invoking agent
482
476
  if (!noCache) {
@@ -489,12 +483,12 @@ async function runGenerateSkill(skill, opts, verbose = false) {
489
483
  // Skip agent invocation — jump to view
490
484
  const viewResult = { skill, agent, sessionId: sessionId ?? '' };
491
485
  if (process.stdout.isTTY) {
492
- const { waitUntilExit } = render(createElement(GenerateView, { result: viewResult, onExit: () => void exitWithAnalytics(0) }));
486
+ const { waitUntilExit } = render(createElement(GenerateView, { result: viewResult, onExit: () => process.exit(0) }));
493
487
  await waitUntilExit();
494
488
  }
495
489
  else {
496
490
  process.stdout.write(`generate complete\nskill: ${skill}\nagent: ${agent}\nsession=${sessionId ?? ''}\n`);
497
- await exitWithAnalytics(0);
491
+ process.exit(0);
498
492
  }
499
493
  return;
500
494
  }
@@ -529,7 +523,7 @@ async function runGenerateSkill(skill, opts, verbose = false) {
529
523
  process.stderr.write(`Error: agent produced no set_token calls.\n` +
530
524
  `Run with --dry-run to inspect the prompt.\n\n` +
531
525
  `Agent output:\n${result.stdout}\n`);
532
- await exitWithAnalytics(1);
526
+ process.exit(1);
533
527
  }
534
528
  if (tokenWarnings.length > 0) {
535
529
  process.stderr.write(`Warnings:\n${tokenWarnings.map((w) => ` ${w}`).join('\n')}\n`);
@@ -554,13 +548,13 @@ async function runGenerateSkill(skill, opts, verbose = false) {
554
548
  if (process.stdout.isTTY) {
555
549
  const { waitUntilExit } = render(createElement(GenerateView, {
556
550
  result: viewResult,
557
- onExit: () => void exitWithAnalytics(0),
551
+ onExit: () => process.exit(0),
558
552
  }));
559
553
  await waitUntilExit();
560
554
  }
561
555
  else {
562
556
  process.stdout.write(`generate complete\nskill: ${skill}\nagent: ${agent}\nsession=${sessionId ?? ''}\n`);
563
- await exitWithAnalytics(0);
557
+ process.exit(0);
564
558
  }
565
559
  }
566
560
  function addAgentFlags(cmd) {
@@ -99,7 +99,6 @@ async function runNonInteractive(opts, skill) {
99
99
  process.stderr.write(`Accepted: ${accepted.length} Rejected: ${rejected.length}\n`);
100
100
  }
101
101
  export function registerGenerateEditCommand(parent, skill) {
102
- // TODO(analytics): bindAnalyticsSessionId when generate edit ships — tracked in schema as generate_edit.
103
102
  parent
104
103
  .command('edit')
105
104
  .description(`Review and correct generate ${skill} output before pushing`)
@@ -6,19 +6,17 @@ import { openPipelineDb, getOrCreateSession, createStep, updateStep, findLatestS
6
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
- import { getDebugLogger } from '../lib/debug-logger.js';
10
- import { bindAnalyticsSession, emitSessionStarted } from '../analytics/index.js';
11
- import { pipelineSubprocessEnv } from '../analytics/env.js';
9
+ import { getDebugLogger, debugEnvForSubprocess } from '../lib/debug-logger.js';
12
10
  function findCliPath() {
13
11
  return join(fileURLToPath(import.meta.url), '..', '..', '..', '..', 'bin', 'cli.js');
14
12
  }
15
- async function runStep(args, cliPath, analyticsSessionId, env = {}, streamStderr = false) {
13
+ async function runStep(args, cliPath, env = {}, streamStderr = false) {
16
14
  const debug = getDebugLogger();
17
15
  const startedAt = Date.now();
18
16
  debug.event('import', 'subprocess.spawn', { cliPath, args });
19
17
  return new Promise((res) => {
20
18
  const child = execFile('node', [cliPath, ...args], {
21
- env: pipelineSubprocessEnv({ ...process.env, ...env }, analyticsSessionId),
19
+ env: debugEnvForSubprocess({ ...process.env, ...env }),
22
20
  });
23
21
  let stdout = '';
24
22
  let stderr = '';
@@ -110,10 +108,6 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
110
108
  inputPath: projectRoot,
111
109
  outDir,
112
110
  });
113
- await bindAnalyticsSession(sessionId, {
114
- ...(opts.spaceId ? { space_key: opts.spaceId, environment_key: opts.environmentId } : {}),
115
- });
116
- await emitSessionStarted('import');
117
111
  progressWriter(`Experience Design System CLI — Pipeline Import`);
118
112
  progressWriter(`Project: ${projectRoot}`);
119
113
  progressWriter(`Output: ${outDir}`);
@@ -165,7 +159,7 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
165
159
  if (opts.agent)
166
160
  analyzeArgs.push('--agent', opts.agent);
167
161
  }
168
- const r = await runStep(analyzeArgs, cliPath, sessionId);
162
+ const r = await runStep(analyzeArgs, cliPath);
169
163
  const durationMs = Date.now() - t0;
170
164
  if (r.exitCode !== 0) {
171
165
  if (r.stderr)
@@ -237,7 +231,7 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
237
231
  editArgs.push('--select-all');
238
232
  }
239
233
  }
240
- const rEdit = await runStep(editArgs, cliPath, sessionId, { FORCE_COLOR: '1' }, useAgentSelect);
234
+ const rEdit = await runStep(editArgs, cliPath, { FORCE_COLOR: '1' }, useAgentSelect);
241
235
  const editDurationMs = Date.now() - t0Edit;
242
236
  if (rEdit.exitCode !== 0) {
243
237
  if (rEdit.stderr && !useAgentSelect)
@@ -298,7 +292,7 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
298
292
  extractSession: extractSessionId ?? '',
299
293
  });
300
294
  const t0 = Date.now();
301
- const r = await runStep(generateArgs, cliPath, sessionId, { FORCE_COLOR: '1' }, true);
295
+ const r = await runStep(generateArgs, cliPath, { FORCE_COLOR: '1' }, true);
302
296
  const durationMs = Date.now() - t0;
303
297
  if (r.exitCode !== 0) {
304
298
  updateStep(db, stepId, 'failed', {}, r.stderr);
@@ -361,7 +355,7 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
361
355
  out: componentsPath,
362
356
  });
363
357
  const t0 = Date.now();
364
- const r = await runStep(printArgs, cliPath, sessionId);
358
+ const r = await runStep(printArgs, cliPath);
365
359
  const durationMs = Date.now() - t0;
366
360
  if (r.exitCode !== 0) {
367
361
  if (r.stderr)
@@ -431,7 +425,7 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
431
425
  components: componentsPath,
432
426
  });
433
427
  const t0 = Date.now();
434
- let r = await runStep(pushArgs, cliPath, sessionId, { FORCE_COLOR: '1' }, true);
428
+ let r = await runStep(pushArgs, cliPath, { FORCE_COLOR: '1' }, true);
435
429
  const excludedByRetry = [];
436
430
  let validationRetryCount = 0;
437
431
  while (validationRetryCount < MAX_VALIDATION_RETRIES && isPreviewValidationError(r) && extractSessionId) {
@@ -448,10 +442,10 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
448
442
  '--exclude-components',
449
443
  offenders.join(','),
450
444
  ];
451
- const rejectResult = await runStep(rejectArgs, cliPath, sessionId);
445
+ const rejectResult = await runStep(rejectArgs, cliPath);
452
446
  if (rejectResult.exitCode !== 0)
453
447
  break;
454
- r = await runStep(pushArgs, cliPath, sessionId, { FORCE_COLOR: '1' }, true);
448
+ r = await runStep(pushArgs, cliPath, { FORCE_COLOR: '1' }, true);
455
449
  validationRetryCount++;
456
450
  }
457
451
  const durationMs = Date.now() - t0;
@@ -486,10 +480,10 @@ export async function runPipeline(opts, progressWriter, cliPathOverride) {
486
480
  '--exclude-components',
487
481
  cycleNames.join(','),
488
482
  ];
489
- const rejectResult = await runStep(rejectArgs, cliPath, sessionId);
483
+ const rejectResult = await runStep(rejectArgs, cliPath);
490
484
  if (rejectResult.exitCode === 0) {
491
485
  const retryT0 = Date.now();
492
- const retryR = await runStep(pushArgs, cliPath, sessionId, { FORCE_COLOR: '1' }, true);
486
+ const retryR = await runStep(pushArgs, cliPath, { FORCE_COLOR: '1' }, true);
493
487
  const retryDurationMs = Date.now() - t0 + (Date.now() - retryT0);
494
488
  if (isSlotCycleError(retryR)) {
495
489
  const retryReport = extractCycleReport(retryR.stderr);
package/dist/src/index.js CHANGED
@@ -1,12 +1,7 @@
1
1
  import { createProgram } from './program.js';
2
- import { failActiveCommand, flushAnalytics } from './analytics/index.js';
3
2
  createProgram()
4
3
  .parseAsync()
5
- .catch(async (err) => {
6
- await failActiveCommand({
7
- error_name: err instanceof Error ? err.name : 'Error',
8
- });
9
- await flushAnalytics();
4
+ .catch((err) => {
10
5
  process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n`);
11
6
  process.exit(1);
12
7
  });