@duyquangnvx/agent-cli 0.0.0-stage → 0.2.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/CHANGELOG.md +34 -0
- package/README.md +10 -2
- package/dist/built-ins.d.ts +4 -0
- package/dist/built-ins.js +20 -0
- package/dist/built-ins.js.map +1 -0
- package/dist/command-spec.d.ts +28 -0
- package/dist/command-spec.js +31 -0
- package/dist/command-spec.js.map +1 -0
- package/dist/confirm.d.ts +7 -0
- package/dist/confirm.js +22 -0
- package/dist/confirm.js.map +1 -0
- package/dist/define.d.ts +132 -0
- package/dist/define.js +10 -0
- package/dist/define.js.map +1 -0
- package/dist/doctor-rows.d.ts +3 -0
- package/dist/doctor-rows.js +115 -0
- package/dist/doctor-rows.js.map +1 -0
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.js +100 -0
- package/dist/doctor.js.map +1 -0
- package/dist/errors.d.ts +34 -0
- package/dist/errors.js +72 -0
- package/dist/errors.js.map +1 -0
- package/dist/execute.d.ts +21 -0
- package/dist/execute.js +26 -0
- package/dist/execute.js.map +1 -0
- package/dist/flags.d.ts +50 -0
- package/dist/flags.js +59 -0
- package/dist/flags.js.map +1 -0
- package/dist/global-install.d.ts +13 -0
- package/dist/global-install.js +51 -0
- package/dist/global-install.js.map +1 -0
- package/dist/help-json.d.ts +4 -0
- package/dist/help-json.js +44 -0
- package/dist/help-json.js.map +1 -0
- package/dist/help.d.ts +5 -0
- package/dist/help.js +64 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/input.d.ts +22 -0
- package/dist/input.js +63 -0
- package/dist/input.js.map +1 -0
- package/dist/interrupts.d.ts +18 -0
- package/dist/interrupts.js +118 -0
- package/dist/interrupts.js.map +1 -0
- package/dist/invocation.d.ts +9 -0
- package/dist/invocation.js +37 -0
- package/dist/invocation.js.map +1 -0
- package/dist/list.d.ts +44 -0
- package/dist/list.js +126 -0
- package/dist/list.js.map +1 -0
- package/dist/npm.d.ts +24 -0
- package/dist/npm.js +181 -0
- package/dist/npm.js.map +1 -0
- package/dist/output.d.ts +33 -0
- package/dist/output.js +65 -0
- package/dist/output.js.map +1 -0
- package/dist/parse-input.d.ts +19 -0
- package/dist/parse-input.js +147 -0
- package/dist/parse-input.js.map +1 -0
- package/dist/route.d.ts +25 -0
- package/dist/route.js +75 -0
- package/dist/route.js.map +1 -0
- package/dist/run-cli.d.ts +16 -0
- package/dist/run-cli.js +85 -0
- package/dist/run-cli.js.map +1 -0
- package/dist/run-process.d.ts +2 -0
- package/dist/run-process.js +37 -0
- package/dist/run-process.js.map +1 -0
- package/dist/semver.d.ts +9 -0
- package/dist/semver.js +70 -0
- package/dist/semver.js.map +1 -0
- package/dist/skills.d.ts +11 -0
- package/dist/skills.js +58 -0
- package/dist/skills.js.map +1 -0
- package/dist/style.d.ts +13 -0
- package/dist/style.js +38 -0
- package/dist/style.js.map +1 -0
- package/dist/suggest.d.ts +6 -0
- package/dist/suggest.js +49 -0
- package/dist/suggest.js.map +1 -0
- package/dist/tokenize.d.ts +20 -0
- package/dist/tokenize.js +79 -0
- package/dist/tokenize.js.map +1 -0
- package/dist/update.d.ts +3 -0
- package/dist/update.js +91 -0
- package/dist/update.js.map +1 -0
- package/dist/upgrade-notes.d.ts +9 -0
- package/dist/upgrade-notes.js +41 -0
- package/dist/upgrade-notes.js.map +1 -0
- package/dist/usage.d.ts +5 -0
- package/dist/usage.js +37 -0
- package/dist/usage.js.map +1 -0
- package/package.json +29 -3
package/dist/errors.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export class CliError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
hint;
|
|
4
|
+
retryable;
|
|
5
|
+
constructor({ code, message, hint, retryable }, options) {
|
|
6
|
+
super(message, options);
|
|
7
|
+
this.name = "CliError";
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.hint = hint;
|
|
10
|
+
this.retryable = retryable;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** The caller called the Agent CLI wrong; retrying the same call can't succeed. */
|
|
14
|
+
export class UsageError extends CliError {
|
|
15
|
+
constructor(details) {
|
|
16
|
+
super({ ...details, retryable: false });
|
|
17
|
+
this.name = "UsageError";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const INTERNAL_CODE = "INTERNAL";
|
|
21
|
+
export function isMissingFile(error) {
|
|
22
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
23
|
+
}
|
|
24
|
+
export function debugVariable(cliName) {
|
|
25
|
+
return `${cliName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_DEBUG`;
|
|
26
|
+
}
|
|
27
|
+
export function messageOf(error) {
|
|
28
|
+
return error instanceof Error ? error.message : String(error);
|
|
29
|
+
}
|
|
30
|
+
function isDebug({ env, cliName }) {
|
|
31
|
+
return Boolean(env[debugVariable(cliName)]);
|
|
32
|
+
}
|
|
33
|
+
function detailsOf(error, format) {
|
|
34
|
+
if (error instanceof CliError) {
|
|
35
|
+
const { code, message, hint, retryable } = error;
|
|
36
|
+
return { code, message, hint, retryable };
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
code: INTERNAL_CODE,
|
|
40
|
+
message: messageOf(error),
|
|
41
|
+
hint: isDebug(format)
|
|
42
|
+
? "the stack trace shows where it failed"
|
|
43
|
+
: `rerun with ${debugVariable(format.cliName)}=1 to see the stack trace`,
|
|
44
|
+
retryable: false,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function stackOf(error, format) {
|
|
48
|
+
return isDebug(format) && !(error instanceof CliError) && error instanceof Error
|
|
49
|
+
? error.stack
|
|
50
|
+
: undefined;
|
|
51
|
+
}
|
|
52
|
+
export function formatRuntimeError(error, format) {
|
|
53
|
+
const details = detailsOf(error, format);
|
|
54
|
+
const stack = stackOf(error, format);
|
|
55
|
+
if (format.json) {
|
|
56
|
+
return `${JSON.stringify({ ...details, stack })}\n`;
|
|
57
|
+
}
|
|
58
|
+
const { style } = format;
|
|
59
|
+
const label = style.red(error instanceof CliError ? "error:" : "internal error:");
|
|
60
|
+
const trace = stack === undefined ? "" : `${stack}\n`;
|
|
61
|
+
return `${label} ${details.message}\n${trace}${style.cyan("hint:")} ${details.hint}\n`;
|
|
62
|
+
}
|
|
63
|
+
/** A failure that still prints the Command's data on stdout, as `doctor` does with its rows. */
|
|
64
|
+
export class FailureWithData extends CliError {
|
|
65
|
+
data;
|
|
66
|
+
constructor(details, data) {
|
|
67
|
+
super(details);
|
|
68
|
+
this.name = "FailureWithData";
|
|
69
|
+
this.data = data;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Command, Context } from "./define.js";
|
|
2
|
+
import type { Invocation } from "./invocation.js";
|
|
3
|
+
import type { PageInput } from "./list.js";
|
|
4
|
+
import type { Style } from "./style.js";
|
|
5
|
+
export interface Outcome {
|
|
6
|
+
readonly value: unknown;
|
|
7
|
+
render(style: Style): string;
|
|
8
|
+
}
|
|
9
|
+
export interface ExecuteFlags {
|
|
10
|
+
readonly dryRun: boolean;
|
|
11
|
+
/** The target the caller named with `--confirm`, if any. */
|
|
12
|
+
readonly confirm: string | undefined;
|
|
13
|
+
/** The page a List Command's `run` receives with its input. */
|
|
14
|
+
readonly page: PageInput;
|
|
15
|
+
/** The caller's command line and the Command's, for the hint of a confirmation error. */
|
|
16
|
+
readonly invocation: Invocation;
|
|
17
|
+
readonly commandLine: string;
|
|
18
|
+
}
|
|
19
|
+
/** How the Command prints data it fails with, which is the data its `run` or `apply` returns. */
|
|
20
|
+
export declare function renderOf(command: Command): (data: unknown, style: Style) => string;
|
|
21
|
+
export declare function execute(command: Command, input: Record<string, unknown>, ctx: Context, { dryRun, confirm, page, invocation, commandLine }: ExecuteFlags): Promise<Outcome>;
|
package/dist/execute.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { checkConfirmation } from "./confirm.js";
|
|
2
|
+
function outcomeOf(value, render) {
|
|
3
|
+
return { value, render: (style) => render(value, style) };
|
|
4
|
+
}
|
|
5
|
+
/** How the Command prints data it fails with, which is the data its `run` or `apply` returns. */
|
|
6
|
+
export function renderOf(command) {
|
|
7
|
+
// The union of render signatures only accepts the intersection of their data types.
|
|
8
|
+
return (data, style) => command.render(data, style);
|
|
9
|
+
}
|
|
10
|
+
export async function execute(command, input, ctx, { dryRun, confirm, page, invocation, commandLine }) {
|
|
11
|
+
if (command.rows !== undefined) {
|
|
12
|
+
return outcomeOf(await command.run({ ...input, ...page }, ctx), (data, style) => command.render(data, style));
|
|
13
|
+
}
|
|
14
|
+
if (command.effect === "read") {
|
|
15
|
+
return outcomeOf(await command.run(input, ctx), (data, style) => command.render(data, style));
|
|
16
|
+
}
|
|
17
|
+
const plan = await command.plan(input, ctx);
|
|
18
|
+
if (dryRun) {
|
|
19
|
+
return outcomeOf(plan, (value, style) => command.renderPlan(value, style));
|
|
20
|
+
}
|
|
21
|
+
if (command.effect === "destructive") {
|
|
22
|
+
checkConfirmation({ invocation, commandLine, given: confirm }, command.confirm(plan));
|
|
23
|
+
}
|
|
24
|
+
return outcomeOf(await command.apply(plan, ctx), (data, style) => command.render(data, style));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=execute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../src/execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAsBjD,SAAS,SAAS,CAAQ,KAAY,EAAE,MAA8C;IACpF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,oFAAoF;IACpF,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAE,OAAO,CAAC,MAAkD,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,OAAgB,EAChB,KAA8B,EAC9B,GAAY,EACZ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAgB;IAEhE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAC9E,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAC5B,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAChG,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QACrC,iBAAiB,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,SAAS,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;AACjG,CAAC"}
|
package/dist/flags.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { Command } from "./define.js";
|
|
3
|
+
import { type ListFlagName, type ListSpec } from "./list.js";
|
|
4
|
+
import type { Takes } from "./tokenize.js";
|
|
5
|
+
type Effect = Command["effect"];
|
|
6
|
+
export declare const HELP_FLAG = "--help";
|
|
7
|
+
export declare const HELP_SHORT = "-h";
|
|
8
|
+
export declare const VERSION_FLAG = "--version";
|
|
9
|
+
declare const ROUTING_FLAGS: readonly ["--help", "-h", "--version"];
|
|
10
|
+
export type NameOf<Flag extends string> = Flag extends `--${infer Name}` ? Name : Flag extends `-${infer Name}` ? Name : Flag;
|
|
11
|
+
export interface StandardFlag {
|
|
12
|
+
/** The flag as the caller types it, such as `--json`. */
|
|
13
|
+
readonly flag: string;
|
|
14
|
+
readonly usage: string;
|
|
15
|
+
readonly description: string;
|
|
16
|
+
readonly takes: Takes;
|
|
17
|
+
readonly schema: z.ZodType;
|
|
18
|
+
}
|
|
19
|
+
export declare const JSON_FLAG: StandardFlag & {
|
|
20
|
+
readonly flag: "--json";
|
|
21
|
+
};
|
|
22
|
+
export declare const DRY_RUN_FLAG: StandardFlag & {
|
|
23
|
+
readonly flag: "--dry-run";
|
|
24
|
+
};
|
|
25
|
+
export declare const CONFIRM_FLAG: StandardFlag & {
|
|
26
|
+
readonly flag: "--confirm";
|
|
27
|
+
};
|
|
28
|
+
declare const EFFECT_FLAGS: {
|
|
29
|
+
readonly read: readonly [StandardFlag & {
|
|
30
|
+
readonly flag: "--json";
|
|
31
|
+
}];
|
|
32
|
+
readonly write: readonly [StandardFlag & {
|
|
33
|
+
readonly flag: "--json";
|
|
34
|
+
}, StandardFlag & {
|
|
35
|
+
readonly flag: "--dry-run";
|
|
36
|
+
}];
|
|
37
|
+
readonly destructive: readonly [StandardFlag & {
|
|
38
|
+
readonly flag: "--json";
|
|
39
|
+
}, StandardFlag & {
|
|
40
|
+
readonly flag: "--dry-run";
|
|
41
|
+
}, StandardFlag & {
|
|
42
|
+
readonly flag: "--confirm";
|
|
43
|
+
}];
|
|
44
|
+
};
|
|
45
|
+
export type StandardFlagName = NameOf<(typeof ROUTING_FLAGS)[number]> | NameOf<(typeof EFFECT_FLAGS)[Effect][number]["flag"]> | ListFlagName;
|
|
46
|
+
/** The Standard flags of a Command with this Effect, and of a List Command. */
|
|
47
|
+
export declare function standardFlagsFor(effect: Effect, list: ListSpec | undefined): readonly StandardFlag[];
|
|
48
|
+
/** Throws when the Command declares an arg or option under a Standard flag's name. */
|
|
49
|
+
export declare function checkNoStandardFlags(command: Command): void;
|
|
50
|
+
export {};
|
package/dist/flags.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { argFields, kebab, optionFields } from "./input.js";
|
|
3
|
+
import { LIST_FLAGS } from "./list.js";
|
|
4
|
+
export const HELP_FLAG = "--help";
|
|
5
|
+
export const HELP_SHORT = "-h";
|
|
6
|
+
export const VERSION_FLAG = "--version";
|
|
7
|
+
// The Runtime reads these at every level of the command line, so no Command can declare them.
|
|
8
|
+
const ROUTING_FLAGS = [HELP_FLAG, HELP_SHORT, VERSION_FLAG];
|
|
9
|
+
function nameOf(flag) {
|
|
10
|
+
return flag.replace(/^--?/, "");
|
|
11
|
+
}
|
|
12
|
+
function standardFlag(flag, { placeholder, ...rest }) {
|
|
13
|
+
return { flag, usage: placeholder === undefined ? flag : `${flag} ${placeholder}`, ...rest };
|
|
14
|
+
}
|
|
15
|
+
export const JSON_FLAG = standardFlag("--json", {
|
|
16
|
+
description: "print the result as JSON",
|
|
17
|
+
takes: "nothing",
|
|
18
|
+
schema: z.boolean(),
|
|
19
|
+
});
|
|
20
|
+
export const DRY_RUN_FLAG = standardFlag("--dry-run", {
|
|
21
|
+
description: "print the Plan without changing anything",
|
|
22
|
+
takes: "nothing",
|
|
23
|
+
schema: z.boolean(),
|
|
24
|
+
});
|
|
25
|
+
export const CONFIRM_FLAG = standardFlag("--confirm", {
|
|
26
|
+
placeholder: "<target>",
|
|
27
|
+
description: "name the target to confirm the change; an error hint gives the exact command",
|
|
28
|
+
takes: "value",
|
|
29
|
+
schema: z.string(),
|
|
30
|
+
});
|
|
31
|
+
const EFFECT_FLAGS = {
|
|
32
|
+
read: [JSON_FLAG],
|
|
33
|
+
write: [JSON_FLAG, DRY_RUN_FLAG],
|
|
34
|
+
destructive: [JSON_FLAG, DRY_RUN_FLAG, CONFIRM_FLAG],
|
|
35
|
+
};
|
|
36
|
+
// Every name is reserved on every Command, whatever flags it gets, so a name means one thing.
|
|
37
|
+
const RESERVED = new Map([...ROUTING_FLAGS, ...EFFECT_FLAGS.destructive.map(({ flag }) => flag), ...LIST_FLAGS].map((flag) => [nameOf(flag), flag]));
|
|
38
|
+
/** The Standard flags of a Command with this Effect, and of a List Command. */
|
|
39
|
+
export function standardFlagsFor(effect, list) {
|
|
40
|
+
return [...EFFECT_FLAGS[effect], ...(list?.standardFlags ?? [])];
|
|
41
|
+
}
|
|
42
|
+
/** Throws when the Command declares an arg or option under a Standard flag's name. */
|
|
43
|
+
export function checkNoStandardFlags(command) {
|
|
44
|
+
const declared = [
|
|
45
|
+
...argFields(command.args).map(({ key }) => ({ kind: "arg", key })),
|
|
46
|
+
...optionFields(command.options).map(({ key }) => ({ kind: "option", key })),
|
|
47
|
+
];
|
|
48
|
+
const lines = declared.flatMap(({ kind, key }) => {
|
|
49
|
+
const flag = RESERVED.get(kebab(key));
|
|
50
|
+
return flag === undefined ? [] : [` ${kind} '${key}' is the Standard flag ${flag}`];
|
|
51
|
+
});
|
|
52
|
+
if (lines.length > 0) {
|
|
53
|
+
throw new Error([
|
|
54
|
+
`Command '${command.name}' declares Standard flags the Runtime adds; rename them:`,
|
|
55
|
+
...lines,
|
|
56
|
+
].join("\n"));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=flags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type NpmContext } from "./npm.js";
|
|
2
|
+
/** Where npm installed this copy of the CLI globally. */
|
|
3
|
+
export interface InstalledCopy {
|
|
4
|
+
readonly prefix: string;
|
|
5
|
+
readonly packageDir: string;
|
|
6
|
+
}
|
|
7
|
+
/** Where npm puts global packages under its global prefix. */
|
|
8
|
+
export declare function globalModulesDir(prefix: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* The global npm install this copy runs from, found by asking npm for its global prefix.
|
|
11
|
+
* `bin` is the script that started the CLI; throws `NOT_GLOBAL_INSTALL` when it is not inside that install.
|
|
12
|
+
*/
|
|
13
|
+
export declare function globalInstallOf(bin: string | undefined, ctx: NpmContext): Promise<InstalledCopy>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { lstat, realpath } from "node:fs/promises";
|
|
2
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
3
|
+
import { CliError, isMissingFile } from "./errors.js";
|
|
4
|
+
import { globalPrefix, installCommandLine } from "./npm.js";
|
|
5
|
+
/** Where npm puts global packages under its global prefix. */
|
|
6
|
+
export function globalModulesDir(prefix) {
|
|
7
|
+
return process.platform === "win32"
|
|
8
|
+
? join(prefix, "node_modules")
|
|
9
|
+
: join(prefix, "lib", "node_modules");
|
|
10
|
+
}
|
|
11
|
+
function notGlobal(ctx, message) {
|
|
12
|
+
return new CliError({
|
|
13
|
+
code: "NOT_GLOBAL_INSTALL",
|
|
14
|
+
message,
|
|
15
|
+
hint: `install it with npm, so \`${ctx.cliName} update\` can replace it: ${installCommandLine(ctx.install)}`,
|
|
16
|
+
retryable: false,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
async function realpathOrUndefined(path) {
|
|
20
|
+
return realpath(path).catch((error) => {
|
|
21
|
+
if (isMissingFile(error))
|
|
22
|
+
return undefined;
|
|
23
|
+
throw error;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function isInside(dir, path) {
|
|
27
|
+
const inner = relative(dir, path);
|
|
28
|
+
return inner !== "" && !inner.startsWith("..") && !isAbsolute(inner);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The global npm install this copy runs from, found by asking npm for its global prefix.
|
|
32
|
+
* `bin` is the script that started the CLI; throws `NOT_GLOBAL_INSTALL` when it is not inside that install.
|
|
33
|
+
*/
|
|
34
|
+
export async function globalInstallOf(bin, ctx) {
|
|
35
|
+
if (bin === undefined) {
|
|
36
|
+
throw notGlobal(ctx, `${ctx.cliName} runs from source, not from an npm install`);
|
|
37
|
+
}
|
|
38
|
+
const prefix = await globalPrefix(ctx);
|
|
39
|
+
const packageDir = join(globalModulesDir(prefix), ctx.install.package);
|
|
40
|
+
const installed = await realpathOrUndefined(packageDir);
|
|
41
|
+
const here = (await realpathOrUndefined(bin)) ?? bin;
|
|
42
|
+
if (installed === undefined || !isInside(installed, here)) {
|
|
43
|
+
throw notGlobal(ctx, `${ctx.cliName} runs from ${here}, not from npm's global install at ${packageDir}`);
|
|
44
|
+
}
|
|
45
|
+
// `npm link` puts a symlink to a source checkout where the install would be.
|
|
46
|
+
if ((await lstat(packageDir)).isSymbolicLink()) {
|
|
47
|
+
throw notGlobal(ctx, `${ctx.cliName} runs from a link to ${installed} (npm link), not from an npm install`);
|
|
48
|
+
}
|
|
49
|
+
return { prefix, packageDir };
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=global-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-install.js","sourceRoot":"","sources":["../src/global-install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAmB,MAAM,UAAU,CAAC;AAQ7E,8DAA8D;AAC9D,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO;QACjC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC;QAC9B,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,SAAS,CAAC,GAAe,EAAE,OAAe;IACjD,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,oBAAoB;QAC1B,OAAO;QACP,IAAI,EAAE,6BAA6B,GAAG,CAAC,OAAO,6BAA6B,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;QAC5G,SAAS,EAAE,KAAK;KACjB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,IAAY;IAC7C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAC7C,IAAI,aAAa,CAAC,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAC3C,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,IAAY;IACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAClC,OAAO,KAAK,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAuB,EACvB,GAAe;IAEf,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,4CAA4C,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,CAAC,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC;IACrD,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC;QAC1D,MAAM,SAAS,CACb,GAAG,EACH,GAAG,GAAG,CAAC,OAAO,cAAc,IAAI,sCAAsC,UAAU,EAAE,CACnF,CAAC;IACJ,CAAC;IACD,6EAA6E;IAC7E,IAAI,CAAC,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC;QAC/C,MAAM,SAAS,CACb,GAAG,EACH,GAAG,GAAG,CAAC,OAAO,wBAAwB,SAAS,sCAAsC,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CommandSpec, GroupSpec, SpecNode } from "./command-spec.js";
|
|
2
|
+
export declare function cliHelpJson(version: string, root: SpecNode): string;
|
|
3
|
+
export declare function groupHelpJson(group: GroupSpec): string;
|
|
4
|
+
export declare function commandHelpJson(spec: CommandSpec): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
// Transforms and other unrepresentable parts become `{}` rather than failing the whole help.
|
|
3
|
+
function inputSchema(schema) {
|
|
4
|
+
return z.toJSONSchema(schema, { io: "input", unrepresentable: "any" });
|
|
5
|
+
}
|
|
6
|
+
// Keys are the names the caller types, so option `greetingWord` reads `greeting-word`.
|
|
7
|
+
function optionsSchema(options) {
|
|
8
|
+
return inputSchema(z.object(Object.fromEntries(options.map(({ name, schema }) => [name, schema]))));
|
|
9
|
+
}
|
|
10
|
+
function commandData(spec) {
|
|
11
|
+
return {
|
|
12
|
+
name: spec.commandLine,
|
|
13
|
+
description: spec.description,
|
|
14
|
+
effect: spec.effect,
|
|
15
|
+
examples: spec.examples,
|
|
16
|
+
args: inputSchema(spec.command.args ?? z.object({})),
|
|
17
|
+
options: optionsSchema(spec.options),
|
|
18
|
+
standardFlags: spec.standardFlags.map(({ usage, description, schema }) => ({
|
|
19
|
+
usage,
|
|
20
|
+
description,
|
|
21
|
+
schema: inputSchema(schema),
|
|
22
|
+
})),
|
|
23
|
+
output: spec.output === undefined ? null : z.toJSONSchema(spec.output, { unrepresentable: "any" }),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function nodeData(node) {
|
|
27
|
+
return node.kind === "command" ? commandData(node) : groupData(node);
|
|
28
|
+
}
|
|
29
|
+
function groupData(group) {
|
|
30
|
+
return { name: group.commandLine, commands: Object.values(group.commands).map(nodeData) };
|
|
31
|
+
}
|
|
32
|
+
function printed(data) {
|
|
33
|
+
return `${JSON.stringify(data)}\n`;
|
|
34
|
+
}
|
|
35
|
+
export function cliHelpJson(version, root) {
|
|
36
|
+
return printed({ name: root.commandLine, version, ...nodeData(root) });
|
|
37
|
+
}
|
|
38
|
+
export function groupHelpJson(group) {
|
|
39
|
+
return printed(groupData(group));
|
|
40
|
+
}
|
|
41
|
+
export function commandHelpJson(spec) {
|
|
42
|
+
return printed(commandData(spec));
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=help-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help-json.js","sourceRoot":"","sources":["../src/help-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAMzB,6FAA6F;AAC7F,SAAS,WAAW,CAAC,MAAiB;IACpC,OAAO,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,uFAAuF;AACvF,SAAS,aAAa,CAAC,OAA8B;IACnD,OAAO,WAAW,CAChB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAChF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAiB;IACpC,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,WAAW;QACtB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACpD,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;QACpC,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;YACzE,KAAK;YACL,WAAW;YACX,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC;SAC5B,CAAC,CAAC;QACH,MAAM,EACJ,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;KAC7F,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,IAAc;IAC9B,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,SAAS,CAAC,KAAgB;IACjC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;AAC5F,CAAC;AAED,SAAS,OAAO,CAAC,IAAgB;IAC/B,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,IAAc;IACzD,OAAO,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAgB;IAC5C,OAAO,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAiB;IAC/C,OAAO,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/help.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CommandSpec, GroupSpec } from "./command-spec.js";
|
|
2
|
+
import type { Style } from "./style.js";
|
|
3
|
+
export declare function cliHelp(version: string, root: GroupSpec, style: Style): string;
|
|
4
|
+
export declare function groupHelp(group: GroupSpec, style: Style): string;
|
|
5
|
+
export declare function commandHelp(spec: CommandSpec, style: Style): string;
|
package/dist/help.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
function table(rows) {
|
|
2
|
+
const width = Math.max(...rows.map(([left]) => left.length));
|
|
3
|
+
return rows.map(([left, right]) => right === "" ? ` ${left}` : ` ${left.padEnd(width)} ${right}`);
|
|
4
|
+
}
|
|
5
|
+
function section(title, rows, style) {
|
|
6
|
+
return rows.length === 0 ? [] : ["", style.bold(`${title}:`), ...table(rows)];
|
|
7
|
+
}
|
|
8
|
+
function summaryOf(node) {
|
|
9
|
+
return node.kind === "command"
|
|
10
|
+
? node.description
|
|
11
|
+
: `group: ${Object.keys(node.commands).join(", ")}`;
|
|
12
|
+
}
|
|
13
|
+
function commandRows({ commands }) {
|
|
14
|
+
return Object.entries(commands).map(([key, node]) => [key, summaryOf(node)]);
|
|
15
|
+
}
|
|
16
|
+
function lines(...parts) {
|
|
17
|
+
return `${parts.join("\n")}\n`;
|
|
18
|
+
}
|
|
19
|
+
function listing(heading, group, style) {
|
|
20
|
+
return lines(style.bold(heading), ...section("Commands", commandRows(group), style), "", `Run \`${group.commandLine} <command> --help\` for its examples and input.`);
|
|
21
|
+
}
|
|
22
|
+
export function cliHelp(version, root, style) {
|
|
23
|
+
return listing(`${root.commandLine} ${version}`, root, style);
|
|
24
|
+
}
|
|
25
|
+
export function groupHelp(group, style) {
|
|
26
|
+
return listing(group.commandLine, group, style);
|
|
27
|
+
}
|
|
28
|
+
const EFFECT_NOTES = {
|
|
29
|
+
read: "changes nothing",
|
|
30
|
+
write: "changes something; show the Plan with --dry-run",
|
|
31
|
+
destructive: "changes something hard to undo; show the Plan with --dry-run, run with --confirm",
|
|
32
|
+
};
|
|
33
|
+
function choicesOf(field) {
|
|
34
|
+
return field.choices === undefined ? [] : [`one of: ${field.choices.join(", ")}`];
|
|
35
|
+
}
|
|
36
|
+
function defaultsOf(field) {
|
|
37
|
+
if (field.defaultValue === undefined) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
if (field.type !== "boolean") {
|
|
41
|
+
return [`default: ${JSON.stringify(field.defaultValue)}`];
|
|
42
|
+
}
|
|
43
|
+
// A `--no-` flag sits next to the description of what it turns off, so the row must say so.
|
|
44
|
+
return field.defaultValue === true ? ["on by default; this flag turns it off"] : [];
|
|
45
|
+
}
|
|
46
|
+
function fieldRow(field, notes) {
|
|
47
|
+
const all = [...(field.required ? ["required"] : []), ...notes];
|
|
48
|
+
const suffix = all.length === 0 ? "" : `(${all.join("; ")})`;
|
|
49
|
+
return [field.usage, [field.description ?? "", suffix].filter((part) => part !== "").join(" ")];
|
|
50
|
+
}
|
|
51
|
+
function argRow(field) {
|
|
52
|
+
return fieldRow(field, [...choicesOf(field), ...defaultsOf(field)]);
|
|
53
|
+
}
|
|
54
|
+
// An option's usage already shows its choices, as in `--sort <name|date>`.
|
|
55
|
+
function optionRow(field) {
|
|
56
|
+
return fieldRow(field, defaultsOf(field));
|
|
57
|
+
}
|
|
58
|
+
function flagRow({ usage, description }) {
|
|
59
|
+
return [usage, description];
|
|
60
|
+
}
|
|
61
|
+
export function commandHelp(spec, style) {
|
|
62
|
+
return lines(style.bold(spec.commandLine), spec.description, ...section("Examples", spec.examples.map(({ command, note }) => [command, note]), style), ...section("Arguments", spec.args.map(argRow), style), ...section("Options", spec.options.map(optionRow), style), "", `${style.bold("Effect:")} ${spec.effect} (${EFFECT_NOTES[spec.effect]})`, ...section("Standard flags", spec.standardFlags.map(flagRow), style));
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=help.js.map
|
package/dist/help.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { defineCli } from "./built-ins.js";
|
|
2
|
+
export type { Cli, Command, Commands, Context, DestructiveCommand, DoctorCheck, DoctorFinding, Env, Example, GlobalInstall, ListCommand, ReadCommand, WriteCommand, } from "./define.js";
|
|
3
|
+
export { defineCommand } from "./define.js";
|
|
4
|
+
export type { CliErrorDetails, UsageErrorDetails } from "./errors.js";
|
|
5
|
+
export { CliError, debugVariable, UsageError } from "./errors.js";
|
|
6
|
+
export type { Page, PageInput } from "./list.js";
|
|
7
|
+
export { paginate } from "./list.js";
|
|
8
|
+
export type { RunResult } from "./output.js";
|
|
9
|
+
export type { RunOptions } from "./run-cli.js";
|
|
10
|
+
export { runCli } from "./run-cli.js";
|
|
11
|
+
export { runProcess } from "./run-process.js";
|
|
12
|
+
export type { Style } from "./style.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { defineCli } from "./built-ins.js";
|
|
2
|
+
export { defineCommand } from "./define.js";
|
|
3
|
+
export { CliError, debugVariable, UsageError } from "./errors.js";
|
|
4
|
+
export { paginate } from "./list.js";
|
|
5
|
+
export { runCli } from "./run-cli.js";
|
|
6
|
+
export { runProcess } from "./run-process.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAgB3C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGrC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/input.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { InputSchema } from "./define.js";
|
|
3
|
+
export type ValueType = "string" | "number" | "boolean";
|
|
4
|
+
export interface InputField {
|
|
5
|
+
readonly key: string;
|
|
6
|
+
/** The name the caller sees: the key for an arg, the flag without `--` for an option. */
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly schema: z.ZodType;
|
|
9
|
+
readonly type: ValueType;
|
|
10
|
+
readonly required: boolean;
|
|
11
|
+
readonly defaultValue: unknown;
|
|
12
|
+
readonly description: string | undefined;
|
|
13
|
+
readonly choices: readonly string[] | undefined;
|
|
14
|
+
/** How the caller names it: `<name>` for an arg, `--name` or `--no-name` for an option. */
|
|
15
|
+
readonly label: string;
|
|
16
|
+
/** How the caller passes it: the label plus a value placeholder such as `<value>` or `<a|b>`. */
|
|
17
|
+
readonly usage: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function kebab(key: string): string;
|
|
20
|
+
export declare function optionField(key: string, schema: z.ZodType): InputField;
|
|
21
|
+
export declare function argFields(schema: InputSchema | undefined): InputField[];
|
|
22
|
+
export declare function optionFields(schema: InputSchema | undefined): InputField[];
|
package/dist/input.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
function isWrapper(schema) {
|
|
3
|
+
return (schema instanceof z.ZodOptional ||
|
|
4
|
+
schema instanceof z.ZodNullable ||
|
|
5
|
+
schema instanceof z.ZodDefault ||
|
|
6
|
+
schema instanceof z.ZodPrefault);
|
|
7
|
+
}
|
|
8
|
+
export function kebab(key) {
|
|
9
|
+
return key.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
10
|
+
}
|
|
11
|
+
// Any other schema gets the caller's string, for Zod to accept or reject.
|
|
12
|
+
function typeOf(schema) {
|
|
13
|
+
if (schema instanceof z.ZodNumber) {
|
|
14
|
+
return "number";
|
|
15
|
+
}
|
|
16
|
+
return schema instanceof z.ZodBoolean ? "boolean" : "string";
|
|
17
|
+
}
|
|
18
|
+
function describe(schema) {
|
|
19
|
+
let current = schema;
|
|
20
|
+
let description = current.description;
|
|
21
|
+
let required = true;
|
|
22
|
+
let defaultValue;
|
|
23
|
+
while (isWrapper(current)) {
|
|
24
|
+
if (current instanceof z.ZodDefault || current instanceof z.ZodPrefault) {
|
|
25
|
+
defaultValue = current.def.defaultValue;
|
|
26
|
+
}
|
|
27
|
+
required = false;
|
|
28
|
+
current = current.unwrap();
|
|
29
|
+
description ??= current.description;
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
type: typeOf(current),
|
|
33
|
+
required,
|
|
34
|
+
defaultValue,
|
|
35
|
+
description,
|
|
36
|
+
choices: current instanceof z.ZodEnum ? current.options.map(String) : undefined,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function argField(key, schema) {
|
|
40
|
+
const label = `<${key}>`;
|
|
41
|
+
return { key, name: key, schema, ...describe(schema), label, usage: label };
|
|
42
|
+
}
|
|
43
|
+
export function optionField(key, schema) {
|
|
44
|
+
const described = describe(schema);
|
|
45
|
+
const name = kebab(key);
|
|
46
|
+
const isBoolean = described.type === "boolean";
|
|
47
|
+
// A boolean that defaults to true can only be changed by turning it off.
|
|
48
|
+
const label = isBoolean && described.defaultValue === true ? `--no-${name}` : `--${name}`;
|
|
49
|
+
const usage = isBoolean ? label : `${label} <${described.choices?.join("|") ?? "value"}>`;
|
|
50
|
+
return { key, name, schema, ...described, label, usage };
|
|
51
|
+
}
|
|
52
|
+
function fieldsOf(schema, toField) {
|
|
53
|
+
return schema === undefined
|
|
54
|
+
? []
|
|
55
|
+
: Object.entries(schema.shape).map(([key, value]) => toField(key, value));
|
|
56
|
+
}
|
|
57
|
+
export function argFields(schema) {
|
|
58
|
+
return fieldsOf(schema, argField);
|
|
59
|
+
}
|
|
60
|
+
export function optionFields(schema) {
|
|
61
|
+
return fieldsOf(schema, optionField);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** How long an interrupted Command may take to settle before the run ends without it. */
|
|
2
|
+
export declare const GRACE_MS = 3000;
|
|
3
|
+
export declare const INTERRUPTED = "INTERRUPTED";
|
|
4
|
+
/** One Command run's cancellation: its signal, its deadlines and the steps it must finish. */
|
|
5
|
+
export declare class RunControl {
|
|
6
|
+
#private;
|
|
7
|
+
readonly signal: AbortSignal;
|
|
8
|
+
constructor(commandLine: string, outer: AbortSignal | undefined);
|
|
9
|
+
deadline(ms: number): AbortSignal;
|
|
10
|
+
runToEnd<T>(work: () => Promise<T>): Promise<T>;
|
|
11
|
+
/** Waits for the Command, its must-finish steps, and no longer than the grace once interrupted. */
|
|
12
|
+
settle<T>(work: Promise<T>): Promise<T>;
|
|
13
|
+
/**
|
|
14
|
+
* The error a run ends with: an interrupt or a missed deadline outranks what the Command threw,
|
|
15
|
+
* unless the Command threw its own `INTERRUPTED`, saying what it finished before it stopped.
|
|
16
|
+
*/
|
|
17
|
+
errorAfter(error: unknown): unknown;
|
|
18
|
+
}
|