@contentful/experience-design-system-cli 2.36.2-dev-build-3b8c3735.0 → 2.36.2-dev-build-d983d04c.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/dist/app.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // packages/experience-design-system-cli/app.tsx
2
- import { useEffect as useEffect8, useState as useState10 } from "react";
2
+ import { useState as useState8 } from "react";
3
3
 
4
4
  // packages/experience-design-system-cli/src/tui/home/home.tsx
5
5
  import { useEffect as useEffect2, useState as useState2 } from "react";
@@ -230,202 +230,6 @@ function ImportScreen({ exitCode, onDone }) {
230
230
  ] });
231
231
  }
232
232
 
233
- // packages/experience-design-system-cli/src/tui/import/steps/01-welcome/screen.tsx
234
- import { useState as useState3 } from "react";
235
- import { Box as Box3, Text as Text3 } from "ink";
236
- import TextInput from "ink-text-input";
237
-
238
- // packages/experience-design-system-cli/src/tui/import/steps/01-welcome/controls.ts
239
- import { useInput as useInput3 } from "ink";
240
-
241
- // packages/experience-design-system-cli/src/tui/import/steps/01-welcome/logic.ts
242
- function shouldQuit(value, input, key) {
243
- if (key.escape) return true;
244
- return value === "" && input === "q" && !key.ctrl && !key.meta;
245
- }
246
- function toProjectPath(value) {
247
- const projectPath = value.trim();
248
- return projectPath === "" ? null : projectPath;
249
- }
250
-
251
- // packages/experience-design-system-cli/src/tui/import/steps/01-welcome/controls.ts
252
- var WELCOME_CONTROLS = [
253
- { keys: "Enter", label: "Continue" },
254
- { keys: "Esc/q", label: "Back to menu" }
255
- ];
256
- function useWelcomeControls(projectPath, onQuit) {
257
- useInput3((input, key) => {
258
- if (shouldQuit(projectPath, input, key)) onQuit();
259
- });
260
- }
261
-
262
- // packages/experience-design-system-cli/src/tui/import/steps/01-welcome/screen.tsx
263
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
264
- var RULE = "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
265
- var OVERVIEW = [
266
- { label: "Step 1", description: "Extract components from your codebase" },
267
- { label: "Step 2", description: "Review what was extracted" },
268
- { label: "Step 3", description: "Generate CDF definitions with Claude" },
269
- { label: "Step 4", description: "Review generated definitions" },
270
- { label: "Step 5", description: "Push to Contentful" }
271
- ];
272
- function WelcomeScreen({ onContinue, onQuit, initialPath = "" }) {
273
- const [projectPath, setProjectPath] = useState3(initialPath);
274
- useWelcomeControls(projectPath, onQuit);
275
- const submit = (value) => {
276
- const path = toProjectPath(value);
277
- if (path) onContinue(path);
278
- };
279
- return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [
280
- /* @__PURE__ */ jsx3(Text3, { bold: true, color: PALETTE.success, children: "\u{1F44B} Hey! Let's import your design system into Contentful." }),
281
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "I'll walk you through 5 steps to get your components into Contentful ExO." }),
282
- /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
283
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: RULE }),
284
- OVERVIEW.map((item) => /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
285
- /* @__PURE__ */ jsx3(Text3, { bold: true, children: item.label }),
286
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: item.description })
287
- ] }, item.label)),
288
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: RULE })
289
- ] }),
290
- /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
291
- /* @__PURE__ */ jsx3(Text3, { children: "Where is your component library?" }),
292
- /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
293
- /* @__PURE__ */ jsx3(Text3, { color: PALETTE.accent, children: "?" }),
294
- /* @__PURE__ */ jsx3(Text3, { children: "Project path:" }),
295
- /* @__PURE__ */ jsx3(TextInput, { value: projectPath, onChange: setProjectPath, onSubmit: submit })
296
- ] })
297
- ] }),
298
- /* @__PURE__ */ jsx3(Box3, { marginTop: 1, gap: 3, children: WELCOME_CONTROLS.map((control) => /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
299
- "[",
300
- control.keys,
301
- "] ",
302
- control.label
303
- ] }, control.keys)) })
304
- ] });
305
- }
306
-
307
- // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/screen.tsx
308
- import { useState as useState4 } from "react";
309
- import { Box as Box4, Text as Text4 } from "ink";
310
- import TextInput2 from "ink-text-input";
311
-
312
- // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/controls.ts
313
- import { useInput as useInput4 } from "ink";
314
-
315
- // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/logic.ts
316
- function isPlainKeyOnEmptyField(value, input, key, expected) {
317
- return value === "" && input === expected && !key.ctrl && !key.meta;
318
- }
319
- function shouldGoBack(value, input, key) {
320
- return key.escape || isPlainKeyOnEmptyField(value, input, key, "q");
321
- }
322
- function shouldSkip(value, input, key) {
323
- return isPlainKeyOnEmptyField(value, input, key, "s");
324
- }
325
- function toTokenPath(value) {
326
- const tokenPath = value.trim();
327
- return tokenPath === "" ? null : tokenPath;
328
- }
329
-
330
- // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/controls.ts
331
- var TOKEN_INPUT_CONTROLS = [
332
- { keys: "Enter", label: "Continue (skips if empty)" },
333
- { keys: "s", label: "Skip" },
334
- { keys: "Esc/q", label: "Back" }
335
- ];
336
- function useTokenInputControls(tokenPath, onSkip, onBack) {
337
- useInput4((input, key) => {
338
- if (shouldGoBack(tokenPath, input, key)) onBack();
339
- else if (shouldSkip(tokenPath, input, key)) onSkip();
340
- });
341
- }
342
-
343
- // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/validate-path.ts
344
- import { statSync } from "node:fs";
345
- import { homedir } from "node:os";
346
- import { resolve } from "node:path";
347
- function stripQuotes(value) {
348
- const quoted = value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'");
349
- return value.length >= 2 && quoted ? value.slice(1, -1) : value;
350
- }
351
- function expandHome(value) {
352
- return value === "~" || value.startsWith("~/") || value.startsWith("~\\") ? homedir() + value.slice(1) : value;
353
- }
354
- function validateTokenPath(rawPath) {
355
- const path = resolve(expandHome(stripQuotes(rawPath.trim())));
356
- let stats;
357
- try {
358
- stats = statSync(path);
359
- } catch {
360
- return { ok: false, error: `Path not found: ${path}`, resolvedPath: path };
361
- }
362
- if (stats.isDirectory()) {
363
- return {
364
- ok: false,
365
- error: "That's a directory \u2014 provide a path to a token file (e.g. tokens.json), not a folder.",
366
- resolvedPath: path
367
- };
368
- }
369
- if (!stats.isFile()) {
370
- return { ok: false, error: `Not a regular file: ${path}`, resolvedPath: path };
371
- }
372
- return { ok: true, path };
373
- }
374
-
375
- // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/screen.tsx
376
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
377
- function TokenInputScreen({
378
- onConfirm,
379
- onSkip,
380
- onBack,
381
- initialPath = ""
382
- }) {
383
- const [tokenPath, setTokenPath] = useState4(initialPath);
384
- const [failure, setFailure] = useState4(null);
385
- useTokenInputControls(tokenPath, onSkip, onBack);
386
- const change = (value) => {
387
- setTokenPath(value);
388
- setFailure(null);
389
- };
390
- const submit = (value) => {
391
- const rawPath = toTokenPath(value);
392
- if (!rawPath) {
393
- onSkip();
394
- return;
395
- }
396
- const check = validateTokenPath(rawPath);
397
- if (check.ok) onConfirm(check.path);
398
- else setFailure({ error: check.error, resolvedPath: check.resolvedPath });
399
- };
400
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [
401
- /* @__PURE__ */ jsx4(Text4, { bold: true, children: "Design tokens" }),
402
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Point me to your raw token file (e.g. ~/design-tokens/tokens.json). You can use ~, relative, or absolute paths. Claude will map it to DTCG format." }),
403
- /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
404
- /* @__PURE__ */ jsxs4(Box4, { gap: 1, children: [
405
- /* @__PURE__ */ jsx4(Text4, { color: PALETTE.accent, children: "?" }),
406
- /* @__PURE__ */ jsx4(Text4, { children: "Token path:" }),
407
- /* @__PURE__ */ jsx4(TextInput2, { value: tokenPath, onChange: change, onSubmit: submit })
408
- ] }),
409
- failure && /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
410
- /* @__PURE__ */ jsxs4(Text4, { color: PALETTE.error, children: [
411
- "\u2717 ",
412
- failure.error
413
- ] }),
414
- /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
415
- " Resolved to: ",
416
- failure.resolvedPath
417
- ] })
418
- ] })
419
- ] }),
420
- /* @__PURE__ */ jsx4(Box4, { marginTop: 1, gap: 3, children: TOKEN_INPUT_CONTROLS.map((control) => /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
421
- "[",
422
- control.keys,
423
- "] ",
424
- control.label
425
- ] }, control.keys)) })
426
- ] });
427
- }
428
-
429
233
  // packages/experience-design-system-cli/src/tui/import/spawn-v1-import.ts
