@kaynooo/cli-out 0.7.0 → 0.7.1
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/cli.js +211 -153
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
|
-
import
|
|
5
|
+
import process13 from "process";
|
|
6
6
|
|
|
7
7
|
// ../kit/src/args.ts
|
|
8
|
-
import
|
|
9
|
-
import process3 from "process";
|
|
8
|
+
import process4 from "process";
|
|
10
9
|
import { parseArgs } from "util";
|
|
11
10
|
|
|
12
11
|
// ../kit/src/format.ts
|
|
@@ -344,6 +343,55 @@ function printJson(value) {
|
|
|
344
343
|
console.log(JSON.stringify(value, undefined, 2));
|
|
345
344
|
}
|
|
346
345
|
|
|
346
|
+
// ../kit/src/help.ts
|
|
347
|
+
import process3 from "process";
|
|
348
|
+
var OPTIONAL = /\[[^\]]+\]/g;
|
|
349
|
+
var USAGE_PREFIX = /^usage:\s*/i;
|
|
350
|
+
var FULL_STOP = /\.$/;
|
|
351
|
+
function usageLine(usage, colors = paint(process3.stdout)) {
|
|
352
|
+
return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
|
|
353
|
+
}
|
|
354
|
+
function helpText(usage, options, colors = paint(process3.stdout), { examples = [], replaces } = {}) {
|
|
355
|
+
return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exampleRows(examples, colors)].join(`
|
|
356
|
+
`);
|
|
357
|
+
}
|
|
358
|
+
function replacesRows(replaces, colors = paint(process3.stdout)) {
|
|
359
|
+
return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
|
|
360
|
+
}
|
|
361
|
+
function wantsHelpJson(env = process3.env) {
|
|
362
|
+
return env.KIT_HELP === "json";
|
|
363
|
+
}
|
|
364
|
+
function description(usage, { examples = [], replaces } = {}) {
|
|
365
|
+
const lines = usage.replace(USAGE_PREFIX, "").split(`
|
|
366
|
+
`);
|
|
367
|
+
const first = lines[0];
|
|
368
|
+
const colon = first.indexOf(": ");
|
|
369
|
+
const prose = lines[lines.indexOf("") + 1] ?? "";
|
|
370
|
+
const fallback = lines.includes("") ? `${prose.charAt(0).toLowerCase()}${prose.slice(1)}`.replace(FULL_STOP, "") : "";
|
|
371
|
+
return {
|
|
372
|
+
synopsis: colon === -1 ? first : first.slice(0, colon),
|
|
373
|
+
summary: colon === -1 ? fallback : first.slice(colon + 2),
|
|
374
|
+
...replaces === undefined ? {} : { replaces },
|
|
375
|
+
examples: examples.map((example) => typeof example === "string" ? { line: example } : { line: example[0], note: example[1] })
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function exampleRows(examples, colors = paint(process3.stdout)) {
|
|
379
|
+
if (examples.length === 0)
|
|
380
|
+
return [];
|
|
381
|
+
return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
|
|
382
|
+
}
|
|
383
|
+
function optionRows(options, colors = paint(process3.stdout)) {
|
|
384
|
+
const rows = Object.entries(options).map(([name, option]) => {
|
|
385
|
+
const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
|
|
386
|
+
const named = option.choices === undefined ? "<value>" : `<${option.choices.join("|")}>`;
|
|
387
|
+
const placeholder = option.optional === undefined ? named : `[${named}]`;
|
|
388
|
+
const value = option.type === "string" ? ` ${colors.dim(placeholder)}` : "";
|
|
389
|
+
return { flag: `${short}${colors.cyan(`--${name}`)}${value}`, width: `-x, --${name}`.length + (option.type === "string" ? placeholder.length + 1 : 0), description: option.description ?? "" };
|
|
390
|
+
});
|
|
391
|
+
const width = Math.max(0, ...rows.map((row) => row.width));
|
|
392
|
+
return rows.map((row) => row.description === "" ? ` ${row.flag}` : ` ${row.flag}${" ".repeat(width - row.width)} ${colors.dim(row.description)}`);
|
|
393
|
+
}
|
|
394
|
+
|
|
347
395
|
// ../kit/src/text.ts
|
|
348
396
|
var ANSI = new RegExp(`${String.fromCharCode(27)}\\[[\\d;?]*[a-z]`, "gi");
|
|
349
397
|
function stripAnsi(text) {
|
|
@@ -366,8 +414,35 @@ function closest(name, names) {
|
|
|
366
414
|
const [best] = names.map((known) => ({ known, far: distance(name, known) })).sort((a, b) => a.far - b.far);
|
|
367
415
|
return best !== undefined && best.far <= (name.length < 4 ? 1 : 2) ? best.known : undefined;
|
|
368
416
|
}
|
|
417
|
+
// ../kit/src/input.ts
|
|
418
|
+
import { fstatSync } from "fs";
|
|
419
|
+
var WHOLE = /^\d+$/;
|
|
420
|
+
function wholeNumber(value, name, fallback, min = 1) {
|
|
421
|
+
if (value === undefined)
|
|
422
|
+
return fallback;
|
|
423
|
+
const number = Number(value);
|
|
424
|
+
if (!WHOLE.test(value) || !Number.isSafeInteger(number) || number < min)
|
|
425
|
+
badUsage(`${name.startsWith("<") ? name : `--${name}`} takes a whole number from ${min}, not ${value}`);
|
|
426
|
+
return number;
|
|
427
|
+
}
|
|
428
|
+
var DURATION = /^(\d+(?:\.\d+)?)(ms|[smhd])?$/;
|
|
429
|
+
var UNIT_MS = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };
|
|
430
|
+
function duration(value, name, fallback, unit = "s") {
|
|
431
|
+
if (value === undefined)
|
|
432
|
+
return fallback;
|
|
433
|
+
const match = DURATION.exec(value.trim());
|
|
434
|
+
const ms = match === null ? 0 : Number(match[1]) * UNIT_MS[match[2] ?? unit];
|
|
435
|
+
if (ms < 1)
|
|
436
|
+
badUsage(`--${name} takes a duration such as 30s, 5m, 1h or 7d, not ${value}`);
|
|
437
|
+
return ms;
|
|
438
|
+
}
|
|
439
|
+
function isStdinPiped() {
|
|
440
|
+
const stat = fstatSync(0);
|
|
441
|
+
return stat.isFIFO() || stat.isFile();
|
|
442
|
+
}
|
|
369
443
|
|
|
370
444
|
// ../kit/src/args.ts
|
|
445
|
+
var DASHES = /^-+/;
|
|
371
446
|
function jsonOption(holds) {
|
|
372
447
|
return { type: "boolean", description: holds === undefined ? "print JSON" : `print JSON: ${holds}` };
|
|
373
448
|
}
|
|
@@ -411,58 +486,11 @@ class Completing {
|
|
|
411
486
|
}
|
|
412
487
|
}
|
|
413
488
|
var completion = { active: false };
|
|
414
|
-
var OPTIONAL = /\[[^\]]+\]/g;
|
|
415
|
-
var USAGE_PREFIX = /^usage:\s*/i;
|
|
416
|
-
var FULL_STOP = /\.$/;
|
|
417
|
-
var DASHES = /^-+/;
|
|
418
|
-
function usageLine(usage, colors = paint(process3.stdout)) {
|
|
419
|
-
return `${colors.bold("Usage:")} ${usage.replace(USAGE_PREFIX, "").replaceAll(OPTIONAL, (part) => colors.dim(part))}`;
|
|
420
|
-
}
|
|
421
|
-
function helpText(usage, options, colors = paint(process3.stdout), { examples = [], replaces } = {}) {
|
|
422
|
-
return [usageLine(usage, colors), ...replacesRows(replaces, colors), "", colors.bold("Options:"), ...optionRows(options, colors), ...exampleRows(examples, colors)].join(`
|
|
423
|
-
`);
|
|
424
|
-
}
|
|
425
|
-
function replacesRows(replaces, colors = paint(process3.stdout)) {
|
|
426
|
-
return replaces === undefined ? [] : ["", `${colors.bold("Instead of:")} ${replaces}`];
|
|
427
|
-
}
|
|
428
|
-
function wantsHelpJson(env = process3.env) {
|
|
429
|
-
return env.KIT_HELP === "json";
|
|
430
|
-
}
|
|
431
|
-
function description(usage, { examples = [], replaces } = {}) {
|
|
432
|
-
const lines = usage.replace(USAGE_PREFIX, "").split(`
|
|
433
|
-
`);
|
|
434
|
-
const first = lines[0];
|
|
435
|
-
const colon = first.indexOf(": ");
|
|
436
|
-
const prose = lines[lines.indexOf("") + 1] ?? "";
|
|
437
|
-
const fallback = lines.includes("") ? `${prose.charAt(0).toLowerCase()}${prose.slice(1)}`.replace(FULL_STOP, "") : "";
|
|
438
|
-
return {
|
|
439
|
-
synopsis: colon === -1 ? first : first.slice(0, colon),
|
|
440
|
-
summary: colon === -1 ? fallback : first.slice(colon + 2),
|
|
441
|
-
...replaces === undefined ? {} : { replaces },
|
|
442
|
-
examples: examples.map((example) => typeof example === "string" ? { line: example } : { line: example[0], note: example[1] })
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
function exampleRows(examples, colors = paint(process3.stdout)) {
|
|
446
|
-
if (examples.length === 0)
|
|
447
|
-
return [];
|
|
448
|
-
return ["", colors.bold("Examples:"), ...examples.map((example) => typeof example === "string" ? ` ${example}` : ` ${example[0]} ${colors.dim(`# ${example[1]}`)}`)];
|
|
449
|
-
}
|
|
450
|
-
function optionRows(options, colors = paint(process3.stdout)) {
|
|
451
|
-
const rows = Object.entries(options).map(([name, option]) => {
|
|
452
|
-
const short = option.short === undefined ? " " : `${colors.cyan(`-${option.short}`)}, `;
|
|
453
|
-
const named = option.choices === undefined ? "<value>" : `<${option.choices.join("|")}>`;
|
|
454
|
-
const placeholder = option.optional === undefined ? named : `[${named}]`;
|
|
455
|
-
const value = option.type === "string" ? ` ${colors.dim(placeholder)}` : "";
|
|
456
|
-
return { flag: `${short}${colors.cyan(`--${name}`)}${value}`, width: `-x, --${name}`.length + (option.type === "string" ? placeholder.length + 1 : 0), description: option.description ?? "" };
|
|
457
|
-
});
|
|
458
|
-
const width = Math.max(0, ...rows.map((row) => row.width));
|
|
459
|
-
return rows.map((row) => row.description === "" ? ` ${row.flag}` : ` ${row.flag}${" ".repeat(width - row.width)} ${colors.dim(row.description)}`);
|
|
460
|
-
}
|
|
461
489
|
var OUTPUT_OPTIONS = {
|
|
462
490
|
color: { type: "string", description: "auto (on a terminal alone), always or never" },
|
|
463
491
|
plain: { type: "boolean", description: "plain text, no colour or spinner: --color never" }
|
|
464
492
|
};
|
|
465
|
-
function applyOutput(color, plain, env =
|
|
493
|
+
function applyOutput(color, plain, env = process4.env) {
|
|
466
494
|
const when = plain === true ? "never" : color ?? "auto";
|
|
467
495
|
if (when === "auto")
|
|
468
496
|
return;
|
|
@@ -619,33 +647,9 @@ function nearestOption(message, options, allowNegative) {
|
|
|
619
647
|
const meant = closest(word, known.map((flag) => flag.replace(DASHES, "")));
|
|
620
648
|
return meant === undefined ? undefined : `did you mean ${known.find((flag) => flag.replace(DASHES, "") === meant)}?`;
|
|
621
649
|
}
|
|
622
|
-
var WHOLE = /^\d+$/;
|
|
623
|
-
function wholeNumber(value, name, fallback, min = 1) {
|
|
624
|
-
if (value === undefined)
|
|
625
|
-
return fallback;
|
|
626
|
-
const number = Number(value);
|
|
627
|
-
if (!WHOLE.test(value) || !Number.isSafeInteger(number) || number < min)
|
|
628
|
-
badUsage(`${name.startsWith("<") ? name : `--${name}`} takes a whole number from ${min}, not ${value}`);
|
|
629
|
-
return number;
|
|
630
|
-
}
|
|
631
|
-
var DURATION = /^(\d+(?:\.\d+)?)(ms|[smhd])?$/;
|
|
632
|
-
var UNIT_MS = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };
|
|
633
|
-
function duration(value, name, fallback, unit = "s") {
|
|
634
|
-
if (value === undefined)
|
|
635
|
-
return fallback;
|
|
636
|
-
const match = DURATION.exec(value.trim());
|
|
637
|
-
const ms = match === null ? 0 : Number(match[1]) * UNIT_MS[match[2] ?? unit];
|
|
638
|
-
if (ms < 1)
|
|
639
|
-
badUsage(`--${name} takes a duration such as 30s, 5m, 1h or 7d, not ${value}`);
|
|
640
|
-
return ms;
|
|
641
|
-
}
|
|
642
|
-
function isStdinPiped() {
|
|
643
|
-
const stat = fstatSync(0);
|
|
644
|
-
return stat.isFIFO() || stat.isFile();
|
|
645
|
-
}
|
|
646
650
|
// ../kit/src/process.ts
|
|
647
651
|
import { constants } from "os";
|
|
648
|
-
import
|
|
652
|
+
import process5 from "process";
|
|
649
653
|
var KILL_GRACE_MS = 2000;
|
|
650
654
|
var SIGNALS = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
651
655
|
function exitCodeOf(code, signal) {
|
|
@@ -667,7 +671,7 @@ function holdSignals(cleanup) {
|
|
|
667
671
|
},
|
|
668
672
|
release: () => {
|
|
669
673
|
for (const signal of SIGNALS)
|
|
670
|
-
|
|
674
|
+
process5.off(signal, onSignal);
|
|
671
675
|
}
|
|
672
676
|
};
|
|
673
677
|
function onSignal(signal) {
|
|
@@ -680,10 +684,10 @@ function holdSignals(cleanup) {
|
|
|
680
684
|
return;
|
|
681
685
|
held.release();
|
|
682
686
|
cleanup(signal);
|
|
683
|
-
|
|
687
|
+
process5.kill(process5.pid, signal);
|
|
684
688
|
}
|
|
685
689
|
for (const signal of SIGNALS)
|
|
686
|
-
|
|
690
|
+
process5.on(signal, onSignal);
|
|
687
691
|
return held;
|
|
688
692
|
}
|
|
689
693
|
async function runCommand(argv, { cwd, env, stdin = "ignore", timeoutMs, signal, maxBytes = Infinity, onChunk, onStart } = {}) {
|
|
@@ -697,7 +701,7 @@ async function runCommand(argv, { cwd, env, stdin = "ignore", timeoutMs, signal,
|
|
|
697
701
|
return;
|
|
698
702
|
try {
|
|
699
703
|
if (grouped)
|
|
700
|
-
|
|
704
|
+
process5.kill(-proc.pid, killing);
|
|
701
705
|
else
|
|
702
706
|
proc.kill(killing);
|
|
703
707
|
} catch {}
|
|
@@ -771,15 +775,114 @@ var ESCAPE_CODE = new RegExp(`${ESC}(?:\\[[\\x30-\\x3F]*[\\x20-\\x2F]*[\\x40-\\x
|
|
|
771
775
|
var RESET_STYLE = `${ESC}[0m`;
|
|
772
776
|
var CLOSE_LINK = `${ESC}]8;;${ESC}\\`;
|
|
773
777
|
// ../kit/src/cli.ts
|
|
774
|
-
import
|
|
778
|
+
import process8 from "process";
|
|
779
|
+
|
|
780
|
+
// ../kit/src/usage.ts
|
|
781
|
+
import { appendFileSync, mkdirSync } from "fs";
|
|
782
|
+
import { homedir as homedir2 } from "os";
|
|
783
|
+
import { dirname, isAbsolute, join as join2 } from "path";
|
|
784
|
+
import process7 from "process";
|
|
785
|
+
|
|
786
|
+
// ../kit/src/logs.ts
|
|
787
|
+
import { lstatSync, openSync } from "fs";
|
|
788
|
+
import { mkdir, mkdtemp, readdir, rm, stat } from "fs/promises";
|
|
789
|
+
import { homedir, tmpdir } from "os";
|
|
790
|
+
import { join } from "path";
|
|
791
|
+
import process6 from "process";
|
|
792
|
+
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
793
|
+
var CLI_FOLDER = "kaynooo-cli";
|
|
794
|
+
function isPrivateDirectory(path) {
|
|
795
|
+
try {
|
|
796
|
+
const info = lstatSync(path, { throwIfNoEntry: false });
|
|
797
|
+
return info !== undefined && info.isDirectory() && info.uid === (process6.getuid?.() ?? info.uid) && (info.mode & 63) === 0;
|
|
798
|
+
} catch {
|
|
799
|
+
return false;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
async function privateLogDirectory(name, env = process6.env) {
|
|
803
|
+
const runtime = env.XDG_RUNTIME_DIR;
|
|
804
|
+
const base = runtime === undefined || runtime === "" ? join(homedir(), ".cache", CLI_FOLDER) : join(runtime, CLI_FOLDER);
|
|
805
|
+
const path = join(base, name);
|
|
806
|
+
try {
|
|
807
|
+
await mkdir(path, { recursive: true, mode: 448 });
|
|
808
|
+
if (isPrivateDirectory(path))
|
|
809
|
+
return path;
|
|
810
|
+
} catch {}
|
|
811
|
+
return mkdtemp(join(tmpdir(), `${name.replaceAll("/", "-")}-`));
|
|
812
|
+
}
|
|
813
|
+
async function sweepLogs(dir, maxAgeMs = DAY_MS, now = Date.now()) {
|
|
814
|
+
let names;
|
|
815
|
+
try {
|
|
816
|
+
names = await readdir(dir);
|
|
817
|
+
} catch {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
for (const name of names) {
|
|
821
|
+
const path = join(dir, name);
|
|
822
|
+
try {
|
|
823
|
+
const info = await stat(path);
|
|
824
|
+
if (info.isDirectory())
|
|
825
|
+
await sweepLogs(path, maxAgeMs, now);
|
|
826
|
+
if (now - info.mtimeMs > maxAgeMs)
|
|
827
|
+
await rm(path, { force: true, recursive: info.isDirectory() });
|
|
828
|
+
} catch {
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
function createLog(path) {
|
|
834
|
+
return openSync(path, "wx", 384);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// ../kit/src/usage.ts
|
|
838
|
+
var UNKNOWN_OPTION2 = /unknown option '(--[a-z][a-z0-9-]*)[=']/;
|
|
839
|
+
var FLAG_NAME = /^(?:--[a-z][a-z0-9-]*|-[a-zA-Z])$/;
|
|
840
|
+
var LONGEST_NAME = 40;
|
|
841
|
+
var usageError;
|
|
842
|
+
function noteUsageError(message) {
|
|
843
|
+
usageError = message;
|
|
844
|
+
}
|
|
845
|
+
function stateHome(env = process7.env) {
|
|
846
|
+
const dir = env.XDG_STATE_HOME;
|
|
847
|
+
return dir !== undefined && isAbsolute(dir) ? dir : join2(homedir2(), ".local", "state");
|
|
848
|
+
}
|
|
849
|
+
function usagePath(env = process7.env) {
|
|
850
|
+
return join2(stateHome(env), CLI_FOLDER, "usage.jsonl");
|
|
851
|
+
}
|
|
852
|
+
function usageRecorded(env = process7.env) {
|
|
853
|
+
const off = env.KAYNOOO_CLI_NO_USAGE;
|
|
854
|
+
return env.NODE_ENV !== "test" && (off === undefined || off === "" || off === "0");
|
|
855
|
+
}
|
|
856
|
+
function flagNames(argv) {
|
|
857
|
+
const end = argv.indexOf("--");
|
|
858
|
+
const names = (end === -1 ? argv : argv.slice(0, end)).filter((word) => word.startsWith("-") && word !== "-").map((word) => word.includes("=") ? word.slice(0, word.indexOf("=")) : word);
|
|
859
|
+
return [...new Set(names)].filter((name) => name.length <= LONGEST_NAME && FLAG_NAME.test(name));
|
|
860
|
+
}
|
|
861
|
+
function usageEntry(bin, command, argv, code, now = new Date) {
|
|
862
|
+
const unknown = code === 2 && usageError !== undefined ? UNKNOWN_OPTION2.exec(usageError)?.[1] : undefined;
|
|
863
|
+
usageError = undefined;
|
|
864
|
+
return { at: now.toISOString(), bin, ...command === undefined ? {} : { command }, flags: flagNames(argv), code, ...unknown === undefined ? {} : { unknown } };
|
|
865
|
+
}
|
|
866
|
+
function recordUsage(entry, env = process7.env) {
|
|
867
|
+
if (!usageRecorded(env))
|
|
868
|
+
return;
|
|
869
|
+
try {
|
|
870
|
+
const path = usagePath(env);
|
|
871
|
+
mkdirSync(dirname(path), { recursive: true, mode: 448 });
|
|
872
|
+
appendFileSync(path, `${JSON.stringify(entry)}
|
|
873
|
+
`, { mode: 384 });
|
|
874
|
+
} catch {}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// ../kit/src/cli.ts
|
|
775
878
|
var LEVEL_OPTIONS = {
|
|
776
879
|
...OUTPUT_OPTIONS,
|
|
777
880
|
help: { type: "boolean", short: "h", description: "show this help" }
|
|
778
881
|
};
|
|
779
882
|
var TOP_OPTIONS = { ...LEVEL_OPTIONS, version: { type: "boolean", short: "v", description: "print the version" } };
|
|
780
883
|
function printError(prefix, message, hint, cause) {
|
|
781
|
-
const colors = paint(
|
|
782
|
-
const styled = takesControlCodes(
|
|
884
|
+
const colors = paint(process8.stderr);
|
|
885
|
+
const styled = takesControlCodes(process8.stderr);
|
|
783
886
|
const head = styled ? `${colors.red.bold("error")} ${colors.dim(`${prefix}:`)}` : `error: ${prefix}:`;
|
|
784
887
|
const under = (label, text, tint) => text === undefined ? "" : `
|
|
785
888
|
${styled ? tint(label) : `${label}:`} ${text}`;
|
|
@@ -798,6 +901,8 @@ function reportThrown(prefix, error, redact = (text) => text, json = false) {
|
|
|
798
901
|
const help = error instanceof UsageError ? `run ${prefix} --help for its options` : undefined;
|
|
799
902
|
const named = error instanceof Error && !(error instanceof Exit) && error.name !== "Error" ? `${error.name}: ${error.message}` : undefined;
|
|
800
903
|
const cause = error instanceof Error && error.cause instanceof Error ? redact(error.cause.message) : undefined;
|
|
904
|
+
if (error instanceof UsageError)
|
|
905
|
+
noteUsageError(error.message);
|
|
801
906
|
const report = json ? printJsonError : (message, hint, causeText) => printError(prefix, message, hint, causeText);
|
|
802
907
|
report(redact(named ?? (error instanceof Error ? error.message : String(error))), error instanceof Exit ? error.hint ?? help : undefined, cause);
|
|
803
908
|
return error instanceof Exit ? error.code : 1;
|
|
@@ -859,68 +964,22 @@ async function printCandidates(found) {
|
|
|
859
964
|
console.log(line);
|
|
860
965
|
return 0;
|
|
861
966
|
}
|
|
862
|
-
async function runMain({ name, version, run, redact }, argv =
|
|
967
|
+
async function runMain({ name, version, run, redact, usage }, argv = process8.argv.slice(2)) {
|
|
863
968
|
if (argv[0] === COMPLETE)
|
|
864
969
|
return printCandidates(leafCandidates(run, argv.slice(1)));
|
|
865
970
|
if (argv.length === 1 && (argv[0] === "--version" || argv[0] === "-v")) {
|
|
866
971
|
console.log(version);
|
|
867
972
|
return 0;
|
|
868
973
|
}
|
|
974
|
+
let code;
|
|
869
975
|
try {
|
|
870
|
-
|
|
976
|
+
code = await run(argv);
|
|
871
977
|
} catch (error) {
|
|
872
|
-
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
// ../kit/src/logs.ts
|
|
876
|
-
import { lstatSync, openSync } from "fs";
|
|
877
|
-
import { mkdir, mkdtemp, readdir, rm, stat } from "fs/promises";
|
|
878
|
-
import { homedir, tmpdir } from "os";
|
|
879
|
-
import { join } from "path";
|
|
880
|
-
import process6 from "process";
|
|
881
|
-
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
882
|
-
var CLI_FOLDER = "kaynooo-cli";
|
|
883
|
-
function isPrivateDirectory(path) {
|
|
884
|
-
try {
|
|
885
|
-
const info = lstatSync(path, { throwIfNoEntry: false });
|
|
886
|
-
return info !== undefined && info.isDirectory() && info.uid === (process6.getuid?.() ?? info.uid) && (info.mode & 63) === 0;
|
|
887
|
-
} catch {
|
|
888
|
-
return false;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
async function privateLogDirectory(name, env = process6.env) {
|
|
892
|
-
const runtime = env.XDG_RUNTIME_DIR;
|
|
893
|
-
const base = runtime === undefined || runtime === "" ? join(homedir(), ".cache", CLI_FOLDER) : join(runtime, CLI_FOLDER);
|
|
894
|
-
const path = join(base, name);
|
|
895
|
-
try {
|
|
896
|
-
await mkdir(path, { recursive: true, mode: 448 });
|
|
897
|
-
if (isPrivateDirectory(path))
|
|
898
|
-
return path;
|
|
899
|
-
} catch {}
|
|
900
|
-
return mkdtemp(join(tmpdir(), `${name.replaceAll("/", "-")}-`));
|
|
901
|
-
}
|
|
902
|
-
async function sweepLogs(dir, maxAgeMs = DAY_MS, now = Date.now()) {
|
|
903
|
-
let names;
|
|
904
|
-
try {
|
|
905
|
-
names = await readdir(dir);
|
|
906
|
-
} catch {
|
|
907
|
-
return;
|
|
978
|
+
code = reportThrown(name, error, redact, wantsJson(argv));
|
|
908
979
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
const info = await stat(path);
|
|
913
|
-
if (info.isDirectory())
|
|
914
|
-
await sweepLogs(path, maxAgeMs, now);
|
|
915
|
-
if (now - info.mtimeMs > maxAgeMs)
|
|
916
|
-
await rm(path, { force: true, recursive: info.isDirectory() });
|
|
917
|
-
} catch {
|
|
918
|
-
continue;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
function createLog(path) {
|
|
923
|
-
return openSync(path, "wx", 384);
|
|
980
|
+
if (usage !== false)
|
|
981
|
+
recordUsage(usageEntry(name, undefined, argv, code));
|
|
982
|
+
return code;
|
|
924
983
|
}
|
|
925
984
|
// ../kit/src/secrets.ts
|
|
926
985
|
var SECRET_WORDS = new Set(["key", "pass", "pwd", "auth", "salt", "cookie", "session", "jwt", "ssn", "iban", "card", "cvv", "otp"]);
|
|
@@ -929,7 +988,7 @@ var {Glob } = globalThis.Bun;
|
|
|
929
988
|
var SESSION_FILES = new Glob("*.json");
|
|
930
989
|
var ACCOUNT_DIRS = new Glob("*/sessions");
|
|
931
990
|
// package.json
|
|
932
|
-
var version = "0.7.
|
|
991
|
+
var version = "0.7.1";
|
|
933
992
|
|
|
934
993
|
// src/shape.ts
|
|
935
994
|
var HEX_LITERAL = /\b0x[0-9a-f]+\b/gi;
|
|
@@ -1111,11 +1170,11 @@ function fold(text, { threshold, logPath }) {
|
|
|
1111
1170
|
|
|
1112
1171
|
// src/run.ts
|
|
1113
1172
|
import { closeSync, rmSync, writeSync } from "fs";
|
|
1114
|
-
import
|
|
1173
|
+
import process12 from "process";
|
|
1115
1174
|
|
|
1116
1175
|
// src/logs.ts
|
|
1117
|
-
import { join as
|
|
1118
|
-
import
|
|
1176
|
+
import { join as join3 } from "path";
|
|
1177
|
+
import process10 from "process";
|
|
1119
1178
|
var MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
1120
1179
|
async function logDir() {
|
|
1121
1180
|
return privateLogDirectory("out");
|
|
@@ -1124,7 +1183,7 @@ async function cleanLogs(dir, now = Date.now()) {
|
|
|
1124
1183
|
await sweepLogs(dir, MAX_AGE_MS, now);
|
|
1125
1184
|
}
|
|
1126
1185
|
function newLog(dir) {
|
|
1127
|
-
const path =
|
|
1186
|
+
const path = join3(dir, `${new Date().toISOString().replaceAll(/[:.]/g, "-")}-${process10.pid}.log`);
|
|
1128
1187
|
return { path, fd: createLog(path) };
|
|
1129
1188
|
}
|
|
1130
1189
|
|
|
@@ -1379,10 +1438,9 @@ function filtered(text, stages) {
|
|
|
1379
1438
|
}
|
|
1380
1439
|
|
|
1381
1440
|
// src/stats.ts
|
|
1382
|
-
import { appendFileSync, mkdirSync } from "fs";
|
|
1383
|
-
import {
|
|
1384
|
-
import
|
|
1385
|
-
import process9 from "process";
|
|
1441
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
1442
|
+
import { basename, dirname as dirname2, join as join4 } from "path";
|
|
1443
|
+
import process11 from "process";
|
|
1386
1444
|
var BYTES_PER_TOKEN = 4;
|
|
1387
1445
|
var KEY_WORD = /^[a-z][a-z:_-]*$/;
|
|
1388
1446
|
var KEY_WORDS = 3;
|
|
@@ -1391,8 +1449,8 @@ var ASSIGNMENT = /^\w+=/;
|
|
|
1391
1449
|
var CHAIN = /&&|\|\||;/;
|
|
1392
1450
|
var SHELLS2 = new Set(["sh", "bash", "zsh"]);
|
|
1393
1451
|
var TOP = 10;
|
|
1394
|
-
function statsPath(env =
|
|
1395
|
-
return
|
|
1452
|
+
function statsPath(env = process11.env) {
|
|
1453
|
+
return join4(stateHome(env), CLI_FOLDER, "out", "stats.jsonl");
|
|
1396
1454
|
}
|
|
1397
1455
|
function commandKey(command) {
|
|
1398
1456
|
const [program = "", ...rest] = command.slice(Math.max(0, command.findIndex((word) => !ASSIGNMENT.test(word))));
|
|
@@ -1410,8 +1468,8 @@ function commandKey(command) {
|
|
|
1410
1468
|
}
|
|
1411
1469
|
function record(entry, path = statsPath()) {
|
|
1412
1470
|
try {
|
|
1413
|
-
|
|
1414
|
-
|
|
1471
|
+
mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
|
|
1472
|
+
appendFileSync2(path, `${JSON.stringify(entry)}
|
|
1415
1473
|
`, { mode: 384 });
|
|
1416
1474
|
} catch {}
|
|
1417
1475
|
}
|
|
@@ -1537,11 +1595,11 @@ ${decode(this.tail)}`;
|
|
|
1537
1595
|
}
|
|
1538
1596
|
function replay(chunks) {
|
|
1539
1597
|
for (const { stream, data } of chunks)
|
|
1540
|
-
|
|
1598
|
+
process12[stream].write(data);
|
|
1541
1599
|
}
|
|
1542
1600
|
function count(recorder, shown, recorded) {
|
|
1543
1601
|
const baseline = recorded.was.length === 0 || recorder.overflowing ? undefined : filtered(recorder.text, recorded.was);
|
|
1544
|
-
record({ at: new Date().toISOString(), dir:
|
|
1602
|
+
record({ at: new Date().toISOString(), dir: process12.cwd(), command: recorded.command, bytes: recorder.bytes, baseline: baseline === undefined ? recorder.bytes : Buffer.byteLength(baseline), shown, folded: shown !== recorder.bytes });
|
|
1545
1603
|
}
|
|
1546
1604
|
async function run(command, threshold, was = []) {
|
|
1547
1605
|
const dir = await logDir();
|
|
@@ -1605,7 +1663,7 @@ function present(recorder, threshold) {
|
|
|
1605
1663
|
replay(recorder.chunks);
|
|
1606
1664
|
return recorder.bytes;
|
|
1607
1665
|
}
|
|
1608
|
-
|
|
1666
|
+
process12.stdout.write(printed);
|
|
1609
1667
|
return Buffer.byteLength(printed);
|
|
1610
1668
|
}
|
|
1611
1669
|
|
|
@@ -1654,4 +1712,4 @@ async function main(argv) {
|
|
|
1654
1712
|
${USAGE}`);
|
|
1655
1713
|
return run(command, lines, was);
|
|
1656
1714
|
}
|
|
1657
|
-
|
|
1715
|
+
process13.exitCode = await runMain({ name: "out", version, run: main });
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaynooo/cli-out",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.1",
|
|
5
5
|
"description": "out: shortens noisy command output for Claude Code, folding long logs and keeping errors, with the full log saved to a file.",
|
|
6
6
|
"author": "Kaynooo <contact@kaynooo.fr>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -28,6 +28,6 @@
|
|
|
28
28
|
"out": "$npm_execpath src/cli.ts"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@kaynooo/cli-kit": "0.
|
|
31
|
+
"@kaynooo/cli-kit": "0.20.0"
|
|
32
32
|
}
|
|
33
33
|
}
|