@contentful/experience-design-system-cli 2.37.1-dev-build-41b62bf7.0 → 2.37.1-dev-build-e051d273.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
@@ -2116,21 +2116,71 @@ var init_config = __esm({
2116
2116
  });
2117
2117
 
2118
2118
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
2119
+ function toRetentionDays(value) {
2120
+ return RETENTION_CHOICES.find((choice) => choice === value) ?? DEFAULT_RETENTION_DAYS;
2121
+ }
2119
2122
  async function readDebugModeSetting() {
2120
2123
  const { debugMode } = await readSettings2();
2121
- return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
2124
+ const saved = debugMode ?? {};
2125
+ return {
2126
+ enabled: typeof saved.enabled === "boolean" ? saved.enabled : true,
2127
+ retentionDays: toRetentionDays(saved.retentionDays)
2128
+ };
2122
2129
  }
2123
- async function writeDebugModeSetting(setting) {
2124
- await updateSettings2({ debugMode: setting });
2130
+ async function writeDebugModeSetting(change) {
2131
+ await updateSettings2({ debugMode: { ...await readDebugModeSetting(), ...change } });
2125
2132
  }
2126
- var DEFAULT_DEBUG_MODE_SETTING;
2133
+ var RETENTION_CHOICES, DEFAULT_RETENTION_DAYS;
2127
2134
  var init_debug_mode_store = __esm({
2128
2135
  "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
2129
2136
  "use strict";
2130
2137
  init_config();
2131
- DEFAULT_DEBUG_MODE_SETTING = {
2132
- enabled: true
2133
- };
2138
+ RETENTION_CHOICES = [30, 60, 90];
2139
+ DEFAULT_RETENTION_DAYS = 30;
2140
+ }
2141
+ });
2142
+
2143
+ // packages/experience-design-system-cli/src/tui/debug-prune.ts
2144
+ import { readdir as readdir3, rm, stat as stat5 } from "node:fs/promises";
2145
+ import { join as join24 } from "node:path";
2146
+ async function logFilesIn(dir) {
2147
+ const entries = await readdir3(dir, { withFileTypes: true });
2148
+ const nested = await Promise.all(
2149
+ entries.map(async (entry) => {
2150
+ const path5 = join24(dir, entry.name);
2151
+ if (entry.isDirectory()) return logFilesIn(path5);
2152
+ return entry.isFile() && entry.name.endsWith(".md") ? [path5] : [];
2153
+ })
2154
+ );
2155
+ return nested.flat();
2156
+ }
2157
+ async function pruneExpiredLogs(base, retentionDays, now = Date.now()) {
2158
+ const cutoff = now - retentionDays * DAY_MS;
2159
+ const contentfulDir = join24(base, ".contentful");
2160
+ let deleted = 0;
2161
+ try {
2162
+ const sessions = (await readdir3(contentfulDir)).filter((name) => SESSION_FOLDER.test(name));
2163
+ for (const session of sessions) {
2164
+ const files = await logFilesIn(join24(contentfulDir, session, "debug")).catch(() => []);
2165
+ for (const file of files) {
2166
+ try {
2167
+ if ((await stat5(file)).mtimeMs >= cutoff) continue;
2168
+ await rm(file);
2169
+ deleted += 1;
2170
+ } catch {
2171
+ }
2172
+ }
2173
+ }
2174
+ } catch {
2175
+ }
2176
+ return deleted;
2177
+ }
2178
+ var DAY_MS, SESSION_FOLDER;
2179
+ var init_debug_prune = __esm({
2180
+ "packages/experience-design-system-cli/src/tui/debug-prune.ts"() {
2181
+ "use strict";
2182
+ DAY_MS = 24 * 60 * 60 * 1e3;
2183
+ SESSION_FOLDER = /^\d{2}-\d{2}-\d{4}-session-\d+$/;
2134
2184
  }
2135
2185
  });
2136
2186
 
@@ -2146,7 +2196,7 @@ __export(debug_store_exports, {
2146
2196
  });
2147
2197
  import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
2148
2198
  import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