430
234
  import { spawn } from "node:child_process";
431
235
 
@@ -453,9 +257,6 @@ function buildArgs(options) {
453
257
  if (options.project) {
454
258
  args.push("--project", options.project);
455
259
  }
456
- if (options.tokens) {
457
- args.push("--tokens", options.tokens);
458
- }
459
260
  return args;
460
261
  }
461
262
  async function spawnV1Import(options = {}) {
@@ -479,7 +280,7 @@ function getTerminalHandle() {
479
280
  return process.stdin._handle;
480
281
  }
481
282
  async function stopReadingTerminal() {
482
- await new Promise((resolve2) => setImmediate(resolve2));
283
+ await new Promise((resolve) => setImmediate(resolve));
483
284
  const handle = getTerminalHandle();
484
285
  if (!handle?.readStop) return;
485
286
  handle.reading = false;
@@ -493,235 +294,43 @@ function startReadingTerminal() {
493
294
  }
494
295
 
495
296
  // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
496
- import { useEffect as useEffect3 } from "react";
497
- import { Box as Box5, Text as Text5, useInput as useInput5 } from "ink";
498
-
499
- // packages/experience-design-system-cli/src/tui/debug-store.ts
500
- import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
501
- import { existsSync as existsSync3, readdirSync } from "node:fs";
502
- import { join as join5 } from "node:path";
503
-
504
- // packages/experience-design-system-types/dist/src/config/index.js
505
- import { randomBytes } from "node:crypto";
506
- import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
507
- import { homedir as homedir2 } from "node:os";
508
- import { dirname as dirname2, join as join4 } from "node:path";
509
- function configRoot() {
510
- return process.env["EDS_HOME"] || join4(homedir2(), ".contentful", "experience-design-system-cli");
511
- }
512
- var configFilePath = () => join4(configRoot(), "config.json");
513
- var debugSessionsDir = () => join4(configRoot(), "debug", "sessions");
514
- async function readSettings() {
515
- try {
516
- return JSON.parse(await readFile(configFilePath(), "utf8"));
517
- } catch {
518
- return {};
519
- }
520
- }
521
- async function writeSettings(settings) {
522
- const path = configFilePath();
523
- await mkdir(dirname2(path), { recursive: true });
524
- const tmp = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
525
- await writeFile(tmp, `${JSON.stringify(settings, null, 2)}
526
- `, { mode: 384 });
527
- await rename(tmp, path);
528
- }
529
- async function updateSettings(patch) {
530
- await writeSettings({ ...await readSettings(), ...patch });
531
- }
532
-
533
- // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
534
- var DEFAULT_DEBUG_MODE_SETTING = {
535
- enabled: true
536
- };
537
- async function readDebugModeSetting() {
538
- const { debugMode } = await readSettings();
539
- return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
540
- }
541
- async function writeDebugModeSetting(setting) {
542
- await updateSettings({ debugMode: setting });
543
- }
544
-
545
- // packages/experience-design-system-cli/src/tui/debug-store.ts
546
- var pendingRun;
547
- function generateRunId() {
548
- const now = /* @__PURE__ */ new Date();
549
- const pad = (n) => String(n).padStart(2, "0");
550
- return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
551
- }
552
- function datePrefix(now = /* @__PURE__ */ new Date()) {
553
- const pad = (n) => String(n).padStart(2, "0");
554
- return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
555
- }
556
- function slugify(value) {
557
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
558
- }
559
- function generateSessionId() {
560
- const today = datePrefix();
561
- const root = debugSessionsDir();
562
- const existing = existsSync3(root) ? readdirSync(root) : [];
563
- const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
564
- const maxSeq = existing.reduce((max, entry) => {
565
- const match = seqPattern.exec(entry);
566
- return match ? Math.max(max, Number(match[1])) : max;
567
- }, 0);
568
- return `${today}-session-${maxSeq + 1}`;
569
- }
570
- var SESSION_ID = generateSessionId();
571
- function sessionDebugDir() {
572
- return join5(debugSessionsDir(), SESSION_ID);
573
- }
574
- void isDebugModeEnabled().then((enabled) => {
575
- if (!enabled) return void 0;
576
- return mkdir2(sessionDebugDir(), { recursive: true });
577
- });
578
- async function isDebugModeEnabled() {
579
- try {
580
- return (await readDebugModeSetting()).enabled;
581
- } catch {
582
- return true;
583
- }
584
- }
585
- function redact(value) {
586
- const clone = { ...value };
587
- if ("cma_token" in clone) {
588
- const raw = clone.cma_token;
589
- clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
590
- }
591
- return clone;
592
- }
593
- function startDebugRun({
594
- flow,
595
- step,
596
- menuOption,
597
- inputs
598
- }) {
599
- const runId = generateRunId();
600
- const startedAt = Date.now();
601
- const redactedInputs = redact(inputs);
602
- isDebugModeEnabled().then((enabled) => {
603
- if (!enabled) return;
604
- pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
605
- });
606
- }
607
- async function finishDebugRun({
608
- outputs,
609
- status,
610
- exitMethod
611
- }) {
612
- const run = pendingRun;
613
- if (!run) return;
614
- pendingRun = void 0;
615
- const durationMs = Date.now() - run.startedAt;
616
- const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
617
- const flowSegments = run.flow.split("/");
618
- const dir = join5(sessionDebugDir(), ...flowSegments);
619
- await mkdir2(dir, { recursive: true });
620
- const filename = nextAttemptFilename(dir, run.menuOption);
621
- await writeFile2(join5(dir, filename), content, { mode: 384 });
622
- }
623
- function nextAttemptFilename(dir, menuOption) {
624
- const today = datePrefix();
625
- const optionSlug = slugify(menuOption);
626
- const existing = existsSync3(dir) ? readdirSync(dir) : [];
627
- const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
628
- const maxAttempt = existing.reduce((max, entry) => {
629
- const match = attemptPattern.exec(entry);
630
- return match ? Math.max(max, Number(match[1])) : max;
631
- }, 0);
632
- return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
633
- }
634
- function renderMarkdown(run, finish) {
635
- const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
636
- const stepLabel = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
637
- const flowSlug = run.flow.split("/").join("-");
638
- return `# Debug Log
639
-
640
- - Run ID: ${run.runId}
641
- - Flow: ${flowSlug}
642
- - Step: ${stepLabel}
643
- - Menu option: ${run.menuOption}
644
- - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
645
- - CLI version: ${readPackageVersion()}
646
- - Platform: ${process.platform} / Node ${process.version}
647
- - Duration on screen: ${finish.durationMs}ms
648
- - Status: ${finish.status}
649
- - Exit method: ${finish.exitMethod}
650
-
651
- ## Inputs
652
- \`\`\`json
653
- ${JSON.stringify(run.inputs, null, 2)}
654
- \`\`\`
655
-
656
- ## Outputs
657
- \`\`\`json
658
- ${JSON.stringify(finish.outputs, null, 2)}
659
- \`\`\`
660
- `;
661
- }
662
- function handleCrash() {
663
- return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
664
- }
665
- process.once("uncaughtException", (err) => {
666
- void handleCrash().finally(() => {
667
- throw err;
668
- });
669
- });
670
- process.once("unhandledRejection", (reason) => {
671
- void handleCrash().finally(() => {
672
- throw reason;
673
- });
674
- });
675
- process.once("SIGINT", () => {
676
- void handleCrash().finally(() => {
677
- process.exit(130);
678
- });
679
- });
680
-
681
- // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
682
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
297
+ import { Box as Box3, Text as Text3, useInput as useInput3 } from "ink";
298
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
683
299
  function HelpScreen({ onDone }) {
684
- useEffect3(() => {
685
- startDebugRun({ flow: "help", step: "01-help", menuOption: "Help", inputs: {} });
686
- }, []);
687
- const leave = (exitMethod) => {
688
- void finishDebugRun({ outputs: {}, status: "success", exitMethod });
689
- onDone();
690
- };
691
- useInput5((input, key) => {
300
+ useInput3((input, key) => {
692
301
  if (key.return) {
693
- leave("saved");
302
+ onDone();
694
303
  return;
695
304
  }
696
305
  if (key.escape || input === "q") {
697
- leave("discarded");
306
+ onDone();
698
307
  return;
699
308
  }
700
309
  });
701
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
702
- /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Help" }),
703
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
704
- /* @__PURE__ */ jsx5(Text5, { children: "This is a placeholder screen for v2 help content." }),
705
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
706
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[Enter] Complete [Esc/q] Exit \u2014 both return to Start" })
310
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
311
+ /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Help" }),
312
+ /* @__PURE__ */ jsx3(Text3, { children: " " }),
313
+ /* @__PURE__ */ jsx3(Text3, { children: "This is a placeholder screen for v2 help content." }),
314
+ /* @__PURE__ */ jsx3(Text3, { children: " " }),
315
+ /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "[Enter] Complete [Esc/q] Exit \u2014 both return to Start" })
707
316
  ] });
