@contentful/experience-design-system-cli 2.36.2-dev-build-a6f80ae6.0 → 2.36.2-dev-build-7907fec3.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/index.js CHANGED
@@ -167,10 +167,23 @@ var init_use_terminal_width = __esm({
167
167
  }
168
168
  });
169
169
 
170
+ // packages/experience-design-system-cli/src/tui/control-hints.tsx
171
+ import { Text } from "ink";
172
+ import { jsx } from "react/jsx-runtime";
173
+ function ControlHints({ hints }) {
174
+ return /* @__PURE__ */ jsx(Text, { color: PALETTE.muted, children: hints.map((hint) => `${hint.keys} ${hint.label}`).join(" \xB7 ") });
175
+ }
176
+ var init_control_hints = __esm({
177
+ "packages/experience-design-system-cli/src/tui/control-hints.tsx"() {
178
+ "use strict";
179
+ init_home_theme();
180
+ }
181
+ });
182
+
170
183
  // packages/experience-design-system-cli/src/tui/home/home.tsx
171
184
  import { useEffect as useEffect2, useState as useState2 } from "react";
172
- import { Box, Text, useApp, useInput } from "ink";
173
- import { jsx, jsxs } from "react/jsx-runtime";
185
+ import { Box, Text as Text2, useApp, useInput } from "ink";
186
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
174
187
  function upgradeItemDisplay(upgradeCheck) {
175
188
  if (upgradeCheck?.status === "update-available") {
176
189
  return { label: `Upgrade Version (v${upgradeCheck.latest} available)`, color: PALETTE.success };
@@ -213,27 +226,27 @@ function HomeScreen({ onNavigate }) {
213
226
  });
214
227
  if (tooNarrow) {
215
228
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
216
- /* @__PURE__ */ jsx(Text, { bold: true, color: PALETTE.warning, children: "Terminal too small" }),
217
- /* @__PURE__ */ jsx(Text, { color: PALETTE.muted, children: "Press q to quit, make your terminal full screen, then run experiences import again." })
229
+ /* @__PURE__ */ jsx2(Text2, { bold: true, color: PALETTE.warning, children: "Terminal too small" }),
230
+ /* @__PURE__ */ jsx2(Text2, { color: PALETTE.muted, children: "Press q to quit, make your terminal full screen, then run experiences import again." })
218
231
  ] });
219
232
  }
220
233
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
221
234
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "center", children: [
222
- /* @__PURE__ */ jsx(Text, { bold: true, color: PALETTE.heading, children: HEADING }),
223
- /* @__PURE__ */ jsx(Text, { children: brandBar(HEADING.length).map((segment, i) => /* @__PURE__ */ jsx(Text, { color: segment.color, children: segment.text }, i)) }),
224
- /* @__PURE__ */ jsx(Text, { color: PALETTE.muted, children: SUBTITLE }),
225
- /* @__PURE__ */ jsxs(Text, { color: PALETTE.muted, children: [
235
+ /* @__PURE__ */ jsx2(Text2, { bold: true, color: PALETTE.heading, children: HEADING }),
236
+ /* @__PURE__ */ jsx2(Text2, { children: brandBar(HEADING.length).map((segment, i) => /* @__PURE__ */ jsx2(Text2, { color: segment.color, children: segment.text }, i)) }),
237
+ /* @__PURE__ */ jsx2(Text2, { color: PALETTE.muted, children: SUBTITLE }),
238
+ /* @__PURE__ */ jsxs(Text2, { color: PALETTE.muted, children: [
226
239
  "v",
227
240
  VERSION
228
241
  ] })
229
242
  ] }),
230
- /* @__PURE__ */ jsx(Box, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: START_ITEMS.map((item, i) => {
243
+ /* @__PURE__ */ jsx2(Box, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsx2(Box, { flexDirection: "column", children: START_ITEMS.map((item, i) => {
231
244
  const focused = i === focusIdx;
232
245
  const isUpgradeItem = item.screen === "upgrade";
233
246
  const display = isUpgradeItem ? upgradeItemDisplay(upgradeCheck) : { label: item.label };
234
247
  const dimmed = isUpgradeItem && upgradeDisabled;
235
248
  return /* @__PURE__ */ jsxs(
236
- Text,
249
+ Text2,
237
250
  {
238
251
  bold: focused && !dimmed,
239
252
  dimColor: dimmed,
@@ -246,7 +259,16 @@ function HomeScreen({ onNavigate }) {
246
259
  item.label
247
260
  );
248
261
  }) }) }),
249
- /* @__PURE__ */ jsx(Box, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsx(Text, { color: PALETTE.muted, children: "\u2191/\u2193 move \xB7 \u23CE select \xB7 q quit" }) })
262
+ /* @__PURE__ */ jsx2(Box, { marginTop: 1, justifyContent: "center", children: /* @__PURE__ */ jsx2(
263
+ ControlHints,
264
+ {
265
+ hints: [
266
+ { keys: "\u2191/\u2193", label: "move" },
267
+ { keys: "\u23CE", label: "select" },
268
+ { keys: "q", label: "quit" }
269
+ ]
270
+ }
271
+ ) })
250
272
  ] });
251
273
  }
252
274
  var VERSION, HEADING, SUBTITLE, MIN_TERMINAL_WIDTH, START_ITEMS;
@@ -256,6 +278,7 @@ var init_home = __esm({
256
278
  init_home_theme();
257
279
  init_version();
258
280
  init_use_terminal_width();
281
+ init_control_hints();
259
282
  VERSION = readPackageVersion();
260
283
  HEADING = "Contentful Experiences";
261
284
  SUBTITLE = "Let's import your design system into Contentful";
@@ -270,8 +293,8 @@ var init_home = __esm({
270
293
  });
271
294
 
272
295
  // packages/experience-design-system-cli/src/tui/import/PageContainer.tsx
273
- import { Box as Box2, Text as Text2, useInput as useInput2 } from "ink";
274
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
296
+ import { Box as Box2, Text as Text3, useInput as useInput2 } from "ink";
297
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
275
298
  function ImportScreen({ exitCode, onDone }) {
276
299
  useInput2((input, key) => {
277
300
  if (key.return || key.escape || input === "q") {
@@ -280,14 +303,14 @@ function ImportScreen({ exitCode, onDone }) {
280
303
  });
281
304
  const isSuccess = exitCode === 0;
282
305
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
283
- /* @__PURE__ */ jsx2(Text2, { bold: true, children: "Import" }),
284
- /* @__PURE__ */ jsx2(Text2, { children: " " }),
285
- isSuccess ? /* @__PURE__ */ jsx2(Text2, { color: PALETTE.success, children: "\u2713 Import complete" }) : /* @__PURE__ */ jsxs2(Text2, { color: PALETTE.error, children: [
306
+ /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Import" }),
307
+ /* @__PURE__ */ jsx3(Text3, { children: " " }),
308
+ isSuccess ? /* @__PURE__ */ jsx3(Text3, { color: PALETTE.success, children: "\u2713 Import complete" }) : /* @__PURE__ */ jsxs2(Text3, { color: PALETTE.error, children: [
286
309
  "\u2717 Import failed: process exited with code ",
287
310
  exitCode ?? "unknown"
288
311
  ] }),
289
- /* @__PURE__ */ jsx2(Text2, { children: " " }),
290
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "[Enter] Back to Start" })
312
+ /* @__PURE__ */ jsx3(Text3, { children: " " }),
313
+ /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "[Enter] Back to Start" })
291
314
  ] });
292
315
  }
