@kaynooo/cli-doctor 0.11.0 → 0.13.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/README.md +6 -0
- package/dist/cli-bin.js +414 -112
- package/dist/cli.js +341 -101
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
|
-
import
|
|
5
|
+
import process20 from "process";
|
|
6
6
|
// ../kit/src/args.ts
|
|
7
|
-
import
|
|
7
|
+
import process9 from "process";
|
|
8
8
|
import { parseArgs } from "util";
|
|
9
9
|
|
|
10
10
|
// ../kit/src/format.ts
|
|
11
|
-
import
|
|
11
|
+
import process7 from "process";
|
|
12
12
|
|
|
13
13
|
// ../kit/src/mode.ts
|
|
14
14
|
import process2 from "process";
|
|
@@ -32,7 +32,7 @@ function isInteractive(streams = process2) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// ../kit/src/style.ts
|
|
35
|
-
import
|
|
35
|
+
import process6 from "process";
|
|
36
36
|
|
|
37
37
|
// ../../node_modules/.bun/@kaynooo+utils@2.31.2+d0769e28dc4dad16/node_modules/@kaynooo/utils/dist/chunk-mtetydvc.js
|
|
38
38
|
function x(s) {
|
|
@@ -295,28 +295,188 @@ function le(i = {}) {
|
|
|
295
295
|
}
|
|
296
296
|
var t = le();
|
|
297
297
|
|
|
298
|
+
// ../kit/src/theme.ts
|
|
299
|
+
import { existsSync as existsSync3, readFileSync, statSync } from "fs";
|
|
300
|
+
import { homedir as homedir2 } from "os";
|
|
301
|
+
import { join as join3, resolve as resolve2 } from "path";
|
|
302
|
+
import process5 from "process";
|
|
303
|
+
|
|
304
|
+
// ../kit/src/config.ts
|
|
305
|
+
import { existsSync } from "fs";
|
|
306
|
+
import { dirname, join, resolve } from "path";
|
|
307
|
+
import process3 from "process";
|
|
308
|
+
function findUp(names, from = process3.cwd(), stop = () => false) {
|
|
309
|
+
const wanted = typeof names === "string" ? [names] : names;
|
|
310
|
+
for (let dir = resolve(from);; dir = dirname(dir)) {
|
|
311
|
+
const found = wanted.map((name) => join(dir, name)).find((path) => existsSync(path));
|
|
312
|
+
if (found !== undefined)
|
|
313
|
+
return found;
|
|
314
|
+
if (stop(dir) || dirname(dir) === dir)
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
298
319
|
// ../kit/src/user-config.ts
|
|
320
|
+
import { existsSync as existsSync2 } from "fs";
|
|
299
321
|
import { homedir } from "os";
|
|
300
|
-
import { join } from "path";
|
|
301
|
-
import
|
|
322
|
+
import { join as join2 } from "path";
|
|
323
|
+
import process4 from "process";
|
|
302
324
|
function configBase(where = {}) {
|
|
303
|
-
const xdg = where.xdg ?? (where.home === undefined ?
|
|
304
|
-
return xdg !== undefined && xdg !== "" ? xdg :
|
|
325
|
+
const xdg = where.xdg ?? (where.home === undefined ? process4.env.XDG_CONFIG_HOME : undefined);
|
|
326
|
+
return xdg !== undefined && xdg !== "" ? xdg : join2(where.home ?? homedir(), ".config");
|
|
305
327
|
}
|
|
306
328
|
function userConfigPath(bin, where = {}) {
|
|
307
|
-
return
|
|
329
|
+
return join2(configBase(where), "kaynooo-cli", `${bin}.json`);
|
|
330
|
+
}
|
|
331
|
+
function userConfigReadPath(bin, legacy = [], where = {}) {
|
|
332
|
+
const current = userConfigPath(bin, where);
|
|
333
|
+
if (existsSync2(current))
|
|
334
|
+
return current;
|
|
335
|
+
const base = configBase(where);
|
|
336
|
+
return legacy.map((parts) => join2(base, ...parts)).find((path) => existsSync2(path)) ?? current;
|
|
308
337
|
}
|
|
309
338
|
|
|
310
339
|
// ../kit/src/theme.ts
|
|
340
|
+
var DEFAULT = {
|
|
341
|
+
colors: { accent: "cyan", id: "yellow", path: "blue", label: "dim", value: "bold", ok: "green", warn: "yellow", problem: "red", note: "dim", passed: "green", failed: "red", running: "cyan", queued: "yellow", skipped: "dim" },
|
|
342
|
+
glyphs: { ok: "\u2713", warn: "\u25B2", problem: "\u2717", note: "\u203A", passed: "\u2713", failed: "\u2717", running: "\u25CF", queued: "\u25CB", skipped: "-", bar: "\u2501" },
|
|
343
|
+
accents: ["cyan", "magenta", "green", "blue", "yellow", "redBright"],
|
|
344
|
+
bins: {}
|
|
345
|
+
};
|
|
346
|
+
var BRIGHT = { accent: "cyanBright", id: "yellowBright", path: "blueBright", label: "white", value: "bold whiteBright", ok: "greenBright", warn: "yellowBright", problem: "redBright", note: "white", passed: "greenBright", failed: "redBright", running: "cyanBright", queued: "yellowBright", skipped: "white" };
|
|
347
|
+
var MONO = { accent: "bold", id: "bold", path: "underline", label: "dim", value: "bold", ok: "bold", warn: "bold", problem: "bold", note: "dim", passed: "bold", failed: "bold", running: "bold", queued: "dim", skipped: "dim" };
|
|
348
|
+
var ASCII = { ok: "+", warn: "!", problem: "x", note: ">", passed: "+", failed: "x", running: "*", queued: "o", skipped: "-", bar: "#" };
|
|
349
|
+
var PRESETS = {
|
|
350
|
+
default: {},
|
|
351
|
+
"high-contrast": { colors: BRIGHT, accents: ["cyanBright", "magentaBright", "greenBright", "blueBright", "yellowBright", "redBright"] },
|
|
352
|
+
mono: { colors: MONO, accents: ["bold"] },
|
|
353
|
+
ascii: { glyphs: ASCII }
|
|
354
|
+
};
|
|
311
355
|
var STYLES = new Set(["bold", "dim", "italic", "underline", "inverse", "strikethrough", "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "gray", "grey", "blackBright", "redBright", "greenBright", "yellowBright", "blueBright", "magentaBright", "cyanBright", "whiteBright"]);
|
|
356
|
+
var HEX = /^#[0-9a-f]{6}$/i;
|
|
357
|
+
var CONTROL = /\p{Cc}/u;
|
|
312
358
|
var MAX_FILE_BYTES = 64 * 1024;
|
|
359
|
+
var SPACES = /\s+/;
|
|
360
|
+
function isColorSpec(spec) {
|
|
361
|
+
if (typeof spec === "number")
|
|
362
|
+
return Number.isInteger(spec) && spec >= 0 && spec <= 255;
|
|
363
|
+
return typeof spec === "string" && spec.trim() !== "" && spec.trim().split(SPACES).every((token) => STYLES.has(token) || HEX.test(token));
|
|
364
|
+
}
|
|
365
|
+
function isRecord(value) {
|
|
366
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
367
|
+
}
|
|
368
|
+
function readThemeFile(path, warn) {
|
|
369
|
+
try {
|
|
370
|
+
const stat = statSync(path, { throwIfNoEntry: false });
|
|
371
|
+
if (stat === undefined)
|
|
372
|
+
return;
|
|
373
|
+
if (!stat.isFile() || stat.size > MAX_FILE_BYTES) {
|
|
374
|
+
warn(`${path} is not a regular file under ${MAX_FILE_BYTES / 1024} KiB, theme ignored`);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
378
|
+
if (isRecord(parsed))
|
|
379
|
+
return parsed;
|
|
380
|
+
warn(`${path} is not a JSON object, theme ignored`);
|
|
381
|
+
} catch (error) {
|
|
382
|
+
warn(`${path} does not parse (${error instanceof Error ? error.message : String(error)}), theme ignored`);
|
|
383
|
+
}
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
function applyPreset(theme, name, warn, where) {
|
|
387
|
+
if (name === undefined)
|
|
388
|
+
return;
|
|
389
|
+
if (typeof name !== "string" || !Object.hasOwn(PRESETS, name)) {
|
|
390
|
+
warn(`${where}: no preset ${String(name)}, one of ${Object.keys(PRESETS).join(", ")}`);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const preset = PRESETS[name];
|
|
394
|
+
Object.assign(theme.colors, preset.colors);
|
|
395
|
+
Object.assign(theme.glyphs, preset.glyphs);
|
|
396
|
+
if (preset.accents !== undefined)
|
|
397
|
+
theme.accents = [...preset.accents];
|
|
398
|
+
return name;
|
|
399
|
+
}
|
|
400
|
+
function applyFile(theme, file, where, warn) {
|
|
401
|
+
if (isRecord(file.colors)) {
|
|
402
|
+
for (const [key, value] of Object.entries(file.colors)) {
|
|
403
|
+
if (!Object.hasOwn(DEFAULT.colors, key))
|
|
404
|
+
warn(`${where}: no colour ${key}, one of ${Object.keys(DEFAULT.colors).join(", ")}`);
|
|
405
|
+
else if (!isColorSpec(value))
|
|
406
|
+
warn(`${where}: colour ${key} is not an ANSI name, \`#rrggbb\` or a number up to 255`);
|
|
407
|
+
else
|
|
408
|
+
theme.colors[key] = value;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (isRecord(file.glyphs)) {
|
|
412
|
+
for (const [key, value] of Object.entries(file.glyphs)) {
|
|
413
|
+
if (!Object.hasOwn(DEFAULT.glyphs, key))
|
|
414
|
+
warn(`${where}: no glyph ${key}, one of ${Object.keys(DEFAULT.glyphs).join(", ")}`);
|
|
415
|
+
else if (typeof value !== "string" || CONTROL.test(value) || Bun.stringWidth(value) !== 1)
|
|
416
|
+
warn(`${where}: glyph ${key} must be one visible character wide, with no control character`);
|
|
417
|
+
else
|
|
418
|
+
theme.glyphs[key] = value;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (Array.isArray(file.accents) && file.accents.length > 0 && file.accents.every(isColorSpec))
|
|
422
|
+
theme.accents = [...file.accents];
|
|
423
|
+
else if (file.accents !== undefined)
|
|
424
|
+
warn(`${where}: accents must be a non-empty list of colours`);
|
|
425
|
+
if (isRecord(file.bins)) {
|
|
426
|
+
for (const [bin, value] of Object.entries(file.bins)) {
|
|
427
|
+
if (isColorSpec(value))
|
|
428
|
+
theme.bins[bin] = value;
|
|
429
|
+
else
|
|
430
|
+
warn(`${where}: bin ${bin} has no valid colour`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
function endsWalk(home) {
|
|
435
|
+
return (dir) => dir === resolve2(home) || existsSync3(join3(dir, ".git"));
|
|
436
|
+
}
|
|
313
437
|
var warned = new Set;
|
|
438
|
+
function warnOnce(message) {
|
|
439
|
+
if (warned.has(message))
|
|
440
|
+
return;
|
|
441
|
+
warned.add(message);
|
|
442
|
+
console.error(`warning: theme ${message}`);
|
|
443
|
+
}
|
|
444
|
+
function isPath(chosen) {
|
|
445
|
+
return chosen.includes("/") || chosen.endsWith(".json");
|
|
446
|
+
}
|
|
447
|
+
function loadTheme({ env = process5.env, from = process5.cwd(), home = homedir2(), warn = warnOnce } = {}) {
|
|
448
|
+
const theme = { colors: { ...DEFAULT.colors }, glyphs: { ...DEFAULT.glyphs }, accents: [...DEFAULT.accents], bins: Object.create(null) };
|
|
449
|
+
const sources = [];
|
|
450
|
+
const chosen = env.KIT_THEME ?? "";
|
|
451
|
+
const wanted = chosen === "" ? [userConfigPath("theme", { home, xdg: env.XDG_CONFIG_HOME }), findUp(join3(".kaynooo", "theme.json"), from, endsWalk(home))] : [];
|
|
452
|
+
if (isPath(chosen))
|
|
453
|
+
wanted.push(resolve2(from, chosen));
|
|
454
|
+
const files = [];
|
|
455
|
+
for (const path of wanted) {
|
|
456
|
+
const file = path === undefined ? undefined : readThemeFile(path, warn);
|
|
457
|
+
if (path !== undefined && file !== undefined)
|
|
458
|
+
files.push({ path, file });
|
|
459
|
+
}
|
|
460
|
+
let preset = "default";
|
|
461
|
+
if (chosen !== "" && !isPath(chosen)) {
|
|
462
|
+
preset = applyPreset(theme, chosen, warn, "KIT_THEME") ?? preset;
|
|
463
|
+
} else {
|
|
464
|
+
const named = files.findLast(({ file }) => file.preset !== undefined);
|
|
465
|
+
if (named !== undefined)
|
|
466
|
+
preset = applyPreset(theme, named.file.preset, warn, named.path) ?? preset;
|
|
467
|
+
}
|
|
468
|
+
for (const { path, file } of files) {
|
|
469
|
+
applyFile(theme, file, path, warn);
|
|
470
|
+
sources.push(path);
|
|
471
|
+
}
|
|
472
|
+
return { theme, sources, preset };
|
|
473
|
+
}
|
|
314
474
|
|
|
315
475
|
// ../kit/src/style.ts
|
|
316
|
-
function takesControlCodes(stream, env =
|
|
476
|
+
function takesControlCodes(stream, env = process6.env) {
|
|
317
477
|
return stream.isTTY === true && env.NO_COLOR === undefined && env.NODE_DISABLE_COLORS === undefined && env.TERM !== "dumb" && outputMode(stream, env) === "terminal";
|
|
318
478
|
}
|
|
319
|
-
function paint(stream, env =
|
|
479
|
+
function paint(stream, env = process6.env) {
|
|
320
480
|
return le({ stream: { isTTY: takesControlCodes(stream, env) }, env });
|
|
321
481
|
}
|
|
322
482
|
var STATUS_WORDS = {
|
|
@@ -341,7 +501,7 @@ var ESCAPE = String.fromCharCode(27);
|
|
|
341
501
|
function textWidth(text) {
|
|
342
502
|
return Bun.stringWidth(text);
|
|
343
503
|
}
|
|
344
|
-
function table(rows, { cellWidth, header = false, align = [], fit, stream =
|
|
504
|
+
function table(rows, { cellWidth, header = false, align = [], fit, stream = process7.stdout, env = process7.env } = {}) {
|
|
345
505
|
const cells = cellWidth === undefined ? rows : rows.map((row) => row.map((cell) => truncate(cell.replaceAll(LINE_BREAKS, " "), cellWidth)));
|
|
346
506
|
if (outputMode(stream, env) === "agent")
|
|
347
507
|
return cells.map((row) => row.map((cell) => Bun.stripANSI(cell).replaceAll(/[\t\r\n]+/g, " ")).join("\t")).join(`
|
|
@@ -380,7 +540,7 @@ function narrow(rows, widths, limit) {
|
|
|
380
540
|
}
|
|
381
541
|
return rows.map((row) => row.map((cell, index) => textWidth(cell) > (widths[index] ?? 0) ? truncate(cell, widths[index] ?? 0) : cell));
|
|
382
542
|
}
|
|
383
|
-
function jsonText(value, replacer, { stream =
|
|
543
|
+
function jsonText(value, replacer, { stream = process7.stdout, env = process7.env } = {}) {
|
|
384
544
|
return JSON.stringify(value, replacer, outputMode(stream, env) === "agent" ? undefined : 2);
|
|
385
545
|
}
|
|
386
546
|
function printJson(value) {
|
|
@@ -388,27 +548,27 @@ function printJson(value) {
|
|
|
388
548
|
}
|
|
389
549
|
|
|
390
550
|
// ../kit/src/help.ts
|
|
391
|
-
import
|
|
551
|
+
import process8 from "process";
|
|
392
552
|
var OPTIONAL = /\[[^\]]+\]/g;
|
|
393
553
|
var USAGE_PREFIX = /^usage:\s*/i;
|
|
394
554
|
var FULL_STOP = /\.$/;
|
|
395
|
-
function usageLine(usage, colors = paint(
|
|
555
|
+
function usageLine(usage, colors = paint(process8.stdout)) {
|
|
396
556
|
return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
|
|
397
557
|
}
|
|
398
|
-
function helpText(usage, options, colors = paint(
|
|
558
|
+
function helpText(usage, options, colors = paint(process8.stdout), { examples = [], replaces, exits = [] } = {}) {
|
|
399
559
|
return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exitRows(exits, colors), ...exampleRows(examples, colors)].join(`
|
|
400
560
|
`);
|
|
401
561
|
}
|
|
402
|
-
function exitRows(exits, colors = paint(
|
|
562
|
+
function exitRows(exits, colors = paint(process8.stdout)) {
|
|
403
563
|
if (exits.length === 0)
|
|
404
564
|
return [];
|
|
405
565
|
const width = Math.max(...exits.map(([code]) => String(code).length));
|
|
406
566
|
return ["", colors.bold("Exits:"), ...exits.map(([code, meaning]) => ` ${colors.cyan(String(code).padEnd(width))} ${meaning}`)];
|
|
407
567
|
}
|
|
408
|
-
function replacesRows(replaces, colors = paint(
|
|
568
|
+
function replacesRows(replaces, colors = paint(process8.stdout)) {
|
|
409
569
|
return replaces === undefined || outputMode() === "agent" ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
|
|
410
570
|
}
|
|
411
|
-
function wantsHelpJson(env =
|
|
571
|
+
function wantsHelpJson(env = process8.env) {
|
|
412
572
|
return env.KIT_HELP === "json";
|
|
413
573
|
}
|
|
414
574
|
function description(usage, { examples = [], replaces, exits } = {}, options) {
|
|
@@ -427,12 +587,12 @@ function description(usage, { examples = [], replaces, exits } = {}, options) {
|
|
|
427
587
|
...options === undefined ? {} : { options: Object.entries(options).map(([name, { short, description }]) => ({ name, ...short === undefined ? {} : { short }, ...description === undefined ? {} : { description } })) }
|
|
428
588
|
};
|
|
429
589
|
}
|
|
430
|
-
function exampleRows(examples, colors = paint(
|
|
590
|
+
function exampleRows(examples, colors = paint(process8.stdout)) {
|
|
431
591
|
if (examples.length === 0 || outputMode() === "agent")
|
|
432
592
|
return [];
|
|
433
593
|
return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
|
|
434
594
|
}
|
|
435
|
-
function optionRows(options, colors = paint(
|
|
595
|
+
function optionRows(options, colors = paint(process8.stdout)) {
|
|
436
596
|
const rows = Object.entries(options).map(([name, option]) => {
|
|
437
597
|
const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
|
|
438
598
|
const named = option.choices === undefined ? "<value>" : `<${option.choices.join("|")}>`;
|
|
@@ -524,7 +684,7 @@ var OUTPUT_OPTIONS = {
|
|
|
524
684
|
color: { type: "string", description: "auto (on a terminal alone), always or never" },
|
|
525
685
|
plain: { type: "boolean", description: "plain text, no colour or spinner: --color never" }
|
|
526
686
|
};
|
|
527
|
-
function applyOutput(color, plain, env =
|
|
687
|
+
function applyOutput(color, plain, env = process9.env) {
|
|
528
688
|
const when = plain === true ? "never" : color ?? "auto";
|
|
529
689
|
if (when === "auto")
|
|
530
690
|
return;
|
|
@@ -695,7 +855,7 @@ function nearestOption(message, options, allowNegative) {
|
|
|
695
855
|
}
|
|
696
856
|
// ../kit/src/process.ts
|
|
697
857
|
import { constants } from "os";
|
|
698
|
-
import
|
|
858
|
+
import process10 from "process";
|
|
699
859
|
var KILL_GRACE_MS = 2000;
|
|
700
860
|
function exitCodeOf(code, signal) {
|
|
701
861
|
if (code !== null)
|
|
@@ -715,7 +875,7 @@ async function runCommand(argv, { cwd, env, stdin = "ignore", timeoutMs, signal,
|
|
|
715
875
|
return;
|
|
716
876
|
try {
|
|
717
877
|
if (grouped)
|
|
718
|
-
|
|
878
|
+
process10.kill(-proc.pid, killing);
|
|
719
879
|
else
|
|
720
880
|
proc.kill(killing);
|
|
721
881
|
} catch {}
|
|
@@ -789,15 +949,15 @@ var ESCAPE_CODE = new RegExp(`${ESC}(?:\\[[\\x30-\\x3F]*[\\x20-\\x2F]*[\\x40-\\x
|
|
|
789
949
|
var RESET_STYLE = `${ESC}[0m`;
|
|
790
950
|
var CLOSE_LINK = `${ESC}]8;;${ESC}\\`;
|
|
791
951
|
// ../kit/src/cli.ts
|
|
792
|
-
import { readFileSync, realpathSync } from "fs";
|
|
793
|
-
import { dirname as
|
|
794
|
-
import
|
|
952
|
+
import { readFileSync as readFileSync2, realpathSync } from "fs";
|
|
953
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
954
|
+
import process12 from "process";
|
|
795
955
|
|
|
796
956
|
// ../kit/src/usage.ts
|
|
797
957
|
import { appendFileSync, mkdirSync } from "fs";
|
|
798
|
-
import { homedir as
|
|
799
|
-
import { dirname, isAbsolute, join as
|
|
800
|
-
import
|
|
958
|
+
import { homedir as homedir3 } from "os";
|
|
959
|
+
import { dirname as dirname2, isAbsolute, join as join4 } from "path";
|
|
960
|
+
import process11 from "process";
|
|
801
961
|
|
|
802
962
|
// ../kit/src/logs.ts
|
|
803
963
|
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
@@ -811,14 +971,14 @@ var usageError;
|
|
|
811
971
|
function noteUsageError(message) {
|
|
812
972
|
usageError = message;
|
|
813
973
|
}
|
|
814
|
-
function stateHome(env =
|
|
974
|
+
function stateHome(env = process11.env) {
|
|
815
975
|
const dir = env.XDG_STATE_HOME;
|
|
816
|
-
return dir !== undefined && isAbsolute(dir) ? dir :
|
|
976
|
+
return dir !== undefined && isAbsolute(dir) ? dir : join4(homedir3(), ".local", "state");
|
|
817
977
|
}
|
|
818
|
-
function usagePath(env =
|
|
819
|
-
return
|
|
978
|
+
function usagePath(env = process11.env) {
|
|
979
|
+
return join4(stateHome(env), CLI_FOLDER, "usage.jsonl");
|
|
820
980
|
}
|
|
821
|
-
function usageRecorded(env =
|
|
981
|
+
function usageRecorded(env = process11.env) {
|
|
822
982
|
const off = env.KAYNOOO_CLI_NO_USAGE;
|
|
823
983
|
return env.NODE_ENV !== "test" && (off === undefined || off === "" || off === "0");
|
|
824
984
|
}
|
|
@@ -832,12 +992,12 @@ function usageEntry(bin, command, argv, code, now = new Date) {
|
|
|
832
992
|
usageError = undefined;
|
|
833
993
|
return { at: now.toISOString(), bin, ...command === undefined ? {} : { command }, flags: flagNames(argv), code, ...unknown === undefined ? {} : { unknown } };
|
|
834
994
|
}
|
|
835
|
-
function recordUsage(entry, env =
|
|
995
|
+
function recordUsage(entry, env = process11.env) {
|
|
836
996
|
if (!usageRecorded(env))
|
|
837
997
|
return;
|
|
838
998
|
try {
|
|
839
999
|
const path = usagePath(env);
|
|
840
|
-
mkdirSync(
|
|
1000
|
+
mkdirSync(dirname2(path), { recursive: true, mode: 448 });
|
|
841
1001
|
appendFileSync(path, `${JSON.stringify(entry)}
|
|
842
1002
|
`, { mode: 384 });
|
|
843
1003
|
} catch {}
|
|
@@ -971,8 +1131,8 @@ async function help2({ path, header, summary: lazySummary, commands, defaultComm
|
|
|
971
1131
|
`);
|
|
972
1132
|
}
|
|
973
1133
|
function printError(prefix, message, hint, cause) {
|
|
974
|
-
const colors = paint(
|
|
975
|
-
const styled = takesControlCodes(
|
|
1134
|
+
const colors = paint(process12.stderr);
|
|
1135
|
+
const styled = takesControlCodes(process12.stderr);
|
|
976
1136
|
const head = styled ? `${colors.red.bold("error")} ${colors.dim(`${prefix}:`)}` : `error: ${prefix}:`;
|
|
977
1137
|
const under = (label, text, tint) => text === undefined ? "" : `
|
|
978
1138
|
${styled ? tint(label) : `${label}:`} ${text}`;
|
|
@@ -1015,11 +1175,11 @@ async function dispatch(level, typed, { version, redact }) {
|
|
|
1015
1175
|
}
|
|
1016
1176
|
}
|
|
1017
1177
|
if (name === undefined && level.path.length > 1) {
|
|
1018
|
-
console.error(await help2(await expand(level, [...level.path.slice(1), ...argv]),
|
|
1178
|
+
console.error(await help2(await expand(level, [...level.path.slice(1), ...argv]), process12.stderr));
|
|
1019
1179
|
return 2;
|
|
1020
1180
|
}
|
|
1021
1181
|
if (name === undefined || name === "help" || name === "--help" || name === "-h") {
|
|
1022
|
-
console.log(await help2(await expand(level, [...level.path.slice(1), ...argv]),
|
|
1182
|
+
console.log(await help2(await expand(level, [...level.path.slice(1), ...argv]), process12.stdout));
|
|
1023
1183
|
return 0;
|
|
1024
1184
|
}
|
|
1025
1185
|
if (level.path.length === 1 && (name === "--version" || name === "-v")) {
|
|
@@ -1136,17 +1296,17 @@ async function printCandidates(found) {
|
|
|
1136
1296
|
return 0;
|
|
1137
1297
|
}
|
|
1138
1298
|
function packageVersion(entry = Bun.main) {
|
|
1139
|
-
for (let dir =
|
|
1299
|
+
for (let dir = dirname3(realpathSync(entry));; dir = dirname3(dir)) {
|
|
1140
1300
|
try {
|
|
1141
|
-
const { version } = JSON.parse(
|
|
1301
|
+
const { version } = JSON.parse(readFileSync2(join5(dir, "package.json"), "utf8"));
|
|
1142
1302
|
if (typeof version === "string")
|
|
1143
1303
|
return version;
|
|
1144
1304
|
} catch {}
|
|
1145
|
-
if (
|
|
1305
|
+
if (dirname3(dir) === dir)
|
|
1146
1306
|
return "0.0.0";
|
|
1147
1307
|
}
|
|
1148
1308
|
}
|
|
1149
|
-
async function runCli(cli, argv =
|
|
1309
|
+
async function runCli(cli, argv = process12.argv.slice(2)) {
|
|
1150
1310
|
const version = cli.version ?? packageVersion();
|
|
1151
1311
|
if (argv[0] === COMPLETE)
|
|
1152
1312
|
return printCandidates(candidates(scopeOf(cli.commands, cli.extraCommands, cli.aliases), cli.defaultCommand, argv.slice(1)));
|
|
@@ -1173,7 +1333,7 @@ function commandPath(scope, argv) {
|
|
|
1173
1333
|
}
|
|
1174
1334
|
return path.length === 0 ? undefined : path.join(" ");
|
|
1175
1335
|
}
|
|
1176
|
-
async function runMain({ name, version, run, redact, usage }, argv =
|
|
1336
|
+
async function runMain({ name, version, run, redact, usage }, argv = process12.argv.slice(2)) {
|
|
1177
1337
|
if (argv[0] === COMPLETE)
|
|
1178
1338
|
return printCandidates(leafCandidates(run, argv.slice(1)));
|
|
1179
1339
|
if (argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v")) {
|
|
@@ -1193,6 +1353,8 @@ async function runMain({ name, version, run, redact, usage }, argv = process10.a
|
|
|
1193
1353
|
}
|
|
1194
1354
|
return code;
|
|
1195
1355
|
}
|
|
1356
|
+
// ../kit/src/folders.ts
|
|
1357
|
+
var SKIPPED_FOLDERS = new Set(["node_modules", "vendor", "dist", "build", "target", "coverage", "venv", "__pycache__"]);
|
|
1196
1358
|
// ../kit/src/secrets.ts
|
|
1197
1359
|
var SECRET_WORDS = new Set(["key", "pass", "pwd", "auth", "salt", "cookie", "session", "jwt", "ssn", "iban", "card", "cvv", "otp"]);
|
|
1198
1360
|
// ../kit/src/sessions.ts
|
|
@@ -1200,40 +1362,40 @@ var {Glob } = globalThis.Bun;
|
|
|
1200
1362
|
var SESSION_FILES = new Glob("*.json");
|
|
1201
1363
|
var ACCOUNT_DIRS = new Glob("*/sessions");
|
|
1202
1364
|
// ../kit/src/workspace-root.ts
|
|
1203
|
-
import { existsSync, mkdirSync as mkdirSync2, readFileSync as
|
|
1204
|
-
import { homedir as
|
|
1205
|
-
import { dirname as
|
|
1206
|
-
import
|
|
1365
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
1366
|
+
import { homedir as homedir4 } from "os";
|
|
1367
|
+
import { dirname as dirname4, join as join6, resolve as resolve3 } from "path";
|
|
1368
|
+
import process13 from "process";
|
|
1207
1369
|
function expandHome(path, home) {
|
|
1208
1370
|
if (path === "~")
|
|
1209
1371
|
return home;
|
|
1210
|
-
return path.startsWith("~/") ?
|
|
1372
|
+
return path.startsWith("~/") ? join6(home, path.slice(2)) : path;
|
|
1211
1373
|
}
|
|
1212
1374
|
function configured(env, home) {
|
|
1213
1375
|
const path = userConfigPath("config", { home, xdg: env.XDG_CONFIG_HOME });
|
|
1214
|
-
if (!
|
|
1376
|
+
if (!existsSync4(path))
|
|
1215
1377
|
return;
|
|
1216
1378
|
try {
|
|
1217
|
-
const parsed = JSON.parse(
|
|
1379
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
1218
1380
|
const folder = typeof parsed === "object" && parsed !== null ? parsed.workspace : undefined;
|
|
1219
1381
|
return typeof folder === "string" && folder !== "" ? folder : undefined;
|
|
1220
1382
|
} catch {
|
|
1221
1383
|
return;
|
|
1222
1384
|
}
|
|
1223
1385
|
}
|
|
1224
|
-
function workspaceRoot({ given, env =
|
|
1386
|
+
function workspaceRoot({ given, env = process13.env, home = homedir4() } = {}) {
|
|
1225
1387
|
const fromEnv = env.KAYNOOO_WORKSPACE === "" ? undefined : env.KAYNOOO_WORKSPACE;
|
|
1226
|
-
return
|
|
1388
|
+
return resolve3(expandHome(given ?? fromEnv ?? configured(env, home) ?? join6(home, "Workspace"), home));
|
|
1227
1389
|
}
|
|
1228
|
-
function workspaceChosen({ env =
|
|
1390
|
+
function workspaceChosen({ env = process13.env, home = homedir4() } = {}) {
|
|
1229
1391
|
return (env.KAYNOOO_WORKSPACE ?? "") !== "" || configured(env, home) !== undefined;
|
|
1230
1392
|
}
|
|
1231
|
-
function saveWorkspace(folder, { env =
|
|
1393
|
+
function saveWorkspace(folder, { env = process13.env, home = homedir4() } = {}) {
|
|
1232
1394
|
const path = userConfigPath("config", { home, xdg: env.XDG_CONFIG_HOME });
|
|
1233
1395
|
let current = {};
|
|
1234
|
-
if (
|
|
1396
|
+
if (existsSync4(path)) {
|
|
1235
1397
|
try {
|
|
1236
|
-
const parsed = JSON.parse(
|
|
1398
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
1237
1399
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
1238
1400
|
return false;
|
|
1239
1401
|
current = parsed;
|
|
@@ -1241,17 +1403,17 @@ function saveWorkspace(folder, { env = process11.env, home = homedir3() } = {})
|
|
|
1241
1403
|
return false;
|
|
1242
1404
|
}
|
|
1243
1405
|
}
|
|
1244
|
-
mkdirSync2(
|
|
1406
|
+
mkdirSync2(dirname4(path), { recursive: true });
|
|
1245
1407
|
writeFileSync(path, `${JSON.stringify({ ...current, workspace: folder }, undefined, 2)}
|
|
1246
1408
|
`);
|
|
1247
1409
|
return true;
|
|
1248
1410
|
}
|
|
1249
1411
|
// src/doctor.ts
|
|
1250
|
-
import
|
|
1412
|
+
import process19 from "process";
|
|
1251
1413
|
|
|
1252
1414
|
// src/checks.ts
|
|
1253
|
-
import { existsSync as
|
|
1254
|
-
import { basename, join as
|
|
1415
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
1416
|
+
import { basename, join as join8 } from "path";
|
|
1255
1417
|
|
|
1256
1418
|
// src/catalog.ts
|
|
1257
1419
|
var HOOKS_REQUIRES = "@kaynooo/cli-guard";
|
|
@@ -1287,9 +1449,9 @@ var NEEDS = {
|
|
|
1287
1449
|
};
|
|
1288
1450
|
|
|
1289
1451
|
// src/completions.ts
|
|
1290
|
-
import { existsSync as
|
|
1291
|
-
import { join as
|
|
1292
|
-
import
|
|
1452
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync4, rmSync } from "fs";
|
|
1453
|
+
import { join as join7 } from "path";
|
|
1454
|
+
import process15 from "process";
|
|
1293
1455
|
var MARKER = "# Generated by `cli completions fish`";
|
|
1294
1456
|
var FISH_FILE = /\.fish$/;
|
|
1295
1457
|
var FUNCTION = `functions -q __kaynooo_cli_complete; or function __kaynooo_cli_complete --argument-names bin --description 'what a @kaynooo/cli-* bin offers for the word being typed'
|
|
@@ -1317,14 +1479,36 @@ var BASH_FUNCTION = `__kaynooo_cli_complete() {
|
|
|
1317
1479
|
done
|
|
1318
1480
|
COMPREPLY+=($(compgen -W "$words" -- "$cur"))
|
|
1319
1481
|
}`;
|
|
1482
|
+
var ZSH_FUNCTION = `__kaynooo_cli_complete() {
|
|
1483
|
+
local line
|
|
1484
|
+
local -a described plain
|
|
1485
|
+
for line in \${(f)"$("\${words[1]}" __complete "\${(@)words[2,CURRENT]}" 2>/dev/null)"}; do
|
|
1486
|
+
if [[ $line == __files__ ]]; then
|
|
1487
|
+
_files
|
|
1488
|
+
elif [[ $line == *$'\\t'* ]]; then
|
|
1489
|
+
described+=("\${\${line%%$'\\t'*}//:/\\\\:}:\${line#*$'\\t'}")
|
|
1490
|
+
else
|
|
1491
|
+
plain+=("$line")
|
|
1492
|
+
fi
|
|
1493
|
+
done
|
|
1494
|
+
(( \${#described} )) && _describe -V value described
|
|
1495
|
+
(( \${#plain} )) && compadd -- "\${plain[@]}"
|
|
1496
|
+
return 0
|
|
1497
|
+
}`;
|
|
1498
|
+
function zshScript(bins) {
|
|
1499
|
+
return `# Generated by \`cli completions zsh\`
|
|
1500
|
+
${ZSH_FUNCTION}
|
|
1501
|
+
compdef __kaynooo_cli_complete ${bins.join(" ")}
|
|
1502
|
+
`;
|
|
1503
|
+
}
|
|
1320
1504
|
function bashScript(bins) {
|
|
1321
1505
|
return `# Generated by \`cli completions bash\`
|
|
1322
1506
|
${BASH_FUNCTION}
|
|
1323
1507
|
complete -F __kaynooo_cli_complete ${bins.join(" ")}
|
|
1324
1508
|
`;
|
|
1325
1509
|
}
|
|
1326
|
-
function completionDir(home, env =
|
|
1327
|
-
return
|
|
1510
|
+
function completionDir(home, env = process15.env) {
|
|
1511
|
+
return join7(env.XDG_CACHE_HOME ?? join7(home, ".cache"), "fish", "kaynooo-cli");
|
|
1328
1512
|
}
|
|
1329
1513
|
function installedBins(host) {
|
|
1330
1514
|
return Object.values(TOOLS).flat().filter((bin) => host.which(bin) !== null);
|
|
@@ -1338,14 +1522,14 @@ complete -c ${bin} -f -a '(__kaynooo_cli_complete ${bin})'
|
|
|
1338
1522
|
async function installCompletions(host, dir) {
|
|
1339
1523
|
const bins = installedBins(host);
|
|
1340
1524
|
mkdirSync3(dir, { recursive: true });
|
|
1341
|
-
const removed = readdirSync(dir).filter((name) => FISH_FILE.test(name) && !bins.includes(name.replace(FISH_FILE, "")) &&
|
|
1525
|
+
const removed = readdirSync(dir).filter((name) => FISH_FILE.test(name) && !bins.includes(name.replace(FISH_FILE, "")) && readFileSync4(join7(dir, name), "utf8").startsWith(MARKER));
|
|
1342
1526
|
for (const name of removed)
|
|
1343
|
-
rmSync(
|
|
1344
|
-
await Promise.all(bins.map(async (bin) => Bun.write(
|
|
1527
|
+
rmSync(join7(dir, name));
|
|
1528
|
+
await Promise.all(bins.map(async (bin) => Bun.write(join7(dir, `${bin}.fish`), completionFile(bin))));
|
|
1345
1529
|
return { written: bins, removed: removed.map((name) => name.replace(FISH_FILE, "")) };
|
|
1346
1530
|
}
|
|
1347
1531
|
function missingCompletions(host, dir) {
|
|
1348
|
-
return installedBins(host).filter((bin) => !
|
|
1532
|
+
return installedBins(host).filter((bin) => !existsSync5(join7(dir, `${bin}.fish`)));
|
|
1349
1533
|
}
|
|
1350
1534
|
|
|
1351
1535
|
// src/checks.ts
|
|
@@ -1389,7 +1573,7 @@ function readJsonText(text) {
|
|
|
1389
1573
|
}
|
|
1390
1574
|
}
|
|
1391
1575
|
function readJson(path) {
|
|
1392
|
-
return
|
|
1576
|
+
return existsSync6(path) ? readJsonText(readFileSync5(path, "utf8")) : undefined;
|
|
1393
1577
|
}
|
|
1394
1578
|
function firstLine(text) {
|
|
1395
1579
|
const trimmed = text.trim();
|
|
@@ -1398,7 +1582,7 @@ function firstLine(text) {
|
|
|
1398
1582
|
return end === -1 ? trimmed : trimmed.slice(0, end);
|
|
1399
1583
|
}
|
|
1400
1584
|
function installed(host, name) {
|
|
1401
|
-
return readJson(
|
|
1585
|
+
return readJson(join8(host.globalModules, name, "package.json"));
|
|
1402
1586
|
}
|
|
1403
1587
|
function isInstalled(host, name) {
|
|
1404
1588
|
return installed(host, name)?.version !== undefined;
|
|
@@ -1406,7 +1590,7 @@ function isInstalled(host, name) {
|
|
|
1406
1590
|
function ownBin(host, name, bin) {
|
|
1407
1591
|
const declared = installed(host, name)?.bin;
|
|
1408
1592
|
const file = typeof declared === "string" ? declared : declared?.[bin];
|
|
1409
|
-
return file === undefined ? undefined :
|
|
1593
|
+
return file === undefined ? undefined : join8(host.globalModules, name, file);
|
|
1410
1594
|
}
|
|
1411
1595
|
async function checkTool(host, name, bins) {
|
|
1412
1596
|
const check = name.slice(name.indexOf("/") + 1);
|
|
@@ -1421,17 +1605,29 @@ async function checkTool(host, name, bins) {
|
|
|
1421
1605
|
if (latest !== "" && Bun.semver.order(version, latest) < 0)
|
|
1422
1606
|
return { check, ok: false, detail: `${version}, ${latest} released${off.length > 0 ? `, ${off.join(", ")} not on the PATH` : ""}`, fix: `bun install -g ${name}@${latest}` };
|
|
1423
1607
|
if (off.length > 0)
|
|
1424
|
-
return { check, ok: false, detail: `${version}, ${off.join(", ")} not on the PATH`, fix: `add ${
|
|
1608
|
+
return { check, ok: false, detail: `${version}, ${off.join(", ")} not on the PATH`, fix: `add ${join8(host.globalModules, "..", "..", "..", "bin")} to the PATH` };
|
|
1425
1609
|
if (latest === "")
|
|
1426
1610
|
return { check, ok: true, detail: `${version}, the registry did not answer: ${firstLine(info.stderr) || answered || "no version"}` };
|
|
1427
1611
|
return { check, ok: true, detail: version };
|
|
1428
1612
|
}
|
|
1613
|
+
function extraForgeHosts(home) {
|
|
1614
|
+
try {
|
|
1615
|
+
const path = userConfigReadPath("doctor", [], { home, xdg: process.env.XDG_CONFIG_HOME });
|
|
1616
|
+
if (!existsSync6(path))
|
|
1617
|
+
return [];
|
|
1618
|
+
const raw = Bun.JSONC.parse(readFileSync5(path, "utf8"));
|
|
1619
|
+
return Array.isArray(raw?.forgeHosts) ? raw.forgeHosts.filter((each) => typeof each === "string") : [];
|
|
1620
|
+
} catch {
|
|
1621
|
+
return [];
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1429
1624
|
async function checkTea(host) {
|
|
1430
1625
|
if (host.which("tea") === null)
|
|
1431
1626
|
return { check: "tea", ok: false, detail: "not installed, and ft goes through it", fix: "install tea from https://gitea.com/gitea/tea/releases" };
|
|
1432
1627
|
const logins = await host.run(["tea", "login", "list", "-o", "json"]);
|
|
1433
1628
|
const parsed = logins.code === 0 ? readJsonText(logins.stdout) : undefined;
|
|
1434
|
-
const
|
|
1629
|
+
const hosts = new Set([...FORGE_HOSTS, ...extraForgeHosts(host.home)]);
|
|
1630
|
+
const login = parsed?.find((each) => URL.canParse(each.url) && hosts.has(new URL(each.url).host));
|
|
1435
1631
|
if (login === undefined)
|
|
1436
1632
|
return { check: "tea", ok: false, detail: `no login to ${FORGE}`, fix: `tea login add --url https://${FORGE} --oauth` };
|
|
1437
1633
|
const version = await host.run(["tea", "api", "--login", login.name, "version"]);
|
|
@@ -1442,9 +1638,9 @@ async function checkTea(host) {
|
|
|
1442
1638
|
return { check: "tea", ok: true, detail: `logged in to ${forge} as ${login.name}, Forgejo ${served}` };
|
|
1443
1639
|
}
|
|
1444
1640
|
function hooksWiring(host) {
|
|
1445
|
-
const settings = readJson(
|
|
1641
|
+
const settings = readJson(join8(host.home, ".claude", "settings.json")) ?? {};
|
|
1446
1642
|
const plugin = settings.enabledPlugins?.[PLUGIN] === true;
|
|
1447
|
-
const mod = (settings.env?.CLAUDE_CODE_PLUGIN_DIRS ?? "").split(":").map((dir) => dir.replace(LEADING_TILDE, host.home)).find((dir) => basename(dir) === "cli" &&
|
|
1643
|
+
const mod = (settings.env?.CLAUDE_CODE_PLUGIN_DIRS ?? "").split(":").map((dir) => dir.replace(LEADING_TILDE, host.home)).find((dir) => basename(dir) === "cli" && existsSync6(join8(dir, "hooks", "hooks.json")));
|
|
1448
1644
|
return { plugin, mod };
|
|
1449
1645
|
}
|
|
1450
1646
|
function checkHooks(host) {
|
|
@@ -1487,7 +1683,7 @@ var FORGEJO = "@kaynooo/cli-forgejo";
|
|
|
1487
1683
|
var WORKSPACE = "@kaynooo/cli-workspace";
|
|
1488
1684
|
function checkWorkspace(host, env = process.env) {
|
|
1489
1685
|
const folder = workspaceRoot({ home: host.home, env });
|
|
1490
|
-
if (
|
|
1686
|
+
if (existsSync6(folder))
|
|
1491
1687
|
return { check: "workspace", ok: true, detail: folder };
|
|
1492
1688
|
return { check: "workspace", ok: false, detail: `${folder} does not exist`, fix: `mkdir -p ${folder}, or set "workspace" in ~/.config/kaynooo-cli/config.json to your folder` };
|
|
1493
1689
|
}
|
|
@@ -1549,19 +1745,19 @@ async function applyFixes(host, steps, dry) {
|
|
|
1549
1745
|
}
|
|
1550
1746
|
|
|
1551
1747
|
// src/host.ts
|
|
1552
|
-
import { homedir as
|
|
1553
|
-
import { join as
|
|
1554
|
-
import
|
|
1748
|
+
import { homedir as homedir5 } from "os";
|
|
1749
|
+
import { join as join9 } from "path";
|
|
1750
|
+
import process16 from "process";
|
|
1555
1751
|
var RUN_TIMEOUT_MS = 20000;
|
|
1556
1752
|
function hostHere() {
|
|
1557
|
-
const home =
|
|
1753
|
+
const home = homedir5();
|
|
1558
1754
|
return {
|
|
1559
1755
|
home,
|
|
1560
|
-
globalModules:
|
|
1756
|
+
globalModules: join9(process16.env.BUN_INSTALL ?? join9(home, ".bun"), "install", "global", "node_modules"),
|
|
1561
1757
|
bunVersion: Bun.version,
|
|
1562
1758
|
which: (bin) => Bun.which(bin),
|
|
1563
1759
|
run: async (argv, env) => {
|
|
1564
|
-
const ran = await runCommand(argv, { timeoutMs: RUN_TIMEOUT_MS, ...env === undefined ? {} : { env: { ...
|
|
1760
|
+
const ran = await runCommand(argv, { timeoutMs: RUN_TIMEOUT_MS, ...env === undefined ? {} : { env: { ...process16.env, ...env } } });
|
|
1565
1761
|
if (ran.timedOut)
|
|
1566
1762
|
return { code: 1, stdout: "", stderr: `timed out after ${RUN_TIMEOUT_MS / 1000}s` };
|
|
1567
1763
|
const of = (stream) => Buffer.concat(ran.chunks.filter((chunk) => chunk.stream === stream).map((chunk) => chunk.data)).toString();
|
|
@@ -1571,19 +1767,53 @@ function hostHere() {
|
|
|
1571
1767
|
}
|
|
1572
1768
|
|
|
1573
1769
|
// src/install.ts
|
|
1574
|
-
import
|
|
1770
|
+
import process18 from "process";
|
|
1575
1771
|
|
|
1576
1772
|
// ../kit/src/prompt.ts
|
|
1577
|
-
import
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
var
|
|
1581
|
-
var
|
|
1773
|
+
import process17 from "process";
|
|
1774
|
+
|
|
1775
|
+
// ../kit/src/picker/score.ts
|
|
1776
|
+
var BOUNDARY_AFTER = new Set([" ", "/", "-", "_", ".", ":", "\\", "(", "[", ",", "\t"]);
|
|
1777
|
+
var NONE = Number.NEGATIVE_INFINITY;
|
|
1778
|
+
|
|
1779
|
+
// ../kit/src/picker/state.ts
|
|
1780
|
+
var IS_CONTROL = /[\x00-\x1F\x7F-\x9F]/;
|
|
1582
1781
|
var PASTE_START = "\x1B[200~";
|
|
1583
1782
|
var PASTE_END = "\x1B[201~";
|
|
1584
|
-
var
|
|
1585
|
-
|
|
1783
|
+
var KEY_SEQUENCES = /\x1B\[[0-9;]*[A-Z~]|\x1BO[A-Z]|\x1B[\s\S]|[\s\S]/gu;
|
|
1784
|
+
var KEYS = {
|
|
1785
|
+
"\x1B[A": "up",
|
|
1786
|
+
"\x1BOA": "up",
|
|
1787
|
+
"\x10": "up",
|
|
1788
|
+
"\x1B[B": "down",
|
|
1789
|
+
"\x1BOB": "down",
|
|
1790
|
+
"\x0E": "down",
|
|
1791
|
+
"\x1B[5~": "pageup",
|
|
1792
|
+
"\x1B[6~": "pagedown",
|
|
1793
|
+
"\x1B[H": "home",
|
|
1794
|
+
"\x1B[1~": "home",
|
|
1795
|
+
"\x1BOH": "home",
|
|
1796
|
+
"\x1B[F": "end",
|
|
1797
|
+
"\x1B[4~": "end",
|
|
1798
|
+
"\x1BOF": "end",
|
|
1799
|
+
"\r": "enter",
|
|
1800
|
+
"\n": "enter",
|
|
1801
|
+
"\x03": "cancel",
|
|
1802
|
+
"\x1B": "cancel",
|
|
1803
|
+
"\x7F": "erase",
|
|
1804
|
+
"\b": "erase",
|
|
1805
|
+
"\x15": "clear",
|
|
1806
|
+
"\x17": "word",
|
|
1807
|
+
"\t": "tab",
|
|
1808
|
+
"\x1F": "help",
|
|
1809
|
+
"\x1BOP": "help",
|
|
1810
|
+
"\x1B[11~": "help"
|
|
1811
|
+
};
|
|
1812
|
+
function parseKeys(input, paste = { active: false }, ctrls = []) {
|
|
1813
|
+
const codes = new Map(ctrls.map((name) => [String.fromCharCode(name.codePointAt(name.length - 1) - 96), name]));
|
|
1586
1814
|
return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => {
|
|
1815
|
+
const named = codes.get(sequence);
|
|
1816
|
+
const key = named === undefined ? KEYS[sequence] : { ctrl: named };
|
|
1587
1817
|
if (sequence === PASTE_START || sequence === PASTE_END) {
|
|
1588
1818
|
paste.active = sequence === PASTE_START;
|
|
1589
1819
|
return [];
|
|
@@ -1591,9 +1821,19 @@ function readKeys(input, paste = { active: false }) {
|
|
|
1591
1821
|
if (paste.active && (sequence === "\r" || sequence === `
|
|
1592
1822
|
`))
|
|
1593
1823
|
return [];
|
|
1594
|
-
|
|
1824
|
+
if (key !== undefined)
|
|
1825
|
+
return [key];
|
|
1826
|
+
return IS_CONTROL.test(sequence) || sequence.startsWith("\x1B") ? [] : [{ text: sequence }];
|
|
1595
1827
|
});
|
|
1596
1828
|
}
|
|
1829
|
+
|
|
1830
|
+
// ../kit/src/prompt.ts
|
|
1831
|
+
var WORDS = /\s+/;
|
|
1832
|
+
var MAX_ROWS = 10;
|
|
1833
|
+
var PROMPT_KEYS = new Set(["up", "down", "pageup", "pagedown", "home", "end", "enter", "cancel", "erase"]);
|
|
1834
|
+
function readKeys(input, paste = { active: false }) {
|
|
1835
|
+
return parseKeys(input, paste).filter((key) => typeof key === "object" ? "text" in key : PROMPT_KEYS.has(key));
|
|
1836
|
+
}
|
|
1597
1837
|
function flip(checked, value) {
|
|
1598
1838
|
const next = new Set(checked);
|
|
1599
1839
|
if (!next.delete(value))
|
|
@@ -1733,7 +1973,7 @@ function asking(colors, question, typed, keys) {
|
|
|
1733
1973
|
function answer(colors, question, state, picked) {
|
|
1734
1974
|
return state === "enter" ? `${colors.green("\u2713")} ${question} ${colors.cyan(picked)}` : `${colors.red("\u2717")} ${question} ${colors.dim("cancelled")}`;
|
|
1735
1975
|
}
|
|
1736
|
-
async function ask(question, { hint, terminal =
|
|
1976
|
+
async function ask(question, { hint, terminal = process17 }, render, press) {
|
|
1737
1977
|
const { stdin, stderr } = terminal;
|
|
1738
1978
|
if (!isInteractive(terminal))
|
|
1739
1979
|
fail(`cannot ask "${question}" off a terminal`, 2, hint);
|
|
@@ -1868,7 +2108,7 @@ async function askWorkspace(host) {
|
|
|
1868
2108
|
async function install(host, options, recheck, choosing = ask2) {
|
|
1869
2109
|
const all = candidates2(host);
|
|
1870
2110
|
const pool = all.filter((each) => !each.installed);
|
|
1871
|
-
const { dim, green, red, yellow } = paint(
|
|
2111
|
+
const { dim, green, red, yellow } = paint(process18.stdout);
|
|
1872
2112
|
if (options.list) {
|
|
1873
2113
|
for (const each of pool)
|
|
1874
2114
|
console.log(`${each.label.padEnd(12)} ${dim(each.hint)}`);
|
|
@@ -1976,7 +2216,7 @@ var OPTIONS = {
|
|
|
1976
2216
|
function print(results) {
|
|
1977
2217
|
if (results.length === 0)
|
|
1978
2218
|
return;
|
|
1979
|
-
const { green, red, dim } = paint(
|
|
2219
|
+
const { green, red, dim } = paint(process19.stdout);
|
|
1980
2220
|
const width = Math.max(...results.map((result) => result.check.length));
|
|
1981
2221
|
for (const { check, ok, detail, fix } of results)
|
|
1982
2222
|
console.log(`${ok ? green("ok ") : red("FAIL")} ${check.padEnd(width)} ${detail}${fix === undefined ? "" : ` ${dim("fix:")} ${fix}`}`);
|
|
@@ -1986,7 +2226,7 @@ function print(results) {
|
|
|
1986
2226
|
${dim("fix them all:")} ${INSTALL2}${installs.join(" ")}`);
|
|
1987
2227
|
}
|
|
1988
2228
|
function printOutcomes(outcomes, log) {
|
|
1989
|
-
const { green, red, dim } = paint(
|
|
2229
|
+
const { green, red, dim } = paint(process19.stdout);
|
|
1990
2230
|
const marks = { ran: green("ran "), failed: red("failed "), "dry-run": dim("would "), "not run": dim("not run") };
|
|
1991
2231
|
for (const { command, status, detail } of outcomes)
|
|
1992
2232
|
log(`${marks[status]} ${command}${detail === undefined ? "" : ` ${dim(detail)}`}`);
|
|
@@ -2026,9 +2266,9 @@ after the fixes:`);
|
|
|
2026
2266
|
const absent = Object.keys(TOOLS).filter((name) => !isInstalled(host, name)).length;
|
|
2027
2267
|
if (!json && only.length === 0 && absent > 0)
|
|
2028
2268
|
console.log(`
|
|
2029
|
-
${paint(
|
|
2269
|
+
${paint(process19.stdout).dim(`${absent} packages not installed: doctor --install`)}`);
|
|
2030
2270
|
return results.every((result) => result.ok) ? 0 : 1;
|
|
2031
2271
|
}
|
|
2032
2272
|
|
|
2033
2273
|
// src/cli.ts
|
|
2034
|
-
|
|
2274
|
+
process20.exitCode = await runMain({ name: "doctor", run: async (args) => main(args) });
|