708
317
  }
709
318
 
710
319
  // packages/experience-design-system-cli/src/tui/settings/PageContainer.tsx
711
- import { useState as useState5 } from "react";
712
- import { Box as Box6, Text as Text6, useInput as useInput6 } from "ink";
713
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
320
+ import { useState as useState3 } from "react";
321
+ import { Box as Box4, Text as Text4, useInput as useInput4 } from "ink";
322
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
714
323
  function SettingsScreen({
715
324
  onNavigate,
716
325
  onBack
717
326
  }) {
718
- const [focusIdx, setFocusIdx] = useState5(0);
327
+ const [focusIdx, setFocusIdx] = useState3(0);
719
328
  const items = [
720
329
  { label: "Configuration", screen: "settings-configuration" },
721
330
  { label: "Opt-in Analytics", screen: "settings-opt-in-analytics" },
722
331
  { label: "Debug Mode", screen: "settings-debug-mode" }
723
332
  ];
724
- useInput6((input, key) => {
333
+ useInput4((input, key) => {
725
334
  if (key.upArrow) {
726
335
  setFocusIdx((i) => (i - 1 + items.length) % items.length);
727
336
  return;
@@ -741,26 +350,40 @@ function SettingsScreen({
741
350
  onBack();
742
351
  }
743
352
  });
744
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
745
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Settings" }),
746
- /* @__PURE__ */ jsx6(Text6, { children: " " }),
747
- items.map((item, i) => /* @__PURE__ */ jsxs6(Text6, { color: i === focusIdx ? "cyan" : void 0, children: [
353
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
354
+ /* @__PURE__ */ jsx4(Text4, { bold: true, children: "Settings" }),
355
+ /* @__PURE__ */ jsx4(Text4, { children: " " }),
356
+ items.map((item, i) => /* @__PURE__ */ jsxs4(Text4, { color: i === focusIdx ? "cyan" : void 0, children: [
748
357
  i === focusIdx ? "> " : " ",
749
358
  item.label
750
359
  ] }, item.label)),
751
- /* @__PURE__ */ jsx6(Text6, { children: " " }),
752
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "[\u2191/\u2193] Navigate [Enter] Select [Esc/q] Back to Start" })
360
+ /* @__PURE__ */ jsx4(Text4, { children: " " }),
361
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "[\u2191/\u2193] Navigate [Enter] Select [Esc/q] Back to Start" })
753
362
  ] });
754
363
  }
755
364
 
756
365
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
757
- import { useEffect as useEffect4, useState as useState6 } from "react";
758
- import { Box as Box7, Text as Text7, useInput as useInput7 } from "ink";
759
- import TextInput3 from "ink-text-input";
366
+ import { useEffect as useEffect3, useState as useState4 } from "react";
367
+ import { Box as Box5, Text as Text5, useInput as useInput5 } from "ink";
760
368
 
761
369
  // packages/experience-design-system-cli/src/tui/settings/utils/v1-store.ts
762
- var readV1Store = readSettings;
763
- var writeV1Store = writeSettings;
370
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
371
+ import { join as join4 } from "node:path";
372
+ import { homedir } from "node:os";
373
+ var V1_STORE_PATH = join4(homedir(), ".config", "experiences", "credentials.json");
374
+ async function readV1Store() {
375
+ try {
376
+ const raw = await readFile(V1_STORE_PATH, "utf8");
377
+ return JSON.parse(raw);
378
+ } catch {
379
+ return {};
380
+ }
381
+ }
382
+ async function writeV1Store(data) {
383
+ await mkdir(join4(homedir(), ".config", "experiences"), { recursive: true });
384
+ await writeFile(V1_STORE_PATH, `${JSON.stringify(data, null, 2)}
385
+ `, { mode: 384 });
386
+ }
764
387
 
765
388
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/config-store.ts
766
389
  async function readCredentials() {
@@ -769,9 +392,7 @@ async function readCredentials() {
769
392
  spaceId: store.spaceId || "",
770
393
  environmentId: store.environmentId || "",
771
394
  cmaToken: store.cmaToken || "",
772
- host: store.host || "",
773
- defaultComponentDir: store.defaultComponentDir || "",
774
- defaultTokenFile: store.defaultTokenFile || ""
395
+ host: store.host || ""
775
396
  };
776
397
  }
777
398
  async function writeCredentials(config) {
@@ -787,51 +408,23 @@ async function writeCredentials(config) {
787
408
  }
788
409
 
789
410
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
790
- import { Fragment, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
791
- var FIELD_ORDER = [
792
- "spaceId",
793
- "environmentId",
794
- "cmaToken",
795
- "host",
796
- "defaultComponentDir",
797
- "defaultTokenFile"
798
- ];
799
- function debugFields(config) {
800
- return {
801
- space_id: config?.spaceId ?? "",
802
- environment_id: config?.environmentId ?? "",
803
- cma_token: config?.cmaToken ?? "",
804
- host: config?.host ?? "",
805
- default_component_dir: config?.defaultComponentDir ?? "",
806
- default_token_file: config?.defaultTokenFile ?? ""
807
- };
808
- }
411
+ import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
412
+ var FIELD_ORDER = ["spaceId", "environmentId", "cmaToken", "host"];
809
413
  var FIELD_LABELS = {
810
414
  spaceId: "Space ID",
811
415
  environmentId: "Environment ID",
812
416
  cmaToken: "CMA Token",
813
- host: "API Host (optional)",
814
- defaultComponentDir: "Default component directory (optional)",
815
- defaultTokenFile: "Default token file (optional)"
417
+ host: "API Host (optional)"
816
418
  };
817
419
  function ConfigurationScreen({ onDone }) {
818
- const [stage, setStage] = useState6("loading");
819
- const [config, setConfig] = useState6(null);
820
- const [activeField, setActiveField] = useState6("spaceId");
821
- const [notice, setNotice] = useState6(null);
822
- const [lastSaved, setLastSaved] = useState6(null);
823
- const [editing, setEditing] = useState6(false);
824
- const [valueBeforeEdit, setValueBeforeEdit] = useState6("");
825
- useEffect4(() => {
420
+ const [stage, setStage] = useState4("loading");
421
+ const [config, setConfig] = useState4(null);
422
+ const [activeField, setActiveField] = useState4("spaceId");
423
+ const [message, setMessage] = useState4(null);
424
+ useEffect3(() => {
826
425
  readCredentials().then((cfg) => {
827
426
  setConfig(cfg);
828
427
  setStage("form");
829
- startDebugRun({
830
- flow: "settings/contentful-configuration",
831
- step: "01-configuration",
832
- menuOption: "Configuration",
833
- inputs: debugFields(cfg)
834
- });
835
428
  });
836
429
  }, []);
837
430
  function fieldValue(field) {
@@ -841,46 +434,29 @@ function ConfigurationScreen({ onDone }) {
841
434
  function setFieldValue(field, value) {
842
435
  if (!config) return;
843
436
  setConfig({ ...config, [field]: value });
844
- setNotice(null);
845
437
  }
846
438
  function handleSave() {
847
439
  if (!config) return;
848
440
  setStage("saving");
849
- setNotice(null);
441
+ setMessage(null);
850
442
  writeCredentials(config).then(() => {
851
- setLastSaved(config);
852
- setNotice({ kind: "success", text: "Configuration saved" });
853
- setStage("form");
443
+ setStage("saved");
444
+ setMessage("Configuration saved");
854
445
  }).catch((err) => {
855
- setNotice({ kind: "error", text: err instanceof Error ? err.message : "Failed to save" });
446
+ setMessage(err instanceof Error ? err.message : "Failed to save");
856
447
  setStage("form");
857
448
  });
858
449
  }
859
- function quit() {
860
- void finishDebugRun(
861
- lastSaved ? { outputs: debugFields(lastSaved), status: "success", exitMethod: "saved" } : { outputs: {}, status: "success", exitMethod: "discarded" }
862
- );
863
- onDone();
864
- }
865
- useInput7((input, key) => {
450
+ useInput5((input, key) => {
866
451
  if (stage === "loading" || stage === "saving") return;
867
- if (editing) {
868
- if (key.escape) {
869
- setFieldValue(activeField, valueBeforeEdit);
870
- setEditing(false);
452
+ if (stage === "saved") {
453
+ if (key.return || key.escape || input === "q") {
454
+ onDone();
871
455
  }
872
456
  return;
873
457
  }
874
458
  if (key.escape || input === "q") {
875
- quit();
876
- return;
877
- }
878
- if (input === "s") {
879
- handleSave();
880
- return;
881
- }
882
- if (input === "c") {
883
- setFieldValue(activeField, "");
459
+ onDone();
884
460
  return;
885
461
  }
886
462
  if (key.tab || key.downArrow) {
@@ -894,57 +470,75 @@ function ConfigurationScreen({ onDone }) {
894
470
  return;
895
471
  }
896
472
  if (key.return) {
897
- setValueBeforeEdit(fieldValue(activeField));
898
- setEditing(true);
473
+ const idx = FIELD_ORDER.indexOf(activeField);
474
+ if (idx < FIELD_ORDER.length - 1) {
475
+ setActiveField(FIELD_ORDER[idx + 1]);
476
+ } else {
477
+ handleSave();
478
+ }
479
+ return;
480
+ }
481
+ if (key.backspace || key.delete) {
482
+ const current = fieldValue(activeField);
483
+ setFieldValue(activeField, current.slice(0, -1));
484
+ return;
485
+ }
486
+ if (input && !key.ctrl && !key.meta) {
487
+ setFieldValue(activeField, fieldValue(activeField) + input);
899
488
  }
900
489
  });
901
490
  if (stage === "loading") {
902
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
903
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: "Configuration" }),
904
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
905
- /* @__PURE__ */ jsx7(Text7, { color: PALETTE.accent, children: "Loading..." })
491
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
492
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Configuration" }),
493
+ /* @__PURE__ */ jsx5(Text5, { children: " " }),
494
+ /* @__PURE__ */ jsx5(Text5, { color: PALETTE.accent, children: "Loading..." })
906
495
  ] });
907
496
  }
908
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
909
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: "Configuration" }),
910
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
911
- /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", children: FIELD_ORDER.map((field) => {
497
+ if (stage === "saved") {
498
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
499
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Configuration" }),
500
+ /* @__PURE__ */ jsx5(Text5, { children: " " }),
501
+ /* @__PURE__ */ jsxs5(Text5, { color: PALETTE.success, children: [
502
+ "\u2713 ",
503
+ message
504
+ ] }),
505
+ /* @__PURE__ */ jsx5(Text5, { children: " " }),
506
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[Enter] Back to Settings" })
507
+ ] });
508
+ }
509
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
510
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Configuration" }),
511
+ /* @__PURE__ */ jsx5(Text5, { children: " " }),
512
+ /* @__PURE__ */ jsx5(Text5, { children: "Contentful API Credentials" }),
513
+ /* @__PURE__ */ jsx5(Text5, { children: " " }),
514
+ /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: FIELD_ORDER.map((field) => {
912
515
  const isActive = activeField === field;
913
516
  const value = fieldValue(field);
914
517
  const display = field === "cmaToken" ? "\u2022".repeat(value.length) : value;
915
- return /* @__PURE__ */ jsxs7(Box7, { gap: 1, children: [
916
- /* @__PURE__ */ jsx7(Text7, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
917
- /* @__PURE__ */ jsxs7(Text7, { bold: isActive, children: [
518
+ return /* @__PURE__ */ jsxs5(Box5, { gap: 1, children: [
519
+ /* @__PURE__ */ jsx5(Text5, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
520
+ /* @__PURE__ */ jsxs5(Text5, { bold: isActive, children: [
918
521
  FIELD_LABELS[field],
919
522
  ":"
920
523
  ] }),
921
- isActive && editing ? /* @__PURE__ */ jsx7(
922
- TextInput3,
923
- {
924
- value,
925
- onChange: (next) => setFieldValue(field, next),
926
- onSubmit: () => setEditing(false),
927
- mask: field === "cmaToken" ? "\u2022" : void 0
928
- }
929
- ) : /* @__PURE__ */ jsx7(Text7, { children: display || /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "(empty)" }) })
524
+ /* @__PURE__ */ jsx5(Text5, { children: display || /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "(empty)" }) })
930
525
  ] }, field);
931
526
  }) }),
932
- notice && /* @__PURE__ */ jsxs7(Fragment, { children: [
933
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
934
- /* @__PURE__ */ jsxs7(Text7, { color: notice.kind === "success" ? PALETTE.success : PALETTE.error, children: [
935
- notice.kind === "success" ? "\u2713" : "\u2717",
936
- " ",
937
- notice.text
527
+ message && /* @__PURE__ */ jsxs5(Fragment, { children: [
528
+ /* @__PURE__ */ jsx5(Text5, { children: " " }),
529
+ /* @__PURE__ */ jsxs5(Text5, { color: PALETTE.error, children: [
530
+ "\u2717 ",
531
+ message
938
532
  ] })
939
533
  ] }),
940
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
941
- /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: editing ? "[type] Edit \xB7 [\u2190/\u2192] Move cursor \xB7 [Enter] Done \xB7 [Esc] Cancel edit" : "[\u2191/\u2193] Switch field \xB7 [Enter] Edit \xB7 [c] Clear field \xB7 [s] Save \xB7 [Esc/q] Quit without saving" })
534
+ /* @__PURE__ */ jsx5(Text5, { children: " " }),
535
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[\u2191/\u2193] Switch field \xB7 [Enter] Save/Next \xB7 [Esc/q] Back" })
942
536
  ] });
943
537
  }
944
538
 
945
539
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
946
- import { useEffect as useEffect5, useState as useState7 } from "react";
947
- import { Box as Box8, Text as Text8, useInput as useInput8 } from "ink";
540
+ import { useEffect as useEffect4, useState as useState5 } from "react";
541
+ import { Box as Box6, Text as Text6, useInput as useInput6 } from "ink";
948
542
 
949
543
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/analytics-store.ts
950
544
  async function readAnalyticsSetting() {
@@ -962,23 +556,17 @@ async function writeAnalyticsSetting(setting) {
962
556
  }
963
557
 
964
558
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
965
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
559
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
966
560
  function OptInAnalyticsScreen({ onDone }) {
967
- const [loading, setLoading] = useState7(true);
968
- const [enabled, setEnabled] = useState7(true);
969
- useEffect5(() => {
561
+ const [loading, setLoading] = useState5(true);
562
+ const [enabled, setEnabled] = useState5(true);
563
+ useEffect4(() => {
970
564
  readAnalyticsSetting().then((setting) => {
971
565
  setEnabled(setting.enabled);
972
566
  setLoading(false);
973
- startDebugRun({
974
- flow: "settings/opt-in-analytics",
975
- step: "01-opt-in-analytics",
976
- menuOption: "Opt-in Analytics",
977
- inputs: { enabled: setting.enabled }
978
- });
979
567
  });
980
568
  }, []);
981
- useInput8((input, key) => {
569
+ useInput6((input, key) => {
982
570
  if (loading) return;
983
571
  if (key.return || input === " ") {
984
572
  setEnabled((current) => {
@@ -989,36 +577,208 @@ function OptInAnalyticsScreen({ onDone }) {
989
577
  return;
990
578
  }
991
579
  if (key.escape || input === "q") {
992
- void finishDebugRun({ outputs: { enabled }, status: "success", exitMethod: "saved" });
993
580
  onDone();
994
581
  }
995
582
  });
996
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
997
- /* @__PURE__ */ jsx8(Text8, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
998
- /* @__PURE__ */ jsx8(Text8, { children: " " }),
999
- loading ? /* @__PURE__ */ jsx8(Text8, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
1000
- /* @__PURE__ */ jsxs8(Text8, { children: [
583
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
584
+ /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
585
+ /* @__PURE__ */ jsx6(Text6, { children: " " }),
586
+ loading ? /* @__PURE__ */ jsx6(Text6, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
587
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1001
588
  "Share anonymous usage data:",
1002
589
  " ",
1003
- /* @__PURE__ */ jsx8(Text8, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
590
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
1004
591
  ] }),
1005
- /* @__PURE__ */ jsx8(Text8, { children: " " }),
1006
- /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Shares which CLI commands are used and where imports succeed or fail." }),
1007
- /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Never includes source code, file paths, credentials, or authored content." })
592
+ /* @__PURE__ */ jsx6(Text6, { children: " " }),
593
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Shares which CLI commands are used and where imports succeed or fail." }),
594
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Never includes source code, file paths, credentials, or authored content." })
1008
595
  ] }),
1009
- /* @__PURE__ */ jsx8(Text8, { children: " " }),
1010
- /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "[Enter/Space] Toggle [Esc/q] Back to Settings" })
596
+ /* @__PURE__ */ jsx6(Text6, { children: " " }),
597
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "[Enter/Space] Toggle [Esc/q] Back to Settings" })
1011
598
  ] });
1012
599
  }
1013
600
 
1014
601
  // packages/experience-design-system-cli/src/tui/upgrade/PageContainer.tsx
1015
- import { useEffect as useEffect6, useState as useState8 } from "react";
1016
- import { Box as Box9, Text as Text9, useInput as useInput9 } from "ink";
1017
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
602
+ import { useEffect as useEffect5, useState as useState6 } from "react";
603
+ import { Box as Box7, Text as Text7, useInput as useInput7 } from "ink";
604
+
605
+ // packages/experience-design-system-cli/src/tui/debug-store.ts
606
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
607
+ import { existsSync as existsSync3, readdirSync } from "node:fs";
608
+ import { join as join6 } from "node:path";
609
+
610
+ // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
611
+ import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
612
+ import { dirname as dirname2, join as join5 } from "node:path";
613
+ var PACKAGE_NAME3 = "@contentful/experience-design-system-cli";
614
+ var DEFAULT_DEBUG_MODE_SETTING = {
615
+ enabled: true
616
+ };
617
+ function debugModeSettingPath() {
618
+ return join5(findPackageRoot(import.meta.url, PACKAGE_NAME3), ".contentful", "config", "debug_mode.json");
619
+ }
620
+ async function readDebugModeSetting() {
621
+ try {
622
+ const raw = await readFile2(debugModeSettingPath(), "utf8");
623
+ const parsed = JSON.parse(raw);
624
+ return { ...DEFAULT_DEBUG_MODE_SETTING, ...parsed };
625
+ } catch {
626
+ return { ...DEFAULT_DEBUG_MODE_SETTING };
627
+ }
628
+ }
629
+ async function writeDebugModeSetting(setting) {
630
+ const path = debugModeSettingPath();
631
+ await mkdir2(dirname2(path), { recursive: true });
632
+ await writeFile2(path, `${JSON.stringify(setting, null, 2)}
633
+ `, { mode: 384 });
634
+ }
635
+
636
+ // packages/experience-design-system-cli/src/tui/debug-store.ts
637
+ var PACKAGE_NAME4 = "@contentful/experience-design-system-cli";
638
+ var pendingRun;
639
+ function generateRunId() {
640
+ const now = /* @__PURE__ */ new Date();
641
+ const pad = (n) => String(n).padStart(2, "0");
642
+ return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
643
+ }
644
+ function sessionsRootDir() {
645
+ return join6(findPackageRoot(import.meta.url, PACKAGE_NAME4), ".contentful", "debug", "sessions");
646
+ }
647
+ function datePrefix(now = /* @__PURE__ */ new Date()) {
648
+ const pad = (n) => String(n).padStart(2, "0");
649
+ return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
650
+ }
651
+ function slugify(value) {
652
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
653
+ }
654
+ function generateSessionId() {
655
+ const today = datePrefix();
656
+ const root = sessionsRootDir();
657
+ const existing = existsSync3(root) ? readdirSync(root) : [];
658
+ const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
659
+ const maxSeq = existing.reduce((max, entry) => {
660
+ const match = seqPattern.exec(entry);
661
+ return match ? Math.max(max, Number(match[1])) : max;
662
+ }, 0);
663
+ return `${today}-session-${maxSeq + 1}`;
664
+ }
665
+ var SESSION_ID = generateSessionId();
666
+ function sessionDebugDir() {
667
+ return join6(sessionsRootDir(), SESSION_ID);
668
+ }
669
+ void isDebugModeEnabled().then((enabled) => {
670
+ if (!enabled) return void 0;
671
+ return mkdir3(sessionDebugDir(), { recursive: true });
672
+ });
673
+ async function isDebugModeEnabled() {
674
+ try {
675
+ return (await readDebugModeSetting()).enabled;
676
+ } catch {
677
+ return true;
678
+ }
679
+ }
680
+ function redact(value) {
681
+ const clone = { ...value };
682
+ if ("cma_token" in clone) {
683
+ const raw = clone.cma_token;
684
+ clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
685
+ }
686
+ return clone;
687
+ }
688
+ function startDebugRun({
689
+ flow,
690
+ step,
691
+ menuOption,
692
+ inputs
693
+ }) {
694
+ const runId = generateRunId();
695
+ const startedAt = Date.now();
696
+ const redactedInputs = redact(inputs);
697
+ isDebugModeEnabled().then((enabled) => {
698
+ if (!enabled) return;
699
+ pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
700
+ });
701
+ }
702
+ async function finishDebugRun({
703
+ outputs,
704
+ status,
705
+ exitMethod
706
+ }) {
707
+ const run = pendingRun;
708
+ if (!run) return;
709
+ pendingRun = void 0;
710
+ const durationMs = Date.now() - run.startedAt;
711
+ const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
712
+ const flowSegments = run.flow.split("/");
713
+ const dir = join6(sessionDebugDir(), ...flowSegments);
714
+ await mkdir3(dir, { recursive: true });
715
+ const filename = nextAttemptFilename(dir, run.menuOption);
716
+ await writeFile3(join6(dir, filename), content, { mode: 384 });
717
+ }
718
+ function nextAttemptFilename(dir, menuOption) {
719
+ const today = datePrefix();
720
+ const optionSlug = slugify(menuOption);
721
+ const existing = existsSync3(dir) ? readdirSync(dir) : [];
722
+ const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
723
+ const maxAttempt = existing.reduce((max, entry) => {
724
+ const match = attemptPattern.exec(entry);
725
+ return match ? Math.max(max, Number(match[1])) : max;
726
+ }, 0);
727
+ return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
728
+ }
729
+ function renderMarkdown(run, finish) {
730
+ const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
731
+ const stepLabel = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
732
+ const flowSlug = run.flow.split("/").join("-");
733
+ return `# Debug Log
734
+
735
+ - Run ID: ${run.runId}
736
+ - Flow: ${flowSlug}
737
+ - Step: ${stepLabel}
738
+ - Menu option: ${run.menuOption}
739
+ - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
740
+ - CLI version: ${readPackageVersion()}
741
+ - Platform: ${process.platform} / Node ${process.version}
742
+ - Duration on screen: ${finish.durationMs}ms
743
+ - Status: ${finish.status}
744
+ - Exit method: ${finish.exitMethod}
745
+
746
+ ## Inputs
747
+ \`\`\`json
748
+ ${JSON.stringify(run.inputs, null, 2)}
749
+ \`\`\`
750
+
751
+ ## Outputs
752
+ \`\`\`json
753
+ ${JSON.stringify(finish.outputs, null, 2)}
754
+ \`\`\`
755
+ `;
756
+ }
757
+ function handleCrash() {
758
+ return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
759
+ }
760
+ process.once("uncaughtException", (err) => {
761
+ void handleCrash().finally(() => {
762
+ throw err;
763
+ });
764
+ });
765
+ process.once("unhandledRejection", (reason) => {
766
+ void handleCrash().finally(() => {
767
+ throw reason;
768
+ });
769
+ });
770
+ process.once("SIGINT", () => {
771
+ void handleCrash().finally(() => {
772
+ process.exit(130);
773
+ });
774
+ });
775
+
776
+ // packages/experience-design-system-cli/src/tui/upgrade/PageContainer.tsx
777
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1018
778
  var UPGRADE_COMMANDS = ["git pull", "pnpm install", "pnpm build"];
1019
779
  function UpgradeScreen({ onDone }) {
1020
- const [upgradeCheck, setUpgradeCheck] = useState8();
1021
- useEffect6(() => {
780
+ const [upgradeCheck, setUpgradeCheck] = useState6();
781
+ useEffect5(() => {
1022
782
  startDebugRun({
1023
783
  flow: "upgrade",
1024
784
  step: "01-upgrade",
@@ -1027,7 +787,7 @@ function UpgradeScreen({ onDone }) {
1027
787
  });
1028
788
  checkForUpgrade().then(setUpgradeCheck).catch(() => setUpgradeCheck({ status: "error" }));
1029
789
  }, []);
1030
- useInput9((_input, key) => {
790
+ useInput7((_input, key) => {
1031
791
  if (key.return) {
1032
792
  void finishDebugRun({
1033
793
  outputs: upgradeCheck ?? {},
@@ -1038,12 +798,12 @@ function UpgradeScreen({ onDone }) {
1038
798
  return;
1039
799
  }
1040
800
  });
1041
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
1042
- /* @__PURE__ */ jsx9(Text9, { bold: true, children: "Upgrade" }),
1043
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
801
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
802
+ /* @__PURE__ */ jsx7(Text7, { bold: true, children: "Upgrade" }),
803
+ /* @__PURE__ */ jsx7(Text7, { children: " " }),
1044
804
  renderBody(upgradeCheck),
1045
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
1046
- /* @__PURE__ */ jsxs9(Text9, { bold: true, color: PALETTE.accent, children: [
805
+ /* @__PURE__ */ jsx7(Text7, { children: " " }),
806
+ /* @__PURE__ */ jsxs7(Text7, { bold: true, color: PALETTE.accent, children: [
1047
807
  FOCUS_MARKER,
1048
808
  " Go Back"
1049
809
  ] })
@@ -1051,57 +811,51 @@ function UpgradeScreen({ onDone }) {
1051
811
  }
1052
812
  function renderBody(upgradeCheck) {
1053
813
  if (!upgradeCheck) {
1054
- return /* @__PURE__ */ jsx9(Text9, { color: PALETTE.muted, children: "Checking for updates\u2026" });
814
+ return /* @__PURE__ */ jsx7(Text7, { color: PALETTE.muted, children: "Checking for updates\u2026" });
1055
815
  }
1056
816
  if (upgradeCheck.status === "error") {
1057
- return /* @__PURE__ */ jsx9(Text9, { color: PALETTE.warning, children: "Couldn't check for updates \u2014 check your network connection and try again." });
817
+ return /* @__PURE__ */ jsx7(Text7, { color: PALETTE.warning, children: "Couldn't check for updates \u2014 check your network connection and try again." });
1058
818
  }
1059
819
  if (upgradeCheck.status === "up-to-date") {
1060
- return /* @__PURE__ */ jsxs9(Text9, { color: PALETTE.success, children: [
820
+ return /* @__PURE__ */ jsxs7(Text7, { color: PALETTE.success, children: [
1061
821
  "You're already on the latest version (v",
1062
822
  upgradeCheck.current,
1063
823
  ")."
1064
824
  ] });
1065
825
  }
1066
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
1067
- /* @__PURE__ */ jsxs9(Text9, { color: PALETTE.muted, children: [
1068
- /* @__PURE__ */ jsxs9(Text9, { bold: true, color: PALETTE.success, children: [
826
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
827
+ /* @__PURE__ */ jsxs7(Text7, { color: PALETTE.muted, children: [
828
+ /* @__PURE__ */ jsxs7(Text7, { bold: true, color: PALETTE.success, children: [
1069
829
  "v",
1070
830
  upgradeCheck.latest
1071
831
  ] }),
1072
832
  " ",
1073
833
  "is available (you're on ",
1074
- /* @__PURE__ */ jsxs9(Text9, { bold: true, children: [
834
+ /* @__PURE__ */ jsxs7(Text7, { bold: true, children: [
1075
835
  "v",
1076
836
  upgradeCheck.current
1077
837
  ] }),
1078
838
  "). Exit this program, cd into the root of your local clone of contentful/experience-design-system-sdk-public, then run:"
1079
839
  ] }),
1080
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
1081
- /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", borderStyle: "round", borderColor: PALETTE.border, paddingX: 1, children: UPGRADE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx9(Text9, { bold: true, children: cmd }, cmd)) })
840
+ /* @__PURE__ */ jsx7(Text7, { children: " " }),
841
+ /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", borderStyle: "round", borderColor: PALETTE.border, paddingX: 1, children: UPGRADE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx7(Text7, { bold: true, children: cmd }, cmd)) })
1082
842
  ] });
1083
843
  }
1084
844
 
1085
845
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
1086
- import { useEffect as useEffect7, useState as useState9 } from "react";
1087
- import { Box as Box10, Text as Text10, useInput as useInput10 } from "ink";
1088
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
846
+ import { useEffect as useEffect6, useState as useState7 } from "react";
847
+ import { Box as Box8, Text as Text8, useInput as useInput8 } from "ink";
848
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1089
849
  function DebugModeScreen({ onDone }) {
1090
- const [loading, setLoading] = useState9(true);
1091
- const [enabled, setEnabled] = useState9(true);
1092
- useEffect7(() => {
850
+ const [loading, setLoading] = useState7(true);
851
+ const [enabled, setEnabled] = useState7(true);
852
+ useEffect6(() => {
1093
853
  readDebugModeSetting().then((setting) => {
1094
854
  setEnabled(setting.enabled);
1095
855
  setLoading(false);
1096
- startDebugRun({
1097
- flow: "settings/debug-mode",
1098
- step: "01-debug-mode",
1099
- menuOption: "Debug Mode",
1100
- inputs: { enabled: setting.enabled }
1101
- });
1102
856
  });
1103
857
  }, []);
1104
- useInput10((input, key) => {
858
+ useInput8((input, key) => {
1105
859
  if (loading) return;
1106
860
  if (key.return || input === " ") {
1107
861
  setEnabled((current) => {
@@ -1112,92 +866,64 @@ function DebugModeScreen({ onDone }) {
1112
866
  return;
1113
867
  }
1114
868
  if (key.escape || input === "q") {
1115
- void finishDebugRun({ outputs: { enabled }, status: "success", exitMethod: "saved" });
1116
869
  onDone();
1117
870
  }
1118
871
  });
1119
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
1120
- /* @__PURE__ */ jsx10(Text10, { bold: true, children: "Settings \u203A Debug Mode" }),
1121
- /* @__PURE__ */ jsx10(Text10, { children: " " }),
1122
- loading ? /* @__PURE__ */ jsx10(Text10, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs10(Text10, { children: [
872
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
873
+ /* @__PURE__ */ jsx8(Text8, { bold: true, children: "Settings \u203A Debug Mode" }),
874
+ /* @__PURE__ */ jsx8(Text8, { children: " " }),
875
+ loading ? /* @__PURE__ */ jsx8(Text8, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs8(Text8, { children: [
1123
876
  "Debug logging:",
1124
877
  " ",
1125
- /* @__PURE__ */ jsx10(Text10, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
878
+ /* @__PURE__ */ jsx8(Text8, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
1126
879
  ] }),
1127
- /* @__PURE__ */ jsx10(Text10, { children: " " }),
1128
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "[Enter/Space] Toggle [Esc/q] Back to Settings" })
880
+ /* @__PURE__ */ jsx8(Text8, { children: " " }),
881
+ /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "[Enter/Space] Toggle [Esc/q] Back to Settings" })
1129
882
  ] });
1130
883
  }
1131
884
 
1132
885
  // packages/experience-design-system-cli/app.tsx
1133
- import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
886
+ import { jsx as jsx9 } from "react/jsx-runtime";
1134
887
  function App({ onLaunchImport, importExitCode }) {
1135
888
  const returnedFromImport = importExitCode !== void 0;
1136
- const [screen, setScreen] = useState10(returnedFromImport ? "import" : "start");
1137
- const [showImportResult, setShowImportResult] = useState10(returnedFromImport);
1138
- const [projectPath, setProjectPath] = useState10();
1139
- const [importDefaults, setImportDefaults] = useState10();
1140
- useEffect8(() => {
1141
- if (screen !== "import") {
1142
- setImportDefaults(void 0);
1143
- return;
1144
- }
1145
- void readCredentials().then(
1146
- (saved) => setImportDefaults({ componentDir: saved.defaultComponentDir ?? "", tokenFile: saved.defaultTokenFile ?? "" })
1147
- );
1148
- }, [screen]);
889
+ const [screen, setScreen] = useState8(returnedFromImport ? "import" : "start");
1149
890
  const goToStart = () => setScreen("start");
1150
891
  const goToSettings = () => setScreen("settings");
1151
- const finishImportResult = () => {
1152
- setShowImportResult(false);
1153
- setProjectPath(void 0);
1154
- goToStart();
1155
- };
1156
- const leaveImport = () => {
1157
- setProjectPath(void 0);
1158
- goToStart();
892
+ const navigateFromHome = (next) => {
893
+ if (next === "import" && onLaunchImport) {
894
+ onLaunchImport();
895
+ return;
896
+ }
897
+ setScreen(next);
1159
898
  };
1160
899
  switch (screen) {
1161
900
  case "import":
1162
- if (showImportResult) return /* @__PURE__ */ jsx11(ImportScreen, { exitCode: importExitCode, onDone: finishImportResult });
1163
- if (importDefaults === void 0) return /* @__PURE__ */ jsx11(Fragment3, {});
1164
- if (projectPath === void 0) {
1165
- return /* @__PURE__ */ jsx11(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
1166
- }
1167
- return /* @__PURE__ */ jsx11(
1168
- TokenInputScreen,
1169
- {
1170
- initialPath: importDefaults.tokenFile,
1171
- onConfirm: (tokens) => onLaunchImport?.({ project: projectPath, tokens }),
1172
- onSkip: () => onLaunchImport?.({ project: projectPath }),
1173
- onBack: () => setProjectPath(void 0)
1174
- }
1175
- );
901
+ return /* @__PURE__ */ jsx9(ImportScreen, { exitCode: importExitCode, onDone: goToStart });
1176
902
  case "help":
1177
- return /* @__PURE__ */ jsx11(HelpScreen, { onDone: goToStart });
903
+ return /* @__PURE__ */ jsx9(HelpScreen, { onDone: goToStart });
1178
904
  case "upgrade":
1179
- return /* @__PURE__ */ jsx11(UpgradeScreen, { onDone: goToStart });
905
+ return /* @__PURE__ */ jsx9(UpgradeScreen, { onDone: goToStart });
1180
906
  case "settings":
1181
- return /* @__PURE__ */ jsx11(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
907
+ return /* @__PURE__ */ jsx9(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
1182
908
  case "settings-configuration":
1183
- return /* @__PURE__ */ jsx11(ConfigurationScreen, { onDone: goToSettings });
909
+ return /* @__PURE__ */ jsx9(ConfigurationScreen, { onDone: goToSettings });
1184
910
  case "settings-opt-in-analytics":
1185
- return /* @__PURE__ */ jsx11(OptInAnalyticsScreen, { onDone: goToSettings });
911
+ return /* @__PURE__ */ jsx9(OptInAnalyticsScreen, { onDone: goToSettings });
1186
912
  case "settings-debug-mode":
1187
- return /* @__PURE__ */ jsx11(DebugModeScreen, { onDone: goToSettings });
913
+ return /* @__PURE__ */ jsx9(DebugModeScreen, { onDone: goToSettings });
1188
914
  case "start":
1189
- return /* @__PURE__ */ jsx11(HomeScreen, { onNavigate: setScreen });
915
+ return /* @__PURE__ */ jsx9(HomeScreen, { onNavigate: navigateFromHome });
1190
916
  }
1191
917
  }
1192
918
  async function renderUntilImportRequestedOrExit(renderApp, importExitCode) {
1193
- let requestedImport;
919
+ let importRequested = false;
1194
920
  const instance = renderApp(
1195
- /* @__PURE__ */ jsx11(
921
+ /* @__PURE__ */ jsx9(
1196
922
  App,
1197
923
  {
1198
924
  importExitCode,
1199
- onLaunchImport: (options) => {
1200
- requestedImport = options;
925
+ onLaunchImport: () => {
926
+ importRequested = true;
1201
927
  instance.unmount();
1202
928
  }
1203
929
  }
@@ -1205,15 +931,13 @@ async function renderUntilImportRequestedOrExit(renderApp, importExitCode) {
1205
931
  );
1206
932
  await instance.waitUntilExit();
1207
933
  await stopReadingTerminal();
1208
- return requestedImport;
934
+ return importRequested;
1209
935
  }
1210
936
  async function runApp(renderApp) {
1211
937
  let importExitCode;
1212
- let requestedImport = await renderUntilImportRequestedOrExit(renderApp, importExitCode);
1213
- while (requestedImport !== void 0) {
1214
- importExitCode = (await spawnV1Import(requestedImport)).exitCode;
938
+ while (await renderUntilImportRequestedOrExit(renderApp, importExitCode)) {
939
+ importExitCode = (await spawnV1Import({})).exitCode;
1215
940
  startReadingTerminal();
1216
- requestedImport = await renderUntilImportRequestedOrExit(renderApp, importExitCode);
1217
941
  }
1218
942
  }
1219
943
  export {