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