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