293
316
  var init_PageContainer = __esm({
@@ -297,6 +320,250 @@ var init_PageContainer = __esm({
297
320
  }
298
321
  });
299
322
 
323
+ // packages/experience-design-system-cli/src/tui/import/steps/01-welcome/logic.ts
324
+ function shouldQuit(value, input, key) {
325
+ if (key.escape) return true;
326
+ return value === "" && input === "q" && !key.ctrl && !key.meta;
327
+ }
328
+ function toProjectPath(value) {
329
+ const projectPath = value.trim();
330
+ return projectPath === "" ? null : projectPath;
331
+ }
332
+ var init_logic = __esm({
333
+ "packages/experience-design-system-cli/src/tui/import/steps/01-welcome/logic.ts"() {
334
+ "use strict";
335
+ }
336
+ });
337
+
338
+ // packages/experience-design-system-cli/src/tui/import/steps/01-welcome/controls.ts
339
+ import { useInput as useInput3 } from "ink";
340
+ function useWelcomeControls(projectPath, onQuit) {
341
+ useInput3((input, key) => {
342
+ if (shouldQuit(projectPath, input, key)) onQuit();
343
+ });
344
+ }
345
+ var WELCOME_CONTROLS;
346
+ var init_controls = __esm({
347
+ "packages/experience-design-system-cli/src/tui/import/steps/01-welcome/controls.ts"() {
348
+ "use strict";
349
+ init_logic();
350
+ WELCOME_CONTROLS = [
351
+ { keys: "Enter", label: "Continue" },
352
+ { keys: "Esc/q", label: "Back to menu" }
353
+ ];
354
+ }
355
+ });
356
+
357
+ // packages/experience-design-system-cli/src/tui/import/steps/01-welcome/screen.tsx
358
+ import { useState as useState3 } from "react";
359
+ import { Box as Box3, Text as Text4 } from "ink";
360
+ import TextInput from "ink-text-input";
361
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
362
+ function WelcomeScreen({ onContinue, onQuit, initialPath = "" }) {
363
+ const [projectPath, setProjectPath] = useState3(initialPath);
364
+ useWelcomeControls(projectPath, onQuit);
365
+ const submit = (value) => {
366
+ const path = toProjectPath(value);
367
+ if (path) onContinue(path);
368
+ };
369
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [
370
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: PALETTE.success, children: "\u{1F44B} Hey! Let's import your design system into Contentful." }),
371
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "I'll walk you through 5 steps to get your components into Contentful ExO." }),
372
+ /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
373
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: RULE }),
374
+ OVERVIEW.map((item) => /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
375
+ /* @__PURE__ */ jsx4(Text4, { bold: true, children: item.label }),
376
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: item.description })
377
+ ] }, item.label)),
378
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: RULE })
379
+ ] }),
380
+ /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
381
+ /* @__PURE__ */ jsx4(Text4, { children: "Where is your component library?" }),
382
+ /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
383
+ /* @__PURE__ */ jsx4(Text4, { color: PALETTE.accent, children: "?" }),
384
+ /* @__PURE__ */ jsx4(Text4, { children: "Project path:" }),
385
+ /* @__PURE__ */ jsx4(TextInput, { value: projectPath, onChange: setProjectPath, onSubmit: submit })
386
+ ] })
387
+ ] }),
388
+ /* @__PURE__ */ jsx4(Box3, { marginTop: 1, gap: 3, children: WELCOME_CONTROLS.map((control) => /* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
389
+ "[",
390
+ control.keys,
391
+ "] ",
392
+ control.label
393
+ ] }, control.keys)) })
394
+ ] });
395
+ }
396
+ var RULE, OVERVIEW;
397
+ var init_screen = __esm({
398
+ "packages/experience-design-system-cli/src/tui/import/steps/01-welcome/screen.tsx"() {
399
+ "use strict";
400
+ init_home_theme();
401
+ init_controls();
402
+ init_logic();
403
+ 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";
404
+ OVERVIEW = [
405
+ { label: "Step 1", description: "Extract components from your codebase" },
406
+ { label: "Step 2", description: "Review what was extracted" },
407
+ { label: "Step 3", description: "Generate CDF definitions with Claude" },
408
+ { label: "Step 4", description: "Review generated definitions" },
409
+ { label: "Step 5", description: "Push to Contentful" }
410
+ ];
411
+ }
412
+ });
413
+
414
+ // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/logic.ts
415
+ function isPlainKeyOnEmptyField(value, input, key, expected) {
416
+ return value === "" && input === expected && !key.ctrl && !key.meta;
417
+ }
418
+ function shouldGoBack(value, input, key) {
419
+ return key.escape || isPlainKeyOnEmptyField(value, input, key, "q");
420
+ }
421
+ function shouldSkip(value, input, key) {
422
+ return isPlainKeyOnEmptyField(value, input, key, "s");
423
+ }
424
+ function toTokenPath(value) {
425
+ const tokenPath = value.trim();
426
+ return tokenPath === "" ? null : tokenPath;
427
+ }
428
+ var init_logic2 = __esm({
429
+ "packages/experience-design-system-cli/src/tui/import/steps/02-token-input/logic.ts"() {
430
+ "use strict";
431
+ }
432
+ });
433
+
434
+ // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/controls.ts
435
+ import { useInput as useInput4 } from "ink";
436
+ function useTokenInputControls(tokenPath, onSkip, onBack) {
437
+ useInput4((input, key) => {
438
+ if (shouldGoBack(tokenPath, input, key)) onBack();
439
+ else if (shouldSkip(tokenPath, input, key)) onSkip();
440
+ });
441
+ }
442
+ var TOKEN_INPUT_CONTROLS;
443
+ var init_controls2 = __esm({
444
+ "packages/experience-design-system-cli/src/tui/import/steps/02-token-input/controls.ts"() {
445
+ "use strict";
446
+ init_logic2();
447
+ TOKEN_INPUT_CONTROLS = [
448
+ { keys: "Enter", label: "Continue (skips if empty)" },
449
+ { keys: "s", label: "Skip" },
450
+ { keys: "Esc/q", label: "Back" }
451
+ ];
452
+ }
453
+ });
454
+
455
+ // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/validate-path.ts
456
+ import { statSync } from "node:fs";
457
+ import { homedir } from "node:os";
458
+ import { resolve } from "node:path";
459
+ function stripQuotes(value) {
460
+ const quoted = value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'");
461
+ return value.length >= 2 && quoted ? value.slice(1, -1) : value;
462
+ }
463
+ function expandHome(value) {
464
+ return value === "~" || value.startsWith("~/") || value.startsWith("~\\") ? homedir() + value.slice(1) : value;
465
+ }
466
+ function validateTokenPath(rawPath) {
467
+ const path = resolve(expandHome(stripQuotes(rawPath.trim())));
468
+ let stats;
469
+ try {
470
+ stats = statSync(path);
471
+ } catch {
472
+ return { ok: false, error: `Path not found: ${path}`, resolvedPath: path };
473
+ }
474
+ if (stats.isDirectory()) {
475
+ return {
476
+ ok: false,
477
+ error: "That's a directory \u2014 provide a path to a token file (e.g. tokens.json), not a folder.",
478
+ resolvedPath: path
479
+ };
480
+ }
481
+ if (!stats.isFile()) {
482
+ return { ok: false, error: `Not a regular file: ${path}`, resolvedPath: path };
483
+ }
484
+ return { ok: true, path };
485
+ }
486
+ var init_validate_path = __esm({
487
+ "packages/experience-design-system-cli/src/tui/import/steps/02-token-input/validate-path.ts"() {
488
+ "use strict";
489
+ }
490
+ });
491
+
492
+ // packages/experience-design-system-cli/src/tui/import/steps/02-token-input/screen.tsx
493
+ import { useState as useState4 } from "react";
494
+ import { Box as Box4, Text as Text5 } from "ink";
495
+ import TextInput2 from "ink-text-input";
496
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
497
+ function TokenInputScreen({
498
+ onConfirm,
499
+ onSkip,
500
+ onBack,
501
+ initialPath = ""
502
+ }) {
503
+ const [tokenPath, setTokenPath] = useState4(initialPath);
504
+ const [failure, setFailure] = useState4(null);
505
+ useTokenInputControls(tokenPath, onSkip, onBack);
506
+ const change = (value) => {
507
+ setTokenPath(value);
508
+ setFailure(null);
509
+ };
510
+ const submit = (value) => {
511
+ const rawPath = toTokenPath(value);
512
+ if (!rawPath) {
513
+ onSkip();
514
+ return;
515
+ }
516
+ const check = validateTokenPath(rawPath);
517
+ if (check.ok) onConfirm(check.path);
518
+ else setFailure({ error: check.error, resolvedPath: check.resolvedPath });
519
+ };
520
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, paddingX: 2, paddingY: 1, children: [
521
+ /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Design tokens" }),
522
+ /* @__PURE__ */ jsx5(Text5, { 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." }),
523
+ /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
524
+ /* @__PURE__ */ jsxs4(Box4, { gap: 1, children: [
525
+ /* @__PURE__ */ jsx5(Text5, { color: PALETTE.accent, children: "?" }),
526
+ /* @__PURE__ */ jsx5(Text5, { children: "Token path:" }),
527
+ /* @__PURE__ */ jsx5(TextInput2, { value: tokenPath, onChange: change, onSubmit: submit })
528
+ ] }),
529
+ failure && /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
530
+ /* @__PURE__ */ jsxs4(Text5, { color: PALETTE.error, children: [
531
+ "\u2717 ",
532
+ failure.error
533
+ ] }),
534
+ /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
535
+ " Resolved to: ",
536
+ failure.resolvedPath
537
+ ] })
538
+ ] })
539
+ ] }),
540
+ /* @__PURE__ */ jsx5(Box4, { marginTop: 1, gap: 3, children: TOKEN_INPUT_CONTROLS.map((control) => /* @__PURE__ */ jsxs4(Text5, { dimColor: true, children: [
541
+ "[",
542
+ control.keys,
543
+ "] ",
544
+ control.label
545
+ ] }, control.keys)) })
546
+ ] });
547
+ }
548
+ var init_screen2 = __esm({
549
+ "packages/experience-design-system-cli/src/tui/import/steps/02-token-input/screen.tsx"() {
550
+ "use strict";
551
+ init_home_theme();
552
+ init_controls2();
553
+ init_logic2();
554
+ init_validate_path();
555
+ }
556
+ });
557
+
558
+ // packages/experience-design-system-cli/src/tui/import/steps/index.ts
559
+ var init_steps = __esm({
560
+ "packages/experience-design-system-cli/src/tui/import/steps/index.ts"() {
561
+ "use strict";
562
+ init_screen();
563
+ init_screen2();
564
+ }
565
+ });
566
+
300
567
  // packages/experience-design-system-cli/src/tui/import/spawn-v1-import.ts
301
568
  import { spawn as spawn2 } from "node:child_process";