2149
- import { join as join24, resolve as resolve26 } from "node:path";
2199
+ import { join as join25, resolve as resolve26 } from "node:path";
2150
2200
  function generateRunId() {
2151
2201
  const now = /* @__PURE__ */ new Date();
2152
2202
  const pad = (n) => String(n).padStart(2, "0");
@@ -2178,12 +2228,12 @@ function nextSessionId(contentfulDir) {
2178
2228
  return `${today}-session-${maxSeq + 1}`;
2179
2229
  }
2180
2230
  function startSession(base, { replace }) {
2181
- const contentfulDir = join24(base, ".contentful");
2182
- if (replace || !sessionDir) sessionDir = join24(contentfulDir, nextSessionId(contentfulDir));
2231
+ const contentfulDir = join25(base, ".contentful");
2232
+ if (replace || !sessionDir) sessionDir = join25(contentfulDir, nextSessionId(contentfulDir));
2183
2233
  return sessionDir;
2184
2234
  }
2185
2235
  function currentDebugSessionDir() {
2186
- return sessionDir && join24(sessionDir, "debug");
2236
+ return sessionDir && join25(sessionDir, "debug");
2187
2237
  }
2188
2238
  function currentSessionDir() {
2189
2239
  return sessionDir;
@@ -2191,7 +2241,7 @@ function currentSessionDir() {
2191
2241
  async function startDebugSessionIn(base, { replace = false } = {}) {
2192
2242
  try {
2193
2243
  if (!await isDebugModeEnabled()) return;
2194
- await mkdir9(join24(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
2244
+ await mkdir9(join25(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
2195
2245
  } catch {
2196
2246
  }
2197
2247
  }
@@ -2201,11 +2251,11 @@ function nextImportRunDir(session) {
2201
2251
  const match2 = /^dsi-import-(\d+)$/.exec(entry);
2202
2252
  return match2 ? Math.max(max, Number(match2[1])) : max;
2203
2253
  }, 0);
2204
- return join24(session, `dsi-import-${maxRun + 1}`);
2254
+ return join25(session, `dsi-import-${maxRun + 1}`);
2205
2255
  }
2206
2256
  async function startImportRun(projectPath) {
2207
2257
  await startDebugSessionIn(projectPath);
2208
- if (!sessionDir) return join24(resolve26(projectPath), ".contentful");
2258
+ if (!sessionDir) return join25(resolve26(projectPath), ".contentful");
2209
2259
  const dir = nextImportRunDir(sessionDir);
2210
2260
  await mkdir9(dir, { recursive: true });
2211
2261
  return dir;
@@ -2252,10 +2302,10 @@ async function finishDebugRun({
2252
2302
  const root = currentDebugSessionDir();
2253
2303
  if (!root) return;
2254
2304
  const flowSegments = run.flow.split("/");
2255
- const dir = join24(root, ...flowSegments);
2305
+ const dir = join25(root, ...flowSegments);
2256
2306
  await mkdir9(dir, { recursive: true });
2257
2307
  const filename = nextAttemptFilename(dir, run.menuOption);
2258
- await writeFile8(join24(dir, filename), content, { mode: 384 });
2308
+ await writeFile8(join25(dir, filename), content, { mode: 384 });
2259
2309
  }
2260
2310
  function nextAttemptFilename(dir, menuOption) {
2261
2311
  const today = datePrefix();
@@ -2306,9 +2356,11 @@ var init_debug_store = __esm({
2306
2356
  init_config();
2307
2357
  init_version();
2308
2358
  init_debug_mode_store();
2309
- void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(([enabled, base]) => {
2310
- if (!enabled || !base) return void 0;
2311
- return mkdir9(join24(startSession(base, { replace: false }), "debug"), { recursive: true });
2359
+ init_debug_prune();
2360
+ void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(async ([enabled, base]) => {
2361
+ if (!base) return;
2362
+ await readDebugModeSetting().then(({ retentionDays }) => pruneExpiredLogs(base, retentionDays)).catch(() => void 0);
2363
+ if (enabled) await mkdir9(join25(startSession(base, { replace: false }), "debug"), { recursive: true });
2312
2364
  });
2313
2365
  process.once("uncaughtException", (err) => {
2314
2366
  void handleCrash().finally(() => {
@@ -2329,7 +2381,7 @@ var init_debug_store = __esm({
2329
2381
  });
2330
2382
 
2331
2383
  // packages/experience-design-system-cli/app.tsx
2332
- import { join as join26 } from "node:path";
2384
+ import { join as join27 } from "node:path";
2333
2385
  import { useEffect as useEffect27, useState as useState36 } from "react";
2334
2386
 
2335
2387
  // packages/experience-design-system-cli/src/tui/home/home.tsx
@@ -2586,8 +2638,7 @@ function WelcomeScreen({ onContinue, onQuit, initialPath = "" }) {
2586
2638
  /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, children: [
2587
2639
  /* @__PURE__ */ jsx4(Text4, { children: "Where is your component library?" }),
2588
2640
  /* @__PURE__ */ jsxs3(Box3, { children: [
2589
- /* @__PURE__ */ jsx4(Text4, { color: PALETTE.text, children: "?" }),
2590
- /* @__PURE__ */ jsx4(Text4, { children: "Project path:" }),
2641
+ /* @__PURE__ */ jsx4(Text4, { children: "Project path: " }),
2591
2642
  /* @__PURE__ */ jsx4(TextInput, { value: projectPath, onChange: setProjectPath, onSubmit: submit })
2592
2643
  ] })
2593
2644
  ] }),
@@ -8779,8 +8830,8 @@ function getWorkspacePackageDirs(workspaceRoot) {
8779
8830
  continue;
8780
8831
  const entryPath = join7(dir, entry);
8781
8832
  try {
8782
- const stat5 = statSync3(entryPath);
8783
- if (stat5.isDirectory()) {
8833
+ const stat6 = statSync3(entryPath);
8834
+ if (stat6.isDirectory()) {
8784
8835
  scanDir(entryPath, depth + 1);
8785
8836
  }
8786
8837
  } catch {
@@ -12867,15 +12918,15 @@ function walkProjectTree(dir, result, includeContent) {
12867
12918
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/helpers/collect-files/collect-files.js
12868
12919
  function collectFiles(root, options = {}) {
12869
12920
  const resolved = path4.resolve(root);
12870
- let stat5;
12921
+ let stat6;
12871
12922
  try {
12872
- stat5 = statSync4(resolved);
12923
+ stat6 = statSync4(resolved);
12873
12924
  } catch (err) {
12874
12925
  return { ok: false, failure: classifyStatError(err.code), rootPath: resolved };
12875
12926
  }
12876
- if (stat5.isFile())
12927
+ if (stat6.isFile())
12877
12928
  return { ok: false, failure: "is-file", rootPath: resolved };
12878
- if (!stat5.isDirectory())
12929
+ if (!stat6.isDirectory())
12879
12930
  return { ok: false, failure: "not-directory", rootPath: resolved };
12880
12931
  const result = {
12881
12932
  filePaths: [],
@@ -27917,7 +27968,7 @@ init_debug_mode_store();
27917
27968
  init_version();
27918
27969
 
27919
27970
  // packages/experience-design-system-cli/src/tui/help/file-locations.ts
27920
- import { join as join25, resolve as resolve27 } from "node:path";
27971
+ import { join as join26, resolve as resolve27 } from "node:path";
27921
27972
  function describeFileLocations({
27922
27973
  contentfulBaseDir,
27923
27974
  debugModeEnabled,
@@ -27926,14 +27977,14 @@ function describeFileLocations({
27926
27977
  if (!debugModeEnabled) {
27927
27978
  return {
27928
27979
  debugLogs: "none while Debug Mode is off",
27929
- importFiles: `${join25("<project>", ".contentful")}/ (tokens.json, components.json)`
27980
+ importFiles: `${join26("<project>", ".contentful")}/ (tokens.json, components.json)`
27930
27981
  };
27931
27982
  }
27932
27983
  const base = contentfulBaseDir ? resolve27(contentfulBaseDir) : "<project>";
27933
- const session = currentSessionDir2 ?? join25(base, ".contentful", "<date>-session-<n>");
27984
+ const session = currentSessionDir2 ?? join26(base, ".contentful", "<date>-session-<n>");
27934
27985
  return {
27935
- debugLogs: join25(session, "debug"),
27936
- importFiles: `${join25(session, "dsi-import-<n>")}/ (tokens.json, components.json)`
27986
+ debugLogs: join26(session, "debug"),
27987
+ importFiles: `${join26(session, "dsi-import-<n>")}/ (tokens.json, components.json)`
27937
27988
  };
27938
27989
  }
27939
27990
 
@@ -29186,51 +29237,74 @@ import { useEffect as useEffect26, useState as useState35 } from "react";
29186
29237
  import { Box as Box50, Text as Text53, useInput as useInput16 } from "ink";
29187
29238
  init_debug_mode_store();
29188
29239
  init_debug_store();
29189
- import { jsx as jsx62, jsxs as jsxs51 } from "react/jsx-runtime";
29240
+ import { Fragment as Fragment21, jsx as jsx62, jsxs as jsxs51 } from "react/jsx-runtime";
29241
+ var ROWS = ["enabled", "retentionDays"];
29242
+ var nextRetention = (current) => RETENTION_CHOICES[(RETENTION_CHOICES.indexOf(current) + 1) % RETENTION_CHOICES.length];
29190
29243
  function DebugModeScreen({ onDone }) {
29191
- const [loading, setLoading] = useState35(true);
29192
- const [enabled, setEnabled] = useState35(true);
29244
+ const [setting, setSetting] = useState35(null);
29245
+ const [focus, setFocus] = useState35("enabled");
29193
29246
  useEffect26(() => {
29194
- readDebugModeSetting().then((setting) => {
29195
- setEnabled(setting.enabled);
29196
- setLoading(false);
29247
+ readDebugModeSetting().then((loaded) => {
29248
+ setSetting(loaded);
29197
29249
  startDebugRun({
29198
29250
  flow: "settings/debug-mode",
29199
29251
  step: "01-debug-mode",
29200
29252
  menuOption: "Debug Mode",
29201
- inputs: { enabled: setting.enabled }
29253
+ inputs: { ...loaded }
29202
29254
  });
29203
29255
  });
29204
29256
  }, []);
29257
+ const change = (patch) => {
29258
+ if (!setting) return;
29259
+ setSetting({ ...setting, ...patch });
29260
+ void writeDebugModeSetting(patch);
29261
+ };
29205
29262
  useInput16((input, key) => {
29206
- if (loading) return;
29263
+ if (!setting) return;
29264
+ if (key.upArrow || key.downArrow) {
29265
+ setFocus((current) => ROWS[(ROWS.indexOf(current) + (key.downArrow ? 1 : ROWS.length - 1)) % ROWS.length]);
29266
+ return;
29267
+ }
29207
29268
  if (key.return || input === " ") {
29208
- setEnabled((current) => {
29209
- const next = !current;
29210
- void writeDebugModeSetting({ enabled: next });
29211
- return next;
29212
- });
29269
+ if (focus === "enabled") change({ enabled: !setting.enabled });
29270
+ else change({ retentionDays: nextRetention(setting.retentionDays) });
29213
29271
  return;
29214
29272
  }
29215
29273
  if (key.escape || input === "q") {
29216
- void finishDebugRun({ outputs: { enabled }, status: "success", exitMethod: "saved" });
29274
+ void finishDebugRun({ outputs: { ...setting }, status: "success", exitMethod: "saved" });
29217
29275
  onDone();
29218
29276
  }
29219
29277
  });
29278
+ const marker = (row) => focus === row ? "\u276F" : " ";
29220
29279
  return /* @__PURE__ */ jsxs51(Box50, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
29221
29280
  /* @__PURE__ */ jsx62(Text53, { bold: true, children: "Settings \u203A Debug Mode" }),
29222
29281
  /* @__PURE__ */ jsx62(Text53, { children: " " }),
29223
- loading ? /* @__PURE__ */ jsx62(Text53, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs51(Text53, { children: [
29224
- "Debug logging:",
29225
- " ",
29226
- /* @__PURE__ */ jsx62(Text53, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
29227
- ] }),
29282
+ setting ? /* @__PURE__ */ jsxs51(Fragment21, { children: [
29283
+ /* @__PURE__ */ jsxs51(Text53, { children: [
29284
+ marker("enabled"),
29285
+ " Debug logging:",
29286
+ " ",
29287
+ /* @__PURE__ */ jsx62(Text53, { bold: true, color: setting.enabled ? PALETTE.success : PALETTE.muted, children: setting.enabled ? "On" : "Off" })
29288
+ ] }),
29289
+ /* @__PURE__ */ jsxs51(Text53, { children: [
29290
+ marker("retentionDays"),
29291
+ " Delete logs after:",
29292
+ " ",
29293
+ /* @__PURE__ */ jsxs51(Text53, { bold: true, color: PALETTE.accent, children: [
29294
+ setting.retentionDays,
29295
+ " days"
29296
+ ] })
29297
+ ] }),
29298
+ /* @__PURE__ */ jsx62(Text53, { children: " " }),
29299
+ /* @__PURE__ */ jsx62(Text53, { color: PALETTE.muted, children: "Older logs are deleted the next time the CLI starts." })
29300
+ ] }) : /* @__PURE__ */ jsx62(Text53, { color: PALETTE.muted, children: "Loading\u2026" }),
29228
29301
  /* @__PURE__ */ jsx62(Text53, { children: " " }),
29229
29302
  /* @__PURE__ */ jsx62(
29230
29303
  ControlHints,
29231
29304
  {
29232
29305
  hints: [
29233
- { keys: "\u23CE/Space", label: "toggle" },
29306
+ { keys: "\u2191/\u2193", label: "move" },
29307
+ { keys: "\u23CE/Space", label: "change" },
29234
29308
  { keys: "Esc/q", label: "back" }
29235
29309
  ]
29236
29310
  }
@@ -29239,7 +29313,7 @@ function DebugModeScreen({ onDone }) {
29239
29313
  }
29240
29314
 
29241
29315
  // packages/experience-design-system-cli/app.tsx
29242
- import { Fragment as Fragment21, jsx as jsx63 } from "react/jsx-runtime";
29316
+ import { Fragment as Fragment22, jsx as jsx63 } from "react/jsx-runtime";
29243
29317
  function App({ importOptions, inkClear }) {
29244
29318
  const [screen, setScreen] = useState36("start");
29245
29319
  const [importExitCode, setImportExitCode] = useState36();
@@ -29288,7 +29362,7 @@ function App({ importOptions, inkClear }) {
29288
29362
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
29289
29363
  const state2 = await inspectTokens({
29290
29364
  rawTokensPath: tokens,
29291
- contentfulDir: join26(resolveUserPath(projectPath2), ".contentful"),
29365
+ contentfulDir: join27(resolveUserPath(projectPath2), ".contentful"),
29292
29366
  cache: importOptions.cache
29293
29367
  });
29294
29368
  if (state2.kind === "cached") {
@@ -29408,7 +29482,7 @@ function App({ importOptions, inkClear }) {
29408
29482
  }
29409
29483
  );
29410
29484
  }
29411
- if (importDefaults === void 0) return /* @__PURE__ */ jsx63(Fragment21, {});
29485
+ if (importDefaults === void 0) return /* @__PURE__ */ jsx63(Fragment22, {});
29412
29486
  if (projectPath === void 0) {
29413
29487
  return /* @__PURE__ */ jsx63(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
29414
29488
  }
@@ -29447,7 +29521,7 @@ function App({ importOptions, inkClear }) {
29447
29521
  }
29448
29522
  );
29449
29523
  }
29450
- return /* @__PURE__ */ jsx63(Fragment21, {});
29524
+ return /* @__PURE__ */ jsx63(Fragment22, {});
29451
29525
  }
29452
29526
  if (scopeRun && scopeFlow) {
29453
29527
  if (scopeFlow.status === "failed") {
@@ -29484,7 +29558,7 @@ function App({ importOptions, inkClear }) {
29484
29558
  }
29485
29559
  );
29486
29560
  }
29487
- return /* @__PURE__ */ jsx63(Fragment21, {});
29561
+ return /* @__PURE__ */ jsx63(Fragment22, {});
29488
29562
  }
29489
29563
  if (pendingLaunch?.cached) {
29490
29564
  return /* @__PURE__ */ jsx63(
package/dist/index.js CHANGED
@@ -8266,8 +8266,8 @@ function getWorkspacePackageDirs(workspaceRoot) {
8266
8266
  continue;
8267
8267
  const entryPath = join5(dir, entry);
8268
8268
  try {
8269
- const stat5 = statSync2(entryPath);
8270
- if (stat5.isDirectory()) {
8269
+ const stat6 = statSync2(entryPath);
8270
+ if (stat6.isDirectory()) {
8271
8271
  scanDir(entryPath, depth + 1);
8272
8272
  }
8273
8273
  } catch {
@@ -12911,15 +12911,15 @@ import { statSync as statSync3 } from "node:fs";
12911
12911
  import path4 from "node:path";
12912
12912
  function collectFiles(root, options = {}) {
12913
12913
  const resolved = path4.resolve(root);
12914
- let stat5;
12914
+ let stat6;
12915
12915
  try {
12916
- stat5 = statSync3(resolved);
12916
+ stat6 = statSync3(resolved);
12917
12917
  } catch (err) {
12918
12918
  return { ok: false, failure: classifyStatError(err.code), rootPath: resolved };
12919
12919
  }
12920
- if (stat5.isFile())
12920
+ if (stat6.isFile())
12921
12921
  return { ok: false, failure: "is-file", rootPath: resolved };
12922
- if (!stat5.isDirectory())
12922
+ if (!stat6.isDirectory())
12923
12923
  return { ok: false, failure: "not-directory", rootPath: resolved };
12924
12924
  const result = {
12925
12925
  filePaths: [],
@@ -18573,8 +18573,7 @@ function WelcomeScreen({ onContinue, onQuit, initialPath = "" }) {
18573
18573
  /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, children: [
18574
18574
  /* @__PURE__ */ jsx4(Text4, { children: "Where is your component library?" }),
18575
18575
  /* @__PURE__ */ jsxs3(Box3, { children: [
18576
- /* @__PURE__ */ jsx4(Text4, { color: PALETTE.text, children: "?" }),
18577
- /* @__PURE__ */ jsx4(Text4, { children: "Project path:" }),
18576
+ /* @__PURE__ */ jsx4(Text4, { children: "Project path: " }),
18578
18577
  /* @__PURE__ */ jsx4(TextInput, { value: projectPath, onChange: setProjectPath, onSubmit: submit })
18579
18578
  ] })
18580
18579
  ] }),
@@ -31253,21 +31252,71 @@ var init_use_flow = __esm({
31253
31252
  });
31254
31253
 
31255
31254
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts
31255
+ function toRetentionDays(value) {
31256
+ return RETENTION_CHOICES.find((choice) => choice === value) ?? DEFAULT_RETENTION_DAYS;
31257
+ }
31256
31258
  async function readDebugModeSetting() {
31257
31259
  const { debugMode } = await readSettings2();
31258
- return { ...DEFAULT_DEBUG_MODE_SETTING, ...debugMode };
31260
+ const saved = debugMode ?? {};
31261
+ return {
31262
+ enabled: typeof saved.enabled === "boolean" ? saved.enabled : true,
31263
+ retentionDays: toRetentionDays(saved.retentionDays)
31264
+ };
31259
31265
  }
31260
- async function writeDebugModeSetting(setting) {
31261
- await updateSettings2({ debugMode: setting });
31266
+ async function writeDebugModeSetting(change) {
31267
+ await updateSettings2({ debugMode: { ...await readDebugModeSetting(), ...change } });
31262
31268
  }
31263
- var DEFAULT_DEBUG_MODE_SETTING;
31269
+ var RETENTION_CHOICES, DEFAULT_RETENTION_DAYS;
31264
31270
  var init_debug_mode_store = __esm({
31265
31271
  "packages/experience-design-system-cli/src/tui/settings/debug-mode/debug-mode-store.ts"() {
31266
31272
  "use strict";
31267
31273
  init_config();
31268
- DEFAULT_DEBUG_MODE_SETTING = {
31269
- enabled: true
31270
- };
31274
+ RETENTION_CHOICES = [30, 60, 90];
31275
+ DEFAULT_RETENTION_DAYS = 30;
31276
+ }
31277
+ });
31278
+
31279
+ // packages/experience-design-system-cli/src/tui/debug-prune.ts
31280
+ import { readdir as readdir3, rm, stat as stat5 } from "node:fs/promises";
31281
+ import { join as join25 } from "node:path";
31282
+ async function logFilesIn(dir) {
31283
+ const entries = await readdir3(dir, { withFileTypes: true });
31284
+ const nested = await Promise.all(
31285
+ entries.map(async (entry) => {
31286
+ const path5 = join25(dir, entry.name);
31287
+ if (entry.isDirectory()) return logFilesIn(path5);
31288
+ return entry.isFile() && entry.name.endsWith(".md") ? [path5] : [];
31289
+ })
31290
+ );
31291
+ return nested.flat();
31292
+ }
31293
+ async function pruneExpiredLogs(base, retentionDays, now = Date.now()) {
31294
+ const cutoff = now - retentionDays * DAY_MS;
31295
+ const contentfulDir = join25(base, ".contentful");
31296
+ let deleted = 0;
31297
+ try {
31298
+ const sessions = (await readdir3(contentfulDir)).filter((name) => SESSION_FOLDER.test(name));
31299
+ for (const session of sessions) {
31300
+ const files = await logFilesIn(join25(contentfulDir, session, "debug")).catch(() => []);
31301
+ for (const file of files) {
31302
+ try {
31303
+ if ((await stat5(file)).mtimeMs >= cutoff) continue;
31304
+ await rm(file);
31305
+ deleted += 1;
31306
+ } catch {
31307
+ }
31308
+ }
31309
+ }
31310
+ } catch {
31311
+ }
31312
+ return deleted;
31313
+ }
31314
+ var DAY_MS, SESSION_FOLDER;
31315
+ var init_debug_prune = __esm({
31316
+ "packages/experience-design-system-cli/src/tui/debug-prune.ts"() {
31317
+ "use strict";
31318
+ DAY_MS = 24 * 60 * 60 * 1e3;
31319
+ SESSION_FOLDER = /^\d{2}-\d{2}-\d{4}-session-\d+$/;
31271
31320
  }
31272
31321
  });
31273
31322
 
@@ -31283,7 +31332,7 @@ __export(debug_store_exports, {
31283
31332
  });
31284
31333
  import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
31285
31334
  import { existsSync as existsSync10, readdirSync as readdirSync4 } from "node:fs";
31286
- import { join as join25, resolve as resolve26 } from "node:path";
31335
+ import { join as join26, resolve as resolve26 } from "node:path";
31287
31336
  function generateRunId() {
31288
31337
  const now = /* @__PURE__ */ new Date();
31289
31338
  const pad = (n) => String(n).padStart(2, "0");
@@ -31315,12 +31364,12 @@ function nextSessionId(contentfulDir) {
31315
31364
  return `${today}-session-${maxSeq + 1}`;
31316
31365
  }
31317
31366
  function startSession(base, { replace }) {
31318
- const contentfulDir = join25(base, ".contentful");
31319
- if (replace || !sessionDir) sessionDir = join25(contentfulDir, nextSessionId(contentfulDir));
31367
+ const contentfulDir = join26(base, ".contentful");
31368
+ if (replace || !sessionDir) sessionDir = join26(contentfulDir, nextSessionId(contentfulDir));
31320
31369
  return sessionDir;
31321
31370
  }
31322
31371
  function currentDebugSessionDir() {
31323
- return sessionDir && join25(sessionDir, "debug");
31372
+ return sessionDir && join26(sessionDir, "debug");
31324
31373
  }
31325
31374
  function currentSessionDir() {
31326
31375
  return sessionDir;
@@ -31328,7 +31377,7 @@ function currentSessionDir() {
31328
31377
  async function startDebugSessionIn(base, { replace = false } = {}) {
31329
31378
  try {
31330
31379
  if (!await isDebugModeEnabled()) return;
31331
- await mkdir9(join25(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
31380
+ await mkdir9(join26(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
31332
31381
  } catch {
31333
31382
  }
31334
31383
  }
@@ -31338,11 +31387,11 @@ function nextImportRunDir(session) {
31338
31387
  const match2 = /^dsi-import-(\d+)$/.exec(entry);
31339
31388
  return match2 ? Math.max(max, Number(match2[1])) : max;
31340
31389
  }, 0);
31341
- return join25(session, `dsi-import-${maxRun + 1}`);
31390
+ return join26(session, `dsi-import-${maxRun + 1}`);
31342
31391
  }
31343
31392
  async function startImportRun(projectPath) {
31344
31393
  await startDebugSessionIn(projectPath);
31345
- if (!sessionDir) return join25(resolve26(projectPath), ".contentful");
31394
+ if (!sessionDir) return join26(resolve26(projectPath), ".contentful");
31346
31395
  const dir = nextImportRunDir(sessionDir);
31347
31396
  await mkdir9(dir, { recursive: true });
31348
31397
  return dir;
@@ -31389,10 +31438,10 @@ async function finishDebugRun({
31389
31438
  const root = currentDebugSessionDir();
31390
31439
  if (!root) return;
31391
31440
  const flowSegments = run.flow.split("/");
31392
- const dir = join25(root, ...flowSegments);
31441
+ const dir = join26(root, ...flowSegments);
31393
31442
  await mkdir9(dir, { recursive: true });
31394
31443
  const filename = nextAttemptFilename(dir, run.menuOption);
31395
- await writeFile8(join25(dir, filename), content, { mode: 384 });
31444
+ await writeFile8(join26(dir, filename), content, { mode: 384 });
31396
31445
  }
31397
31446
  function nextAttemptFilename(dir, menuOption) {
31398
31447
  const today = datePrefix();
@@ -31443,9 +31492,11 @@ var init_debug_store = __esm({
31443
31492
  init_config();
31444
31493
  init_version();
31445
31494
  init_debug_mode_store();
31446
- void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(([enabled, base]) => {
31447
- if (!enabled || !base) return void 0;
31448
- return mkdir9(join25(startSession(base, { replace: false }), "debug"), { recursive: true });
31495
+ init_debug_prune();
31496
+ void Promise.all([isDebugModeEnabled(), readBaseDir()]).then(async ([enabled, base]) => {
31497
+ if (!base) return;
31498
+ await readDebugModeSetting().then(({ retentionDays }) => pruneExpiredLogs(base, retentionDays)).catch(() => void 0);
31499
+ if (enabled) await mkdir9(join26(startSession(base, { replace: false }), "debug"), { recursive: true });
31449
31500
  });
31450
31501
  process.once("uncaughtException", (err) => {
31451
31502
  void handleCrash().finally(() => {
@@ -31466,7 +31517,7 @@ var init_debug_store = __esm({
31466
31517
  });
31467
31518
 
31468
31519
  // packages/experience-design-system-cli/src/tui/help/file-locations.ts
31469
- import { join as join26, resolve as resolve27 } from "node:path";
31520
+ import { join as join27, resolve as resolve27 } from "node:path";
31470
31521
  function describeFileLocations({
31471
31522
  contentfulBaseDir,
31472
31523
  debugModeEnabled,
@@ -31475,14 +31526,14 @@ function describeFileLocations({
31475
31526
  if (!debugModeEnabled) {
31476
31527
  return {
31477
31528
  debugLogs: "none while Debug Mode is off",
31478
- importFiles: `${join26("<project>", ".contentful")}/ (tokens.json, components.json)`
31529
+ importFiles: `${join27("<project>", ".contentful")}/ (tokens.json, components.json)`
31479
31530
  };
31480
31531
  }
31481
31532
  const base = contentfulBaseDir ? resolve27(contentfulBaseDir) : "<project>";
31482
- const session = currentSessionDir2 ?? join26(base, ".contentful", "<date>-session-<n>");
31533
+ const session = currentSessionDir2 ?? join27(base, ".contentful", "<date>-session-<n>");
31483
31534
  return {
31484
- debugLogs: join26(session, "debug"),
31485
- importFiles: `${join26(session, "dsi-import-<n>")}/ (tokens.json, components.json)`
31535
+ debugLogs: join27(session, "debug"),
31536
+ importFiles: `${join27(session, "dsi-import-<n>")}/ (tokens.json, components.json)`
31486
31537
  };
31487
31538
  }
31488
31539
  var init_file_locations = __esm({
@@ -32764,57 +32815,79 @@ var init_screen11 = __esm({
32764
32815
  // packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx
32765
32816
  import { useEffect as useEffect26, useState as useState35 } from "react";
32766
32817
  import { Box as Box50, Text as Text53, useInput as useInput16 } from "ink";
32767
- import { jsx as jsx62, jsxs as jsxs51 } from "react/jsx-runtime";
32818
+ import { Fragment as Fragment21, jsx as jsx62, jsxs as jsxs51 } from "react/jsx-runtime";
32768
32819
  function DebugModeScreen({ onDone }) {
32769
- const [loading, setLoading] = useState35(true);
32770
- const [enabled, setEnabled] = useState35(true);
32820
+ const [setting, setSetting] = useState35(null);
32821
+ const [focus, setFocus] = useState35("enabled");
32771
32822
  useEffect26(() => {
32772
- readDebugModeSetting().then((setting) => {
32773
- setEnabled(setting.enabled);
32774
- setLoading(false);
32823
+ readDebugModeSetting().then((loaded) => {
32824
+ setSetting(loaded);
32775
32825
  startDebugRun({
32776
32826
  flow: "settings/debug-mode",
32777
32827
  step: "01-debug-mode",
32778
32828
  menuOption: "Debug Mode",
32779
- inputs: { enabled: setting.enabled }
32829
+ inputs: { ...loaded }
32780
32830
  });
32781
32831
  });
32782
32832
  }, []);
32833
+ const change = (patch) => {
32834
+ if (!setting) return;
32835
+ setSetting({ ...setting, ...patch });
32836
+ void writeDebugModeSetting(patch);
32837
+ };
32783
32838
  useInput16((input, key) => {
32784
- if (loading) return;
32839
+ if (!setting) return;
32840
+ if (key.upArrow || key.downArrow) {
32841
+ setFocus((current) => ROWS[(ROWS.indexOf(current) + (key.downArrow ? 1 : ROWS.length - 1)) % ROWS.length]);
32842
+ return;
32843
+ }
32785
32844
  if (key.return || input === " ") {
32786
- setEnabled((current) => {
32787
- const next = !current;
32788
- void writeDebugModeSetting({ enabled: next });
32789
- return next;
32790
- });
32845
+ if (focus === "enabled") change({ enabled: !setting.enabled });
32846
+ else change({ retentionDays: nextRetention(setting.retentionDays) });
32791
32847
  return;
32792
32848
  }
32793
32849
  if (key.escape || input === "q") {
32794
- void finishDebugRun({ outputs: { enabled }, status: "success", exitMethod: "saved" });
32850
+ void finishDebugRun({ outputs: { ...setting }, status: "success", exitMethod: "saved" });
32795
32851
  onDone();
32796
32852
  }
32797
32853
  });
32854
+ const marker = (row) => focus === row ? "\u276F" : " ";
32798
32855
  return /* @__PURE__ */ jsxs51(Box50, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
32799
32856
  /* @__PURE__ */ jsx62(Text53, { bold: true, children: "Settings \u203A Debug Mode" }),
32800
32857
  /* @__PURE__ */ jsx62(Text53, { children: " " }),
32801
- loading ? /* @__PURE__ */ jsx62(Text53, { color: PALETTE.muted, children: "Loading\u2026" }) : /* @__PURE__ */ jsxs51(Text53, { children: [
32802
- "Debug logging:",
32803
- " ",
32804
- /* @__PURE__ */ jsx62(Text53, { bold: true, color: enabled ? PALETTE.success : PALETTE.muted, children: enabled ? "On" : "Off" })
32805
- ] }),
32858
+ setting ? /* @__PURE__ */ jsxs51(Fragment21, { children: [
32859
+ /* @__PURE__ */ jsxs51(Text53, { children: [
32860
+ marker("enabled"),
32861
+ " Debug logging:",
32862
+ " ",
32863
+ /* @__PURE__ */ jsx62(Text53, { bold: true, color: setting.enabled ? PALETTE.success : PALETTE.muted, children: setting.enabled ? "On" : "Off" })
32864
+ ] }),
32865
+ /* @__PURE__ */ jsxs51(Text53, { children: [
32866
+ marker("retentionDays"),
32867
+ " Delete logs after:",
32868
+ " ",
32869
+ /* @__PURE__ */ jsxs51(Text53, { bold: true, color: PALETTE.accent, children: [
32870
+ setting.retentionDays,
32871
+ " days"
32872
+ ] })
32873
+ ] }),
32874
+ /* @__PURE__ */ jsx62(Text53, { children: " " }),
32875
+ /* @__PURE__ */ jsx62(Text53, { color: PALETTE.muted, children: "Older logs are deleted the next time the CLI starts." })
32876
+ ] }) : /* @__PURE__ */ jsx62(Text53, { color: PALETTE.muted, children: "Loading\u2026" }),
32806
32877
  /* @__PURE__ */ jsx62(Text53, { children: " " }),
32807
32878
  /* @__PURE__ */ jsx62(
32808
32879
  ControlHints,
32809
32880
  {
32810
32881
  hints: [
32811
- { keys: "\u23CE/Space", label: "toggle" },
32882
+ { keys: "\u2191/\u2193", label: "move" },
32883
+ { keys: "\u23CE/Space", label: "change" },
32812
32884
  { keys: "Esc/q", label: "back" }
32813
32885
  ]
32814
32886
  }
32815
32887
  )
32816
32888
  ] });
32817
32889
  }
32890
+ var ROWS, nextRetention;
32818
32891
  var init_screen12 = __esm({
32819
32892
  "packages/experience-design-system-cli/src/tui/settings/debug-mode/screen.tsx"() {
32820
32893
  "use strict";
@@ -32822,6 +32895,8 @@ var init_screen12 = __esm({
32822
32895
  init_debug_mode_store();
32823
32896
  init_debug_store();
32824
32897
  init_control_hints();
32898
+ ROWS = ["enabled", "retentionDays"];
32899
+ nextRetention = (current) => RETENTION_CHOICES[(RETENTION_CHOICES.indexOf(current) + 1) % RETENTION_CHOICES.length];
32825
32900
  }
32826
32901
  });
32827
32902
 
@@ -32830,9 +32905,9 @@ var app_exports = {};
32830
32905
  __export(app_exports, {
32831
32906
  runApp: () => runApp
32832
32907
  });
32833
- import { join as join27 } from "node:path";
32908
+ import { join as join28 } from "node:path";
32834
32909
  import { useEffect as useEffect27, useState as useState36 } from "react";
32835
- import { Fragment as Fragment21, jsx as jsx63 } from "react/jsx-runtime";
32910
+ import { Fragment as Fragment22, jsx as jsx63 } from "react/jsx-runtime";
32836
32911
  function App({ importOptions, inkClear }) {
32837
32912
  const [screen, setScreen] = useState36("start");
32838
32913
  const [importExitCode, setImportExitCode] = useState36();
@@ -32881,7 +32956,7 @@ function App({ importOptions, inkClear }) {
32881
32956
  const launch = { projectPath: projectPath2, tokens, filePaths, ...importOptions };
32882
32957
  const state2 = await inspectTokens({
32883
32958
  rawTokensPath: tokens,
32884
- contentfulDir: join27(resolveUserPath(projectPath2), ".contentful"),
32959
+ contentfulDir: join28(resolveUserPath(projectPath2), ".contentful"),
32885
32960
  cache: importOptions.cache
32886
32961
  });
32887
32962
  if (state2.kind === "cached") {
@@ -33001,7 +33076,7 @@ function App({ importOptions, inkClear }) {
33001
33076
  }
33002
33077
  );
33003
33078
  }
33004
- if (importDefaults === void 0) return /* @__PURE__ */ jsx63(Fragment21, {});
33079
+ if (importDefaults === void 0) return /* @__PURE__ */ jsx63(Fragment22, {});
33005
33080
  if (projectPath === void 0) {
33006
33081
  return /* @__PURE__ */ jsx63(WelcomeScreen, { onContinue: setProjectPath, onQuit: leaveImport, initialPath: importDefaults.componentDir });
33007
33082
  }
@@ -33040,7 +33115,7 @@ function App({ importOptions, inkClear }) {
33040
33115
  }
33041
33116
  );
33042
33117
  }
33043
- return /* @__PURE__ */ jsx63(Fragment21, {});
33118
+ return /* @__PURE__ */ jsx63(Fragment22, {});
33044
33119
  }
33045
33120
  if (scopeRun && scopeFlow) {
33046
33121
  if (scopeFlow.status === "failed") {
@@ -33077,7 +33152,7 @@ function App({ importOptions, inkClear }) {
33077
33152
  }
33078
33153
  );
33079
33154
  }
33080
- return /* @__PURE__ */ jsx63(Fragment21, {});
33155
+ return /* @__PURE__ */ jsx63(Fragment22, {});
33081
33156
  }
33082
33157
  if (pendingLaunch?.cached) {
33083
33158
  return /* @__PURE__ */ jsx63(
@@ -33152,7 +33227,7 @@ var init_app = __esm({
33152
33227
  // packages/experience-design-system-cli/program.ts
33153
33228
  init_src3();
33154
33229
  import { readFileSync as readFileSync9 } from "node:fs";
33155
- import { join as join28 } from "node:path";
33230
+ import { join as join29 } from "node:path";
33156
33231
  import { Command } from "commander";
33157
33232
 
33158
33233
  // packages/experience-design-system-cli/src/commands/import-options.ts
@@ -33218,7 +33293,7 @@ init_analytics_store();
33218
33293
  init_package_root();
33219
33294
  var pkg = JSON.parse(
33220
33295
  readFileSync9(
33221
- join28(findPackageRoot(import.meta.url, "@contentful/experience-design-system-cli"), "package.json"),
33296
+ join29(findPackageRoot(import.meta.url, "@contentful/experience-design-system-cli"), "package.json"),
33222
33297
  "utf8"
33223
33298
  )
33224
33299
  );
@@ -33259,7 +33334,7 @@ init_config();
33259
33334
  init_package_root();
33260
33335
  import { existsSync as existsSync12 } from "node:fs";
33261
33336
  import { mkdir as mkdir10, readFile as readFile19, rename as rename3, rmdir, unlink } from "node:fs/promises";
33262
- import { dirname as dirname16, join as join29 } from "node:path";
33337
+ import { dirname as dirname16, join as join30 } from "node:path";
33263
33338
  var PACKAGE_NAME3 = "@contentful/experience-design-system-cli";
33264
33339
  async function readJson(path5) {
33265
33340
  try {
@@ -33270,9 +33345,9 @@ async function readJson(path5) {
33270
33345
  }
33271
33346
  async function migrateOldConfig() {
33272
33347
  try {
33273
- const oldCredentials = join29(oldConfigDir2(), "credentials.json");
33274
- const oldRuns = join29(oldConfigDir2(), "runs.json");
33275
- const oldDebugMode = join29(
33348
+ const oldCredentials = join30(oldConfigDir2(), "credentials.json");
33349
+ const oldRuns = join30(oldConfigDir2(), "runs.json");
33350
+ const oldDebugMode = join30(
33276
33351
  findPackageRoot(import.meta.url, PACKAGE_NAME3),
33277
33352
  ".contentful",
33278
33353
  "config",
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-41b62bf7.0",
3
+ "version": "2.37.1-dev-build-e051d273.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Deletes the debug logs under `<base>/.contentful` that are older than `retentionDays`. It only looks at `.md` files
3
+ * inside the `debug` folder of a session folder, so nothing the import produced or the user put there is touched. A file
4
+ * that cannot be read or deleted is skipped: this runs at startup and must never get in the user's way. Returns how many
5
+ * logs it deleted.
6
+ */
7
+ export declare function pruneExpiredLogs(base: string, retentionDays: number, now?: number): Promise<number>;
@@ -1,5 +1,11 @@
1
+ /** How long a debug log is kept before the CLI deletes it. Only these values are offered. */
2
+ export declare const RETENTION_CHOICES: readonly [30, 60, 90];
3
+ type RetentionDays = (typeof RETENTION_CHOICES)[number];
1
4
  export type DebugModeSetting = {
2
5
  enabled: boolean;
6
+ retentionDays: RetentionDays;
3
7
  };
4
8
  export declare function readDebugModeSetting(): Promise<DebugModeSetting>;
5
- export declare function writeDebugModeSetting(setting: DebugModeSetting): Promise<void>;
9
+ /** Saves the given fields and keeps the others, so turning logging off does not forget the retention. */
10
+ export declare function writeDebugModeSetting(change: Partial<DebugModeSetting>): Promise<void>;
11
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-41b62bf7.0",
3
+ "version": "2.37.1-dev-build-e051d273.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -45,8 +45,8 @@
45
45
  "ts-morph": "^27.0.2",
46
46
  "typescript": "^5.9.3",
47
47
  "zod": "^4.6.5",
48
- "@contentful/experience-design-system-backend-pipeline": "2.37.1-dev-build-41b62bf7.0",
49
- "@contentful/experience-design-system-types": "2.37.1-dev-build-41b62bf7.0"
48
+ "@contentful/experience-design-system-backend-pipeline": "2.37.1-dev-build-e051d273.0",
49
+ "@contentful/experience-design-system-types": "2.37.1-dev-build-e051d273.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@tsconfig/node24": "^24.0.4",