@duyquangnvx/agent-cli 0.4.0 → 0.6.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 +80 -0
- package/dist/agent-cli.js +2 -2
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent.d.ts +5 -3
- package/dist/agent.js +31 -10
- package/dist/agent.js.map +1 -1
- package/dist/built-ins/commands.d.ts +8 -0
- package/dist/{built-ins.js → built-ins/commands.js} +4 -4
- package/dist/built-ins/commands.js.map +1 -0
- package/dist/built-ins/doctor-rows.d.ts +4 -0
- package/dist/{doctor-rows.js → built-ins/doctor-rows.js} +18 -26
- package/dist/built-ins/doctor-rows.js.map +1 -0
- package/dist/built-ins/doctor.d.ts +5 -0
- package/dist/{doctor.js → built-ins/doctor.js} +27 -20
- package/dist/built-ins/doctor.js.map +1 -0
- package/dist/{global-install.js → built-ins/global-install.js} +1 -1
- package/dist/built-ins/global-install.js.map +1 -0
- package/dist/{npm.d.ts → built-ins/npm.d.ts} +5 -2
- package/dist/{npm.js → built-ins/npm.js} +25 -33
- package/dist/built-ins/npm.js.map +1 -0
- package/dist/built-ins/semver.js.map +1 -0
- package/dist/built-ins/skills.d.ts +18 -0
- package/dist/built-ins/skills.js +97 -0
- package/dist/built-ins/skills.js.map +1 -0
- package/dist/{update.d.ts → built-ins/update.d.ts} +3 -2
- package/dist/{update.js → built-ins/update.js} +28 -18
- package/dist/built-ins/update.js.map +1 -0
- package/dist/{upgrade-notes.js → built-ins/upgrade-notes.js} +1 -1
- package/dist/built-ins/upgrade-notes.js.map +1 -0
- package/dist/clock.d.ts +1 -0
- package/dist/clock.js.map +1 -1
- package/dist/command-spec.d.ts +17 -2
- package/dist/command-spec.js +30 -9
- package/dist/command-spec.js.map +1 -1
- package/dist/confirm.js +6 -2
- package/dist/confirm.js.map +1 -1
- package/dist/context.d.ts +139 -0
- package/dist/context.js +2 -0
- package/dist/context.js.map +1 -0
- package/dist/cost.js +2 -2
- package/dist/cost.js.map +1 -1
- package/dist/define.d.ts +100 -87
- package/dist/define.js +3 -1
- package/dist/define.js.map +1 -1
- package/dist/errno.d.ts +8 -4
- package/dist/errno.js +21 -4
- package/dist/errno.js.map +1 -1
- package/dist/error-table.d.ts +6 -1
- package/dist/error-table.js +5 -1
- package/dist/error-table.js.map +1 -1
- package/dist/errors.d.ts +11 -2
- package/dist/errors.js +21 -8
- package/dist/errors.js.map +1 -1
- package/dist/execute.d.ts +9 -2
- package/dist/execute.js +10 -3
- package/dist/execute.js.map +1 -1
- package/dist/exit-classes.js +38 -38
- package/dist/exit-classes.js.map +1 -1
- package/dist/files.d.ts +30 -8
- package/dist/files.js +104 -17
- package/dist/files.js.map +1 -1
- package/dist/help-json.d.ts +2 -2
- package/dist/help-json.js +6 -2
- package/dist/help-json.js.map +1 -1
- package/dist/help.d.ts +1 -1
- package/dist/help.js +14 -9
- package/dist/help.js.map +1 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/input.d.ts +7 -1
- package/dist/input.js +33 -4
- package/dist/input.js.map +1 -1
- package/dist/interrupts.d.ts +7 -2
- package/dist/interrupts.js +29 -15
- package/dist/interrupts.js.map +1 -1
- package/dist/invocation.d.ts +10 -5
- package/dist/invocation.js +24 -11
- package/dist/invocation.js.map +1 -1
- package/dist/list.d.ts +12 -3
- package/dist/list.js +38 -6
- package/dist/list.js.map +1 -1
- package/dist/manifest.d.ts +17 -0
- package/dist/manifest.js +24 -0
- package/dist/manifest.js.map +1 -0
- package/dist/operator.d.ts +5 -0
- package/dist/operator.js +15 -0
- package/dist/operator.js.map +1 -0
- package/dist/output.d.ts +6 -4
- package/dist/output.js +5 -6
- package/dist/output.js.map +1 -1
- package/dist/outputs.d.ts +24 -1
- package/dist/outputs.js +58 -2
- package/dist/outputs.js.map +1 -1
- package/dist/parse-input.d.ts +11 -2
- package/dist/parse-input.js +78 -27
- package/dist/parse-input.js.map +1 -1
- package/dist/project.d.ts +3 -2
- package/dist/project.js +11 -10
- package/dist/project.js.map +1 -1
- package/dist/route.d.ts +1 -1
- package/dist/route.js +2 -1
- package/dist/route.js.map +1 -1
- package/dist/run-cli.d.ts +8 -33
- package/dist/run-cli.js +50 -157
- package/dist/run-cli.js.map +1 -1
- package/dist/run-command.d.ts +11 -0
- package/dist/run-command.js +234 -0
- package/dist/run-command.js.map +1 -0
- package/dist/run-options.d.ts +48 -0
- package/dist/run-options.js +2 -0
- package/dist/run-options.js.map +1 -0
- package/dist/run-process.js +7 -4
- package/dist/run-process.js.map +1 -1
- package/dist/secrets.d.ts +10 -6
- package/dist/secrets.js +8 -9
- package/dist/secrets.js.map +1 -1
- package/dist/side-task.d.ts +27 -0
- package/dist/side-task.js +31 -0
- package/dist/side-task.js.map +1 -0
- package/dist/spawn.d.ts +29 -6
- package/dist/spawn.js +126 -29
- package/dist/spawn.js.map +1 -1
- package/dist/spill.d.ts +4 -3
- package/dist/spill.js +1 -7
- package/dist/spill.js.map +1 -1
- package/dist/stdin.d.ts +33 -0
- package/dist/stdin.js +92 -0
- package/dist/stdin.js.map +1 -0
- package/dist/style.d.ts +1 -1
- package/dist/tokenize.d.ts +3 -0
- package/dist/tokenize.js +5 -4
- package/dist/tokenize.js.map +1 -1
- package/dist/tools.d.ts +6 -3
- package/dist/tools.js +18 -11
- package/dist/tools.js.map +1 -1
- package/dist/usage.d.ts +2 -0
- package/dist/usage.js +12 -1
- package/dist/usage.js.map +1 -1
- package/dist/version.d.ts +3 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/package.json +1 -1
- package/dist/built-ins.d.ts +0 -3
- package/dist/built-ins.js.map +0 -1
- package/dist/doctor-rows.d.ts +0 -3
- package/dist/doctor-rows.js.map +0 -1
- package/dist/doctor.d.ts +0 -4
- package/dist/doctor.js.map +0 -1
- package/dist/global-install.js.map +0 -1
- package/dist/npm.js.map +0 -1
- package/dist/semver.js.map +0 -1
- package/dist/skills.d.ts +0 -11
- package/dist/skills.js +0 -58
- package/dist/skills.js.map +0 -1
- package/dist/update.js.map +0 -1
- package/dist/upgrade-notes.js.map +0 -1
- /package/dist/{global-install.d.ts → built-ins/global-install.d.ts} +0 -0
- /package/dist/{semver.d.ts → built-ins/semver.d.ts} +0 -0
- /package/dist/{semver.js → built-ins/semver.js} +0 -0
- /package/dist/{upgrade-notes.d.ts → built-ins/upgrade-notes.d.ts} +0 -0
package/dist/secrets.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Env } from "./
|
|
1
|
+
import type { Env } from "./context.js";
|
|
2
|
+
import type { FileError } from "./errno.js";
|
|
2
3
|
export type SecretOrigin = {
|
|
3
4
|
readonly kind: "env";
|
|
4
5
|
} | {
|
|
@@ -6,14 +7,17 @@ export type SecretOrigin = {
|
|
|
6
7
|
readonly path: string;
|
|
7
8
|
};
|
|
8
9
|
export interface Secret {
|
|
10
|
+
/** Report the origin, never the value, so the key does not reach an agent's context. */
|
|
9
11
|
readonly value: string;
|
|
10
12
|
readonly origin: SecretOrigin;
|
|
11
13
|
}
|
|
14
|
+
/** `$XDG_CONFIG_HOME/<cli>/.env`, with `~/.config` when the variable is unset or empty. */
|
|
15
|
+
export declare function envFileOf(cliName: string, env: Env): string;
|
|
12
16
|
export interface SecretScope {
|
|
13
|
-
readonly
|
|
17
|
+
readonly envFile: string;
|
|
14
18
|
readonly env: Env;
|
|
15
|
-
/**
|
|
16
|
-
readonly
|
|
19
|
+
/** Classifies a failure to read the `.env`. */
|
|
20
|
+
readonly fileError: FileError;
|
|
17
21
|
}
|
|
18
|
-
/** Looks `name` up in the env, then in
|
|
19
|
-
export declare function secretOf({
|
|
22
|
+
/** Looks `name` up in the env, then in `envFile`; an empty value counts as unset. */
|
|
23
|
+
export declare function secretOf({ envFile, env, fileError }: SecretScope, name: string): Secret | undefined;
|
package/dist/secrets.js
CHANGED
|
@@ -2,13 +2,13 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { parseEnv } from "node:util";
|
|
5
|
-
import { classifyErrno } from "./errno.js";
|
|
6
5
|
import { isMissingFile } from "./errors.js";
|
|
7
|
-
|
|
6
|
+
/** `$XDG_CONFIG_HOME/<cli>/.env`, with `~/.config` when the variable is unset or empty. */
|
|
7
|
+
export function envFileOf(cliName, env) {
|
|
8
8
|
const config = env.XDG_CONFIG_HOME || join(env.HOME || homedir(), ".config");
|
|
9
9
|
return join(config, cliName, ".env");
|
|
10
10
|
}
|
|
11
|
-
function readDotenv(path,
|
|
11
|
+
function readDotenv(path, fileError) {
|
|
12
12
|
let text;
|
|
13
13
|
try {
|
|
14
14
|
text = readFileSync(path, "utf8");
|
|
@@ -16,17 +16,16 @@ function readDotenv(path, env, callerLine) {
|
|
|
16
16
|
catch (error) {
|
|
17
17
|
if (isMissingFile(error))
|
|
18
18
|
return {};
|
|
19
|
-
throw
|
|
19
|
+
throw fileError(error, { path, access: "read" });
|
|
20
20
|
}
|
|
21
21
|
return parseEnv(text);
|
|
22
22
|
}
|
|
23
|
-
/** Looks `name` up in the env, then in
|
|
24
|
-
export function secretOf({
|
|
23
|
+
/** Looks `name` up in the env, then in `envFile`; an empty value counts as unset. */
|
|
24
|
+
export function secretOf({ envFile, env, fileError }, name) {
|
|
25
25
|
const fromEnv = env[name];
|
|
26
26
|
if (fromEnv)
|
|
27
27
|
return { value: fromEnv, origin: { kind: "env" } };
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
return fromFile ? { value: fromFile, origin: { kind: "file", path } } : undefined;
|
|
28
|
+
const fromFile = readDotenv(envFile, fileError)[name];
|
|
29
|
+
return fromFile ? { value: fromFile, origin: { kind: "file", path: envFile } } : undefined;
|
|
31
30
|
}
|
|
32
31
|
//# sourceMappingURL=secrets.js.map
|
package/dist/secrets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGrC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAY5C,2FAA2F;AAC3F,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,GAAQ;IACjD,MAAM,MAAM,GAAG,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAC7E,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,UAAU,CACjB,IAAY,EACZ,SAAoB;IAEpB,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,aAAa,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACpC,MAAM,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AASD,qFAAqF;AACrF,MAAM,UAAU,QAAQ,CACtB,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAe,EACxC,IAAY;IAEZ,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,OAAO;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;IAChE,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7F,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Clock } from "./clock.js";
|
|
2
|
+
import type { PortsBase } from "./context.js";
|
|
3
|
+
/** How long a run waits for its Side task once its output is written. */
|
|
4
|
+
export declare const SIDE_TASK_WAIT_MS = 1000;
|
|
5
|
+
/** What a CLI's Side task receives for one Command run. */
|
|
6
|
+
export interface SideTaskRun<Ports = unknown> extends PortsBase {
|
|
7
|
+
/** The Command's path as the caller typed its words, such as `["voices", "list"]`. */
|
|
8
|
+
readonly command: readonly string[];
|
|
9
|
+
/** Whether the caller passed `--dry-run`. */
|
|
10
|
+
readonly dryRun: boolean;
|
|
11
|
+
/** Built on first read, as `ctx.ports` is, from this `PortsBase`, so they carry its `signal`. */
|
|
12
|
+
readonly ports: Ports;
|
|
13
|
+
/**
|
|
14
|
+
* The Side task's own signal: it aborts once the run has waited `SIDE_TASK_WAIT_MS` for it, never
|
|
15
|
+
* on the Ctrl-C that stops the Command; a second Ctrl-C ends the process at once.
|
|
16
|
+
*/
|
|
17
|
+
readonly signal: AbortSignal;
|
|
18
|
+
}
|
|
19
|
+
export type SideTask = (run: SideTaskRun) => Promise<void> | undefined;
|
|
20
|
+
export type FinishSideTask = () => Promise<void>;
|
|
21
|
+
export declare const noSideTask: FinishSideTask;
|
|
22
|
+
export interface SideTaskOptions {
|
|
23
|
+
readonly clock: Clock;
|
|
24
|
+
/** Told what the Side task threw, or that it ran past the wait. */
|
|
25
|
+
readonly failed: (error: unknown) => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function startSideTask(sideTask: SideTask | undefined, runWith: (signal: AbortSignal) => SideTaskRun, { clock, failed }: SideTaskOptions): FinishSideTask;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { after } from "./clock.js";
|
|
2
|
+
/** How long a run waits for its Side task once its output is written. */
|
|
3
|
+
export const SIDE_TASK_WAIT_MS = 1000;
|
|
4
|
+
export const noSideTask = async () => { };
|
|
5
|
+
function waitOver() {
|
|
6
|
+
return new DOMException(`the side task ran past its ${SIDE_TASK_WAIT_MS} ms wait`, "TimeoutError");
|
|
7
|
+
}
|
|
8
|
+
export function startSideTask(sideTask, runWith, { clock, failed }) {
|
|
9
|
+
if (sideTask === undefined)
|
|
10
|
+
return noSideTask;
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const { signal } = controller;
|
|
13
|
+
// A Side task is the CLI's own business, such as a usage count: what it throws must never change
|
|
14
|
+
// the run's output or exit code, so it is only reported, which shows under debug.
|
|
15
|
+
const running = (async () => sideTask(runWith(signal)))().catch((error) => {
|
|
16
|
+
if (!(signal.aborted && error === signal.reason))
|
|
17
|
+
failed(error);
|
|
18
|
+
});
|
|
19
|
+
return async () => {
|
|
20
|
+
const waited = new AbortController();
|
|
21
|
+
const capped = new Promise((resolve) => after(clock, SIDE_TASK_WAIT_MS, waited.signal, () => {
|
|
22
|
+
const over = waitOver();
|
|
23
|
+
failed(over);
|
|
24
|
+
controller.abort(over);
|
|
25
|
+
resolve();
|
|
26
|
+
}));
|
|
27
|
+
await Promise.race([running, capped]);
|
|
28
|
+
waited.abort();
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=side-task.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"side-task.js","sourceRoot":"","sources":["../src/side-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAc,MAAM,YAAY,CAAC;AAG/C,yEAAyE;AACzE,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAqBtC,MAAM,CAAC,MAAM,UAAU,GAAmB,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;AAEzD,SAAS,QAAQ;IACf,OAAO,IAAI,YAAY,CACrB,8BAA8B,iBAAiB,UAAU,EACzD,cAAc,CACf,CAAC;AACJ,CAAC;AAQD,MAAM,UAAU,aAAa,CAC3B,QAA8B,EAC9B,OAA6C,EAC7C,EAAE,KAAK,EAAE,MAAM,EAAmB;IAElC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,UAAU,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC;IAC9B,iGAAiG;IACjG,kFAAkF;IAClF,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACjF,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC;YAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAC3C,KAAK,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE;YAClD,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,CAAC;YACb,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CACH,CAAC;QACF,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/spawn.d.ts
CHANGED
|
@@ -1,29 +1,52 @@
|
|
|
1
|
-
import type { Env } from "./
|
|
1
|
+
import type { Env } from "./context.js";
|
|
2
|
+
import type { FileError } from "./errno.js";
|
|
2
3
|
export declare const TOOL_FAILED = "TOOL_FAILED";
|
|
3
4
|
export interface SpawnResult {
|
|
4
5
|
readonly stdout: string;
|
|
5
6
|
readonly stderr: string;
|
|
6
7
|
readonly exitCode: number;
|
|
7
8
|
}
|
|
8
|
-
/**
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Runs a child process to its end; a test replaces it through `runCli`. `onLine`, when given,
|
|
11
|
+
* receives each line of the child's stdout and stderr as it arrives, without its line ending.
|
|
12
|
+
*/
|
|
13
|
+
export type Spawn = (command: string, args: readonly string[], options: ChildOptions) => Promise<SpawnResult>;
|
|
14
|
+
interface ChildOptions {
|
|
10
15
|
readonly cwd: string;
|
|
11
16
|
readonly env: Env;
|
|
12
17
|
readonly signal: AbortSignal;
|
|
13
|
-
|
|
18
|
+
readonly onLine?: (line: string) => void;
|
|
19
|
+
}
|
|
14
20
|
export interface SpawnOptions {
|
|
15
21
|
/** `ctx.cwd` when absent. */
|
|
16
22
|
readonly cwd?: string;
|
|
17
23
|
/** `ctx.env` when absent. */
|
|
18
24
|
readonly env?: Env;
|
|
19
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Fails the run with `TOOL_FAILED` (exit 2) and the tail of the child's stderr when it exits
|
|
27
|
+
* non-zero.
|
|
28
|
+
*/
|
|
20
29
|
readonly check?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Passes each line of the child's stdout and stderr through `ctx.progress` as it arrives; the
|
|
32
|
+
* result still holds the whole output.
|
|
33
|
+
*/
|
|
34
|
+
readonly progress?: boolean;
|
|
21
35
|
}
|
|
22
36
|
export type ContextSpawn = (command: string, args?: readonly string[], options?: SpawnOptions) => Promise<SpawnResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Runs a child process to its end; it is killed on abort, and the promise settles only once it has
|
|
39
|
+
* exited. A `detached` child leaves the terminal's process group on POSIX, and so its Ctrl-C.
|
|
40
|
+
*/
|
|
41
|
+
export declare function spawnChild(command: string, args: readonly string[], { cwd, env, signal, onLine, detached }: ChildOptions & {
|
|
42
|
+
readonly detached?: boolean;
|
|
43
|
+
}): Promise<SpawnResult>;
|
|
23
44
|
export declare const realSpawn: Spawn;
|
|
24
45
|
/** `ctx.spawn`: `spawn` bound to the run, its start failures classified by errno. */
|
|
25
46
|
export declare function contextSpawn(run: Spawn, defaults: {
|
|
26
47
|
readonly cwd: string;
|
|
27
48
|
readonly env: Env;
|
|
28
49
|
readonly signal: AbortSignal;
|
|
29
|
-
|
|
50
|
+
readonly progress: (message: string) => void;
|
|
51
|
+
}, fileError: FileError): ContextSpawn;
|
|
52
|
+
export {};
|
package/dist/spawn.js
CHANGED
|
@@ -1,42 +1,138 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { constants } from "node:os";
|
|
3
|
-
import { classifyErrno } from "./errno.js";
|
|
4
3
|
import { CliError, isMissingFile } from "./errors.js";
|
|
5
4
|
import { lastLines } from "./tail.js";
|
|
6
|
-
import { TOOL_MISSING } from "./tools.js";
|
|
5
|
+
import { findTool, TOOL_MISSING } from "./tools.js";
|
|
7
6
|
export const TOOL_FAILED = "TOOL_FAILED";
|
|
8
7
|
const STDERR_TAIL_LINES = 20;
|
|
9
8
|
// A shell reports a child killed by a signal as 128 plus the signal's number.
|
|
10
9
|
const SIGNAL_EXIT_BASE = 128;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
const BATCH_FILE = /\.(?:cmd|bat)$/i;
|
|
11
|
+
const CMD_SHIM = /\.cmd$/i;
|
|
12
|
+
// What cmd.exe acts on even inside quotes, as cross-spawn escapes it.
|
|
13
|
+
const CMD_META = /([()\][%!^"`<>&|;, *?])/g;
|
|
14
|
+
const PATH_SEPARATOR = /[\\/]/;
|
|
15
|
+
const TRAILING_CR = /\r$/;
|
|
16
|
+
function escapedForCmd(text) {
|
|
17
|
+
return text.replace(CMD_META, "^$1");
|
|
18
|
+
}
|
|
19
|
+
// Quoted as the C runtime splits a command line, then escaped for cmd.exe (BatBadBut). npm's .cmd
|
|
20
|
+
// shims hand `%*` to a second cmd.exe parse, so their arguments are escaped twice, as cross-spawn does.
|
|
21
|
+
function batchArgument(arg, shim) {
|
|
22
|
+
const quoted = `"${arg.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, "$1$1")}"`;
|
|
23
|
+
const escaped = escapedForCmd(quoted);
|
|
24
|
+
return shim ? escapedForCmd(escaped) : escaped;
|
|
25
|
+
}
|
|
26
|
+
// A batch file runs only through cmd.exe, so it and its arguments go escaped on one command line.
|
|
27
|
+
// The command is never quoted: cmd.exe resolves %~dp0 against the working directory for a quoted
|
|
28
|
+
// batch name found on PATH.
|
|
29
|
+
function batchCommandLine(command, file, args) {
|
|
30
|
+
const shim = CMD_SHIM.test(file);
|
|
31
|
+
return [escapedForCmd(command), ...args.map((arg) => batchArgument(arg, shim))].join(" ");
|
|
32
|
+
}
|
|
33
|
+
async function windowsLaunch(command, args, env) {
|
|
34
|
+
const file = PATH_SEPARATOR.test(command) ? command : await findTool(command, env);
|
|
35
|
+
if (file === undefined || !BATCH_FILE.test(file))
|
|
36
|
+
return { command, args, shell: false };
|
|
37
|
+
return { command: batchCommandLine(command, file, args), args: [], shell: true };
|
|
38
|
+
}
|
|
39
|
+
// On Windows, killing cmd.exe or a launcher leaves its children running; only a tree kill reaches them.
|
|
40
|
+
function stop(child) {
|
|
41
|
+
if (process.platform !== "win32" || child.pid === undefined) {
|
|
20
42
|
child.kill();
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
child.
|
|
24
|
-
|
|
25
|
-
|
|
43
|
+
return Promise.resolve();
|
|
44
|
+
}
|
|
45
|
+
const pid = String(child.pid);
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const taskkill = spawn("taskkill", ["/pid", pid, "/t", "/f"], {
|
|
48
|
+
stdio: "ignore",
|
|
49
|
+
windowsHide: true,
|
|
50
|
+
});
|
|
51
|
+
taskkill.once("error", () => {
|
|
52
|
+
// Without taskkill, killing the child itself is the most that can be done.
|
|
53
|
+
child.kill();
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
taskkill.once("exit", () => resolve());
|
|
26
57
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
58
|
+
}
|
|
59
|
+
/** Calls `onLine` with each complete line pushed, and with the unterminated rest at the end. */
|
|
60
|
+
function lineSplitter(onLine) {
|
|
61
|
+
let rest = "";
|
|
62
|
+
const emit = (line) => onLine?.(line.replace(TRAILING_CR, ""));
|
|
63
|
+
return {
|
|
64
|
+
push(text) {
|
|
65
|
+
if (onLine === undefined)
|
|
66
|
+
return;
|
|
67
|
+
const lines = (rest + text).split("\n");
|
|
68
|
+
rest = lines.pop() ?? "";
|
|
69
|
+
for (const line of lines)
|
|
70
|
+
emit(line);
|
|
71
|
+
},
|
|
72
|
+
end() {
|
|
73
|
+
if (rest !== "")
|
|
74
|
+
emit(rest);
|
|
75
|
+
rest = "";
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Runs a child process to its end; it is killed on abort, and the promise settles only once it has
|
|
81
|
+
* exited. A `detached` child leaves the terminal's process group on POSIX, and so its Ctrl-C.
|
|
82
|
+
*/
|
|
83
|
+
export async function spawnChild(command, args, { cwd, env, signal, onLine, detached = false }) {
|
|
84
|
+
signal.throwIfAborted();
|
|
85
|
+
const launch = process.platform === "win32"
|
|
86
|
+
? await windowsLaunch(command, args, env)
|
|
87
|
+
: { command, args, shell: false };
|
|
88
|
+
signal.throwIfAborted();
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
const child = spawn(launch.command, launch.args, {
|
|
91
|
+
cwd,
|
|
92
|
+
env,
|
|
93
|
+
shell: launch.shell,
|
|
94
|
+
windowsHide: true,
|
|
95
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
96
|
+
detached: detached && process.platform !== "win32",
|
|
97
|
+
});
|
|
98
|
+
let stdout = "";
|
|
99
|
+
let stderr = "";
|
|
100
|
+
const stdoutLines = lineSplitter(onLine);
|
|
101
|
+
const stderrLines = lineSplitter(onLine);
|
|
102
|
+
child.stdout.setEncoding("utf8").on("data", (chunk) => {
|
|
103
|
+
stdout += chunk;
|
|
104
|
+
stdoutLines.push(chunk);
|
|
105
|
+
});
|
|
106
|
+
child.stderr.setEncoding("utf8").on("data", (chunk) => {
|
|
107
|
+
stderr += chunk;
|
|
108
|
+
stderrLines.push(chunk);
|
|
109
|
+
});
|
|
110
|
+
let stopped = Promise.resolve();
|
|
111
|
+
const kill = () => {
|
|
112
|
+
stopped = stop(child);
|
|
113
|
+
};
|
|
114
|
+
signal.addEventListener("abort", kill, { once: true });
|
|
115
|
+
child.on("error", (error) => {
|
|
116
|
+
signal.removeEventListener("abort", kill);
|
|
117
|
+
reject(error);
|
|
118
|
+
});
|
|
119
|
+
child.on("close", (code, killedBy) => {
|
|
120
|
+
signal.removeEventListener("abort", kill);
|
|
121
|
+
if (signal.aborted) {
|
|
122
|
+
void stopped.then(() => reject(signal.reason));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
stdoutLines.end();
|
|
126
|
+
stderrLines.end();
|
|
127
|
+
resolve({
|
|
128
|
+
stdout,
|
|
129
|
+
stderr,
|
|
130
|
+
exitCode: code ?? SIGNAL_EXIT_BASE + (killedBy === null ? 0 : constants.signals[killedBy]),
|
|
131
|
+
});
|
|
37
132
|
});
|
|
38
133
|
});
|
|
39
|
-
}
|
|
134
|
+
}
|
|
135
|
+
export const realSpawn = (command, args, options) => spawnChild(command, args, options);
|
|
40
136
|
function failedError(command, { exitCode, stderr }) {
|
|
41
137
|
const tail = lastLines(stderr, STDERR_TAIL_LINES);
|
|
42
138
|
return new CliError({
|
|
@@ -55,7 +151,7 @@ function missingError(command, cause) {
|
|
|
55
151
|
}, { cause });
|
|
56
152
|
}
|
|
57
153
|
/** `ctx.spawn`: `spawn` bound to the run, its start failures classified by errno. */
|
|
58
|
-
export function contextSpawn(run, defaults,
|
|
154
|
+
export function contextSpawn(run, defaults, fileError) {
|
|
59
155
|
return async (command, args = [], options = {}) => {
|
|
60
156
|
let result;
|
|
61
157
|
try {
|
|
@@ -63,12 +159,13 @@ export function contextSpawn(run, defaults, callerLine) {
|
|
|
63
159
|
cwd: options.cwd ?? defaults.cwd,
|
|
64
160
|
env: options.env ?? defaults.env,
|
|
65
161
|
signal: defaults.signal,
|
|
162
|
+
onLine: options.progress === true ? defaults.progress : undefined,
|
|
66
163
|
});
|
|
67
164
|
}
|
|
68
165
|
catch (error) {
|
|
69
166
|
if (isMissingFile(error))
|
|
70
167
|
throw missingError(command, error);
|
|
71
|
-
throw
|
|
168
|
+
throw fileError(error, { path: command, access: "read" });
|
|
72
169
|
}
|
|
73
170
|
if (options.check === true && result.exitCode !== 0) {
|
|
74
171
|
throw failedError(command, result);
|
package/dist/spawn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.js","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"spawn.js","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"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"}
|
package/dist/spill.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Clock } from "./clock.js";
|
|
2
|
-
import type { Env } from "./
|
|
2
|
+
import type { Env } from "./context.js";
|
|
3
|
+
import type { FileError } from "./errno.js";
|
|
3
4
|
import type { Files } from "./files.js";
|
|
4
5
|
export interface SpillTarget {
|
|
5
6
|
readonly cliName: string;
|
|
@@ -8,8 +9,8 @@ export interface SpillTarget {
|
|
|
8
9
|
readonly clock: Clock;
|
|
9
10
|
/** Writes the spill file; its failures are already classified. */
|
|
10
11
|
readonly files: Files;
|
|
11
|
-
/**
|
|
12
|
-
readonly
|
|
12
|
+
/** Classifies a failure to prepare the spill folder. */
|
|
13
|
+
readonly fileError: FileError;
|
|
13
14
|
}
|
|
14
15
|
/** Turns printed data into what stdout carries: the data itself, or where it was spilled. */
|
|
15
16
|
export type Spill = (printed: string, json: boolean) => Promise<string>;
|
package/dist/spill.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { mkdir, readdir, rm, stat } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { classifyErrno } from "./errno.js";
|
|
5
4
|
import { isMissingFile } from "./errors.js";
|
|
6
5
|
const STDOUT_BUDGET_CHARS = 30_000;
|
|
7
6
|
const SPILL_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
@@ -33,12 +32,7 @@ async function prepare(folder, cutoff, target) {
|
|
|
33
32
|
await pruneOld(folder, cutoff);
|
|
34
33
|
}
|
|
35
34
|
catch (error) {
|
|
36
|
-
throw
|
|
37
|
-
path: folder,
|
|
38
|
-
access: "write",
|
|
39
|
-
callerLine: target.callerLine,
|
|
40
|
-
env: target.env,
|
|
41
|
-
});
|
|
35
|
+
throw target.fileError(error, { path: folder, access: "write" });
|
|
42
36
|
}
|
|
43
37
|
}
|
|
44
38
|
// An empty TMPDIR means unset, as it does to the shell.
|
package/dist/spill.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spill.js","sourceRoot":"","sources":["../src/spill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"spill.js","sourceRoot":"","sources":["../src/spill.ts"],"names":[],"mappings":"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"}
|
package/dist/stdin.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Readable } from "node:stream";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { type Clock } from "./clock.js";
|
|
4
|
+
import { CliError } from "./errors.js";
|
|
5
|
+
export declare const STDIN_OPERAND = "-";
|
|
6
|
+
/**
|
|
7
|
+
* Marks a string arg as also taking its text from stdin when the caller passes `-`: all of stdin as
|
|
8
|
+
* UTF-8, judged by the same schema, read before `plan`, `run` or `start` and stopped by Ctrl-C and the run deadline.
|
|
9
|
+
* A stdin that is not a terminal fails with `STDIN_STALLED` (exit 1) once it sends nothing for `STDIN_IDLE_MS`,
|
|
10
|
+
* counted from the start of the read and from each chunk. Wrap the whole string
|
|
11
|
+
* schema (`.optional()` and `.describe()` may follow), on at most one arg and never an option.
|
|
12
|
+
*/
|
|
13
|
+
export declare function orStdin<Schema extends z.ZodType<unknown, string>>(schema: Schema): Schema;
|
|
14
|
+
export declare function isStdinSchema(schema: z.ZodType): boolean;
|
|
15
|
+
/** Where a `-` operand's text comes from: a test's text, or a stream such as `process.stdin`. */
|
|
16
|
+
export type StdinSource = string | Readable;
|
|
17
|
+
/** The progress line shown before reading a terminal, so a person isn't left facing silence. */
|
|
18
|
+
export declare function readingLine(name: string, platform: NodeJS.Platform): string;
|
|
19
|
+
export declare function isTerminal(source: StdinSource): boolean;
|
|
20
|
+
export declare const STDIN_STALLED = "STDIN_STALLED";
|
|
21
|
+
/** How long a stdin that is not a terminal may send nothing, from the start of the read and from each chunk. */
|
|
22
|
+
export declare const STDIN_IDLE_MS = 30000;
|
|
23
|
+
export declare function stdinStalled(callerLine: string): CliError;
|
|
24
|
+
/** The clock a stream's idle time runs on, and the error a stalled stream rejects with. */
|
|
25
|
+
export interface StdinIdle {
|
|
26
|
+
readonly clock: Clock;
|
|
27
|
+
readonly stalled: () => unknown;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The whole of `source` as UTF-8; rejects with the signal's reason once it aborts, and with
|
|
31
|
+
* `idle.stalled()` once a stream that is not a terminal sends nothing for `STDIN_IDLE_MS`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function readStdin(source: StdinSource, signal: AbortSignal, idle: StdinIdle): Promise<string>;
|
package/dist/stdin.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { after } from "./clock.js";
|
|
3
|
+
import { CliError } from "./errors.js";
|
|
4
|
+
export const STDIN_OPERAND = "-";
|
|
5
|
+
const STDIN_META = "stdin";
|
|
6
|
+
/**
|
|
7
|
+
* Marks a string arg as also taking its text from stdin when the caller passes `-`: all of stdin as
|
|
8
|
+
* UTF-8, judged by the same schema, read before `plan`, `run` or `start` and stopped by Ctrl-C and the run deadline.
|
|
9
|
+
* A stdin that is not a terminal fails with `STDIN_STALLED` (exit 1) once it sends nothing for `STDIN_IDLE_MS`,
|
|
10
|
+
* counted from the start of the read and from each chunk. Wrap the whole string
|
|
11
|
+
* schema (`.optional()` and `.describe()` may follow), on at most one arg and never an option.
|
|
12
|
+
*/
|
|
13
|
+
export function orStdin(schema) {
|
|
14
|
+
return schema.meta({ [STDIN_META]: true });
|
|
15
|
+
}
|
|
16
|
+
export function isStdinSchema(schema) {
|
|
17
|
+
return z.globalRegistry.get(schema)?.[STDIN_META] === true;
|
|
18
|
+
}
|
|
19
|
+
function endOfInputKeys(platform) {
|
|
20
|
+
return platform === "win32" ? "Ctrl-Z then Enter" : "Ctrl-D";
|
|
21
|
+
}
|
|
22
|
+
/** The progress line shown before reading a terminal, so a person isn't left facing silence. */
|
|
23
|
+
export function readingLine(name, platform) {
|
|
24
|
+
return `reading <${name}> from stdin; end it with ${endOfInputKeys(platform)}`;
|
|
25
|
+
}
|
|
26
|
+
export function isTerminal(source) {
|
|
27
|
+
return typeof source !== "string" && "isTTY" in source && source.isTTY === true;
|
|
28
|
+
}
|
|
29
|
+
export const STDIN_STALLED = "STDIN_STALLED";
|
|
30
|
+
/** How long a stdin that is not a terminal may send nothing, from the start of the read and from each chunk. */
|
|
31
|
+
export const STDIN_IDLE_MS = 30_000;
|
|
32
|
+
export function stdinStalled(callerLine) {
|
|
33
|
+
return new CliError({
|
|
34
|
+
code: STDIN_STALLED,
|
|
35
|
+
message: `stdin sent nothing for ${STDIN_IDLE_MS} ms`,
|
|
36
|
+
hint: `stdin never ended: close the pipe or heredoc that feeds \`${callerLine}\`, ` +
|
|
37
|
+
"pass the text as an argument instead, " +
|
|
38
|
+
"or write a slow producer's output to a file and redirect it in",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The whole of `source` as UTF-8; rejects with the signal's reason once it aborts, and with
|
|
43
|
+
* `idle.stalled()` once a stream that is not a terminal sends nothing for `STDIN_IDLE_MS`.
|
|
44
|
+
*/
|
|
45
|
+
export function readStdin(source, signal, idle) {
|
|
46
|
+
if (typeof source === "string") {
|
|
47
|
+
return signal.aborted ? Promise.reject(signal.reason) : Promise.resolve(source);
|
|
48
|
+
}
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const chunks = [];
|
|
51
|
+
let idleWindow = new AbortController();
|
|
52
|
+
const watchIdle = () => {
|
|
53
|
+
idleWindow.abort();
|
|
54
|
+
idleWindow = new AbortController();
|
|
55
|
+
if (isTerminal(source))
|
|
56
|
+
return;
|
|
57
|
+
after(idle.clock, STDIN_IDLE_MS, idleWindow.signal, () => {
|
|
58
|
+
stop();
|
|
59
|
+
reject(idle.stalled());
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
const onData = (chunk) => {
|
|
63
|
+
chunks.push(chunk instanceof Uint8Array ? chunk : Buffer.from(String(chunk)));
|
|
64
|
+
watchIdle();
|
|
65
|
+
};
|
|
66
|
+
const onEnd = () => {
|
|
67
|
+
stop();
|
|
68
|
+
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
69
|
+
};
|
|
70
|
+
const onError = (error) => {
|
|
71
|
+
stop();
|
|
72
|
+
reject(error);
|
|
73
|
+
};
|
|
74
|
+
const onAbort = () => {
|
|
75
|
+
stop();
|
|
76
|
+
reject(signal.reason);
|
|
77
|
+
};
|
|
78
|
+
const stop = () => {
|
|
79
|
+
source.off("data", onData).off("end", onEnd).off("error", onError).pause();
|
|
80
|
+
signal.removeEventListener("abort", onAbort);
|
|
81
|
+
idleWindow.abort();
|
|
82
|
+
};
|
|
83
|
+
if (signal.aborted) {
|
|
84
|
+
reject(signal.reason);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
88
|
+
watchIdle();
|
|
89
|
+
source.on("data", onData).once("end", onEnd).once("error", onError);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=stdin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdin.js","sourceRoot":"","sources":["../src/stdin.ts"],"names":[],"mappings":"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"}
|
package/dist/style.d.ts
CHANGED
package/dist/tokenize.d.ts
CHANGED
|
@@ -15,6 +15,9 @@ export interface Words {
|
|
|
15
15
|
readonly unknownOptions: readonly string[];
|
|
16
16
|
/** The last value of each known flag passed; `true` for a switch or a flag given no value. */
|
|
17
17
|
readonly values: ReadonlyMap<string, string | true>;
|
|
18
|
+
/** Every value of each known flag passed, in order. */
|
|
19
|
+
readonly occurrences: ReadonlyMap<string, readonly (string | true)[]>;
|
|
18
20
|
}
|
|
21
|
+
export declare function isOptionLike(word: string | undefined): boolean;
|
|
19
22
|
/** Splits a Command's words into operands, unknown options and the values of known flags. */
|
|
20
23
|
export declare function tokenize(words: readonly string[], known: readonly KnownFlag[]): Words;
|