@duyquangnvx/agent-cli 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +11 -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 +0 -1
- package/dist/confirm.js +4 -4
- package/dist/confirm.js.map +1 -1
- package/dist/define.d.ts +30 -6
- package/dist/define.js +2 -0
- package/dist/define.js.map +1 -1
- package/dist/execute.d.ts +12 -3
- package/dist/execute.js +10 -2
- package/dist/execute.js.map +1 -1
- package/dist/flags.d.ts +44 -6
- package/dist/flags.js +53 -16
- package/dist/flags.js.map +1 -1
- package/dist/global-install.d.ts +2 -0
- package/dist/global-install.js +5 -4
- package/dist/global-install.js.map +1 -1
- package/dist/help-json.d.ts +4 -4
- package/dist/help-json.js +26 -42
- package/dist/help-json.js.map +1 -1
- package/dist/help.d.ts +4 -5
- package/dist/help.js +15 -12
- package/dist/help.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/input.d.ts +8 -8
- package/dist/input.js +9 -16
- package/dist/input.js.map +1 -1
- package/dist/list.d.ts +44 -0
- package/dist/list.js +126 -0
- package/dist/list.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 +18 -4
- package/dist/parse-input.js +82 -49
- package/dist/parse-input.js.map +1 -1
- 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 +2 -6
- package/dist/run-cli.js +53 -179
- package/dist/run-cli.js.map +1 -1
- package/dist/suggest.d.ts +4 -0
- package/dist/suggest.js +19 -11
- package/dist/suggest.js.map +1 -1
- package/dist/tokenize.d.ts +20 -0
- package/dist/tokenize.js +79 -0
- package/dist/tokenize.js.map +1 -0
- package/dist/usage.d.ts +3 -11
- package/dist/usage.js +20 -55
- package/dist/usage.js.map +1 -1
- package/package.json +1 -4
- package/dist/fields.d.ts +0 -14
- package/dist/fields.js +0 -71
- package/dist/fields.js.map +0 -1
- package/dist/page.d.ts +0 -26
- package/dist/page.js +0 -49
- package/dist/page.js.map +0 -1
package/dist/parse-input.js
CHANGED
|
@@ -1,39 +1,36 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
import { UsageError } from "./errors.js";
|
|
3
|
-
import {
|
|
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";
|
|
4
6
|
import { closestFlag } from "./suggest.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
function
|
|
9
|
-
return
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const head = tokens.slice(0, split);
|
|
17
|
-
const parsed = end !== -1 && head.at(-1) === END_OF_OPTIONS ? head.slice(0, -1) : head;
|
|
18
|
-
const literal = tokens.slice(split).map((value) => ({ value, afterUnknownOption: false }));
|
|
19
|
-
return {
|
|
20
|
-
operands: [
|
|
21
|
-
...parsed.flatMap((value, index) => isOptionLike(value) ? [] : [{ value, afterUnknownOption: isOptionLike(parsed[index - 1]) }]),
|
|
22
|
-
...literal,
|
|
23
|
-
],
|
|
24
|
-
unknownOptions: parsed.filter(isOptionLike),
|
|
25
|
-
};
|
|
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
|
+
];
|
|
26
18
|
}
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
return cmd.parent === null ? [...own, HELP_FLAG] : [...own, ...flagsOf(cmd.parent)];
|
|
19
|
+
function candidateFlags(known) {
|
|
20
|
+
return [...known.map(({ flag }) => flag), VERSION_FLAG, HELP_FLAG];
|
|
30
21
|
}
|
|
31
|
-
function unknownOptionsOf(
|
|
32
|
-
return
|
|
33
|
-
const flag =
|
|
34
|
-
return { flag, suggestion: closestFlag(flag,
|
|
22
|
+
function unknownOptionsOf(words, candidates) {
|
|
23
|
+
return words.map((word) => {
|
|
24
|
+
const flag = word.split("=")[0] ?? word;
|
|
25
|
+
return { flag, suggestion: closestFlag(flag, candidates) };
|
|
35
26
|
});
|
|
36
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
|
+
}
|
|
37
34
|
// Strings that read as numbers are converted so authors can write `z.number()`; anything else
|
|
38
35
|
// stays a string for Zod to reject with the caller's own value.
|
|
39
36
|
function converted(field, raw) {
|
|
@@ -47,7 +44,7 @@ function parse(schema, values) {
|
|
|
47
44
|
const input = Object.fromEntries([...values]
|
|
48
45
|
.filter(([, raw]) => raw !== undefined)
|
|
49
46
|
.map(([field, raw]) => [field.key, converted(field, raw)]));
|
|
50
|
-
return
|
|
47
|
+
return schema.safeParse(input);
|
|
51
48
|
}
|
|
52
49
|
function issueLines(result, values, howToPass, reported) {
|
|
53
50
|
if (result.success) {
|
|
@@ -70,45 +67,81 @@ function issueLines(result, values, howToPass, reported) {
|
|
|
70
67
|
function unknownLine({ flag, suggestion }) {
|
|
71
68
|
return ` unknown option '${flag}'${suggestion === undefined ? "" : ` (did you mean ${suggestion}?)`}`;
|
|
72
69
|
}
|
|
73
|
-
function invalidInput(
|
|
70
|
+
function invalidInput(commandLine, invocation, unknown, otherLines) {
|
|
74
71
|
const renames = new Map(unknown.flatMap(({ flag, suggestion }) => suggestion === undefined ? [] : [[flag, suggestion]]));
|
|
75
72
|
const correctable = otherLines.length === 0 && renames.size === unknown.length;
|
|
76
73
|
return new UsageError({
|
|
77
74
|
code: "INVALID_INPUT",
|
|
78
|
-
message: [
|
|
75
|
+
message: [
|
|
76
|
+
`invalid input for \`${commandLine}\``,
|
|
77
|
+
...unknown.map(unknownLine),
|
|
78
|
+
...otherLines,
|
|
79
|
+
].join("\n"),
|
|
79
80
|
hint: correctable
|
|
80
81
|
? `did you mean \`${commandLineRenaming(invocation, renames)}\`?`
|
|
81
|
-
: `run \`${
|
|
82
|
+
: `run \`${commandLine} --help\` to see the expected input`,
|
|
82
83
|
});
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
-
const {
|
|
86
|
-
const
|
|
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
|
+
}
|
|
87
93
|
// A value option given without a value is collected as `true`.
|
|
88
|
-
const missing =
|
|
89
|
-
const argValues = new Map(
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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));
|
|
94
106
|
const otherLines = [
|
|
95
107
|
...missing.map((field) => ` ${field.label}: missing value, pass ${field.usage}`),
|
|
96
108
|
...operands
|
|
97
|
-
.slice(
|
|
109
|
+
.slice(argFields.length)
|
|
98
110
|
// A word right after an unknown flag may be its value, so it isn't an extra arg.
|
|
99
111
|
.filter((operand) => !operand.afterUnknownOption)
|
|
100
112
|
.map((operand) => ` unexpected argument ${JSON.stringify(operand.value)}`),
|
|
101
|
-
...issueLines(args, argValues, (field) => `pass it as argument ${
|
|
113
|
+
...issueLines(args, argValues, (field) => `pass it as argument ${argFields.indexOf(field) + 1}`, []),
|
|
102
114
|
...issueLines(options, optionValues, (field) => `pass ${field.usage}`, missing),
|
|
115
|
+
...issueLines(page, pageValues, (field) => `pass ${field.usage}`, missing),
|
|
103
116
|
];
|
|
104
|
-
if (unknown.length === 0 &&
|
|
105
|
-
|
|
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 };
|
|
106
123
|
}
|
|
107
|
-
const line = commandLine(sub);
|
|
108
124
|
const [only] = unknown;
|
|
109
125
|
if (only !== undefined && unknown.length === 1 && otherLines.length === 0) {
|
|
110
|
-
throw unknownOptionError(
|
|
126
|
+
throw unknownOptionError(spec.commandLine, invocation, only.flag, only.suggestion === undefined ? [] : [only.suggestion]);
|
|
111
127
|
}
|
|
112
|
-
throw invalidInput(
|
|
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
|
+
};
|
|
113
146
|
}
|
|
114
147
|
//# sourceMappingURL=parse-input.js.map
|
package/dist/parse-input.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-input.js","sourceRoot":"","sources":["../src/parse-input.ts"],"names":[],"mappings":"
|
|
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":"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"}
|
package/dist/run-cli.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Cli, Env } from "./define.js";
|
|
2
|
+
import { type RunResult } from "./output.js";
|
|
2
3
|
export interface RunOptions {
|
|
3
4
|
readonly env: Env;
|
|
4
5
|
readonly cwd: string;
|
|
@@ -11,10 +12,5 @@ export interface RunOptions {
|
|
|
11
12
|
*/
|
|
12
13
|
readonly bin?: string;
|
|
13
14
|
}
|
|
14
|
-
export interface RunResult {
|
|
15
|
-
readonly stdout: string;
|
|
16
|
-
readonly stderr: string;
|
|
17
|
-
readonly exitCode: number;
|
|
18
|
-
}
|
|
19
15
|
export declare function runCli(cli: Cli, argv: readonly string[], options: RunOptions): Promise<RunResult>;
|
|
20
16
|
export declare function runWithProgress(cli: Cli, argv: readonly string[], options: RunOptions, writeProgress: (line: string) => void): Promise<RunResult>;
|
package/dist/run-cli.js
CHANGED
|
@@ -1,154 +1,49 @@
|
|
|
1
|
-
import { Command as Commander } from "commander";
|
|
2
1
|
import { builtInCommands } from "./built-ins.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { execute } from "./execute.js";
|
|
6
|
-
import { fieldsOption, projected, renderRows, rowFieldsOf, selectedFields } from "./fields.js";
|
|
7
|
-
import { JSON_FLAG, runtimeFlagsFor } from "./flags.js";
|
|
8
|
-
import { cliHelp, commandHelp, groupHelp } from "./help.js";
|
|
9
|
-
import { cliHelpJson, commandHelpJson, groupHelpJson } from "./help-json.js";
|
|
10
|
-
import { inputFields, registerInput } from "./input.js";
|
|
2
|
+
import { commandSpec, groupSpec } from "./command-spec.js";
|
|
3
|
+
import { execute, renderOf } from "./execute.js";
|
|
11
4
|
import { RunControl } from "./interrupts.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
5
|
+
import { commandResult, errorResult, helpResult, versionResult, } from "./output.js";
|
|
6
|
+
import { parseCommand } from "./parse-input.js";
|
|
7
|
+
import { route } from "./route.js";
|
|
14
8
|
import { styleFor } from "./style.js";
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
function isJson(cmd) {
|
|
22
|
-
return cmd.optsWithGlobals().json === true;
|
|
23
|
-
}
|
|
24
|
-
function isDryRun(cmd) {
|
|
25
|
-
return cmd.opts().dryRun === true;
|
|
26
|
-
}
|
|
27
|
-
function confirmOf(cmd) {
|
|
28
|
-
return cmd.opts().confirm;
|
|
29
|
-
}
|
|
30
|
-
function printed(outcome, { json, invocation, style, fields }) {
|
|
31
|
-
if (!(outcome.value instanceof Page)) {
|
|
32
|
-
return json ? `${JSON.stringify(outcome.value)}\n` : withTrailingNewline(outcome.render(style));
|
|
33
|
-
}
|
|
34
|
-
const page = printedPage(outcome.value, invocation);
|
|
35
|
-
if (fields === undefined) {
|
|
36
|
-
return json
|
|
37
|
-
? `${JSON.stringify(page)}\n`
|
|
38
|
-
: `${withTrailingNewline(outcome.render(style))}${pageFooter(page)}`;
|
|
39
|
-
}
|
|
40
|
-
const rows = projected(page.items, fields);
|
|
41
|
-
// The author's render may read any field, so selected rows are rendered by the Runtime.
|
|
42
|
-
return json
|
|
43
|
-
? `${JSON.stringify({ ...page, items: rows })}\n`
|
|
44
|
-
: `${renderRows(rows, fields)}${pageFooter(page)}`;
|
|
45
|
-
}
|
|
46
|
-
function failure(error, format) {
|
|
47
|
-
return {
|
|
48
|
-
stdout: "",
|
|
49
|
-
stderr: formatRuntimeError(error, format),
|
|
50
|
-
exitCode: error instanceof UsageError ? USAGE_EXIT_CODE : RUNTIME_EXIT_CODE,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
async function runCommand(sub, command, fields, { base, signal, style, invocation, errorFormat }) {
|
|
54
|
-
const json = isJson(sub);
|
|
55
|
-
let input;
|
|
56
|
-
let selected;
|
|
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;
|
|
57
14
|
try {
|
|
58
|
-
|
|
59
|
-
const rowFields = rowFieldsOf(command);
|
|
60
|
-
selected =
|
|
61
|
-
rowFields === undefined
|
|
62
|
-
? undefined
|
|
63
|
-
: selectedFields(sub.opts().fields, rowFields, commandLine(sub));
|
|
15
|
+
parsed = parseCommand(routed, invocation);
|
|
64
16
|
}
|
|
65
17
|
catch (error) {
|
|
66
|
-
return
|
|
18
|
+
return errorResult(error, format);
|
|
67
19
|
}
|
|
68
|
-
const
|
|
20
|
+
const { input, flags } = parsed;
|
|
21
|
+
const control = new RunControl(commandLine, signal);
|
|
69
22
|
const ctx = {
|
|
70
23
|
...base,
|
|
71
24
|
signal: control.signal,
|
|
72
25
|
deadline: (ms) => control.deadline(ms),
|
|
73
26
|
runToEnd: (work) => control.runToEnd(work),
|
|
74
27
|
};
|
|
28
|
+
let settled;
|
|
75
29
|
try {
|
|
76
30
|
const outcome = await control.settle(execute(command, input, ctx, {
|
|
77
|
-
dryRun:
|
|
78
|
-
|
|
31
|
+
dryRun: flags.dryRun,
|
|
32
|
+
confirm: flags.confirm,
|
|
33
|
+
page: flags.page,
|
|
34
|
+
invocation,
|
|
35
|
+
commandLine,
|
|
79
36
|
}));
|
|
80
|
-
|
|
81
|
-
stdout: printed(outcome, { json, invocation, style, fields: selected }),
|
|
82
|
-
stderr: "",
|
|
83
|
-
exitCode: 0,
|
|
84
|
-
};
|
|
37
|
+
settled = { ok: true, outcome };
|
|
85
38
|
}
|
|
86
39
|
catch (error) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
const outcome = {
|
|
93
|
-
value: reported.data,
|
|
94
|
-
render: (renderStyle) => command.render(reported.data, renderStyle),
|
|
40
|
+
settled = {
|
|
41
|
+
ok: false,
|
|
42
|
+
error: control.errorAfter(error),
|
|
43
|
+
render: renderOf(command),
|
|
95
44
|
};
|
|
96
|
-
return { ...result, stdout: printed(outcome, { json, invocation, style, fields: selected }) };
|
|
97
45
|
}
|
|
98
|
-
}
|
|
99
|
-
// Commander parses every option before it prints help, so `--json` counts on either side of `--help`.
|
|
100
|
-
function helpFor(cmd, text, json) {
|
|
101
|
-
cmd.configureHelp({ formatHelp: () => (isJson(cmd) ? json() : text()) });
|
|
102
|
-
}
|
|
103
|
-
function configureCommand(sub, command, setup, json = () => commandHelpJson(commandLine(sub), command)) {
|
|
104
|
-
const fields = inputFields(command);
|
|
105
|
-
const rowFields = rowFieldsOf(command);
|
|
106
|
-
const helpFields = rowFields === undefined
|
|
107
|
-
? fields
|
|
108
|
-
: { ...fields, options: [...fields.options, fieldsOption(rowFields)] };
|
|
109
|
-
helpFor(sub, () => commandHelp(commandLine(sub), command, helpFields, setup.style), json);
|
|
110
|
-
registerInput(sub, helpFields.options);
|
|
111
|
-
// The root already carries --json, for every Command.
|
|
112
|
-
for (const flag of runtimeFlagsFor(command.effect).filter((flag) => flag !== JSON_FLAG)) {
|
|
113
|
-
sub.option(flag.usage, flag.description);
|
|
114
|
-
}
|
|
115
|
-
sub.action(async () => {
|
|
116
|
-
setup.finish(await runCommand(sub, command, fields, setup));
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
function addCommand(parent, command, setup) {
|
|
120
|
-
const sub = stopAt(parent.command(command.name).description(command.description));
|
|
121
|
-
configureCommand(sub, command, setup);
|
|
122
|
-
}
|
|
123
|
-
function addCommands(parent, commands, setup) {
|
|
124
|
-
for (const [key, node] of Object.entries(commands)) {
|
|
125
|
-
if (isCommand(node)) {
|
|
126
|
-
addCommand(parent, node, setup);
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
const group = stopAt(parent.command(key));
|
|
130
|
-
helpFor(group, () => groupHelp(commandLine(group), node, setup.style), () => groupHelpJson(commandLine(group), node));
|
|
131
|
-
addCommands(group, node, setup);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
function stopped(error, { commanderOut, invocation, errorFormat }) {
|
|
136
|
-
if (!(error instanceof ParseStop)) {
|
|
137
|
-
return failure(error, errorFormat);
|
|
138
|
-
}
|
|
139
|
-
if (error.reason.exitCode === 0) {
|
|
140
|
-
return { stdout: commanderOut, stderr: "", exitCode: 0 };
|
|
141
|
-
}
|
|
142
|
-
// A group called without a Command answers with its help, the same as its --help.
|
|
143
|
-
if (error.reason.code === "commander.help") {
|
|
144
|
-
return { stdout: error.command.helpInformation(), stderr: "", exitCode: 0 };
|
|
145
|
-
}
|
|
146
|
-
return failure(usageErrorOf(error, invocation), { ...errorFormat, json: isJson(error.command) });
|
|
147
|
-
}
|
|
148
|
-
function versionLine({ version, build }) {
|
|
149
|
-
if (build === undefined)
|
|
150
|
-
return version;
|
|
151
|
-
return `${version} (${build.sha}${build.dirty ? "+dirty" : ""})`;
|
|
46
|
+
return commandResult(settled, { ...format, fields: flags.fields });
|
|
152
47
|
}
|
|
153
48
|
export async function runCli(cli, argv, options) {
|
|
154
49
|
const progress = [];
|
|
@@ -157,55 +52,34 @@ export async function runCli(cli, argv, options) {
|
|
|
157
52
|
}
|
|
158
53
|
// Progress is written as it happens: an Agent harness kills a process that stays silent too long.
|
|
159
54
|
export async function runWithProgress(cli, argv, options, writeProgress) {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
writeOut: (text) => commanderOut.push(text),
|
|
167
|
-
// Commander writes here only the help for a group called without a Command, answered below.
|
|
168
|
-
writeErr: () => { },
|
|
169
|
-
outputError: () => { },
|
|
170
|
-
// The Runtime decides colour itself, so commander must not strip it by reading `process`.
|
|
171
|
-
stripColor: (text) => text,
|
|
172
|
-
})
|
|
173
|
-
.helpCommand(false)
|
|
174
|
-
.version(versionLine(cli), "--version")
|
|
175
|
-
.option(JSON_FLAG.usage, JSON_FLAG.description);
|
|
176
|
-
const invocation = { cliName: cli.name, argv };
|
|
177
|
-
let commandResult;
|
|
178
|
-
const setup = {
|
|
179
|
-
base: {
|
|
180
|
-
cwd: options.cwd,
|
|
181
|
-
env: options.env,
|
|
182
|
-
progress: (message) => writeProgress(`${message}\n`),
|
|
183
|
-
},
|
|
184
|
-
signal: options.signal,
|
|
185
|
-
style,
|
|
186
|
-
invocation,
|
|
187
|
-
errorFormat,
|
|
188
|
-
finish: (result) => {
|
|
189
|
-
commandResult = result;
|
|
190
|
-
},
|
|
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,
|
|
191
61
|
};
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
+
});
|
|
208
83
|
}
|
|
209
|
-
return commandResult;
|
|
210
84
|
}
|
|
211
85
|
//# sourceMappingURL=run-cli.js.map
|