@kaynooo/cli-doctor 0.10.0 → 0.11.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/cli-bin.js +42 -14
- package/dist/cli.js +42 -14
- package/package.json +2 -2
package/dist/cli-bin.js
CHANGED
|
@@ -481,7 +481,6 @@ var DASHES = /^-+/;
|
|
|
481
481
|
function jsonOption(holds) {
|
|
482
482
|
return { type: "boolean", description: holds === undefined ? "print JSON" : `print JSON: ${holds}` };
|
|
483
483
|
}
|
|
484
|
-
|
|
485
484
|
class Exit extends Error {
|
|
486
485
|
code;
|
|
487
486
|
hint;
|
|
@@ -1582,9 +1581,20 @@ var KEY_SEQUENCES = /\x1B\[[0-9;]*[A-Z~]|\x1BO[A-Z]|[\s\S]/giu;
|
|
|
1582
1581
|
var CONTROL = /^[\x00-\x1F\x7F]/;
|
|
1583
1582
|
var WORDS = /\s+/;
|
|
1584
1583
|
var MAX_ROWS = 10;
|
|
1585
|
-
var
|
|
1586
|
-
|
|
1587
|
-
|
|
1584
|
+
var PASTE_START = "\x1B[200~";
|
|
1585
|
+
var PASTE_END = "\x1B[201~";
|
|
1586
|
+
var KEYS = { "\x1B[A": "up", "\x1BOA": "up", "\x1B[B": "down", "\x1BOB": "down", "\x1B[5~": "pageup", "\x1B[6~": "pagedown", "\x1B[H": "home", "\x1B[1~": "home", "\x1BOH": "home", "\x1B[F": "end", "\x1B[4~": "end", "\x1BOF": "end", "\r": "enter", "\n": "enter", "\x03": "cancel", "\x1B": "cancel", "\x7F": "erase", "\b": "erase" };
|
|
1587
|
+
function readKeys(input, paste = { active: false }) {
|
|
1588
|
+
return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => {
|
|
1589
|
+
if (sequence === PASTE_START || sequence === PASTE_END) {
|
|
1590
|
+
paste.active = sequence === PASTE_START;
|
|
1591
|
+
return [];
|
|
1592
|
+
}
|
|
1593
|
+
if (paste.active && (sequence === "\r" || sequence === `
|
|
1594
|
+
`))
|
|
1595
|
+
return [];
|
|
1596
|
+
return KEYS[sequence] ?? (CONTROL.test(sequence) ? [] : [{ text: sequence }]);
|
|
1597
|
+
});
|
|
1588
1598
|
}
|
|
1589
1599
|
function flip(checked, value) {
|
|
1590
1600
|
const next = new Set(checked);
|
|
@@ -1683,6 +1693,12 @@ class List {
|
|
|
1683
1693
|
this.cursor = (this.cursor + (key === "up" ? this.matches.length - 1 : 1)) % this.matches.length;
|
|
1684
1694
|
return;
|
|
1685
1695
|
}
|
|
1696
|
+
if (key === "home" || key === "end" || key === "pageup" || key === "pagedown") {
|
|
1697
|
+
const last = this.matches.length - 1;
|
|
1698
|
+
const to = { home: 0, end: last, pageup: this.cursor - MAX_ROWS, pagedown: this.cursor + MAX_ROWS }[key];
|
|
1699
|
+
this.cursor = Math.max(0, Math.min(last, to));
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1686
1702
|
if (key === "erase")
|
|
1687
1703
|
this.filter([...this.query].slice(0, -1).join(""));
|
|
1688
1704
|
else if (typeof key === "object")
|
|
@@ -1724,22 +1740,29 @@ async function ask(question, { hint, terminal = process15 }, render, press) {
|
|
|
1724
1740
|
if (!isInteractive(terminal))
|
|
1725
1741
|
fail(`cannot ask "${question}" off a terminal`, 2, hint);
|
|
1726
1742
|
const colors = paint(stderr);
|
|
1727
|
-
let drawn =
|
|
1743
|
+
let drawn = [];
|
|
1744
|
+
let current = "asking";
|
|
1728
1745
|
let outcome;
|
|
1746
|
+
const columns = () => stderr.columns || 80;
|
|
1729
1747
|
const draw = (state) => {
|
|
1730
|
-
const frame = render(colors, state, { columns:
|
|
1731
|
-
|
|
1748
|
+
const frame = render(colors, state, { columns: columns(), rows: stderr.rows || 24 });
|
|
1749
|
+
const rows = drawn.reduce((sum, line) => sum + Math.max(1, Math.ceil(Bun.stringWidth(line) / columns())), 0);
|
|
1750
|
+
stderr.write(`${rows > 1 ? `\x1B[${rows - 1}A` : ""}\r\x1B[0J${frame.join(`
|
|
1732
1751
|
`)}`);
|
|
1733
|
-
drawn = frame
|
|
1752
|
+
drawn = frame;
|
|
1753
|
+
current = state;
|
|
1734
1754
|
};
|
|
1755
|
+
const redraw = () => draw(current);
|
|
1756
|
+
const paste = { active: false };
|
|
1735
1757
|
try {
|
|
1758
|
+
stderr.on?.("resize", redraw);
|
|
1736
1759
|
stdin.setRawMode(true);
|
|
1737
1760
|
stdin.resume();
|
|
1738
|
-
stderr.write("\x1B[?25l");
|
|
1761
|
+
stderr.write("\x1B[?25l\x1B[?2004h");
|
|
1739
1762
|
draw("asking");
|
|
1740
1763
|
return await new Promise((resolve) => {
|
|
1741
1764
|
function onData(data) {
|
|
1742
|
-
for (const key of readKeys(data.toString())) {
|
|
1765
|
+
for (const key of readKeys(data.toString(), paste)) {
|
|
1743
1766
|
const pressed = press(key);
|
|
1744
1767
|
if (pressed !== undefined) {
|
|
1745
1768
|
settle(pressed);
|
|
@@ -1761,9 +1784,10 @@ async function ask(question, { hint, terminal = process15 }, render, press) {
|
|
|
1761
1784
|
stdin.on("end", onEnd);
|
|
1762
1785
|
});
|
|
1763
1786
|
} finally {
|
|
1787
|
+
stderr.off?.("resize", redraw);
|
|
1764
1788
|
draw(outcome ?? "cancel");
|
|
1765
1789
|
stderr.write(`
|
|
1766
|
-
\x1B[?25h`);
|
|
1790
|
+
\x1B[?25h\x1B[?2004l`);
|
|
1767
1791
|
stdin.setRawMode(false);
|
|
1768
1792
|
stdin.pause();
|
|
1769
1793
|
}
|
|
@@ -1854,7 +1878,7 @@ async function install(host, options, recheck, choosing = ask2) {
|
|
|
1854
1878
|
console.log("everything is installed");
|
|
1855
1879
|
return 0;
|
|
1856
1880
|
}
|
|
1857
|
-
if (pool.length === 0 && options.names.length > 0) {
|
|
1881
|
+
if (pool.length === 0 && (options.names.length > 0 || !isInteractive())) {
|
|
1858
1882
|
console.log("everything is installed");
|
|
1859
1883
|
return 0;
|
|
1860
1884
|
}
|
|
@@ -1917,10 +1941,14 @@ async function install(host, options, recheck, choosing = ask2) {
|
|
|
1917
1941
|
return 1;
|
|
1918
1942
|
}
|
|
1919
1943
|
}
|
|
1920
|
-
if (removing.plugin && host.which("claude")
|
|
1944
|
+
if (removing.plugin && host.which("claude") === null) {
|
|
1945
|
+
console.error(`${yellow("not run")} ${PLUGIN_UNINSTALL.join(" ")}: claude is not on PATH`);
|
|
1946
|
+
} else if (removing.plugin) {
|
|
1921
1947
|
const ran = await host.run(PLUGIN_UNINSTALL);
|
|
1922
|
-
if (ran.code !== 0)
|
|
1948
|
+
if (ran.code !== 0) {
|
|
1923
1949
|
console.error(`${red("failed")} ${PLUGIN_UNINSTALL.join(" ")}: exit ${ran.code}: ${firstLine(ran.stderr || ran.stdout)}`);
|
|
1950
|
+
return 1;
|
|
1951
|
+
}
|
|
1924
1952
|
}
|
|
1925
1953
|
console.log(`
|
|
1926
1954
|
after the install:`);
|
package/dist/cli.js
CHANGED
|
@@ -481,7 +481,6 @@ var DASHES = /^-+/;
|
|
|
481
481
|
function jsonOption(holds) {
|
|
482
482
|
return { type: "boolean", description: holds === undefined ? "print JSON" : `print JSON: ${holds}` };
|
|
483
483
|
}
|
|
484
|
-
|
|
485
484
|
class Exit extends Error {
|
|
486
485
|
code;
|
|
487
486
|
hint;
|
|
@@ -1580,9 +1579,20 @@ var KEY_SEQUENCES = /\x1B\[[0-9;]*[A-Z~]|\x1BO[A-Z]|[\s\S]/giu;
|
|
|
1580
1579
|
var CONTROL = /^[\x00-\x1F\x7F]/;
|
|
1581
1580
|
var WORDS = /\s+/;
|
|
1582
1581
|
var MAX_ROWS = 10;
|
|
1583
|
-
var
|
|
1584
|
-
|
|
1585
|
-
|
|
1582
|
+
var PASTE_START = "\x1B[200~";
|
|
1583
|
+
var PASTE_END = "\x1B[201~";
|
|
1584
|
+
var KEYS = { "\x1B[A": "up", "\x1BOA": "up", "\x1B[B": "down", "\x1BOB": "down", "\x1B[5~": "pageup", "\x1B[6~": "pagedown", "\x1B[H": "home", "\x1B[1~": "home", "\x1BOH": "home", "\x1B[F": "end", "\x1B[4~": "end", "\x1BOF": "end", "\r": "enter", "\n": "enter", "\x03": "cancel", "\x1B": "cancel", "\x7F": "erase", "\b": "erase" };
|
|
1585
|
+
function readKeys(input, paste = { active: false }) {
|
|
1586
|
+
return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => {
|
|
1587
|
+
if (sequence === PASTE_START || sequence === PASTE_END) {
|
|
1588
|
+
paste.active = sequence === PASTE_START;
|
|
1589
|
+
return [];
|
|
1590
|
+
}
|
|
1591
|
+
if (paste.active && (sequence === "\r" || sequence === `
|
|
1592
|
+
`))
|
|
1593
|
+
return [];
|
|
1594
|
+
return KEYS[sequence] ?? (CONTROL.test(sequence) ? [] : [{ text: sequence }]);
|
|
1595
|
+
});
|
|
1586
1596
|
}
|
|
1587
1597
|
function flip(checked, value) {
|
|
1588
1598
|
const next = new Set(checked);
|
|
@@ -1681,6 +1691,12 @@ class List {
|
|
|
1681
1691
|
this.cursor = (this.cursor + (key === "up" ? this.matches.length - 1 : 1)) % this.matches.length;
|
|
1682
1692
|
return;
|
|
1683
1693
|
}
|
|
1694
|
+
if (key === "home" || key === "end" || key === "pageup" || key === "pagedown") {
|
|
1695
|
+
const last = this.matches.length - 1;
|
|
1696
|
+
const to = { home: 0, end: last, pageup: this.cursor - MAX_ROWS, pagedown: this.cursor + MAX_ROWS }[key];
|
|
1697
|
+
this.cursor = Math.max(0, Math.min(last, to));
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1684
1700
|
if (key === "erase")
|
|
1685
1701
|
this.filter([...this.query].slice(0, -1).join(""));
|
|
1686
1702
|
else if (typeof key === "object")
|
|
@@ -1722,22 +1738,29 @@ async function ask(question, { hint, terminal = process15 }, render, press) {
|
|
|
1722
1738
|
if (!isInteractive(terminal))
|
|
1723
1739
|
fail(`cannot ask "${question}" off a terminal`, 2, hint);
|
|
1724
1740
|
const colors = paint(stderr);
|
|
1725
|
-
let drawn =
|
|
1741
|
+
let drawn = [];
|
|
1742
|
+
let current = "asking";
|
|
1726
1743
|
let outcome;
|
|
1744
|
+
const columns = () => stderr.columns || 80;
|
|
1727
1745
|
const draw = (state) => {
|
|
1728
|
-
const frame = render(colors, state, { columns:
|
|
1729
|
-
|
|
1746
|
+
const frame = render(colors, state, { columns: columns(), rows: stderr.rows || 24 });
|
|
1747
|
+
const rows = drawn.reduce((sum, line) => sum + Math.max(1, Math.ceil(Bun.stringWidth(line) / columns())), 0);
|
|
1748
|
+
stderr.write(`${rows > 1 ? `\x1B[${rows - 1}A` : ""}\r\x1B[0J${frame.join(`
|
|
1730
1749
|
`)}`);
|
|
1731
|
-
drawn = frame
|
|
1750
|
+
drawn = frame;
|
|
1751
|
+
current = state;
|
|
1732
1752
|
};
|
|
1753
|
+
const redraw = () => draw(current);
|
|
1754
|
+
const paste = { active: false };
|
|
1733
1755
|
try {
|
|
1756
|
+
stderr.on?.("resize", redraw);
|
|
1734
1757
|
stdin.setRawMode(true);
|
|
1735
1758
|
stdin.resume();
|
|
1736
|
-
stderr.write("\x1B[?25l");
|
|
1759
|
+
stderr.write("\x1B[?25l\x1B[?2004h");
|
|
1737
1760
|
draw("asking");
|
|
1738
1761
|
return await new Promise((resolve) => {
|
|
1739
1762
|
function onData(data) {
|
|
1740
|
-
for (const key of readKeys(data.toString())) {
|
|
1763
|
+
for (const key of readKeys(data.toString(), paste)) {
|
|
1741
1764
|
const pressed = press(key);
|
|
1742
1765
|
if (pressed !== undefined) {
|
|
1743
1766
|
settle(pressed);
|
|
@@ -1759,9 +1782,10 @@ async function ask(question, { hint, terminal = process15 }, render, press) {
|
|
|
1759
1782
|
stdin.on("end", onEnd);
|
|
1760
1783
|
});
|
|
1761
1784
|
} finally {
|
|
1785
|
+
stderr.off?.("resize", redraw);
|
|
1762
1786
|
draw(outcome ?? "cancel");
|
|
1763
1787
|
stderr.write(`
|
|
1764
|
-
\x1B[?25h`);
|
|
1788
|
+
\x1B[?25h\x1B[?2004l`);
|
|
1765
1789
|
stdin.setRawMode(false);
|
|
1766
1790
|
stdin.pause();
|
|
1767
1791
|
}
|
|
@@ -1852,7 +1876,7 @@ async function install(host, options, recheck, choosing = ask2) {
|
|
|
1852
1876
|
console.log("everything is installed");
|
|
1853
1877
|
return 0;
|
|
1854
1878
|
}
|
|
1855
|
-
if (pool.length === 0 && options.names.length > 0) {
|
|
1879
|
+
if (pool.length === 0 && (options.names.length > 0 || !isInteractive())) {
|
|
1856
1880
|
console.log("everything is installed");
|
|
1857
1881
|
return 0;
|
|
1858
1882
|
}
|
|
@@ -1915,10 +1939,14 @@ async function install(host, options, recheck, choosing = ask2) {
|
|
|
1915
1939
|
return 1;
|
|
1916
1940
|
}
|
|
1917
1941
|
}
|
|
1918
|
-
if (removing.plugin && host.which("claude")
|
|
1942
|
+
if (removing.plugin && host.which("claude") === null) {
|
|
1943
|
+
console.error(`${yellow("not run")} ${PLUGIN_UNINSTALL.join(" ")}: claude is not on PATH`);
|
|
1944
|
+
} else if (removing.plugin) {
|
|
1919
1945
|
const ran = await host.run(PLUGIN_UNINSTALL);
|
|
1920
|
-
if (ran.code !== 0)
|
|
1946
|
+
if (ran.code !== 0) {
|
|
1921
1947
|
console.error(`${red("failed")} ${PLUGIN_UNINSTALL.join(" ")}: exit ${ran.code}: ${firstLine(ran.stderr || ran.stdout)}`);
|
|
1948
|
+
return 1;
|
|
1949
|
+
}
|
|
1922
1950
|
}
|
|
1923
1951
|
console.log(`
|
|
1924
1952
|
after the install:`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaynooo/cli-doctor",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"description": "doctor: checks the @kaynooo/cli-* install of a host: each bin's version against the registry, tea's login to Forgejo, the Claude Code hooks and the Bun floor; cli list: every bin in one line, read from its own help.",
|
|
6
6
|
"author": "Kaynooo <contact@kaynooo.fr>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -37,6 +37,6 @@
|
|
|
37
37
|
"doctor": "$npm_execpath src/cli.ts"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@kaynooo/cli-kit": "0.
|
|
40
|
+
"@kaynooo/cli-kit": "0.24.0"
|
|
41
41
|
}
|
|
42
42
|
}
|