hacksh 0.16.0 → 0.18.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 +149 -28
- package/dist/{command-B-Ok_6KW.d.ts → command-Czf4qXhe.d.ts} +32 -13
- package/dist/index.d.ts +3 -3
- package/dist/index.js +110 -63
- package/dist/index.js.map +1 -1
- package/dist/{pretty-DJ2CE6TU.js → pretty-BjzGnVLM.js} +109 -42
- package/dist/pretty-BjzGnVLM.js.map +1 -0
- package/dist/printer-api.d.ts +2 -2
- package/dist/printer-api.js +1 -1
- package/package.json +3 -1
- package/dist/pretty-DJ2CE6TU.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as createExec, c as
|
|
1
|
+
import { a as createExec, c as HackshExitError, d as HackshValidationError, f as summarizeError, i as resolveOutputMode, l as HackshPromptError, n as createJsonPrinter, o as HackshError, p as summarizeErrors, r as createPrintQueue, s as HackshExecError, t as createPrettyPrinter, u as HackshUsageError } from "./pretty-BjzGnVLM.js";
|
|
2
2
|
import { globalRegistry, safeParseAsync } from "zod/v4/core";
|
|
3
3
|
import { parseArgs as parseArgs$1 } from "node:util";
|
|
4
4
|
import { readFile, realpath } from "node:fs/promises";
|
|
@@ -619,6 +619,44 @@ function promptError(reason, prompt, message, cause) {
|
|
|
619
619
|
function validateMessage(kind, message, choices) {
|
|
620
620
|
if (typeof message !== "string" || message.length === 0) throw promptError("invalid-options", details$1(kind, message, choices), `Invalid ${kind} prompt: message must be a non-empty string`);
|
|
621
621
|
}
|
|
622
|
+
function validateChoices(kind, options) {
|
|
623
|
+
const choices = Array.isArray(options?.options) ? options.options.map((option) => typeof option === "object" && option !== null && typeof option.value === "string" ? option.value : "[Invalid choice]") : [];
|
|
624
|
+
const prompt = details$1(kind, options?.message, choices);
|
|
625
|
+
validateMessage(kind, options?.message, choices);
|
|
626
|
+
if (!Array.isArray(options.options) || options.options.length === 0) throw promptError("invalid-options", prompt, `A ${kind} prompt requires at least one choice`);
|
|
627
|
+
const seen = /* @__PURE__ */ new Set();
|
|
628
|
+
for (const option of options.options) {
|
|
629
|
+
if (typeof option !== "object" || option === null || typeof option.value !== "string" || option.value.length === 0 || option.label !== void 0 && typeof option.label !== "string" || option.hint !== void 0 && typeof option.hint !== "string") throw promptError("invalid-options", prompt, `${kind === "select" ? "Select" : "Autocomplete"} choices must have valid string values`);
|
|
630
|
+
if (seen.has(option.value)) throw promptError("invalid-options", prompt, `Duplicate ${kind} choice: ${option.value}`);
|
|
631
|
+
seen.add(option.value);
|
|
632
|
+
}
|
|
633
|
+
return prompt;
|
|
634
|
+
}
|
|
635
|
+
function sortedChoices(options, prompt) {
|
|
636
|
+
const { sortBy } = options;
|
|
637
|
+
if (sortBy === void 0) return options.options;
|
|
638
|
+
if (typeof sortBy !== "function") throw promptError("invalid-options", prompt, "sortBy must be a function");
|
|
639
|
+
let keyType;
|
|
640
|
+
const keyed = options.options.map((item) => {
|
|
641
|
+
let key;
|
|
642
|
+
try {
|
|
643
|
+
key = sortBy(item);
|
|
644
|
+
} catch (cause) {
|
|
645
|
+
throw promptError("input-error", prompt, "Choice sort key could not be computed", cause);
|
|
646
|
+
}
|
|
647
|
+
if (typeof key !== "string" && (typeof key !== "number" || Number.isNaN(key))) throw promptError("invalid-options", prompt, "sortBy must return a string or a non-NaN number");
|
|
648
|
+
const type = typeof key;
|
|
649
|
+
if (keyType !== void 0 && keyType !== type) throw promptError("invalid-options", prompt, "sortBy keys must all have the same type");
|
|
650
|
+
keyType = type;
|
|
651
|
+
return {
|
|
652
|
+
item,
|
|
653
|
+
key
|
|
654
|
+
};
|
|
655
|
+
});
|
|
656
|
+
keyed.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
|
|
657
|
+
return keyed.map(({ item }) => item);
|
|
658
|
+
}
|
|
659
|
+
const graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
622
660
|
function asInput(value, prompt) {
|
|
623
661
|
if (typeof value !== "object" || value === null || typeof Reflect.get(value, "on") !== "function" || typeof Reflect.get(value, "removeListener") !== "function" || typeof Reflect.get(value, "resume") !== "function" || typeof Reflect.get(value, "pause") !== "function") throw promptError("input-error", prompt, "Interactive input is not a readable stream");
|
|
624
662
|
return value;
|
|
@@ -647,7 +685,7 @@ var PromptController = class {
|
|
|
647
685
|
throw promptError("printer-error", prompt, "The prompt could not be displayed", cause);
|
|
648
686
|
}
|
|
649
687
|
}
|
|
650
|
-
async #run(prompt, initial, accept, update, submitted, closed) {
|
|
688
|
+
async #run(prompt, initial, accept, update, submitted, closed, cancelOnEscape = () => true) {
|
|
651
689
|
if (!this.#interactive) throw promptError("non-interactive", prompt, `Cannot request ${prompt.kind} input in non-interactive mode: ${prompt.message}`);
|
|
652
690
|
if (this.#signal.aborted) throw promptError("aborted", prompt, "Prompt aborted", this.#signal.reason);
|
|
653
691
|
const input = asInput(this.#inputValue, prompt);
|
|
@@ -689,7 +727,7 @@ var PromptController = class {
|
|
|
689
727
|
};
|
|
690
728
|
const handleKeypress = async (character, key = {}) => {
|
|
691
729
|
if (settled) return;
|
|
692
|
-
if (key.ctrl && key.name === "c" || key.name === "escape") {
|
|
730
|
+
if (key.ctrl && key.name === "c" || key.name === "escape" && cancelOnEscape()) {
|
|
693
731
|
fail("cancelled", "Prompt cancelled");
|
|
694
732
|
return;
|
|
695
733
|
}
|
|
@@ -797,36 +835,71 @@ var PromptController = class {
|
|
|
797
835
|
}
|
|
798
836
|
}
|
|
799
837
|
async select(options) {
|
|
800
|
-
const
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
if (!Array.isArray(options.options) || options.options.length === 0) throw promptError("invalid-options", prompt, "A select prompt requires at least one choice");
|
|
804
|
-
const seen = /* @__PURE__ */ new Set();
|
|
805
|
-
for (const option of options.options) {
|
|
806
|
-
if (typeof option !== "object" || option === null || typeof option.value !== "string" || option.value.length === 0 || option.label !== void 0 && typeof option.label !== "string" || option.hint !== void 0 && typeof option.hint !== "string") throw promptError("invalid-options", prompt, "Select choices must have valid string values");
|
|
807
|
-
if (seen.has(option.value)) throw promptError("invalid-options", prompt, `Duplicate select choice: ${option.value}`);
|
|
808
|
-
seen.add(option.value);
|
|
809
|
-
}
|
|
810
|
-
let selected = options.initialValue === void 0 ? 0 : choices.indexOf(options.initialValue);
|
|
838
|
+
const prompt = validateChoices("select", options);
|
|
839
|
+
const choices = sortedChoices(options, prompt);
|
|
840
|
+
let selected = options.initialValue === void 0 ? 0 : choices.findIndex(({ value }) => value === options.initialValue);
|
|
811
841
|
if (selected < 0) throw promptError("invalid-options", prompt, `Unknown initial select value: ${String(options.initialValue)}`);
|
|
812
842
|
const state = (status = "active") => ({
|
|
813
843
|
kind: "select",
|
|
814
844
|
message: options.message,
|
|
815
845
|
status,
|
|
816
|
-
value:
|
|
817
|
-
choices:
|
|
846
|
+
value: choices[selected].value,
|
|
847
|
+
choices: choices.map(({ value, label, hint }, index) => ({
|
|
818
848
|
value,
|
|
819
849
|
label: label ?? value,
|
|
820
850
|
...hint === void 0 ? {} : { hint },
|
|
821
851
|
selected: index === selected
|
|
822
852
|
}))
|
|
823
853
|
});
|
|
824
|
-
return await this.#run(prompt, state(), (_character, key) => key.name === "return" || key.name === "enter" ?
|
|
854
|
+
return await this.#run(prompt, state(), (_character, key) => key.name === "return" || key.name === "enter" ? choices[selected].value : void 0, (_character, key) => {
|
|
825
855
|
if (key.name !== "up" && key.name !== "down") return void 0;
|
|
826
|
-
selected = (selected + (key.name === "up" ? -1 : 1) +
|
|
856
|
+
selected = (selected + (key.name === "up" ? -1 : 1) + choices.length) % choices.length;
|
|
827
857
|
return state();
|
|
828
858
|
}, () => state("submitted"), () => state("closed"));
|
|
829
859
|
}
|
|
860
|
+
async autocomplete(options) {
|
|
861
|
+
const prompt = validateChoices("autocomplete", options);
|
|
862
|
+
if (options.placeholder !== void 0 && typeof options.placeholder !== "string") throw promptError("invalid-options", prompt, "Autocomplete placeholder must be a string");
|
|
863
|
+
const choices = sortedChoices(options, prompt);
|
|
864
|
+
let query = "";
|
|
865
|
+
let selected = -1;
|
|
866
|
+
let filtered = choices;
|
|
867
|
+
const state = (status = "active") => ({
|
|
868
|
+
kind: "autocomplete",
|
|
869
|
+
message: options.message,
|
|
870
|
+
status,
|
|
871
|
+
query,
|
|
872
|
+
phase: selected < 0 ? "input" : "select",
|
|
873
|
+
...options.placeholder === void 0 ? {} : { placeholder: options.placeholder },
|
|
874
|
+
...selected < 0 ? {} : { value: filtered[selected].value },
|
|
875
|
+
choices: filtered.map(({ value, label, hint }, index) => ({
|
|
876
|
+
value,
|
|
877
|
+
label: label ?? value,
|
|
878
|
+
...hint === void 0 ? {} : { hint },
|
|
879
|
+
selected: index === selected
|
|
880
|
+
}))
|
|
881
|
+
});
|
|
882
|
+
return await this.#run(prompt, state(), (_character, key) => selected >= 0 && (key.name === "return" || key.name === "enter") ? filtered[selected].value : void 0, (character, key) => {
|
|
883
|
+
if (key.name === "down") {
|
|
884
|
+
if (selected >= filtered.length - 1) return void 0;
|
|
885
|
+
selected += 1;
|
|
886
|
+
} else if (key.name === "up") {
|
|
887
|
+
if (selected < 0) return void 0;
|
|
888
|
+
selected -= 1;
|
|
889
|
+
} else if (key.name === "escape") selected = -1;
|
|
890
|
+
else {
|
|
891
|
+
if (key.name === "backspace") {
|
|
892
|
+
const last = graphemeSegmenter.segment(query).containing(query.length - 1);
|
|
893
|
+
query = last === void 0 ? "" : query.slice(0, last.index);
|
|
894
|
+
} else if (!key.ctrl && !key.meta && character.length > 0 && !/\p{Cc}/u.test(character)) query += character;
|
|
895
|
+
else return void 0;
|
|
896
|
+
selected = -1;
|
|
897
|
+
const search = query.toLowerCase();
|
|
898
|
+
filtered = search.length === 0 ? choices : choices.filter(({ value, label }) => (label ?? value).toLowerCase().includes(search));
|
|
899
|
+
}
|
|
900
|
+
return state();
|
|
901
|
+
}, () => state("submitted"), () => state("closed"), () => selected < 0);
|
|
902
|
+
}
|
|
830
903
|
async confirm(options) {
|
|
831
904
|
const prompt = details$1("confirm", options?.message);
|
|
832
905
|
validateMessage("confirm", options?.message);
|
|
@@ -1178,13 +1251,6 @@ async function runCommand(root, argv, options = {}) {
|
|
|
1178
1251
|
await output.drain();
|
|
1179
1252
|
}
|
|
1180
1253
|
}
|
|
1181
|
-
async function drainAndExit(output, code = 1) {
|
|
1182
|
-
try {
|
|
1183
|
-
await output.drain();
|
|
1184
|
-
} finally {
|
|
1185
|
-
process.exit(code);
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
1254
|
function commandErrorExitCode(error) {
|
|
1189
1255
|
if (error instanceof HackshExitError) return error.exitCode;
|
|
1190
1256
|
return error instanceof HackshPromptError && error.reason === "cancelled" ? 130 : 1;
|
|
@@ -1213,21 +1279,6 @@ function listenForExitSignals() {
|
|
|
1213
1279
|
}
|
|
1214
1280
|
};
|
|
1215
1281
|
}
|
|
1216
|
-
async function reportOutputSetupError(error, options) {
|
|
1217
|
-
if (options.onError) {
|
|
1218
|
-
await options.onError(error);
|
|
1219
|
-
return drainAndExit(createPrintQueue(options.printer ?? { print: () => void 0 }));
|
|
1220
|
-
}
|
|
1221
|
-
const output = createPrintQueue(options.printer ?? createJsonPrinter({
|
|
1222
|
-
stdout: options.stdout ?? process.stdout,
|
|
1223
|
-
stderr: options.stderr ?? process.stderr
|
|
1224
|
-
}));
|
|
1225
|
-
await output.printer.print({
|
|
1226
|
-
type: "error",
|
|
1227
|
-
error: summarizeError(error)
|
|
1228
|
-
});
|
|
1229
|
-
return drainAndExit(output);
|
|
1230
|
-
}
|
|
1231
1282
|
async function reportCommandError(error, output) {
|
|
1232
1283
|
if (error instanceof HackshExitError && error.message === "") return;
|
|
1233
1284
|
await output.printer.print({
|
|
@@ -1240,37 +1291,33 @@ async function reportCommandError(error, output) {
|
|
|
1240
1291
|
});
|
|
1241
1292
|
}
|
|
1242
1293
|
async function runMain(command, options = {}) {
|
|
1243
|
-
|
|
1244
|
-
try {
|
|
1245
|
-
output = prepareOutput(options, options.env ?? process.env);
|
|
1246
|
-
} catch (error) {
|
|
1247
|
-
return reportOutputSetupError(error, options);
|
|
1248
|
-
}
|
|
1294
|
+
const output = prepareOutput(options, options.env ?? process.env);
|
|
1249
1295
|
const signals = listenForExitSignals();
|
|
1250
|
-
|
|
1251
|
-
signals.release();
|
|
1252
|
-
return drainAndExit(output, signals.exitCode() ?? code);
|
|
1253
|
-
};
|
|
1296
|
+
let exitCode;
|
|
1254
1297
|
try {
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1298
|
+
try {
|
|
1299
|
+
await executeCommand(command, options.argv ?? process.argv.slice(2), output, options.env, signals.signal, () => findPackageVersion(process.argv[1]));
|
|
1300
|
+
} catch (error) {
|
|
1301
|
+
const signalExitCode = signals.exitCode();
|
|
1302
|
+
if (signalExitCode !== void 0 && error === signals.signal.reason) exitCode = signalExitCode;
|
|
1303
|
+
else {
|
|
1304
|
+
if (!(error instanceof HackshError)) throw error;
|
|
1305
|
+
if (options.onError) await options.onError(error);
|
|
1306
|
+
else await reportCommandError(error, output);
|
|
1307
|
+
exitCode = commandErrorExitCode(error);
|
|
1308
|
+
}
|
|
1260
1309
|
}
|
|
1310
|
+
} finally {
|
|
1261
1311
|
try {
|
|
1262
|
-
await
|
|
1312
|
+
await output.drain();
|
|
1263
1313
|
} finally {
|
|
1264
|
-
|
|
1314
|
+
signals.release();
|
|
1265
1315
|
}
|
|
1266
|
-
} finally {
|
|
1267
|
-
signals.release();
|
|
1268
1316
|
}
|
|
1269
|
-
const
|
|
1270
|
-
if (
|
|
1271
|
-
await output.drain();
|
|
1317
|
+
const code = signals.exitCode() ?? exitCode;
|
|
1318
|
+
if (code !== void 0) process.exit(code);
|
|
1272
1319
|
}
|
|
1273
1320
|
//#endregion
|
|
1274
|
-
export { HackshExecError, HackshExitError, HackshPromptError, HackshUsageError, HackshValidationError, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage, summarizeUsage };
|
|
1321
|
+
export { HackshError, HackshExecError, HackshExitError, HackshPromptError, HackshUsageError, HackshValidationError, defineCommand, parseArgs, renderUsage, runCommand, runMain, showUsage, summarizeUsage };
|
|
1275
1322
|
|
|
1276
1323
|
//# sourceMappingURL=index.js.map
|