@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/output.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { FailureWithData, formatRuntimeError, UsageError } from "./errors.js";
|
|
2
|
+
import { cliHelp, commandHelp, groupHelp } from "./help.js";
|
|
3
|
+
import { cliHelpJson, commandHelpJson, groupHelpJson } from "./help-json.js";
|
|
4
|
+
import { Page, pageFooter, printedPage, projected, renderRows } from "./list.js";
|
|
5
|
+
const SUCCESS_EXIT_CODE = 0;
|
|
6
|
+
const FAILURE_EXIT_CODE = 1;
|
|
7
|
+
const USAGE_EXIT_CODE = 2;
|
|
8
|
+
function withTrailingNewline(text) {
|
|
9
|
+
return text === "" || text.endsWith("\n") ? text : `${text}\n`;
|
|
10
|
+
}
|
|
11
|
+
function printed(value, render, { json, invocation, style, fields }) {
|
|
12
|
+
if (!(value instanceof Page)) {
|
|
13
|
+
return json ? `${JSON.stringify(value)}\n` : withTrailingNewline(render(style));
|
|
14
|
+
}
|
|
15
|
+
const page = printedPage(value, invocation);
|
|
16
|
+
if (fields === undefined) {
|
|
17
|
+
return json
|
|
18
|
+
? `${JSON.stringify(page)}\n`
|
|
19
|
+
: `${withTrailingNewline(render(style))}${pageFooter(page)}`;
|
|
20
|
+
}
|
|
21
|
+
const rows = projected(page.items, fields);
|
|
22
|
+
// The author's render may read any field, so selected rows are rendered by the Runtime.
|
|
23
|
+
return json
|
|
24
|
+
? `${JSON.stringify({ ...page, items: rows })}\n`
|
|
25
|
+
: `${renderRows(rows, fields)}${pageFooter(page)}`;
|
|
26
|
+
}
|
|
27
|
+
export function errorResult(error, format) {
|
|
28
|
+
return {
|
|
29
|
+
stdout: "",
|
|
30
|
+
stderr: formatRuntimeError(error, format),
|
|
31
|
+
exitCode: error instanceof UsageError ? USAGE_EXIT_CODE : FAILURE_EXIT_CODE,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function commandResult(settled, format) {
|
|
35
|
+
if (settled.ok) {
|
|
36
|
+
const { value, render } = settled.outcome;
|
|
37
|
+
return { stdout: printed(value, render, format), stderr: "", exitCode: SUCCESS_EXIT_CODE };
|
|
38
|
+
}
|
|
39
|
+
const { error, render } = settled;
|
|
40
|
+
const result = errorResult(error, format);
|
|
41
|
+
if (!(error instanceof FailureWithData)) {
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
const stdout = printed(error.data, (style) => render(error.data, style), format);
|
|
45
|
+
return { ...result, stdout };
|
|
46
|
+
}
|
|
47
|
+
// The root's help names the CLI and its version; a single Command is its CLI's root.
|
|
48
|
+
function helpOf(node, root, cli, style, json) {
|
|
49
|
+
if (json) {
|
|
50
|
+
if (node === root)
|
|
51
|
+
return cliHelpJson(cli.version, node);
|
|
52
|
+
return node.kind === "command" ? commandHelpJson(node) : groupHelpJson(node);
|
|
53
|
+
}
|
|
54
|
+
if (node.kind === "command")
|
|
55
|
+
return commandHelp(node, style);
|
|
56
|
+
return node === root ? cliHelp(cli.version, node, style) : groupHelp(node, style);
|
|
57
|
+
}
|
|
58
|
+
export function helpResult(node, root, cli, { style, json }) {
|
|
59
|
+
return { stdout: helpOf(node, root, cli, style, json), stderr: "", exitCode: SUCCESS_EXIT_CODE };
|
|
60
|
+
}
|
|
61
|
+
export function versionResult({ version, build }) {
|
|
62
|
+
const line = build === undefined ? version : `${version} (${build.sha}${build.dirty ? "+dirty" : ""})`;
|
|
63
|
+
return { stdout: `${line}\n`, stderr: "", exitCode: SUCCESS_EXIT_CODE };
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Invocation } from "./invocation.js";
|
|
2
|
+
import { type PageInput } from "./list.js";
|
|
3
|
+
import type { CommandRoute } from "./route.js";
|
|
4
|
+
/** The Standard flag values of one run of a Command. */
|
|
5
|
+
export interface StandardValues {
|
|
6
|
+
readonly json: boolean;
|
|
7
|
+
readonly dryRun: boolean;
|
|
8
|
+
readonly confirm: string | undefined;
|
|
9
|
+
/** The page a List Command was asked for; the default page for any other Command. */
|
|
10
|
+
readonly page: PageInput;
|
|
11
|
+
/** The row fields to print, or undefined when the caller gave no `--fields`. */
|
|
12
|
+
readonly fields: readonly string[] | undefined;
|
|
13
|
+
}
|
|
14
|
+
export interface ParsedCommand {
|
|
15
|
+
readonly input: Record<string, unknown>;
|
|
16
|
+
readonly flags: StandardValues;
|
|
17
|
+
}
|
|
18
|
+
/** The validated input and Standard flag values of the routed Command, or one usage error. */
|
|
19
|
+
export declare function parseCommand({ spec, words, json }: CommandRoute, invocation: Invocation): ParsedCommand;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { UsageError } from "./errors.js";
|
|
3
|
+
import { CONFIRM_FLAG, DRY_RUN_FLAG, HELP_FLAG, VERSION_FLAG } from "./flags.js";
|
|
4
|
+
import { commandLineRenaming } from "./invocation.js";
|
|
5
|
+
import { PAGE_INPUT, selectedFields } from "./list.js";
|
|
6
|
+
import { closestFlag } from "./suggest.js";
|
|
7
|
+
import { tokenize } from "./tokenize.js";
|
|
8
|
+
import { invalidInputError, unknownOptionError } from "./usage.js";
|
|
9
|
+
const NO_INPUT = z.object({});
|
|
10
|
+
function knownFlags(spec) {
|
|
11
|
+
return [
|
|
12
|
+
...spec.options.map((field) => ({
|
|
13
|
+
flag: field.label,
|
|
14
|
+
takes: field.type === "boolean" ? "nothing" : "optional value",
|
|
15
|
+
})),
|
|
16
|
+
...spec.standardFlags.map(({ flag, takes }) => ({ flag, takes })),
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
function candidateFlags(known) {
|
|
20
|
+
return [...known.map(({ flag }) => flag), VERSION_FLAG, HELP_FLAG];
|
|
21
|
+
}
|
|
22
|
+
function unknownOptionsOf(words, candidates) {
|
|
23
|
+
return words.map((word) => {
|
|
24
|
+
const flag = word.split("=")[0] ?? word;
|
|
25
|
+
return { flag, suggestion: closestFlag(flag, candidates) };
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
// A `--no-` switch turns its option off.
|
|
29
|
+
function optionValue(field, raw) {
|
|
30
|
+
return field.type === "boolean" && raw === true && field.label === `--no-${field.name}`
|
|
31
|
+
? false
|
|
32
|
+
: raw;
|
|
33
|
+
}
|
|
34
|
+
// Strings that read as numbers are converted so authors can write `z.number()`; anything else
|
|
35
|
+
// stays a string for Zod to reject with the caller's own value.
|
|
36
|
+
function converted(field, raw) {
|
|
37
|
+
if (field.type !== "number" || typeof raw !== "string" || raw.trim() === "") {
|
|
38
|
+
return raw;
|
|
39
|
+
}
|
|
40
|
+
const number = Number(raw);
|
|
41
|
+
return Number.isNaN(number) ? raw : number;
|
|
42
|
+
}
|
|
43
|
+
function parse(schema, values) {
|
|
44
|
+
const input = Object.fromEntries([...values]
|
|
45
|
+
.filter(([, raw]) => raw !== undefined)
|
|
46
|
+
.map(([field, raw]) => [field.key, converted(field, raw)]));
|
|
47
|
+
return schema.safeParse(input);
|
|
48
|
+
}
|
|
49
|
+
function issueLines(result, values, howToPass, reported) {
|
|
50
|
+
if (result.success) {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
return result.error.issues.flatMap((issue) => {
|
|
54
|
+
const field = [...values.keys()].find((candidate) => candidate.key === issue.path[0]);
|
|
55
|
+
if (field === undefined) {
|
|
56
|
+
return [` ${issue.message}`];
|
|
57
|
+
}
|
|
58
|
+
if (reported.includes(field)) {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
const raw = values.get(field);
|
|
62
|
+
return raw === undefined
|
|
63
|
+
? [` ${field.label}: required, ${howToPass(field)}`]
|
|
64
|
+
: [` ${field.label} ${JSON.stringify(raw)}: ${issue.message}`];
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function unknownLine({ flag, suggestion }) {
|
|
68
|
+
return ` unknown option '${flag}'${suggestion === undefined ? "" : ` (did you mean ${suggestion}?)`}`;
|
|
69
|
+
}
|
|
70
|
+
function invalidInput(commandLine, invocation, unknown, otherLines) {
|
|
71
|
+
const renames = new Map(unknown.flatMap(({ flag, suggestion }) => suggestion === undefined ? [] : [[flag, suggestion]]));
|
|
72
|
+
const correctable = otherLines.length === 0 && renames.size === unknown.length;
|
|
73
|
+
return new UsageError({
|
|
74
|
+
code: "INVALID_INPUT",
|
|
75
|
+
message: [
|
|
76
|
+
`invalid input for \`${commandLine}\``,
|
|
77
|
+
...unknown.map(unknownLine),
|
|
78
|
+
...otherLines,
|
|
79
|
+
].join("\n"),
|
|
80
|
+
hint: correctable
|
|
81
|
+
? `did you mean \`${commandLineRenaming(invocation, renames)}\`?`
|
|
82
|
+
: `run \`${commandLine} --help\` to see the expected input`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
function parseInput(spec, words, invocation) {
|
|
86
|
+
const { command, args: argFields, options: optionFields } = spec;
|
|
87
|
+
const pageFields = spec.list?.pageFields ?? [];
|
|
88
|
+
const known = knownFlags(spec);
|
|
89
|
+
const { operands, unknownOptions, values } = tokenize(words, known);
|
|
90
|
+
if (values.get(CONFIRM_FLAG.flag) === true) {
|
|
91
|
+
throw invalidInputError(spec.commandLine, `option '${CONFIRM_FLAG.usage}' argument missing`);
|
|
92
|
+
}
|
|
93
|
+
// A value option given without a value is collected as `true`.
|
|
94
|
+
const missing = [...optionFields, ...pageFields].filter((field) => field.type !== "boolean" && values.get(field.label) === true);
|
|
95
|
+
const argValues = new Map(argFields.map((field, index) => [field, operands[index]?.value]));
|
|
96
|
+
const valuesOf = (fields) => new Map(fields.map((field) => [
|
|
97
|
+
field,
|
|
98
|
+
missing.includes(field) ? undefined : optionValue(field, values.get(field.label)),
|
|
99
|
+
]));
|
|
100
|
+
const optionValues = valuesOf(optionFields);
|
|
101
|
+
const pageValues = valuesOf(pageFields);
|
|
102
|
+
const args = parse(command.args ?? NO_INPUT, argValues);
|
|
103
|
+
const options = parse(command.options ?? NO_INPUT, optionValues);
|
|
104
|
+
const page = parse(PAGE_INPUT, pageValues);
|
|
105
|
+
const unknown = unknownOptionsOf(unknownOptions, candidateFlags(known));
|
|
106
|
+
const otherLines = [
|
|
107
|
+
...missing.map((field) => ` ${field.label}: missing value, pass ${field.usage}`),
|
|
108
|
+
...operands
|
|
109
|
+
.slice(argFields.length)
|
|
110
|
+
// A word right after an unknown flag may be its value, so it isn't an extra arg.
|
|
111
|
+
.filter((operand) => !operand.afterUnknownOption)
|
|
112
|
+
.map((operand) => ` unexpected argument ${JSON.stringify(operand.value)}`),
|
|
113
|
+
...issueLines(args, argValues, (field) => `pass it as argument ${argFields.indexOf(field) + 1}`, []),
|
|
114
|
+
...issueLines(options, optionValues, (field) => `pass ${field.usage}`, missing),
|
|
115
|
+
...issueLines(page, pageValues, (field) => `pass ${field.usage}`, missing),
|
|
116
|
+
];
|
|
117
|
+
if (unknown.length === 0 &&
|
|
118
|
+
otherLines.length === 0 &&
|
|
119
|
+
args.success &&
|
|
120
|
+
options.success &&
|
|
121
|
+
page.success) {
|
|
122
|
+
return { input: { ...args.data, ...options.data }, page: page.data, values };
|
|
123
|
+
}
|
|
124
|
+
const [only] = unknown;
|
|
125
|
+
if (only !== undefined && unknown.length === 1 && otherLines.length === 0) {
|
|
126
|
+
throw unknownOptionError(spec.commandLine, invocation, only.flag, only.suggestion === undefined ? [] : [only.suggestion]);
|
|
127
|
+
}
|
|
128
|
+
throw invalidInput(spec.commandLine, invocation, unknown, otherLines);
|
|
129
|
+
}
|
|
130
|
+
/** The validated input and Standard flag values of the routed Command, or one usage error. */
|
|
131
|
+
export function parseCommand({ spec, words, json }, invocation) {
|
|
132
|
+
const { input, page, values } = parseInput(spec, words, invocation);
|
|
133
|
+
const confirm = values.get(CONFIRM_FLAG.flag);
|
|
134
|
+
return {
|
|
135
|
+
input,
|
|
136
|
+
flags: {
|
|
137
|
+
json,
|
|
138
|
+
dryRun: values.get(DRY_RUN_FLAG.flag) === true,
|
|
139
|
+
confirm: typeof confirm === "string" ? confirm : undefined,
|
|
140
|
+
page,
|
|
141
|
+
fields: spec.list === undefined
|
|
142
|
+
? undefined
|
|
143
|
+
: selectedFields(values, spec.list.rowFields, spec.commandLine),
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=parse-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-input.js","sourceRoot":"","sources":["../src/parse-input.ts"],"names":[],"mappings":"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"}
|
package/dist/route.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { CommandSpec, SpecNode } from "./command-spec.js";
|
|
2
|
+
import type { UsageError } from "./errors.js";
|
|
3
|
+
import { type Invocation } from "./invocation.js";
|
|
4
|
+
/** Where the command line leads; `json` is set when the caller passed `--json` before any `--`. */
|
|
5
|
+
export type Route = {
|
|
6
|
+
readonly kind: "version";
|
|
7
|
+
readonly json: boolean;
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: "help";
|
|
10
|
+
readonly node: SpecNode;
|
|
11
|
+
readonly json: boolean;
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "usage error";
|
|
14
|
+
readonly error: UsageError;
|
|
15
|
+
readonly json: boolean;
|
|
16
|
+
} | CommandRoute;
|
|
17
|
+
export interface CommandRoute {
|
|
18
|
+
readonly kind: "command";
|
|
19
|
+
readonly spec: CommandSpec;
|
|
20
|
+
/** The words after the Command's name, without `--json`. */
|
|
21
|
+
readonly words: readonly string[];
|
|
22
|
+
readonly json: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** Walks the caller's command line through the Commands to the one it names, or to a stop. */
|
|
25
|
+
export declare function route(root: SpecNode, invocation: Invocation): Route;
|
package/dist/route.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { HELP_FLAG, HELP_SHORT, JSON_FLAG, VERSION_FLAG } from "./flags.js";
|
|
2
|
+
import { END_OF_OPTIONS } from "./invocation.js";
|
|
3
|
+
import { closestFlags, closestNames } from "./suggest.js";
|
|
4
|
+
import { unknownCommandError, unknownOptionError } from "./usage.js";
|
|
5
|
+
// The flags a group accepts: `--json` and `--version` count anywhere before `--`.
|
|
6
|
+
const GROUP_FLAGS = [HELP_FLAG, VERSION_FLAG, JSON_FLAG.flag];
|
|
7
|
+
function beforeEnd(words) {
|
|
8
|
+
const end = words.indexOf(END_OF_OPTIONS);
|
|
9
|
+
return end === -1 ? words : words.slice(0, end);
|
|
10
|
+
}
|
|
11
|
+
function wantsHelp(words) {
|
|
12
|
+
return beforeEnd(words).some((word) => word === HELP_FLAG || word === HELP_SHORT);
|
|
13
|
+
}
|
|
14
|
+
function childOf(group, name) {
|
|
15
|
+
return Object.hasOwn(group.commands, name) ? group.commands[name] : undefined;
|
|
16
|
+
}
|
|
17
|
+
// At a group a negative number is an option too: no group takes an operand.
|
|
18
|
+
function isFlagLike(word) {
|
|
19
|
+
return word.length > 1 && word[0] === "-";
|
|
20
|
+
}
|
|
21
|
+
function walk(node, words, json, invocation) {
|
|
22
|
+
const help = { kind: "help", node, json };
|
|
23
|
+
if (node.kind === "command") {
|
|
24
|
+
return wantsHelp(words) ? help : { kind: "command", spec: node, words, json };
|
|
25
|
+
}
|
|
26
|
+
const [first, ...rest] = words;
|
|
27
|
+
if (first === undefined) {
|
|
28
|
+
return help;
|
|
29
|
+
}
|
|
30
|
+
const child = childOf(node, first);
|
|
31
|
+
if (child !== undefined) {
|
|
32
|
+
return walk(child, rest, json, invocation);
|
|
33
|
+
}
|
|
34
|
+
// After `--` every word is an operand, the next Command's name included.
|
|
35
|
+
if (first === END_OF_OPTIONS) {
|
|
36
|
+
const [name, ...after] = rest;
|
|
37
|
+
if (name === undefined) {
|
|
38
|
+
return help;
|
|
39
|
+
}
|
|
40
|
+
const named = childOf(node, name);
|
|
41
|
+
if (named !== undefined) {
|
|
42
|
+
return walk(named, [END_OF_OPTIONS, ...after], json, invocation);
|
|
43
|
+
}
|
|
44
|
+
return unknownCommand(node, name, json);
|
|
45
|
+
}
|
|
46
|
+
if (wantsHelp(words)) {
|
|
47
|
+
return help;
|
|
48
|
+
}
|
|
49
|
+
if (isFlagLike(first)) {
|
|
50
|
+
const suggestions = closestFlags(first, GROUP_FLAGS);
|
|
51
|
+
const error = unknownOptionError(node.commandLine, invocation, first, suggestions);
|
|
52
|
+
return { kind: "usage error", error, json };
|
|
53
|
+
}
|
|
54
|
+
return unknownCommand(node, first, json);
|
|
55
|
+
}
|
|
56
|
+
function unknownCommand(group, name, json) {
|
|
57
|
+
const suggestions = closestNames(name, Object.keys(group.commands));
|
|
58
|
+
return {
|
|
59
|
+
kind: "usage error",
|
|
60
|
+
error: unknownCommandError(group.commandLine, name, suggestions),
|
|
61
|
+
json,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Walks the caller's command line through the Commands to the one it names, or to a stop. */
|
|
65
|
+
export function route(root, invocation) {
|
|
66
|
+
const { argv } = invocation;
|
|
67
|
+
const options = beforeEnd(argv);
|
|
68
|
+
const json = options.includes(JSON_FLAG.flag);
|
|
69
|
+
if (options.includes(VERSION_FLAG)) {
|
|
70
|
+
return { kind: "version", json };
|
|
71
|
+
}
|
|
72
|
+
const words = argv.filter((word, index) => !(index < options.length && word === JSON_FLAG.flag));
|
|
73
|
+
return walk(root, words, json, invocation);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAmB,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErE,kFAAkF;AAClF,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;AAiB9D,SAAS,SAAS,CAAC,KAAwB;IACzC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,SAAS,CAAC,KAAwB;IACzC,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,UAAU,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,OAAO,CAAC,KAAgB,EAAE,IAAY;IAC7C,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAChF,CAAC;AAED,4EAA4E;AAC5E,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;AAC5C,CAAC;AAED,SAAS,IAAI,CACX,IAAc,EACd,KAAwB,EACxB,IAAa,EACb,UAAsB;IAEtB,MAAM,IAAI,GAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAChF,CAAC;IACD,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC;IAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7C,CAAC;IACD,yEAAyE;IACzE,IAAI,KAAK,KAAK,cAAc,EAAE,CAAC;QAC7B,MAAM,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC;QAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,cAAc,EAAE,GAAG,KAAK,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;QACnF,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,cAAc,CAAC,KAAgB,EAAE,IAAY,EAAE,IAAa;IACnE,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpE,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,mBAAmB,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,WAAW,CAAC;QAChE,IAAI;KACL,CAAC;AACJ,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,KAAK,CAAC,IAAc,EAAE,UAAsB;IAC1D,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC;IAC5B,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACjG,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Cli, Env } from "./define.js";
|
|
2
|
+
import { type RunResult } from "./output.js";
|
|
3
|
+
export interface RunOptions {
|
|
4
|
+
readonly env: Env;
|
|
5
|
+
readonly cwd: string;
|
|
6
|
+
readonly stdoutIsTTY?: boolean;
|
|
7
|
+
/** Aborting it interrupts the running Command, which then ends with `INTERRUPTED`. */
|
|
8
|
+
readonly signal?: AbortSignal;
|
|
9
|
+
/**
|
|
10
|
+
* The script that started the CLI, as `process.argv[1]`; `doctor` checks it is inside npm's
|
|
11
|
+
* global install. Absent, the CLI counts as run from source.
|
|
12
|
+
*/
|
|
13
|
+
readonly bin?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function runCli(cli: Cli, argv: readonly string[], options: RunOptions): Promise<RunResult>;
|
|
16
|
+
export declare function runWithProgress(cli: Cli, argv: readonly string[], options: RunOptions, writeProgress: (line: string) => void): Promise<RunResult>;
|
package/dist/run-cli.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { builtInCommands } from "./built-ins.js";
|
|
2
|
+
import { commandSpec, groupSpec } from "./command-spec.js";
|
|
3
|
+
import { execute, renderOf } from "./execute.js";
|
|
4
|
+
import { RunControl } from "./interrupts.js";
|
|
5
|
+
import { commandResult, errorResult, helpResult, versionResult, } from "./output.js";
|
|
6
|
+
import { parseCommand } from "./parse-input.js";
|
|
7
|
+
import { route } from "./route.js";
|
|
8
|
+
import { styleFor } from "./style.js";
|
|
9
|
+
async function runCommand(routed, { base, signal, format: baseFormat }) {
|
|
10
|
+
const { command, commandLine } = routed.spec;
|
|
11
|
+
const format = { ...baseFormat, json: routed.json };
|
|
12
|
+
const { invocation } = format;
|
|
13
|
+
let parsed;
|
|
14
|
+
try {
|
|
15
|
+
parsed = parseCommand(routed, invocation);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return errorResult(error, format);
|
|
19
|
+
}
|
|
20
|
+
const { input, flags } = parsed;
|
|
21
|
+
const control = new RunControl(commandLine, signal);
|
|
22
|
+
const ctx = {
|
|
23
|
+
...base,
|
|
24
|
+
signal: control.signal,
|
|
25
|
+
deadline: (ms) => control.deadline(ms),
|
|
26
|
+
runToEnd: (work) => control.runToEnd(work),
|
|
27
|
+
};
|
|
28
|
+
let settled;
|
|
29
|
+
try {
|
|
30
|
+
const outcome = await control.settle(execute(command, input, ctx, {
|
|
31
|
+
dryRun: flags.dryRun,
|
|
32
|
+
confirm: flags.confirm,
|
|
33
|
+
page: flags.page,
|
|
34
|
+
invocation,
|
|
35
|
+
commandLine,
|
|
36
|
+
}));
|
|
37
|
+
settled = { ok: true, outcome };
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
settled = {
|
|
41
|
+
ok: false,
|
|
42
|
+
error: control.errorAfter(error),
|
|
43
|
+
render: renderOf(command),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return commandResult(settled, { ...format, fields: flags.fields });
|
|
47
|
+
}
|
|
48
|
+
export async function runCli(cli, argv, options) {
|
|
49
|
+
const progress = [];
|
|
50
|
+
const result = await runWithProgress(cli, argv, options, (line) => progress.push(line));
|
|
51
|
+
return { ...result, stderr: progress.join("") + result.stderr };
|
|
52
|
+
}
|
|
53
|
+
// Progress is written as it happens: an Agent harness kills a process that stays silent too long.
|
|
54
|
+
export async function runWithProgress(cli, argv, options, writeProgress) {
|
|
55
|
+
const format = {
|
|
56
|
+
cliName: cli.name,
|
|
57
|
+
env: options.env,
|
|
58
|
+
style: styleFor(options.env, options.stdoutIsTTY === true),
|
|
59
|
+
invocation: { cliName: cli.name, argv },
|
|
60
|
+
json: false,
|
|
61
|
+
};
|
|
62
|
+
const root = cli.commands === undefined
|
|
63
|
+
? commandSpec(cli.name, cli.command)
|
|
64
|
+
: groupSpec(cli.name, { ...cli.commands, ...builtInCommands(cli, options.bin) });
|
|
65
|
+
const routed = route(root, format.invocation);
|
|
66
|
+
switch (routed.kind) {
|
|
67
|
+
case "version":
|
|
68
|
+
return versionResult(cli);
|
|
69
|
+
case "help":
|
|
70
|
+
return helpResult(routed.node, root, cli, { ...format, json: routed.json });
|
|
71
|
+
case "usage error":
|
|
72
|
+
return errorResult(routed.error, { ...format, json: routed.json });
|
|
73
|
+
case "command":
|
|
74
|
+
return runCommand(routed, {
|
|
75
|
+
base: {
|
|
76
|
+
cwd: options.cwd,
|
|
77
|
+
env: options.env,
|
|
78
|
+
progress: (message) => writeProgress(`${message}\n`),
|
|
79
|
+
},
|
|
80
|
+
signal: options.signal,
|
|
81
|
+
format,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=run-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-cli.js","sourceRoot":"","sources":["../src/run-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { runWithProgress } from "./run-cli.js";
|
|
2
|
+
const SIGNAL_EXIT_CODES = { SIGINT: 130, SIGTERM: 143 };
|
|
3
|
+
function written(stream, text) {
|
|
4
|
+
return new Promise((resolve) => stream.write(text, () => resolve()));
|
|
5
|
+
}
|
|
6
|
+
export async function runProcess(cli) {
|
|
7
|
+
const stop = new AbortController();
|
|
8
|
+
// A second signal quits at once, accepting lost output, so a stuck Command never traps a person.
|
|
9
|
+
const onSignal = (signal) => {
|
|
10
|
+
if (stop.signal.aborted) {
|
|
11
|
+
process.exit(SIGNAL_EXIT_CODES[signal]);
|
|
12
|
+
}
|
|
13
|
+
process.stderr.write("\nstopping… (Ctrl-C again to quit now)\n");
|
|
14
|
+
stop.abort();
|
|
15
|
+
};
|
|
16
|
+
process.on("SIGINT", onSignal);
|
|
17
|
+
process.on("SIGTERM", onSignal);
|
|
18
|
+
try {
|
|
19
|
+
const result = await runWithProgress(cli, process.argv.slice(2), {
|
|
20
|
+
env: process.env,
|
|
21
|
+
cwd: process.cwd(),
|
|
22
|
+
stdoutIsTTY: process.stdout.isTTY === true,
|
|
23
|
+
signal: stop.signal,
|
|
24
|
+
bin: process.argv[1],
|
|
25
|
+
}, (line) => process.stderr.write(line));
|
|
26
|
+
await written(process.stdout, result.stdout);
|
|
27
|
+
await written(process.stderr, result.stderr);
|
|
28
|
+
process.exitCode = result.exitCode;
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
process.off("SIGINT", onSignal);
|
|
32
|
+
process.off("SIGTERM", onSignal);
|
|
33
|
+
}
|
|
34
|
+
// A Command may leave a timer or socket holding the event loop open; its output is written by now.
|
|
35
|
+
process.exit();
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=run-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-process.js","sourceRoot":"","sources":["../src/run-process.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,iBAAiB,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAW,CAAC;AAIjE,SAAS,OAAO,CAAC,MAA0B,EAAE,IAAY;IACvD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAQ;IACvC,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;IACnC,iGAAiG;IACjG,MAAM,QAAQ,GAAG,CAAC,MAAkB,EAAQ,EAAE;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACjE,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAClC,GAAG,EACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EACrB;YACE,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI;YAC1C,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;SACrB,EACD,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CACrC,CAAC;QACF,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7C,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACrC,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IACD,mGAAmG;IACnG,OAAO,CAAC,IAAI,EAAE,CAAC;AACjB,CAAC"}
|
package/dist/semver.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function isVersion(text: string): boolean;
|
|
2
|
+
/** Negative when `a` is older than `b`, positive when newer, 0 when the same release. */
|
|
3
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
4
|
+
export type Standing = "behind" | "current" | "ahead";
|
|
5
|
+
/** Where `version` stands against `latest`. */
|
|
6
|
+
export declare function standingOf(version: string, latest: string): Standing;
|
|
7
|
+
/** The minimum an `engines.node` range asks for, or undefined when it is not `>=X[.Y[.Z]]`. */
|
|
8
|
+
export declare function engineMinimum(range: string): readonly number[] | undefined;
|
|
9
|
+
export declare function meetsMinimum(version: string, minimum: readonly number[]): boolean;
|
package/dist/semver.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const VERSION = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
2
|
+
const ENGINE = /^>=\s*(\d+)(?:\.(\d+))?(?:\.(\d+))?$/;
|
|
3
|
+
export function isVersion(text) {
|
|
4
|
+
return VERSION.test(text);
|
|
5
|
+
}
|
|
6
|
+
// Numeric identifiers compare as numbers and rank below alphanumeric ones.
|
|
7
|
+
function compareIdentifiers(x, y) {
|
|
8
|
+
const xNumeric = /^\d+$/.test(x);
|
|
9
|
+
const yNumeric = /^\d+$/.test(y);
|
|
10
|
+
if (xNumeric && yNumeric)
|
|
11
|
+
return Number(x) - Number(y);
|
|
12
|
+
if (xNumeric !== yNumeric)
|
|
13
|
+
return xNumeric ? -1 : 1;
|
|
14
|
+
if (x === y)
|
|
15
|
+
return 0;
|
|
16
|
+
return x < y ? -1 : 1;
|
|
17
|
+
}
|
|
18
|
+
function comparePrerelease(a, b) {
|
|
19
|
+
if (a === b)
|
|
20
|
+
return 0;
|
|
21
|
+
// A release outranks its prereleases: 1.0.0 > 1.0.0-rc.1.
|
|
22
|
+
if (a === undefined)
|
|
23
|
+
return 1;
|
|
24
|
+
if (b === undefined)
|
|
25
|
+
return -1;
|
|
26
|
+
const left = a.split(".");
|
|
27
|
+
const right = b.split(".");
|
|
28
|
+
for (let i = 0; i < Math.min(left.length, right.length); i += 1) {
|
|
29
|
+
const difference = compareIdentifiers(left[i] ?? "", right[i] ?? "");
|
|
30
|
+
if (difference !== 0)
|
|
31
|
+
return difference;
|
|
32
|
+
}
|
|
33
|
+
return left.length - right.length;
|
|
34
|
+
}
|
|
35
|
+
/** Negative when `a` is older than `b`, positive when newer, 0 when the same release. */
|
|
36
|
+
export function compareVersions(a, b) {
|
|
37
|
+
const left = VERSION.exec(a);
|
|
38
|
+
const right = VERSION.exec(b);
|
|
39
|
+
if (left === null || right === null) {
|
|
40
|
+
throw new Error(`cannot compare ${a} with ${b}: both must be X.Y.Z versions`);
|
|
41
|
+
}
|
|
42
|
+
for (const part of [1, 2, 3]) {
|
|
43
|
+
const difference = Number(left[part]) - Number(right[part]);
|
|
44
|
+
if (difference !== 0)
|
|
45
|
+
return difference;
|
|
46
|
+
}
|
|
47
|
+
return comparePrerelease(left[4], right[4]);
|
|
48
|
+
}
|
|
49
|
+
/** Where `version` stands against `latest`. */
|
|
50
|
+
export function standingOf(version, latest) {
|
|
51
|
+
const difference = compareVersions(version, latest);
|
|
52
|
+
if (difference < 0)
|
|
53
|
+
return "behind";
|
|
54
|
+
return difference > 0 ? "ahead" : "current";
|
|
55
|
+
}
|
|
56
|
+
/** The minimum an `engines.node` range asks for, or undefined when it is not `>=X[.Y[.Z]]`. */
|
|
57
|
+
export function engineMinimum(range) {
|
|
58
|
+
const match = ENGINE.exec(range.trim());
|
|
59
|
+
return match === null ? undefined : match.slice(1).map((part) => Number(part ?? 0));
|
|
60
|
+
}
|
|
61
|
+
export function meetsMinimum(version, minimum) {
|
|
62
|
+
const parts = version.split(".").map(Number);
|
|
63
|
+
for (const [i, wanted] of minimum.entries()) {
|
|
64
|
+
const found = parts[i] ?? 0;
|
|
65
|
+
if (found !== wanted)
|
|
66
|
+
return found > wanted;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=semver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semver.js","sourceRoot":"","sources":["../src/semver.ts"],"names":[],"mappings":"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"}
|
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Env } from "./define.js";
|
|
2
|
+
import { type Standing } from "./semver.js";
|
|
3
|
+
export declare function skillUpdateCommand(cliName: string): string;
|
|
4
|
+
export type SkillState = Standing | "unversioned" | "unreadable";
|
|
5
|
+
export interface SkillCopy {
|
|
6
|
+
readonly path: string;
|
|
7
|
+
readonly version: string | undefined;
|
|
8
|
+
readonly state: SkillState;
|
|
9
|
+
}
|
|
10
|
+
/** Every installed copy of the skill named after the CLI, in the project first, then under home. */
|
|
11
|
+
export declare function skillCopies(skillName: string, cliVersion: string, cwd: string, env: Env): Promise<SkillCopy[]>;
|