302
569
  function buildArgs(options) {
@@ -304,6 +571,9 @@ function buildArgs(options) {
304
571
  if (options.project) {
305
572
  args.push("--project", options.project);
306
573
  }
574
+ if (options.tokens) {
575
+ args.push("--tokens", options.tokens);
576
+ }
307
577
  return args;
308
578
  }
309
579
  async function spawnV1Import(options = {}) {
@@ -333,7 +603,7 @@ function getTerminalHandle() {
333
603
  return process.stdin._handle;
334
604
  }
335
605
  async function stopReadingTerminal() {
336
- await new Promise((resolve) => setImmediate(resolve));
606
+ await new Promise((resolve2) => setImmediate(resolve2));
337
607
  const handle = getTerminalHandle();
338
608
  if (!handle?.readStop) return;
339
609
  handle.reading = false;
@@ -351,49 +621,319 @@ var init_terminal_input = __esm({
351
621
  }
352
622
  });
353
623
 
624
+ // packages/experience-design-system-types/dist/src/config/index.js
625
+ import { randomBytes } from "node:crypto";
626
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
627
+ import { homedir as homedir2 } from "node:os";
628
+ import { dirname as dirname2, join as join4 } from "node:path";
629
+ function configRoot() {
630
+ return process.env["EDS_HOME"] || join4(homedir2(), ".contentful", "experience-design-system-cli");
631
+ }
632
+ async function readSettings() {
633
+ try {
634
+ return JSON.parse(await readFile(configFilePath(), "utf8"));
635
+ } catch {
636
+ return {};
637
+ }
638
+ }
639
+ async function writeSettings(settings) {
640
+ const path = configFilePath();
641
+ await mkdir(dirname2(path), { recursive: true });
642
+ const tmp = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
643
+ await writeFile(tmp, `${JSON.stringify(settings, null, 2)}
644
+ `, { mode: 384 });
645
+ await rename(tmp, path);
646
+ }
647
+ async function updateSettings(patch) {
648
+ await writeSettings({ ...await readSettings(), ...patch });
649
+ }
650
+ var configFilePath, runsFilePath, debugSessionsDir, oldConfigDir;
651
+ var init_config = __esm({
652
+ "packages/experience-design-system-types/dist/src/config/index.js"() {
653
+ "use strict";
654
+ configFilePath = () => join4(configRoot(), "config.json");
655
+ runsFilePath = () => join4(configRoot(), "state", "runs.json");
656
+ debugSessionsDir = () => join4(configRoot(), "debug", "sessions");
657
+ oldConfigDir = () => join4(homedir2(), ".config", "experiences");
658
+ }
659
+ });
660
+
661
+ // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
662
+ async function readDebugModeSetting() {
663
+ const { debugMode } = await readSettings();
664
+ return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
665
+ }
666
+ async function writeDebugModeSetting(setting) {
667
+ await updateSettings({ debugMode: setting });
668
+ }
669
+ var DEFAULT_DEBUG_MODE_SETTING;
670
+ var init_debug_mode_store = __esm({
671
+ "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
672
+ "use strict";
673
+ init_config();
674
+ DEFAULT_DEBUG_MODE_SETTING = {
675
+ enabled: true
676
+ };
677
+ }
678
+ });
679
+
680
+ // packages/experience-design-system-cli/src/tui/debug-store.ts
681
+ import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
682
+ import { existsSync as existsSync3, readdirSync } from "node:fs";
683
+ import { join as join5 } from "node:path";
684
+ function generateRunId() {
685
+ const now = /* @__PURE__ */ new Date();
686
+ const pad = (n) => String(n).padStart(2, "0");
687
+ return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
688
+ }
689
+ function datePrefix(now = /* @__PURE__ */ new Date()) {
690
+ const pad = (n) => String(n).padStart(2, "0");
691
+ return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
692
+ }
693
+ function slugify(value) {
694
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
695
+ }
696
+ function generateSessionId() {
697
+ const today = datePrefix();
698
+ const root = debugSessionsDir();
699
+ const existing = existsSync3(root) ? readdirSync(root) : [];
700
+ const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
701
+ const maxSeq = existing.reduce((max, entry) => {
702
+ const match = seqPattern.exec(entry);
703
+ return match ? Math.max(max, Number(match[1])) : max;
704
+ }, 0);
705
+ return `${today}-session-${maxSeq + 1}`;
706
+ }
707
+ function sessionDebugDir() {
708
+ return join5(debugSessionsDir(), SESSION_ID);
709
+ }
710
+ function currentDebugSessionDir() {
711
+ return sessionDebugDir();
712
+ }
713
+ async function isDebugModeEnabled() {
714
+ try {
715
+ return (await readDebugModeSetting()).enabled;
716
+ } catch {
717
+ return true;
718
+ }
719
+ }
720
+ function redact(value) {
721
+ const clone = { ...value };
722
+ if ("cma_token" in clone) {
723
+ const raw = clone.cma_token;
724
+ clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
725
+ }
726
+ return clone;
727
+ }
728
+ function startDebugRun({
729
+ flow,
730
+ step,
731
+ menuOption,
732
+ inputs
733
+ }) {
734
+ const runId = generateRunId();
735
+ const startedAt = Date.now();
736
+ const redactedInputs = redact(inputs);
737
+ isDebugModeEnabled().then((enabled) => {
738
+ if (!enabled) return;
739
+ pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
740
+ });
741
+ }
742
+ async function finishDebugRun({
743
+ outputs,
744
+ status,
745
+ exitMethod
746
+ }) {
747
+ const run = pendingRun;
748
+ if (!run) return;
749
+ pendingRun = void 0;
750
+ const durationMs = Date.now() - run.startedAt;
751
+ const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
752
+ const flowSegments = run.flow.split("/");
753
+ const dir = join5(sessionDebugDir(), ...flowSegments);
754
+ await mkdir2(dir, { recursive: true });
755
+ const filename = nextAttemptFilename(dir, run.menuOption);
756
+ await writeFile2(join5(dir, filename), content, { mode: 384 });
757
+ }
758
+ function nextAttemptFilename(dir, menuOption) {
759
+ const today = datePrefix();
760
+ const optionSlug = slugify(menuOption);
761
+ const existing = existsSync3(dir) ? readdirSync(dir) : [];
762
+ const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
763
+ const maxAttempt = existing.reduce((max, entry) => {
764
+ const match = attemptPattern.exec(entry);
765
+ return match ? Math.max(max, Number(match[1])) : max;
766
+ }, 0);
767
+ return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
768
+ }
769
+ function renderMarkdown(run, finish) {
770
+ const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
771
+ const stepLabel = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
772
+ const flowSlug = run.flow.split("/").join("-");
773
+ return `# Debug Log
774
+
775
+ - Run ID: ${run.runId}
776
+ - Flow: ${flowSlug}
777
+ - Step: ${stepLabel}
778
+ - Menu option: ${run.menuOption}
779
+ - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
780
+ - CLI version: ${readPackageVersion()}
781
+ - Platform: ${process.platform} / Node ${process.version}
782
+ - Duration on screen: ${finish.durationMs}ms
783
+ - Status: ${finish.status}
784
+ - Exit method: ${finish.exitMethod}
785
+
786
+ ## Inputs
787
+ \`\`\`json
788
+ ${JSON.stringify(run.inputs, null, 2)}
789
+ \`\`\`
790
+
791
+ ## Outputs
792
+ \`\`\`json
793
+ ${JSON.stringify(finish.outputs, null, 2)}
794
+ \`\`\`
795
+ `;
796
+ }
797
+ function handleCrash() {
798
+ return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
799
+ }
800
+ var pendingRun, SESSION_ID;
801
+ var init_debug_store = __esm({
802
+ "packages/experience-design-system-cli/src/tui/debug-store.ts"() {
803
+ "use strict";
804
+ init_config();
805
+ init_version();
806
+ init_debug_mode_store();
807
+ SESSION_ID = generateSessionId();
808
+ void isDebugModeEnabled().then((enabled) => {
809
+ if (!enabled) return void 0;
810
+ return mkdir2(sessionDebugDir(), { recursive: true });
811
+ });
812
+ process.once("uncaughtException", (err) => {
813
+ void handleCrash().finally(() => {
814
+ throw err;
815
+ });
816
+ });
817
+ process.once("unhandledRejection", (reason) => {
818
+ void handleCrash().finally(() => {
819
+ throw reason;
820
+ });
821
+ });
822
+ process.once("SIGINT", () => {
823
+ void handleCrash().finally(() => {
824
+ process.exit(130);
825
+ });
826
+ });
827
+ }
828
+ });
829
+
830
+ // packages/experience-design-system-cli/src/tui/help/help-info.ts
831
+ async function readHelpInfo() {
832
+ const debugMode = await readDebugModeSetting();
833
+ return {
834
+ storage: [
835
+ { label: "Config folder", value: configRoot() },
836
+ { label: "Settings file", value: configFilePath() },
837
+ { label: "Debug logs", value: debugSessionsDir() }
838
+ ],
839
+ troubleshooting: [
840
+ { label: "CLI version", value: readPackageVersion() },
841
+ { label: "Node", value: process.version },
842
+ { label: "Platform", value: `${process.platform} ${process.arch}` },
843
+ { label: "Debug Mode", value: debugMode.enabled ? "on" : "off" },
844
+ {
845
+ label: "This session",
846
+ value: debugMode.enabled ? currentDebugSessionDir() : "no logs written while Debug Mode is off"
847
+ }
848
+ ]
849
+ };
850
+ }
851
+ var init_help_info = __esm({
852
+ "packages/experience-design-system-cli/src/tui/help/help-info.ts"() {
853
+ "use strict";
854
+ init_config();
855
+ init_debug_store();
856
+ init_debug_mode_store();
857
+ init_version();
858
+ }
859
+ });
860
+
354
861
  // packages/experience-design-system-cli/src/tui/help/PageContainer.tsx
355
- import { Box as Box3, Text as Text3, useInput as useInput3 } from "ink";
356
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
862
+ import { useEffect as useEffect3, useState as useState5 } from "react";
863
+ import { Box as Box5, Text as Text6, useInput as useInput5 } from "ink";
864
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
865
+ function Section({ title, rows }) {
866
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
867
+ /* @__PURE__ */ jsx6(Text6, { bold: true, color: PALETTE.accent, children: title }),
868
+ rows.map((row) => /* @__PURE__ */ jsxs5(Box5, { gap: 1, children: [
869
+ /* @__PURE__ */ jsx6(Box5, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: row.label }) }),
870
+ /* @__PURE__ */ jsx6(Text6, { children: row.value })
871
+ ] }, row.label))
872
+ ] });
873
+ }
357
874
  function HelpScreen({ onDone }) {
358
- useInput3((input, key) => {
875
+ const [info, setInfo] = useState5();
876
+ useEffect3(() => {
877
+ startDebugRun({ flow: "help", step: "01-help", menuOption: "Help", inputs: {} });
878
+ void readHelpInfo().then(setInfo);
879
+ }, []);
880
+ const leave = (exitMethod) => {
881
+ void finishDebugRun({ outputs: {}, status: "success", exitMethod });
882
+ onDone();
883
+ };
884
+ useInput5((input, key) => {
359
885
  if (key.return) {
360
- onDone();
886
+ leave("saved");
361
887
  return;
362
888
  }
363
889
  if (key.escape || input === "q") {
364
- onDone();
890
+ leave("discarded");
365
891
  return;
366
892
  }
367
893
  });
368
- return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
369
- /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Help" }),
370
- /* @__PURE__ */ jsx3(Text3, { children: " " }),
371
- /* @__PURE__ */ jsx3(Text3, { children: "This is a placeholder screen for v2 help content." }),
372
- /* @__PURE__ */ jsx3(Text3, { children: " " }),
373
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "[Enter] Complete [Esc/q] Exit \u2014 both return to Start" })
894
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 2, paddingY: 1, gap: 1, children: [
895
+ /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Help" }),
896
+ info ? /* @__PURE__ */ jsxs5(Fragment, { children: [
897
+ /* @__PURE__ */ jsx6(Section, { title: "Where things are stored", rows: info.storage }),
898
+ /* @__PURE__ */ jsx6(Section, { title: "Troubleshooting", rows: info.troubleshooting }),
899
+ /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Hit a problem? Turn on Debug Mode in Settings, reproduce it, then share the session folder above. The CMA token is redacted from those logs." })
900
+ ] }) : /* @__PURE__ */ jsx6(Text6, { color: PALETTE.accent, children: "Loading..." }),
901
+ /* @__PURE__ */ jsx6(
902
+ ControlHints,
903
+ {
904
+ hints: [
905
+ { keys: "\u23CE", label: "done" },
906
+ { keys: "Esc/q", label: "back" }
907
+ ]
908
+ }
909
+ )
374
910
  ] });
375
911
  }
376
912
  var init_PageContainer2 = __esm({
377
913
  "packages/experience-design-system-cli/src/tui/help/PageContainer.tsx"() {
378
914
  "use strict";
915
+ init_home_theme();
916
+ init_debug_store();
917
+ init_control_hints();
918
+ init_help_info();
379
919
  }
380
920
  });
381
921
 
382
922
  // packages/experience-design-system-cli/src/tui/settings/PageContainer.tsx
383
- import { useState as useState3 } from "react";
384
- import { Box as Box4, Text as Text4, useInput as useInput4 } from "ink";
385
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
923
+ import { useState as useState6 } from "react";
924
+ import { Box as Box6, Text as Text7, useInput as useInput6 } from "ink";
925
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
386
926
  function SettingsScreen({
387
927
  onNavigate,
388
928
  onBack
389
929
  }) {
390
- const [focusIdx, setFocusIdx] = useState3(0);
930
+ const [focusIdx, setFocusIdx] = useState6(0);
391
931
  const items = [
392
932
  { label: "Configuration", screen: "settings-configuration" },
393
933
  { label: "Opt-in Analytics", screen: "settings-opt-in-analytics" },
394
934
  { label: "Debug Mode", screen: "settings-debug-mode" }
395
935
  ];
396
- useInput4((input, key) => {
936
+ useInput6((input, key) => {
397
937
  if (key.upArrow) {
398
938
  setFocusIdx((i) => (i - 1 + items.length) % items.length);
399
939
  return;
@@ -413,45 +953,41 @@ function SettingsScreen({
413
953
  onBack();
414
954
  }
415
955
  });
416
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
417
- /* @__PURE__ */ jsx4(Text4, { bold: true, children: "Settings" }),
418
- /* @__PURE__ */ jsx4(Text4, { children: " " }),
419
- items.map((item, i) => /* @__PURE__ */ jsxs4(Text4, { color: i === focusIdx ? "cyan" : void 0, children: [
956
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
957
+ /* @__PURE__ */ jsx7(Text7, { bold: true, children: "Settings" }),
958
+ /* @__PURE__ */ jsx7(Text7, { children: " " }),
959
+ items.map((item, i) => /* @__PURE__ */ jsxs6(Text7, { color: i === focusIdx ? "cyan" : void 0, children: [
420
960
  i === focusIdx ? "> " : " ",
421
961
  item.label
422
962
  ] }, item.label)),
423
- /* @__PURE__ */ jsx4(Text4, { children: " " }),
424
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "[\u2191/\u2193] Navigate [Enter] Select [Esc/q] Back to Start" })
963
+ /* @__PURE__ */ jsx7(Text7, { children: " " }),
964
+ /* @__PURE__ */ jsx7(
965
+ ControlHints,
966
+ {
967
+ hints: [
968
+ { keys: "\u2191/\u2193", label: "move" },
969
+ { keys: "\u23CE", label: "select" },
970
+ { keys: "Esc/q", label: "back" }
971
+ ]
972
+ }
973
+ )
425
974
  ] });
426
975
  }
427
976
  var init_PageContainer3 = __esm({
428
977
  "packages/experience-design-system-cli/src/tui/settings/PageContainer.tsx"() {
429
978
  "use strict";
979
+ init_control_hints();
430
980
  }
431
981
  });
432
982
 
433
983
  // packages/experience-design-system-cli/src/tui/settings/utils/v1-store.ts
434
- import { readFile, writeFile, mkdir } from "node:fs/promises";
435
- import { join as join4 } from "node:path";
436
- import { homedir } from "node:os";
437
- async function readV1Store() {
438
- try {
439
- const raw = await readFile(V1_STORE_PATH, "utf8");
440
- return JSON.parse(raw);
441
- } catch {
442
- return {};
443
- }
444
- }
445
- async function writeV1Store(data) {
446
- await mkdir(join4(homedir(), ".config", "experiences"), { recursive: true });
447
- await writeFile(V1_STORE_PATH, `${JSON.stringify(data, null, 2)}
448
- `, { mode: 384 });
449
- }
450
- var V1_STORE_PATH;
984
+ var readV1Store, writeV1Store;
451
985
  var init_v1_store = __esm({
452
986
  "packages/experience-design-system-cli/src/tui/settings/utils/v1-store.ts"() {
453
987
  "use strict";
454
- V1_STORE_PATH = join4(homedir(), ".config", "experiences", "credentials.json");
988
+ init_config();
989
+ readV1Store = readSettings;
990
+ writeV1Store = writeSettings;
455
991
  }
456
992
  });
457
993
 
@@ -462,7 +998,9 @@ async function readCredentials() {
462
998
  spaceId: store.spaceId || "",
463
999
  environmentId: store.environmentId || "",
464
1000
  cmaToken: store.cmaToken || "",
465
- host: store.host || ""
1001
+ host: store.host || "",
1002
+ defaultComponentDir: store.defaultComponentDir || "",
1003
+ defaultTokenFile: store.defaultTokenFile || ""
466
1004
  };
467
1005
  }
468
1006
  async function writeCredentials(config) {
@@ -484,18 +1022,38 @@ var init_config_store = __esm({
484
1022
  });
485
1023
 
486
1024
  // packages/experience-design-system-cli/src/tui/settings/contentful-configuration/ContentfulConfigScreen.tsx
487
- import { useEffect as useEffect3, useState as useState4 } from "react";
488
- import { Box as Box5, Text as Text5, useInput as useInput5 } from "ink";
489
- import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1025
+ import { useEffect as useEffect4, useState as useState7 } from "react";
1026
+ import { Box as Box7, Text as Text8, useInput as useInput7 } from "ink";
1027
+ import TextInput3 from "ink-text-input";
1028
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1029
+ function debugFields(config) {
1030
+ return {
1031
+ space_id: config?.spaceId ?? "",
1032
+ environment_id: config?.environmentId ?? "",
1033
+ cma_token: config?.cmaToken ?? "",
1034
+ host: config?.host ?? "",
1035
+ default_component_dir: config?.defaultComponentDir ?? "",
1036
+ default_token_file: config?.defaultTokenFile ?? ""
1037
+ };
1038
+ }
490
1039
  function ConfigurationScreen({ onDone }) {
491
- const [stage, setStage] = useState4("loading");
492
- const [config, setConfig] = useState4(null);
493
- const [activeField, setActiveField] = useState4("spaceId");
494
- const [message, setMessage] = useState4(null);
495
- useEffect3(() => {
1040
+ const [stage, setStage] = useState7("loading");
1041
+ const [config, setConfig] = useState7(null);
1042
+ const [activeField, setActiveField] = useState7("spaceId");
1043
+ const [notice, setNotice] = useState7(null);
1044
+ const [lastSaved, setLastSaved] = useState7(null);
1045
+ const [editing, setEditing] = useState7(false);
1046
+ const [valueBeforeEdit, setValueBeforeEdit] = useState7("");
1047
+ useEffect4(() => {
496
1048
  readCredentials().then((cfg) => {
497
1049
  setConfig(cfg);
498
1050
  setStage("form");
1051
+ startDebugRun({
1052
+ flow: "settings/contentful-configuration",
1053
+ step: "01-configuration",
1054
+ menuOption: "Configuration",
1055
+ inputs: debugFields(cfg)
1056
+ });
499
1057
  });
500
1058
  }, []);
501
1059
  function fieldValue(field) {
@@ -505,29 +1063,46 @@ function ConfigurationScreen({ onDone }) {
505
1063
  function setFieldValue(field, value) {
506
1064
  if (!config) return;
507
1065
  setConfig({ ...config, [field]: value });
1066
+ setNotice(null);
508
1067
  }
509
1068
  function handleSave() {
510
1069
  if (!config) return;
511
1070
  setStage("saving");
512
- setMessage(null);
1071
+ setNotice(null);
513
1072
  writeCredentials(config).then(() => {
514
- setStage("saved");
515
- setMessage("Configuration saved");
1073
+ setLastSaved(config);
1074
+ setNotice({ kind: "success", text: "Configuration saved" });
1075
+ setStage("form");
516
1076
  }).catch((err) => {
517
- setMessage(err instanceof Error ? err.message : "Failed to save");
1077
+ setNotice({ kind: "error", text: err instanceof Error ? err.message : "Failed to save" });
518
1078
  setStage("form");
519
1079
  });
520
1080
  }
521
- useInput5((input, key) => {
1081
+ function quit() {
1082
+ void finishDebugRun(
1083
+ lastSaved ? { outputs: debugFields(lastSaved), status: "success", exitMethod: "saved" } : { outputs: {}, status: "success", exitMethod: "discarded" }
1084
+ );
1085
+ onDone();
1086
+ }
1087
+ useInput7((input, key) => {
522
1088
  if (stage === "loading" || stage === "saving") return;
523
- if (stage === "saved") {
524
- if (key.return || key.escape || input === "q") {
525
- onDone();
1089
+ if (editing) {
1090
+ if (key.escape) {
1091
+ setFieldValue(activeField, valueBeforeEdit);
1092
+ setEditing(false);
526
1093
  }
527
1094
  return;
528
1095
  }
529
1096
  if (key.escape || input === "q") {
530
- onDone();
1097
+ quit();
1098
+ return;
1099
+ }
1100
+ if (input === "s") {
1101
+ handleSave();
1102
+ return;
1103
+ }
1104
+ if (input === "c") {
1105
+ setFieldValue(activeField, "");
531
1106
  return;
532
1107
  }
533
1108
  if (key.tab || key.downArrow) {
@@ -541,69 +1116,67 @@ function ConfigurationScreen({ onDone }) {
541
1116
  return;
542
1117
  }
543
1118
  if (key.return) {
544
- const idx = FIELD_ORDER.indexOf(activeField);
545
- if (idx < FIELD_ORDER.length - 1) {
546
- setActiveField(FIELD_ORDER[idx + 1]);
547
- } else {
548
- handleSave();
549
- }
550
- return;
551
- }
552
- if (key.backspace || key.delete) {
553
- const current = fieldValue(activeField);
554
- setFieldValue(activeField, current.slice(0, -1));
555
- return;
556
- }
557
- if (input && !key.ctrl && !key.meta) {
558
- setFieldValue(activeField, fieldValue(activeField) + input);
1119
+ setValueBeforeEdit(fieldValue(activeField));
1120
+ setEditing(true);
559
1121
  }
560
1122
  });
561
1123
  if (stage === "loading") {
562
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
563
- /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Configuration" }),
564
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
565
- /* @__PURE__ */ jsx5(Text5, { color: PALETTE.accent, children: "Loading..." })
566
- ] });
567
- }
568
- if (stage === "saved") {
569
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
570
- /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Configuration" }),
571
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
572
- /* @__PURE__ */ jsxs5(Text5, { color: PALETTE.success, children: [
573
- "\u2713 ",
574
- message
575
- ] }),
576
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
577
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[Enter] Back to Settings" })
1124
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
1125
+ /* @__PURE__ */ jsx8(Text8, { bold: true, children: "Configuration" }),
1126
+ /* @__PURE__ */ jsx8(Text8, { children: " " }),
1127
+ /* @__PURE__ */ jsx8(Text8, { color: PALETTE.accent, children: "Loading..." })
578
1128
  ] });
579
1129
  }
580
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
581
- /* @__PURE__ */ jsx5(Text5, { bold: true, children: "Configuration" }),
582
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
583
- /* @__PURE__ */ jsx5(Text5, { children: "Contentful API Credentials" }),
584
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
585
- /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: FIELD_ORDER.map((field) => {
1130
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
1131
+ /* @__PURE__ */ jsx8(Text8, { bold: true, children: "Configuration" }),
1132
+ /* @__PURE__ */ jsx8(Text8, { children: " " }),
1133
+ /* @__PURE__ */ jsx8(Box7, { flexDirection: "column", children: FIELD_ORDER.map((field) => {
586
1134
  const isActive = activeField === field;
587
1135
  const value = fieldValue(field);
588
1136
  const display = field === "cmaToken" ? "\u2022".repeat(value.length) : value;
589
- return /* @__PURE__ */ jsxs5(Box5, { gap: 1, children: [
590
- /* @__PURE__ */ jsx5(Text5, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
591
- /* @__PURE__ */ jsxs5(Text5, { bold: isActive, children: [
1137
+ return /* @__PURE__ */ jsxs7(Box7, { gap: 1, children: [
1138
+ /* @__PURE__ */ jsx8(Text8, { color: isActive ? PALETTE.accent : void 0, children: isActive ? "\u276F" : " " }),
1139
+ /* @__PURE__ */ jsxs7(Text8, { bold: isActive, children: [
592
1140
  FIELD_LABELS[field],
593
1141
  ":"
594
1142
  ] }),
595
- /* @__PURE__ */ jsx5(Text5, { children: display || /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "(empty)" }) })
1143
+ isActive && editing ? /* @__PURE__ */ jsx8(
1144
+ TextInput3,
1145
+ {
1146
+ value,
1147
+ onChange: (next) => setFieldValue(field, next),
1148
+ onSubmit: () => setEditing(false),
1149
+ mask: field === "cmaToken" ? "\u2022" : void 0
1150
+ }
1151
+ ) : /* @__PURE__ */ jsx8(Text8, { children: display || /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "(empty)" }) })
596
1152
  ] }, field);
597
1153
  }) }),
598
- message && /* @__PURE__ */ jsxs5(Fragment, { children: [
599
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
600
- /* @__PURE__ */ jsxs5(Text5, { color: PALETTE.error, children: [
601
- "\u2717 ",
602
- message
1154
+ notice && /* @__PURE__ */ jsxs7(Fragment2, { children: [
1155
+ /* @__PURE__ */ jsx8(Text8, { children: " " }),
1156
+ /* @__PURE__ */ jsxs7(Text8, { color: notice.kind === "success" ? PALETTE.success : PALETTE.error, children: [
1157
+ notice.kind === "success" ? "\u2713" : "\u2717",
1158
+ " ",
1159
+ notice.text
603
1160
  ] })
604
1161
  ] }),
605
- /* @__PURE__ */ jsx5(Text5, { children: " " }),
606
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[\u2191/\u2193] Switch field \xB7 [Enter] Save/Next \xB7 [Esc/q] Back" })
1162
+ /* @__PURE__ */ jsx8(Text8, { children: " " }),
1163
+ /* @__PURE__ */ jsx8(
1164
+ ControlHints,
1165
+ {
1166
+ hints: editing ? [
1167
+ { keys: "type", label: "edit" },
1168
+ { keys: "\u2190/\u2192", label: "move cursor" },
1169
+ { keys: "\u23CE", label: "done" },
1170
+ { keys: "Esc", label: "cancel edit" }
1171
+ ] : [
1172
+ { keys: "\u2191/\u2193", label: "move" },
1173
+ { keys: "\u23CE", label: "edit" },
1174
+ { keys: "c", label: "clear" },
1175
+ { keys: "s", label: "save" },
1176
+ { keys: "Esc/q", label: "quit without saving" }
1177
+ ]
1178
+ }
1179
+ )
607
1180
  ] });
608
1181
  }
609
1182
  var FIELD_ORDER, FIELD_LABELS;
@@ -612,12 +1185,23 @@ var init_ContentfulConfigScreen = __esm({
612
1185
  "use strict";
613
1186
  init_home_theme();
614
1187
  init_config_store();
615
- FIELD_ORDER = ["spaceId", "environmentId", "cmaToken", "host"];
1188
+ init_debug_store();
1189
+ init_control_hints();
1190
+ FIELD_ORDER = [
1191
+ "spaceId",
1192
+ "environmentId",
1193
+ "cmaToken",
1194
+ "host",
1195
+ "defaultComponentDir",
1196
+ "defaultTokenFile"
1197
+ ];
616
1198
  FIELD_LABELS = {
617
1199
  spaceId: "Space ID",
618
1200
  environmentId: "Environment ID",
619
1201
  cmaToken: "CMA Token",
620
- host: "API Host (optional)"
1202
+ host: "API Host (optional)",
1203
+ defaultComponentDir: "Default component directory (optional)",
1204
+ defaultTokenFile: "Default token file (optional)"
621
1205
  };
622
1206
  }
623
1207
  });
@@ -644,19 +1228,25 @@ var init_analytics_store = __esm({
644
1228
  });
645
1229
 
646
1230
  // packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx
647
- import { useEffect as useEffect4, useState as useState5 } from "react";
648
- import { Box as Box6, Text as Text6, useInput as useInput6 } from "ink";
649
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1231
+ import { useEffect as useEffect5, useState as useState8 } from "react";
1232
+ import { Box as Box8, Text as Text9, useInput as useInput8 } from "ink";
1233
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
650
1234
  function OptInAnalyticsScreen({ onDone }) {
651
- const [loading, setLoading] = useState5(true);
652
- const [enabled, setEnabled] = useState5(true);
653
- useEffect4(() => {
1235
+ const [loading, setLoading] = useState8(true);
1236
+ const [enabled, setEnabled] = useState8(true);
1237
+ useEffect5(() => {
654
1238
  readAnalyticsSetting().then((setting) => {
655
1239
  setEnabled(setting.enabled);
656
1240
  setLoading(false);
1241
+ startDebugRun({
1242
+ flow: "settings/opt-in-analytics",
1243
+ step: "01-opt-in-analytics",
1244
+ menuOption: "Opt-in Analytics",
1245
+ inputs: { enabled: setting.enabled }
1246
+ });
657
1247
  });
658
1248
  }, []);
659
- useInput6((input, key) => {
1249
+ useInput8((input, key) => {
660
1250
  if (loading) return;
661
1251
  if (key.return || input === " ") {
662
1252
  setEnabled((current) => {
@@ -667,225 +1257,52 @@ function OptInAnalyticsScreen({ onDone }) {
667
1257
  return;
668
1258
  }
669
1259
  if (key.escape || input === "q") {
1260
+ void finishDebugRun({ outputs: { enabled }, status: "success", exitMethod: "saved" });
670
1261
  onDone();
671
1262
  }
672
1263
  });
673
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
674
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
675
- /* @__PURE__ */ jsx6(Text6, { children: " " }),
676
- loading ? /* @__PURE__ */ jsx6(Text6, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
677
- /* @__PURE__ */ jsxs6(Text6, { children: [
1264
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
1265
+ /* @__PURE__ */ jsx9(Text9, { bold: true, children: "Settings \u203A Opt-in Analytics" }),
1266
+ /* @__PURE__ */ jsx9(Text9, { children: " " }),
1267
+ loading ? /* @__PURE__ */ jsx9(Text9, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs8(Fragment3, { children: [
1268
+ /* @__PURE__ */ jsxs8(Text9, { children: [
678
1269
  "Share anonymous usage data:",
679
1270
  " ",
680
- /* @__PURE__ */ jsx6(Text6, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
1271
+ /* @__PURE__ */ jsx9(Text9, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
681
1272
  ] }),
682
- /* @__PURE__ */ jsx6(Text6, { children: " " }),
683
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Shares which CLI commands are used and where imports succeed or fail." }),
684
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Never includes source code, file paths, credentials, or authored content." })
1273
+ /* @__PURE__ */ jsx9(Text9, { children: " " }),
1274
+ /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Shares which CLI commands are used and where imports succeed or fail." }),
1275
+ /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Never includes source code, file paths, credentials, or authored content." })
685
1276
  ] }),
686
- /* @__PURE__ */ jsx6(Text6, { children: " " }),
687
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "[Enter/Space] Toggle [Esc/q] Back to Settings" })
1277
+ /* @__PURE__ */ jsx9(Text9, { children: " " }),
1278
+ /* @__PURE__ */ jsx9(
1279
+ ControlHints,
1280
+ {
1281
+ hints: [
1282
+ { keys: "\u23CE/Space", label: "toggle" },
1283
+ { keys: "Esc/q", label: "back" }
1284
+ ]
1285
+ }
1286
+ )
688
1287
  ] });
689
1288
  }
690
- var init_screen = __esm({
1289
+ var init_screen3 = __esm({
691
1290
  "packages/experience-design-system-cli/src/tui/settings/opt-in-analytics/screen.tsx"() {
692
1291
  "use strict";
693
1292
  init_home_theme();
694
1293
  init_analytics_store();
695
- }
696
- });
697
-
698
- // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
699
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
700
- import { dirname as dirname2, join as join5 } from "node:path";
701
- function debugModeSettingPath() {
702
- return join5(findPackageRoot(import.meta.url, PACKAGE_NAME3), ".contentful", "config", "debug_mode.json");
703
- }
704
- async function readDebugModeSetting() {
705
- try {
706
- const raw = await readFile2(debugModeSettingPath(), "utf8");
707
- const parsed = JSON.parse(raw);
708
- return { ...DEFAULT_DEBUG_MODE_SETTING, ...parsed };
709
- } catch {
710
- return { ...DEFAULT_DEBUG_MODE_SETTING };
711
- }
712
- }
713
- async function writeDebugModeSetting(setting) {
714
- const path = debugModeSettingPath();
715
- await mkdir2(dirname2(path), { recursive: true });
716
- await writeFile2(path, `${JSON.stringify(setting, null, 2)}
717
- `, { mode: 384 });
718
- }
719
- var PACKAGE_NAME3, DEFAULT_DEBUG_MODE_SETTING;
720
- var init_debug_mode_store = __esm({
721
- "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
722
- "use strict";
723
- init_package_root();
724
- PACKAGE_NAME3 = "@contentful/experience-design-system-cli";
725
- DEFAULT_DEBUG_MODE_SETTING = {
726
- enabled: true
727
- };
728
- }
729
- });
730
-
731
- // packages/experience-design-system-cli/src/tui/debug-store.ts
732
- import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
733
- import { existsSync as existsSync3, readdirSync } from "node:fs";
734
- import { join as join6 } from "node:path";
735
- function generateRunId() {
736
- const now = /* @__PURE__ */ new Date();
737
- const pad = (n) => String(n).padStart(2, "0");
738
- return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
739
- }
740
- function sessionsRootDir() {
741
- return join6(findPackageRoot(import.meta.url, PACKAGE_NAME4), ".contentful", "debug", "sessions");
742
- }
743
- function datePrefix(now = /* @__PURE__ */ new Date()) {
744
- const pad = (n) => String(n).padStart(2, "0");
745
- return `${pad(now.getMonth() + 1)}-${pad(now.getDate())}-${now.getFullYear()}`;
746
- }
747
- function slugify(value) {
748
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
749
- }
750
- function generateSessionId() {
751
- const today = datePrefix();
752
- const root = sessionsRootDir();
753
- const existing = existsSync3(root) ? readdirSync(root) : [];
754
- const seqPattern = new RegExp(`^${today}-session-(\\d+)$`);
755
- const maxSeq = existing.reduce((max, entry) => {
756
- const match = seqPattern.exec(entry);
757
- return match ? Math.max(max, Number(match[1])) : max;
758
- }, 0);
759
- return `${today}-session-${maxSeq + 1}`;
760
- }
761
- function sessionDebugDir() {
762
- return join6(sessionsRootDir(), SESSION_ID);
763
- }
764
- async function isDebugModeEnabled() {
765
- try {
766
- return (await readDebugModeSetting()).enabled;
767
- } catch {
768
- return true;
769
- }
770
- }
771
- function redact(value) {
772
- const clone = { ...value };
773
- if ("cma_token" in clone) {
774
- const raw = clone.cma_token;
775
- clone.cma_token = typeof raw === "string" && raw.length > 0 ? `[present, ${raw.length} chars]` : "[not set]";
776
- }
777
- return clone;
778
- }
779
- function startDebugRun({
780
- flow,
781
- step,
782
- menuOption,
783
- inputs
784
- }) {
785
- const runId = generateRunId();
786
- const startedAt = Date.now();
787
- const redactedInputs = redact(inputs);
788
- isDebugModeEnabled().then((enabled) => {
789
- if (!enabled) return;
790
- pendingRun = { flow, step, runId, menuOption, inputs: redactedInputs, startedAt };
791
- });
792
- }
793
- async function finishDebugRun({
794
- outputs,
795
- status,
796
- exitMethod
797
- }) {
798
- const run = pendingRun;
799
- if (!run) return;
800
- pendingRun = void 0;
801
- const durationMs = Date.now() - run.startedAt;
802
- const content = renderMarkdown(run, { outputs: redact(outputs), status, exitMethod, durationMs });
803
- const flowSegments = run.flow.split("/");
804
- const dir = join6(sessionDebugDir(), ...flowSegments);
805
- await mkdir3(dir, { recursive: true });
806
- const filename = nextAttemptFilename(dir, run.menuOption);
807
- await writeFile3(join6(dir, filename), content, { mode: 384 });
808
- }
809
- function nextAttemptFilename(dir, menuOption) {
810
- const today = datePrefix();
811
- const optionSlug = slugify(menuOption);
812
- const existing = existsSync3(dir) ? readdirSync(dir) : [];
813
- const attemptPattern = new RegExp(`^${today}-${optionSlug}-attempt-(\\d+)\\.md$`);
814
- const maxAttempt = existing.reduce((max, entry) => {
815
- const match = attemptPattern.exec(entry);
816
- return match ? Math.max(max, Number(match[1])) : max;
817
- }, 0);
818
- return `${today}-${optionSlug}-attempt-${maxAttempt + 1}.md`;
819
- }
820
- function renderMarkdown(run, finish) {
821
- const stepMatch = /^(\d+)-(.+)$/.exec(run.step);
822
- const stepLabel = stepMatch ? `${stepMatch[1]} - ${stepMatch[2]}` : run.step;
823
- const flowSlug = run.flow.split("/").join("-");
824
- return `# Debug Log
825
-
826
- - Run ID: ${run.runId}
827
- - Flow: ${flowSlug}
828
- - Step: ${stepLabel}
829
- - Menu option: ${run.menuOption}
830
- - Date: ${(/* @__PURE__ */ new Date()).toISOString()}
831
- - CLI version: ${readPackageVersion()}
832
- - Platform: ${process.platform} / Node ${process.version}
833
- - Duration on screen: ${finish.durationMs}ms
834
- - Status: ${finish.status}
835
- - Exit method: ${finish.exitMethod}
836
-
837
- ## Inputs
838
- \`\`\`json
839
- ${JSON.stringify(run.inputs, null, 2)}
840
- \`\`\`
841
-
842
- ## Outputs
843
- \`\`\`json
844
- ${JSON.stringify(finish.outputs, null, 2)}
845
- \`\`\`
846
- `;
847
- }
848
- function handleCrash() {
849
- return finishDebugRun({ outputs: {}, status: "error", exitMethod: "crashed" });
850
- }
851
- var PACKAGE_NAME4, pendingRun, SESSION_ID;
852
- var init_debug_store = __esm({
853
- "packages/experience-design-system-cli/src/tui/debug-store.ts"() {
854
- "use strict";
855
- init_package_root();
856
- init_version();
857
- init_debug_mode_store();
858
- PACKAGE_NAME4 = "@contentful/experience-design-system-cli";
859
- SESSION_ID = generateSessionId();
860
- void isDebugModeEnabled().then((enabled) => {
861
- if (!enabled) return void 0;
862
- return mkdir3(sessionDebugDir(), { recursive: true });
863
- });
864
- process.once("uncaughtException", (err) => {
865
- void handleCrash().finally(() => {
866
- throw err;
867
- });
868
- });
869
- process.once("unhandledRejection", (reason) => {
870
- void handleCrash().finally(() => {
871
- throw reason;
872
- });
873
- });
874
- process.once("SIGINT", () => {
875
- void handleCrash().finally(() => {
876
- process.exit(130);
877
- });
878
- });
1294
+ init_debug_store();
1295
+ init_control_hints();
879
1296
  }
880
1297
  });
881
1298
 
882
1299
  // packages/experience-design-system-cli/src/tui/upgrade/PageContainer.tsx
883
- import { useEffect as useEffect5, useState as useState6 } from "react";
884
- import { Box as Box7, Text as Text7, useInput as useInput7 } from "ink";
885
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1300
+ import { useEffect as useEffect6, useState as useState9 } from "react";
1301
+ import { Box as Box9, Text as Text10, useInput as useInput9 } from "ink";
1302
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
886
1303
  function UpgradeScreen({ onDone }) {
887
- const [upgradeCheck, setUpgradeCheck] = useState6();
888
- useEffect5(() => {
1304
+ const [upgradeCheck, setUpgradeCheck] = useState9();
1305
+ useEffect6(() => {
889
1306
  startDebugRun({
890
1307
  flow: "upgrade",
891
1308
  step: "01-upgrade",
@@ -894,7 +1311,7 @@ function UpgradeScreen({ onDone }) {
894
1311
  });
895
1312
  checkForUpgrade().then(setUpgradeCheck).catch(() => setUpgradeCheck({ status: "error" }));
896
1313
  }, []);
897
- useInput7((_input, key) => {
1314
+ useInput9((_input, key) => {
898
1315
  if (key.return) {
899
1316
  void finishDebugRun({
900
1317
  outputs: upgradeCheck ?? {},
@@ -905,12 +1322,12 @@ function UpgradeScreen({ onDone }) {
905
1322
  return;
906
1323
  }
907
1324
  });
908
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
909
- /* @__PURE__ */ jsx7(Text7, { bold: true, children: "Upgrade" }),
910
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
1325
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
1326
+ /* @__PURE__ */ jsx10(Text10, { bold: true, children: "Upgrade" }),
1327
+ /* @__PURE__ */ jsx10(Text10, { children: " " }),
911
1328
  renderBody(upgradeCheck),
912
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
913
- /* @__PURE__ */ jsxs7(Text7, { bold: true, color: PALETTE.accent, children: [
1329
+ /* @__PURE__ */ jsx10(Text10, { children: " " }),
1330
+ /* @__PURE__ */ jsxs9(Text10, { bold: true, color: PALETTE.accent, children: [
914
1331
  FOCUS_MARKER,
915
1332
  " Go Back"
916
1333
  ] })
@@ -918,34 +1335,34 @@ function UpgradeScreen({ onDone }) {
918
1335
  }
919
1336
  function renderBody(upgradeCheck) {
920
1337
  if (!upgradeCheck) {
921
- return /* @__PURE__ */ jsx7(Text7, { color: PALETTE.muted, children: "Checking for updates\u2026" });
1338
+ return /* @__PURE__ */ jsx10(Text10, { color: PALETTE.muted, children: "Checking for updates\u2026" });
922
1339
  }
923
1340
  if (upgradeCheck.status === "error") {
924
- return /* @__PURE__ */ jsx7(Text7, { color: PALETTE.warning, children: "Couldn't check for updates \u2014 check your network connection and try again." });
1341
+ return /* @__PURE__ */ jsx10(Text10, { color: PALETTE.warning, children: "Couldn't check for updates \u2014 check your network connection and try again." });
925
1342
  }
926
1343
  if (upgradeCheck.status === "up-to-date") {
927
- return /* @__PURE__ */ jsxs7(Text7, { color: PALETTE.success, children: [
1344
+ return /* @__PURE__ */ jsxs9(Text10, { color: PALETTE.success, children: [
928
1345
  "You're already on the latest version (v",
929
1346
  upgradeCheck.current,
930
1347
  ")."
931
1348
  ] });
932
1349
  }
933
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
934
- /* @__PURE__ */ jsxs7(Text7, { color: PALETTE.muted, children: [
935
- /* @__PURE__ */ jsxs7(Text7, { bold: true, color: PALETTE.success, children: [
1350
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
1351
+ /* @__PURE__ */ jsxs9(Text10, { color: PALETTE.muted, children: [
1352
+ /* @__PURE__ */ jsxs9(Text10, { bold: true, color: PALETTE.success, children: [
936
1353
  "v",
937
1354
  upgradeCheck.latest
938
1355
  ] }),
939
1356
  " ",
940
1357
  "is available (you're on ",
941
- /* @__PURE__ */ jsxs7(Text7, { bold: true, children: [
1358
+ /* @__PURE__ */ jsxs9(Text10, { bold: true, children: [
942
1359
  "v",
943
1360
  upgradeCheck.current
944
1361
  ] }),
945
1362
  "). Exit this program, cd into the root of your local clone of contentful/experience-design-system-sdk-public, then run:"
946
1363
  ] }),
947
- /* @__PURE__ */ jsx7(Text7, { children: " " }),
948
- /* @__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)) })
1364
+ /* @__PURE__ */ jsx10(Text10, { children: " " }),
1365
+ /* @__PURE__ */ jsx10(Box9, { flexDirection: "column", borderStyle: "round", borderColor: PALETTE.border, paddingX: 1, children: UPGRADE_COMMANDS.map((cmd) => /* @__PURE__ */ jsx10(Text10, { bold: true, children: cmd }, cmd)) })
949
1366
  ] });
950
1367
  }
951
1368
  var UPGRADE_COMMANDS;
@@ -960,19 +1377,25 @@ var init_PageContainer4 = __esm({
960
1377
  });
961
1378
 
962
1379
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
963
- import { useEffect as useEffect6, useState as useState7 } from "react";
964
- import { Box as Box8, Text as Text8, useInput as useInput8 } from "ink";
965
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1380
+ import { useEffect as useEffect7, useState as useState10 } from "react";
1381
+ import { Box as Box10, Text as Text11, useInput as useInput10 } from "ink";
1382
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
966
1383
  function DebugModeScreen({ onDone }) {
967
- const [loading, setLoading] = useState7(true);
968
- const [enabled, setEnabled] = useState7(true);
969
- useEffect6(() => {
1384
+ const [loading, setLoading] = useState10(true);
1385
+ const [enabled, setEnabled] = useState10(true);
1386
+ useEffect7(() => {
970
1387
  readDebugModeSetting().then((setting) => {
971
1388
  setEnabled(setting.enabled);
972
1389
  setLoading(false);
1390
+ startDebugRun({
1391
+ flow: "settings/debug-mode",
1392
+ step: "01-debug-mode",
1393
+ menuOption: "Debug Mode",
1394
+ inputs: { enabled: setting.enabled }
1395
+ });
973
1396
  });
974
1397
  }, []);
975
- useInput8((input, key) => {
1398
+ useInput10((input, key) => {
976
1399
  if (loading) return;
977
1400
  if (key.return || input === " ") {
978
1401
  setEnabled((current) => {
@@ -983,26 +1406,37 @@ function DebugModeScreen({ onDone }) {
983
1406
  return;
984
1407
  }
985
1408
  if (key.escape || input === "q") {
1409
+ void finishDebugRun({ outputs: { enabled }, status: "success", exitMethod: "saved" });
986
1410
  onDone();
987
1411
  }
988
1412
  });
989
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
990
- /* @__PURE__ */ jsx8(Text8, { bold: true, children: "Settings \u203A Debug Mode" }),
991
- /* @__PURE__ */ jsx8(Text8, { children: " " }),
992
- loading ? /* @__PURE__ */ jsx8(Text8, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs8(Text8, { children: [
1413
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
1414
+ /* @__PURE__ */ jsx11(Text11, { bold: true, children: "Settings \u203A Debug Mode" }),
1415
+ /* @__PURE__ */ jsx11(Text11, { children: " " }),
1416
+ loading ? /* @__PURE__ */ jsx11(Text11, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs10(Text11, { children: [
993
1417
  "Debug logging:",
994
1418
  " ",
995
- /* @__PURE__ */ jsx8(Text8, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
1419
+ /* @__PURE__ */ jsx11(Text11, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
996
1420
  ] }),
997
- /* @__PURE__ */ jsx8(Text8, { children: " " }),
998
- /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "[Enter/Space] Toggle [Esc/q] Back to Settings" })
1421
+ /* @__PURE__ */ jsx11(Text11, { children: " " }),
1422
+ /* @__PURE__ */ jsx11(
1423
+ ControlHints,
1424
+ {
1425
+ hints: [
1426
+ { keys: "\u23CE/Space", label: "toggle" },
1427
+ { keys: "Esc/q", label: "back" }
1428
+ ]
1429
+ }
1430
+ )
999
1431
  ] });
1000
1432
  }
1001
- var init_screen2 = __esm({
1433
+ var init_screen4 = __esm({
1002
1434
  "packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx"() {
1003
1435
  "use strict";
1004
1436
  init_home_theme();
1005
1437
  init_debug_mode_store();
1438
+ init_debug_store();
1439
+ init_control_hints();
1006
1440
  }
1007
1441
  });
1008
1442
 
@@ -1011,48 +1445,75 @@ var app_exports = {};
1011
1445
  __export(app_exports, {
1012
1446
  runApp: () => runApp
1013
1447
  });
1014
- import { useState as useState8 } from "react";
1015
- import { jsx as jsx9 } from "react/jsx-runtime";
1448
+ import { useEffect as useEffect8, useState as useState11 } from "react";
1449
+ import { Fragment as Fragment4, jsx as jsx12 } from "react/jsx-runtime";
1016
1450
  function App({ onLaunchImport, importExitCode }) {
1017
1451
  const returnedFromImport = importExitCode !== void 0;
1018
- const [screen, setScreen] = useState8(returnedFromImport ? "import" : "start");
1019
- const goToStart = () => setScreen("start");
1020
- const goToSettings = () => setScreen("settings");
1021
- const navigateFromHome = (next) => {
1022
- if (next === "import" && onLaunchImport) {
1023
- onLaunchImport();
1452
+ const [screen, setScreen] = useState11(returnedFromImport ? "import" : "start");
1453
+ const [showImportResult, setShowImportResult] = useState11(returnedFromImport);
1454
+ const [projectPath, setProjectPath] = useState11();
1455
+ const [importDefaults, setImportDefaults] = useState11();
1456
+ useEffect8(() => {
1457
+ if (screen !== "import") {
1458
+ setImportDefaults(void 0);
1024
1459
  return;
1025
1460
  }
1026
- setScreen(next);
1461
+ void readCredentials().then(
1462
+ (saved) => setImportDefaults({ componentDir: saved.defaultComponentDir ?? "", tokenFile: saved.defaultTokenFile ?? "" })
1463
+ );
1464
+ }, [screen]);
1465
+ const goToStart = () => setScreen("start");
1466
+ const goToSettings = () => setScreen("settings");
1467
+ const finishImportResult = () => {
1468
+ setShowImportResult(false);
1469
+ setProjectPath(void 0);
1470
+ goToStart();
1471
+ };
1472
+ const leaveImport = () => {
1473
+ setProjectPath(void 0);
1474
+ goToStart();
1027
1475
  };
1028
1476
  switch (screen) {
1029
1477
  case "import":
1030
- return /* @__PURE__ */ jsx9(ImportScreen, { exitCode: importExitCode, onDone: goToStart });
1478
+ if (showImportResult) return /* @__PURE__ */ jsx12(ImportScreen, { exitCode: importExitCode, onDone: finishImportResult });
1479
+ if (importDefaults === void 0) return /* @__PURE__ */ jsx12(Fragment4, {});
1480
+ if (projectPath === void 0) {
1481
+ return /* @__PURE__ */ jsx12(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
1482
+ }
1483
+ return /* @__PURE__ */ jsx12(
1484
+ TokenInputScreen,
1485
+ {
1486
+ initialPath: importDefaults.tokenFile,
1487
+ onConfirm: (tokens) => onLaunchImport?.({ project: projectPath, tokens }),
1488
+ onSkip: () => onLaunchImport?.({ project: projectPath }),
1489
+ onBack: () => setProjectPath(void 0)
1490
+ }
1491
+ );
1031
1492
  case "help":
1032
- return /* @__PURE__ */ jsx9(HelpScreen, { onDone: goToStart });
1493
+ return /* @__PURE__ */ jsx12(HelpScreen, { onDone: goToStart });
1033
1494
  case "upgrade":
1034
- return /* @__PURE__ */ jsx9(UpgradeScreen, { onDone: goToStart });
1495
+ return /* @__PURE__ */ jsx12(UpgradeScreen, { onDone: goToStart });
1035
1496
  case "settings":
1036
- return /* @__PURE__ */ jsx9(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
1497
+ return /* @__PURE__ */ jsx12(SettingsScreen, { onNavigate: setScreen, onBack: goToStart });
1037
1498
  case "settings-configuration":
1038
- return /* @__PURE__ */ jsx9(ConfigurationScreen, { onDone: goToSettings });
1499
+ return /* @__PURE__ */ jsx12(ConfigurationScreen, { onDone: goToSettings });
1039
1500
  case "settings-opt-in-analytics":
1040
- return /* @__PURE__ */ jsx9(OptInAnalyticsScreen, { onDone: goToSettings });
1501
+ return /* @__PURE__ */ jsx12(OptInAnalyticsScreen, { onDone: goToSettings });
1041
1502
  case "settings-debug-mode":
1042
- return /* @__PURE__ */ jsx9(DebugModeScreen, { onDone: goToSettings });
1503
+ return /* @__PURE__ */ jsx12(DebugModeScreen, { onDone: goToSettings });
1043
1504
  case "start":
1044
- return /* @__PURE__ */ jsx9(HomeScreen, { onNavigate: navigateFromHome });
1505
+ return /* @__PURE__ */ jsx12(HomeScreen, { onNavigate: setScreen });
1045
1506
  }
1046
1507
  }
1047
1508
  async function renderUntilImportRequestedOrExit(renderApp, importExitCode) {
1048
- let importRequested = false;
1509
+ let requestedImport;
1049
1510
  const instance = renderApp(
1050
- /* @__PURE__ */ jsx9(
1511
+ /* @__PURE__ */ jsx12(
1051
1512
  App,
1052
1513
  {
1053
1514
  importExitCode,
1054
- onLaunchImport: () => {
1055
- importRequested = true;
1515
+ onLaunchImport: (options) => {
1516
+ requestedImport = options;
1056
1517
  instance.unmount();
1057
1518
  }
1058
1519
  }
@@ -1060,13 +1521,15 @@ async function renderUntilImportRequestedOrExit(renderApp, importExitCode) {
1060
1521
  );
1061
1522
  await instance.waitUntilExit();
1062
1523
  await stopReadingTerminal();
1063
- return importRequested;
1524
+ return requestedImport;
1064
1525
  }
1065
1526
  async function runApp(renderApp) {
1066
1527
  let importExitCode;
1067
- while (await renderUntilImportRequestedOrExit(renderApp, importExitCode)) {
1068
- importExitCode = (await spawnV1Import({})).exitCode;
1528
+ let requestedImport = await renderUntilImportRequestedOrExit(renderApp, importExitCode);
1529
+ while (requestedImport !== void 0) {
1530
+ importExitCode = (await spawnV1Import(requestedImport)).exitCode;
1069
1531
  startReadingTerminal();
1532
+ requestedImport = await renderUntilImportRequestedOrExit(renderApp, importExitCode);
1070
1533
  }
1071
1534
  }
1072
1535
  var init_app = __esm({
@@ -1074,14 +1537,16 @@ var init_app = __esm({
1074
1537
  "use strict";
1075
1538
  init_home();
1076
1539
  init_PageContainer();
1540
+ init_steps();
1077
1541
  init_spawn_v1_import();
1078
1542
  init_terminal_input();
1079
1543
  init_PageContainer2();
1080
1544
  init_PageContainer3();
1081
1545
  init_ContentfulConfigScreen();
1082
- init_screen();
1546
+ init_screen3();
1083
1547
  init_PageContainer4();
1084
- init_screen2();
1548
+ init_screen4();
1549
+ init_config_store();
1085
1550
  }
1086
1551
  });
1087
1552
 
@@ -1160,7 +1625,51 @@ function createProgram() {
1160
1625
  return program;
1161
1626
  }
1162
1627
 
1628
+ // packages/experience-design-system-cli/src/config/migrate.ts
1629
+ init_config();
1630
+ init_package_root();
1631
+ import { existsSync as existsSync4 } from "node:fs";
1632
+ import { mkdir as mkdir3, readFile as readFile2, rename as rename2, rmdir, unlink } from "node:fs/promises";
1633
+ import { dirname as dirname3, join as join6 } from "node:path";
1634
+ var PACKAGE_NAME3 = "@contentful/experience-design-system-cli";
1635
+ async function readJson(path) {
1636
+ try {
1637
+ return JSON.parse(await readFile2(path, "utf8"));
1638
+ } catch {
1639
+ return void 0;
1640
+ }
1641
+ }
1642
+ async function migrateOldConfig() {
1643
+ try {
1644
+ const oldCredentials = join6(oldConfigDir(), "credentials.json");
1645
+ const oldRuns = join6(oldConfigDir(), "runs.json");
1646
+ const oldDebugMode = join6(
1647
+ findPackageRoot(import.meta.url, PACKAGE_NAME3),
1648
+ ".contentful",
1649
+ "config",
1650
+ "debug_mode.json"
1651
+ );
1652
+ const migrated = {};
1653
+ const debugMode = await readJson(oldDebugMode);
1654
+ if (debugMode) migrated["debugMode"] = debugMode;
1655
+ Object.assign(migrated, await readJson(oldCredentials));
1656
+ if (Object.keys(migrated).length > 0) await updateSettings({ ...migrated, ...await readSettings() });
1657
+ if (existsSync4(oldRuns)) {
1658
+ if (!existsSync4(runsFilePath())) {
1659
+ await mkdir3(dirname3(runsFilePath()), { recursive: true });
1660
+ await rename2(oldRuns, runsFilePath());
1661
+ } else {
1662
+ await unlink(oldRuns);
1663
+ }
1664
+ }
1665
+ await Promise.all([oldCredentials, oldDebugMode].map((f) => unlink(f).catch(() => void 0)));
1666
+ await rmdir(oldConfigDir()).catch(() => void 0);
1667
+ } catch {
1668
+ }
1669
+ }
1670
+
1163
1671
  // packages/experience-design-system-cli/index.ts
1672
+ await migrateOldConfig();
1164
1673
  createProgram().parseAsync().catch((err) => {
1165
1674
  process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
1166
1675
  `);