spec-controller 0.1.0-alpha.3 → 0.1.0-alpha.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -4
- package/dist/cli-allocate/cli.d.ts +2 -0
- package/dist/cli-allocate/cli.d.ts.map +1 -0
- package/dist/cli-allocate/cli.js +45 -0
- package/dist/cli-allocate/cli.js.map +1 -0
- package/dist/cli-allocate/readHistory.d.ts +21 -0
- package/dist/cli-allocate/readHistory.d.ts.map +1 -0
- package/dist/cli-allocate/readHistory.js +97 -0
- package/dist/cli-allocate/readHistory.js.map +1 -0
- package/dist/cli-allocate/readParts.d.ts +3 -0
- package/dist/cli-allocate/readParts.d.ts.map +1 -0
- package/dist/cli-allocate/readParts.js +25 -0
- package/dist/cli-allocate/readParts.js.map +1 -0
- package/dist/cli-allocate/readTree.d.ts +17 -0
- package/dist/cli-allocate/readTree.d.ts.map +1 -0
- package/dist/cli-allocate/readTree.js +63 -0
- package/dist/cli-allocate/readTree.js.map +1 -0
- package/dist/cli-allocate/request.d.ts +11 -0
- package/dist/cli-allocate/request.d.ts.map +1 -0
- package/dist/cli-allocate/request.js +29 -0
- package/dist/cli-allocate/request.js.map +1 -0
- package/dist/cli-allocate/stderr.d.ts +14 -0
- package/dist/cli-allocate/stderr.d.ts.map +1 -0
- package/dist/cli-allocate/stderr.js +33 -0
- package/dist/cli-allocate/stderr.js.map +1 -0
- package/dist/cli-args.d.ts +70 -14
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +239 -18
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-balance/cli.d.ts +18 -1
- package/dist/cli-balance/cli.d.ts.map +1 -1
- package/dist/cli-balance/cli.js +185 -161
- package/dist/cli-balance/cli.js.map +1 -1
- package/dist/cli-registry.d.ts +28 -0
- package/dist/cli-registry.d.ts.map +1 -1
- package/dist/cli-registry.js +39 -34
- package/dist/cli-registry.js.map +1 -1
- package/dist/cli.d.ts +4 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +26 -12
- package/dist/cli.js.map +1 -1
- package/dist/deferralTags.d.ts +2 -2
- package/dist/deferralTags.js +2 -2
- package/dist/host.d.ts +25 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +119 -15
- package/dist/host.js.map +1 -1
- package/dist/ingest/gherkinValidation.d.ts +9 -12
- package/dist/ingest/gherkinValidation.d.ts.map +1 -1
- package/dist/ingest/gherkinValidation.js +9 -12
- package/dist/ingest/gherkinValidation.js.map +1 -1
- package/dist/ingest/ingestQualityChecks.d.ts +3 -49
- package/dist/ingest/ingestQualityChecks.d.ts.map +1 -1
- package/dist/ingest/ingestQualityChecks.js +27 -120
- package/dist/ingest/ingestQualityChecks.js.map +1 -1
- package/dist/ingest/ingestScenarios.d.ts +8 -14
- package/dist/ingest/ingestScenarios.d.ts.map +1 -1
- package/dist/ingest/ingestScenarios.js +32 -55
- package/dist/ingest/ingestScenarios.js.map +1 -1
- package/package.json +2 -7
- package/dist/corpus/cli.d.ts +0 -34
- package/dist/corpus/cli.d.ts.map +0 -1
- package/dist/corpus/cli.js +0 -128
- package/dist/corpus/cli.js.map +0 -1
- package/dist/mutation-ratchet/index.d.ts +0 -46
- package/dist/mutation-ratchet/index.d.ts.map +0 -1
- package/dist/mutation-ratchet/index.js +0 -46
- package/dist/mutation-ratchet/index.js.map +0 -1
- package/dist/mutation-ratchet/record.d.ts +0 -178
- package/dist/mutation-ratchet/record.d.ts.map +0 -1
- package/dist/mutation-ratchet/record.js +0 -314
- package/dist/mutation-ratchet/record.js.map +0 -1
- package/dist/mutation-ratchet/report.d.ts +0 -109
- package/dist/mutation-ratchet/report.d.ts.map +0 -1
- package/dist/mutation-ratchet/report.js +0 -156
- package/dist/mutation-ratchet/report.js.map +0 -1
package/dist/cli-args.d.ts
CHANGED
|
@@ -13,11 +13,9 @@
|
|
|
13
13
|
* command rather than for the one this code was written beside. `checkUnknownFlags` took the
|
|
14
14
|
* registry and looked `balance` up inside itself; the command is a parameter now, exactly as it
|
|
15
15
|
* became one for `renderCommandHelp` (3F-3298). @SCN-CLI-009's scenario is unchanged and still
|
|
16
|
-
* asks about `balance`:
|
|
17
|
-
* residual — that an unregistered flag to `tags` is unproven by a scenario of its own — is named
|
|
18
|
-
* on 3F-3286 rather than left silent.
|
|
16
|
+
* asks about `balance`: a command added later gets the same bounding BY CONSTRUCTION.
|
|
19
17
|
*/
|
|
20
|
-
import type { CliRegistry } from "./cli-registry.js";
|
|
18
|
+
import type { CliRegistry, FlagSpec } from "./cli-registry.js";
|
|
21
19
|
/**
|
|
22
20
|
* Parse `--flag value` pairs from a command's argv into a record, keys with the `--` stripped.
|
|
23
21
|
*
|
|
@@ -25,33 +23,88 @@ import type { CliRegistry } from "./cli-registry.js";
|
|
|
25
23
|
* the boolean flags — `--strict`, `--help` — are recognised: presence is what matters, so callers
|
|
26
24
|
* read them with `!== undefined`.
|
|
27
25
|
*
|
|
28
|
-
* PERMISSIVE BY ITSELF, AND BOUNDED BY THE CALLER. It records whatever it is given
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
26
|
+
* PERMISSIVE BY ITSELF, AND BOUNDED BY THE CALLER. It records whatever it is given — a flag no
|
|
27
|
+
* registry names, the last of two copies, a word after a flag that takes none — and drops a word
|
|
28
|
+
* that follows no flag. `checkArgvShape` and `checkUnknownFlags` below are what refuse those, before
|
|
29
|
+
* anything reads the record (3F-3672). The split is deliberate — the parse has no opinion about which
|
|
30
|
+
* command it is reading for, and the bounding has nothing else to do.
|
|
32
31
|
*/
|
|
33
32
|
export declare function parseArgs(argv: readonly string[]): Record<string, string>;
|
|
33
|
+
/**
|
|
34
|
+
* The value flags of one scope: every flag the registry gives a value placeholder (`arg`), by
|
|
35
|
+
* name and alias, dashes kept. Read from the registry alone, so a value flag added later is one.
|
|
36
|
+
*/
|
|
37
|
+
export declare function valueFlagsOf(flags: readonly FlagSpec[]): Map<string, FlagSpec>;
|
|
38
|
+
/**
|
|
39
|
+
* True when the token after a value flag is not a value: there is none, it is the next flag (the
|
|
40
|
+
* same `--` test `parseArgs` reads a flag by), or it is empty — an unset variable, quoted.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isMissingValue(next: string | undefined): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* A flag that takes a value, given none, is a usage fault (@SCN-CLI-058, 3F-3639). It reads the
|
|
45
|
+
* RAW argv, because `parseArgs` has already turned a missing value into the string "true" — which a
|
|
46
|
+
* path flag then looked for on disk, `--target` recorded, and `--format` dropped on its way to a
|
|
47
|
+
* verdict `--exit-zero` turned green. Returns the refusal for the first such flag, else null.
|
|
48
|
+
*/
|
|
49
|
+
export declare function checkMissingValues(argv: readonly string[], registry: CliRegistry, command: string): string | null;
|
|
50
|
+
/** The refusal for a value flag given none: the flag, the value it takes, and where the flags are listed. */
|
|
51
|
+
export declare function missingValueRefusal(given: string, flag: FlagSpec, scope: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* The shape of a command's argv, read against its registry scope (3F-3672): every token is a flag,
|
|
54
|
+
* or the value of the flag before it, or a usage fault. Returns the refusal for the first token that
|
|
55
|
+
* is neither, else null.
|
|
56
|
+
*/
|
|
57
|
+
export declare function checkArgvShape(argv: readonly string[], registry: CliRegistry, command: string): string | null;
|
|
58
|
+
/**
|
|
59
|
+
* The positional arguments in a command's argv, in order: every word that is no flag and no flag's
|
|
60
|
+
* value. A flag the registry gives no value placeholder takes none, so `--new ZZ` reads ZZ as the
|
|
61
|
+
* positional, never as `--new`'s value — which `parseArgs` alone would make it.
|
|
62
|
+
*/
|
|
63
|
+
export declare function positionalArguments(argv: readonly string[], registry: CliRegistry, command: string): string[];
|
|
64
|
+
/** The refusal for a flag given more than once that is read once: the flag, and where. */
|
|
65
|
+
export declare function givenTwiceRefusal(given: string, scope: string): string;
|
|
66
|
+
/** A flag written with its value after an `=`, as in `--format=json`: a form this CLI does not read. */
|
|
67
|
+
export declare function isEqualsForm(token: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* The refusal for a flag written `--flag=value` (@SCN-CLI-065, 3F-3672): the form as given, and the
|
|
70
|
+
* spelling that is read — the flag and its value as two arguments, or the flag alone when it takes
|
|
71
|
+
* none. Never the unknown-flag pin advice: no version reads the form, so no pin cures it. Refused
|
|
72
|
+
* rather than split, by ruling: one spelling means one reader of argv, where splitting would teach
|
|
73
|
+
* every reader of it the same answer.
|
|
74
|
+
*/
|
|
75
|
+
export declare function equalsFormRefusal(token: string, flags: ReadonlyMap<string, FlagSpec>, scope: string): string;
|
|
76
|
+
/**
|
|
77
|
+
* A host modifier given after the command is out of place, not unknown (@SCN-CLI-061, 3F-3639): the
|
|
78
|
+
* flag exists, so @SCN-CLI-009's advice to bump a pin to a version that accepts it is false. Its own
|
|
79
|
+
* check rather than a branch of `checkUnknownFlags`, because the caller refuses this one through
|
|
80
|
+
* `process.exit` — the unknown-flag path sets a status and returns, which inside a stored run reaches
|
|
81
|
+
* the scaffold that stamps a run.yaml (3F-3650). Returns the refusal for the first such flag, else null.
|
|
82
|
+
*/
|
|
83
|
+
export declare function checkMisplacedHostModifiers(args: Record<string, string>, registry: CliRegistry, command: string): string | null;
|
|
34
84
|
/**
|
|
35
85
|
* The registry-bounded flag check at a command's CLI edge (@SCN-CLI-009). A command accepts ONLY
|
|
36
86
|
* the flags its per-command registry scope LISTS (by `name` or `alias`); an unregistered flag — a
|
|
37
|
-
* typo like `--strcit`, a stray `--bogus` — is a usage error,
|
|
38
|
-
*
|
|
87
|
+
* typo like `--strcit`, a stray `--bogus` — is a usage error, where the permissive parse above would
|
|
88
|
+
* have recorded it. It bounds flag NAMES and nothing else: a word that is no flag, a value given to a
|
|
89
|
+
* flag that takes none, a second copy, a `--flag=value` form, are `checkArgvShape`'s, which runs
|
|
90
|
+
* first (@SCN-CLI-062–066, 3F-3672). This is the structural teeth behind "accepted = registry
|
|
39
91
|
* = help": a flag cannot affect behaviour without a registry entry, and so (by @SCN-CLI-008's
|
|
40
92
|
* guard) without appearing in that command's help.
|
|
41
93
|
*
|
|
42
94
|
* PURE and `@unit`-testable: the parsed args (keys already `--`-stripped) plus the registry and
|
|
43
95
|
* the command to bound against, returning the FIRST unregistered flag as a typed usage error
|
|
44
96
|
* naming it WITH its dashes — routed to stderr and the enumerated usage status 2 by the caller,
|
|
45
|
-
* never 1, never a silent run — else null. The global `--store`/`--run-id` modifiers
|
|
46
|
-
*
|
|
47
|
-
*
|
|
97
|
+
* never 1, never a silent run — else null. The global `--store`/`--run-id` modifiers are consumed
|
|
98
|
+
* by the top-level dispatcher when they come BEFORE the command; written after it they reach the
|
|
99
|
+
* command, and `checkMisplacedHostModifiers` refuses them as out of place before this runs
|
|
100
|
+
* (@SCN-CLI-061).
|
|
48
101
|
*
|
|
49
102
|
* A COMMAND THE REGISTRY DOES NOT NAME ACCEPTS NOTHING, which is the honest reading rather than a
|
|
50
103
|
* degenerate one: an unregistered command has no scope, so every flag given to it is outside it.
|
|
51
104
|
* The dispatcher refuses such a command before this is ever reached, so the case is unreachable
|
|
52
105
|
* today and stated here so it cannot become a silent "accept everything" later.
|
|
53
106
|
*
|
|
54
|
-
* IT NAMES THE VERSION THAT REFUSED, AND THAT IS FOR THE PINNED READER (3F-3105, @SCN-
|
|
107
|
+
* IT NAMES THE VERSION THAT REFUSED, AND THAT IS FOR THE PINNED READER (3F-3105, @SCN-CLI-009).
|
|
55
108
|
* A consumer pins spec-controller and then moves their own tree; the pinned reader is handed argv
|
|
56
109
|
* it was published too early — or too late — to understand, and an unadorned "unknown flag" is
|
|
57
110
|
* indistinguishable from a typo. Naming the running version makes version skew legible from the CI
|
|
@@ -65,6 +118,9 @@ export declare function parseArgs(argv: readonly string[]): Record<string, strin
|
|
|
65
118
|
* refusal is exactly that forbidden wrapper, and no other adopter could write one either. So the
|
|
66
119
|
* refusal is the tool's own, which makes it universal rather than local.
|
|
67
120
|
*
|
|
121
|
+
* EXCEPT FOR A FLAG THE COMMAND HAS RETIRED, where the bump is false advice: `retiredFlagRefusal`
|
|
122
|
+
* below names the retirement and its replacement instead (3F-3528).
|
|
123
|
+
*
|
|
68
124
|
* THE STATUS DOES NOT MOVE. The caller still routes this to stderr and exit 2. A mistyped `--strcit`
|
|
69
125
|
* is still a usage fault, and giving skew its own status would cost every adopter the ordinary
|
|
70
126
|
* reading to serve the rarer one.
|
package/dist/cli-args.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAe,QAAQ,EAAkB,MAAM,mBAAmB,CAAC;AAE5F;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBzE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAO9E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAUf;AAED,6GAA6G;AAC7G,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKxF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW7G;AAgBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAS7G;AAgCD,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtE;AAgBD,wGAAwG;AACxG,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAW5G;AAgDD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CASf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CA2Bf"}
|
package/dist/cli-args.js
CHANGED
|
@@ -13,9 +13,7 @@
|
|
|
13
13
|
* command rather than for the one this code was written beside. `checkUnknownFlags` took the
|
|
14
14
|
* registry and looked `balance` up inside itself; the command is a parameter now, exactly as it
|
|
15
15
|
* became one for `renderCommandHelp` (3F-3298). @SCN-CLI-009's scenario is unchanged and still
|
|
16
|
-
* asks about `balance`:
|
|
17
|
-
* residual — that an unregistered flag to `tags` is unproven by a scenario of its own — is named
|
|
18
|
-
* on 3F-3286 rather than left silent.
|
|
16
|
+
* asks about `balance`: a command added later gets the same bounding BY CONSTRUCTION.
|
|
19
17
|
*/
|
|
20
18
|
/**
|
|
21
19
|
* Parse `--flag value` pairs from a command's argv into a record, keys with the `--` stripped.
|
|
@@ -24,10 +22,11 @@
|
|
|
24
22
|
* the boolean flags — `--strict`, `--help` — are recognised: presence is what matters, so callers
|
|
25
23
|
* read them with `!== undefined`.
|
|
26
24
|
*
|
|
27
|
-
* PERMISSIVE BY ITSELF, AND BOUNDED BY THE CALLER. It records whatever it is given
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
25
|
+
* PERMISSIVE BY ITSELF, AND BOUNDED BY THE CALLER. It records whatever it is given — a flag no
|
|
26
|
+
* registry names, the last of two copies, a word after a flag that takes none — and drops a word
|
|
27
|
+
* that follows no flag. `checkArgvShape` and `checkUnknownFlags` below are what refuse those, before
|
|
28
|
+
* anything reads the record (3F-3672). The split is deliberate — the parse has no opinion about which
|
|
29
|
+
* command it is reading for, and the bounding has nothing else to do.
|
|
31
30
|
*/
|
|
32
31
|
export function parseArgs(argv) {
|
|
33
32
|
const args = {};
|
|
@@ -47,27 +46,228 @@ export function parseArgs(argv) {
|
|
|
47
46
|
}
|
|
48
47
|
return args;
|
|
49
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* The value flags of one scope: every flag the registry gives a value placeholder (`arg`), by
|
|
51
|
+
* name and alias, dashes kept. Read from the registry alone, so a value flag added later is one.
|
|
52
|
+
*/
|
|
53
|
+
export function valueFlagsOf(flags) {
|
|
54
|
+
const valueFlags = new Map();
|
|
55
|
+
for (const flag of flags) {
|
|
56
|
+
if (flag.arg === undefined)
|
|
57
|
+
continue;
|
|
58
|
+
for (const name of [flag.name, ...(flag.aliases ?? [])])
|
|
59
|
+
valueFlags.set(name, flag);
|
|
60
|
+
}
|
|
61
|
+
return valueFlags;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* True when the token after a value flag is not a value: there is none, it is the next flag (the
|
|
65
|
+
* same `--` test `parseArgs` reads a flag by), or it is empty — an unset variable, quoted.
|
|
66
|
+
*/
|
|
67
|
+
export function isMissingValue(next) {
|
|
68
|
+
return next === undefined || next === "" || next.startsWith("--");
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A flag that takes a value, given none, is a usage fault (@SCN-CLI-058, 3F-3639). It reads the
|
|
72
|
+
* RAW argv, because `parseArgs` has already turned a missing value into the string "true" — which a
|
|
73
|
+
* path flag then looked for on disk, `--target` recorded, and `--format` dropped on its way to a
|
|
74
|
+
* verdict `--exit-zero` turned green. Returns the refusal for the first such flag, else null.
|
|
75
|
+
*/
|
|
76
|
+
export function checkMissingValues(argv, registry, command) {
|
|
77
|
+
const entry = registry.commands.find((c) => c.name === command);
|
|
78
|
+
const valueFlags = valueFlagsOf(entry?.flags ?? []);
|
|
79
|
+
for (let i = 0; i < argv.length; i++) {
|
|
80
|
+
const flag = valueFlags.get(argv[i] ?? "");
|
|
81
|
+
if (flag !== undefined && isMissingValue(argv[i + 1])) {
|
|
82
|
+
return missingValueRefusal(argv[i] ?? flag.name, flag, `spec-controller ${command}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
/** The refusal for a value flag given none: the flag, the value it takes, and where the flags are listed. */
|
|
88
|
+
export function missingValueRefusal(given, flag, scope) {
|
|
89
|
+
return (`The ${given} flag of '${scope}' needs a value — ${given} ${flag.arg ?? ""} — and was given none.\n` +
|
|
90
|
+
`Run '${scope} --help' to see the flags this version accepts and the values they take.`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The shape of a command's argv, read against its registry scope (3F-3672): every token is a flag,
|
|
94
|
+
* or the value of the flag before it, or a usage fault. Returns the refusal for the first token that
|
|
95
|
+
* is neither, else null.
|
|
96
|
+
*/
|
|
97
|
+
export function checkArgvShape(argv, registry, command) {
|
|
98
|
+
const scope = flagScopeOf(registry, command);
|
|
99
|
+
const seen = new Set();
|
|
100
|
+
const positionals = positionalsOf(registry, command);
|
|
101
|
+
const walk = { scope, seen, positionals, slotsLeft: positionals.length };
|
|
102
|
+
for (let i = 0; i < argv.length; i++) {
|
|
103
|
+
const read = readToken(argv, i, walk, command);
|
|
104
|
+
if (typeof read === "string")
|
|
105
|
+
return read;
|
|
106
|
+
i += read;
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
/** The positional arguments a command takes, in order; none for a command that takes flags only. */
|
|
111
|
+
function positionalsOf(registry, command) {
|
|
112
|
+
return registry.commands.find((c) => c.name === command)?.positionals ?? [];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The positional arguments in a command's argv, in order: every word that is no flag and no flag's
|
|
116
|
+
* value. A flag the registry gives no value placeholder takes none, so `--new ZZ` reads ZZ as the
|
|
117
|
+
* positional, never as `--new`'s value — which `parseArgs` alone would make it.
|
|
118
|
+
*/
|
|
119
|
+
export function positionalArguments(argv, registry, command) {
|
|
120
|
+
const scope = flagScopeOf(registry, command);
|
|
121
|
+
const words = [];
|
|
122
|
+
for (let i = 0; i < argv.length; i++) {
|
|
123
|
+
const token = argv[i] ?? "";
|
|
124
|
+
if (!isFlagShaped(token))
|
|
125
|
+
words.push(token);
|
|
126
|
+
else if (scope.get(token)?.arg !== undefined)
|
|
127
|
+
i++;
|
|
128
|
+
}
|
|
129
|
+
return words;
|
|
130
|
+
}
|
|
131
|
+
/** One token of the walk: the refusal it earns, or how many of the tokens after it are its value. */
|
|
132
|
+
function readToken(argv, i, walk, command) {
|
|
133
|
+
const token = argv[i] ?? "";
|
|
134
|
+
const next = argv[i + 1];
|
|
135
|
+
if (isEqualsForm(token))
|
|
136
|
+
return equalsFormRefusal(token, walk.scope, `spec-controller ${command}`);
|
|
137
|
+
if (!isFlagShaped(token) && !walk.scope.has(token))
|
|
138
|
+
return positionalRead(token, walk, command);
|
|
139
|
+
const flag = walk.scope.get(token);
|
|
140
|
+
if (flag === undefined)
|
|
141
|
+
return valueTokensAfter(undefined, next);
|
|
142
|
+
return registeredFlagRefusal(flag, token, next, walk, command) ?? valueTokensAfter(flag, next);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The refusal a registered flag earns where it stands: given a second time when the registry does not
|
|
146
|
+
* mark it `repeatable` (by name or alias, one flag), or given a value it does not take.
|
|
147
|
+
*/
|
|
148
|
+
function registeredFlagRefusal(flag, token, next, walk, command) {
|
|
149
|
+
if (walk.seen.has(flag) && flag.repeatable !== true)
|
|
150
|
+
return givenTwiceRefusal(token, `spec-controller ${command}`);
|
|
151
|
+
walk.seen.add(flag);
|
|
152
|
+
if (flag.arg === undefined && next !== undefined && !isFlagShaped(next) && !walk.scope.has(next) && walk.slotsLeft === 0) {
|
|
153
|
+
return takesNoValueRefusal(token, next, command);
|
|
154
|
+
}
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
/** The refusal for a flag given more than once that is read once: the flag, and where. */
|
|
158
|
+
export function givenTwiceRefusal(given, scope) {
|
|
159
|
+
return (`The ${given} flag of '${scope}' was given more than once, and is read once: give it once.\n` +
|
|
160
|
+
`Run '${scope} --help' to see the flags this version accepts.`);
|
|
161
|
+
}
|
|
162
|
+
/** Every flag of one command's scope, by name and alias, dashes kept. */
|
|
163
|
+
function flagScopeOf(registry, command) {
|
|
164
|
+
const scope = new Map();
|
|
165
|
+
for (const flag of registry.commands.find((c) => c.name === command)?.flags ?? []) {
|
|
166
|
+
for (const name of [flag.name, ...(flag.aliases ?? [])])
|
|
167
|
+
scope.set(name, flag);
|
|
168
|
+
}
|
|
169
|
+
return scope;
|
|
170
|
+
}
|
|
171
|
+
/** A token read as a flag whether or not the scope has it: two dashes, as `parseArgs` reads one. */
|
|
172
|
+
function isFlagShaped(token) {
|
|
173
|
+
return token.startsWith("--");
|
|
174
|
+
}
|
|
175
|
+
/** A flag written with its value after an `=`, as in `--format=json`: a form this CLI does not read. */
|
|
176
|
+
export function isEqualsForm(token) {
|
|
177
|
+
return isFlagShaped(token) && token.includes("=");
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The refusal for a flag written `--flag=value` (@SCN-CLI-065, 3F-3672): the form as given, and the
|
|
181
|
+
* spelling that is read — the flag and its value as two arguments, or the flag alone when it takes
|
|
182
|
+
* none. Never the unknown-flag pin advice: no version reads the form, so no pin cures it. Refused
|
|
183
|
+
* rather than split, by ruling: one spelling means one reader of argv, where splitting would teach
|
|
184
|
+
* every reader of it the same answer.
|
|
185
|
+
*/
|
|
186
|
+
export function equalsFormRefusal(token, flags, scope) {
|
|
187
|
+
const at = token.indexOf("=");
|
|
188
|
+
const name = token.slice(0, at);
|
|
189
|
+
const value = token.slice(at + 1);
|
|
190
|
+
const flag = flags.get(name);
|
|
191
|
+
const spelling = flag !== undefined && flag.arg === undefined ? name : `${name} ${value === "" ? (flag?.arg ?? "<value>") : value}`;
|
|
192
|
+
return (`The ${token} form is not read by '${scope}': a flag and its value are two arguments, as in '${spelling}'.\n` +
|
|
193
|
+
`Run '${scope} --help' to see the flags this version accepts.`);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* How many tokens after a flag are its value: one for a value flag given one, and — for a flag the
|
|
197
|
+
* scope does not have — one for the word after it, exactly as `parseArgs` pairs them, so an unknown
|
|
198
|
+
* flag and its word stay @SCN-CLI-009's to refuse. An empty value is consumed as one, so it stays
|
|
199
|
+
* @SCN-CLI-058's missing value rather than becoming a stray argument.
|
|
200
|
+
*/
|
|
201
|
+
function valueTokensAfter(flag, next) {
|
|
202
|
+
if (next === undefined || isFlagShaped(next))
|
|
203
|
+
return 0;
|
|
204
|
+
return flag === undefined || flag.arg !== undefined ? 1 : 0;
|
|
205
|
+
}
|
|
206
|
+
/** The refusal for a value given to a flag that takes none: the flag, and the value it was given. */
|
|
207
|
+
function takesNoValueRefusal(flag, value, command) {
|
|
208
|
+
return (`The ${flag} flag of 'spec-controller ${command}' takes no value, and was given one: '${value}'.\n` +
|
|
209
|
+
`Run 'spec-controller ${command} --help' to see the flags this version accepts and the values they take.`);
|
|
210
|
+
}
|
|
211
|
+
/** A word that is no flag fills the command's next positional slot, or is refused when none is left. */
|
|
212
|
+
function positionalRead(token, walk, command) {
|
|
213
|
+
if (walk.slotsLeft === 0) {
|
|
214
|
+
return walk.positionals.length === 0 ? notAFlagRefusal(token, command) : extraPositionalRefusal(token, walk, command);
|
|
215
|
+
}
|
|
216
|
+
walk.slotsLeft--;
|
|
217
|
+
return 0;
|
|
218
|
+
}
|
|
219
|
+
/** The refusal for a word beyond the positional arguments a command takes: the word, and what it takes. */
|
|
220
|
+
function extraPositionalRefusal(token, walk, command) {
|
|
221
|
+
const takes = walk.positionals.map((positional) => positional.name).join(" ");
|
|
222
|
+
return (`The argument '${token}' is more than 'spec-controller ${command}' takes: it takes ${takes} once, and its flags.\n` +
|
|
223
|
+
`Run 'spec-controller ${command} --help' to see what this version accepts.`);
|
|
224
|
+
}
|
|
225
|
+
/** The refusal for a token that is no flag and no flag's value: the token, and what the command takes. */
|
|
226
|
+
function notAFlagRefusal(token, command) {
|
|
227
|
+
return (`The argument '${token}' is not a flag, nor the value of the flag before it: ` +
|
|
228
|
+
`'spec-controller ${command}' takes only flags and their values.\n` +
|
|
229
|
+
`Run 'spec-controller ${command} --help' to see the flags this version accepts.`);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* A host modifier given after the command is out of place, not unknown (@SCN-CLI-061, 3F-3639): the
|
|
233
|
+
* flag exists, so @SCN-CLI-009's advice to bump a pin to a version that accepts it is false. Its own
|
|
234
|
+
* check rather than a branch of `checkUnknownFlags`, because the caller refuses this one through
|
|
235
|
+
* `process.exit` — the unknown-flag path sets a status and returns, which inside a stored run reaches
|
|
236
|
+
* the scaffold that stamps a run.yaml (3F-3650). Returns the refusal for the first such flag, else null.
|
|
237
|
+
*/
|
|
238
|
+
export function checkMisplacedHostModifiers(args, registry, command) {
|
|
239
|
+
const modifiers = new Set(registry.global.map((flag) => flag.name.replace(/^-+/, "")));
|
|
240
|
+
const key = Object.keys(args).find((k) => modifiers.has(k));
|
|
241
|
+
if (key === undefined)
|
|
242
|
+
return null;
|
|
243
|
+
return (`The --${key} flag is a host modifier: it goes before the command, as in ` +
|
|
244
|
+
`'spec-controller --${key} <value> ${command} …', never after it.\n` +
|
|
245
|
+
`Run 'spec-controller --help' to see the host modifiers this version accepts.`);
|
|
246
|
+
}
|
|
50
247
|
/**
|
|
51
248
|
* The registry-bounded flag check at a command's CLI edge (@SCN-CLI-009). A command accepts ONLY
|
|
52
249
|
* the flags its per-command registry scope LISTS (by `name` or `alias`); an unregistered flag — a
|
|
53
|
-
* typo like `--strcit`, a stray `--bogus` — is a usage error,
|
|
54
|
-
*
|
|
250
|
+
* typo like `--strcit`, a stray `--bogus` — is a usage error, where the permissive parse above would
|
|
251
|
+
* have recorded it. It bounds flag NAMES and nothing else: a word that is no flag, a value given to a
|
|
252
|
+
* flag that takes none, a second copy, a `--flag=value` form, are `checkArgvShape`'s, which runs
|
|
253
|
+
* first (@SCN-CLI-062–066, 3F-3672). This is the structural teeth behind "accepted = registry
|
|
55
254
|
* = help": a flag cannot affect behaviour without a registry entry, and so (by @SCN-CLI-008's
|
|
56
255
|
* guard) without appearing in that command's help.
|
|
57
256
|
*
|
|
58
257
|
* PURE and `@unit`-testable: the parsed args (keys already `--`-stripped) plus the registry and
|
|
59
258
|
* the command to bound against, returning the FIRST unregistered flag as a typed usage error
|
|
60
259
|
* naming it WITH its dashes — routed to stderr and the enumerated usage status 2 by the caller,
|
|
61
|
-
* never 1, never a silent run — else null. The global `--store`/`--run-id` modifiers
|
|
62
|
-
*
|
|
63
|
-
*
|
|
260
|
+
* never 1, never a silent run — else null. The global `--store`/`--run-id` modifiers are consumed
|
|
261
|
+
* by the top-level dispatcher when they come BEFORE the command; written after it they reach the
|
|
262
|
+
* command, and `checkMisplacedHostModifiers` refuses them as out of place before this runs
|
|
263
|
+
* (@SCN-CLI-061).
|
|
64
264
|
*
|
|
65
265
|
* A COMMAND THE REGISTRY DOES NOT NAME ACCEPTS NOTHING, which is the honest reading rather than a
|
|
66
266
|
* degenerate one: an unregistered command has no scope, so every flag given to it is outside it.
|
|
67
267
|
* The dispatcher refuses such a command before this is ever reached, so the case is unreachable
|
|
68
268
|
* today and stated here so it cannot become a silent "accept everything" later.
|
|
69
269
|
*
|
|
70
|
-
* IT NAMES THE VERSION THAT REFUSED, AND THAT IS FOR THE PINNED READER (3F-3105, @SCN-
|
|
270
|
+
* IT NAMES THE VERSION THAT REFUSED, AND THAT IS FOR THE PINNED READER (3F-3105, @SCN-CLI-009).
|
|
71
271
|
* A consumer pins spec-controller and then moves their own tree; the pinned reader is handed argv
|
|
72
272
|
* it was published too early — or too late — to understand, and an unadorned "unknown flag" is
|
|
73
273
|
* indistinguishable from a typo. Naming the running version makes version skew legible from the CI
|
|
@@ -81,6 +281,9 @@ export function parseArgs(argv) {
|
|
|
81
281
|
* refusal is exactly that forbidden wrapper, and no other adopter could write one either. So the
|
|
82
282
|
* refusal is the tool's own, which makes it universal rather than local.
|
|
83
283
|
*
|
|
284
|
+
* EXCEPT FOR A FLAG THE COMMAND HAS RETIRED, where the bump is false advice: `retiredFlagRefusal`
|
|
285
|
+
* below names the retirement and its replacement instead (3F-3528).
|
|
286
|
+
*
|
|
84
287
|
* THE STATUS DOES NOT MOVE. The caller still routes this to stderr and exit 2. A mistyped `--strcit`
|
|
85
288
|
* is still a usage fault, and giving skew its own status would cost every adopter the ordinary
|
|
86
289
|
* reading to serve the rarer one.
|
|
@@ -102,13 +305,31 @@ export function checkUnknownFlags(args, registry, command, toolVersion) {
|
|
|
102
305
|
// whose scope refused it — a consumer running two commands needs to know which help to open.
|
|
103
306
|
for (const key of Object.keys(args)) {
|
|
104
307
|
if (!accepted.has(key)) {
|
|
105
|
-
return (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
308
|
+
return (retiredFlagRefusal(entry, key, command, toolVersion) ??
|
|
309
|
+
`Unknown flag --${key} for 'spec-controller ${command}' — this is spec-controller ` +
|
|
310
|
+
`${toolVersion}, and that flag is not in its ${command} scope.\n` +
|
|
311
|
+
`If this version is pinned, the pin and the tree it is reading have drifted apart: ` +
|
|
312
|
+
`bump the pin to a version whose '${command}' accepts --${key}.\n` +
|
|
313
|
+
`Otherwise run 'spec-controller ${command} --help' to see the flags this version accepts.`);
|
|
110
314
|
}
|
|
111
315
|
}
|
|
112
316
|
return null;
|
|
113
317
|
}
|
|
318
|
+
/**
|
|
319
|
+
* THE REFUSAL FOR A FLAG THE COMMAND HAS RETIRED (@SCN-CLI-023, 3F-3528), or `undefined` when the
|
|
320
|
+
* flag is merely unregistered. The drift advice above is true of a flag newer than the pin and
|
|
321
|
+
* false of a retired one: every earlier version accepts it and no later one will, so the only pin
|
|
322
|
+
* that satisfies "bump the pin to a version that accepts it" is a downgrade back onto the route
|
|
323
|
+
* the retirement removed. So this names the retirement and the replacement, and offers no pin.
|
|
324
|
+
*/
|
|
325
|
+
function retiredFlagRefusal(entry, key, command, toolVersion) {
|
|
326
|
+
const retired = entry?.retiredFlags?.find((flag) => flag.name.replace(/^-+/, "") === key);
|
|
327
|
+
if (retired === undefined)
|
|
328
|
+
return undefined;
|
|
329
|
+
return (`Retired flag ${retired.name} for 'spec-controller ${command}' — retired in spec-controller ` +
|
|
330
|
+
`${retired.retiredIn}, and no later version accepts it (this is spec-controller ${toolVersion}).\n` +
|
|
331
|
+
`Do not pin an earlier version to get it back: that restores the route it was retired with. ` +
|
|
332
|
+
`${retired.replacement}\n` +
|
|
333
|
+
`Run 'spec-controller ${command} --help' to see the flags this version accepts.`);
|
|
334
|
+
}
|
|
114
335
|
//# sourceMappingURL=cli-args.js.map
|
package/dist/cli-args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CAAC,IAAuB;IAC/C,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBAClB,CAAC,EAAE,CAAC;YACN,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAA0B;IACrD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;YAAE,SAAS;QACrC,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAwB;IACrD,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACpE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAuB,EACvB,QAAqB,EACrB,OAAe;IAEf,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3C,IAAI,IAAI,KAAK,SAAS,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACtD,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,mBAAmB,OAAO,EAAE,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6GAA6G;AAC7G,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,IAAc,EAAE,KAAa;IAC9E,OAAO,CACL,OAAO,KAAK,aAAa,KAAK,qBAAqB,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,EAAE,0BAA0B;QACpG,QAAQ,KAAK,0EAA0E,CACxF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAuB,EAAE,QAAqB,EAAE,OAAe;IAC5F,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAY,CAAC;IACjC,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,IAAI,GAAS,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;IAC/E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,CAAC,IAAI,IAAI,CAAC;IACZ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAWD,oGAAoG;AACpG,SAAS,aAAa,CAAC,QAAqB,EAAE,OAAe;IAC3D,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,WAAW,IAAI,EAAE,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAuB,EAAE,QAAqB,EAAE,OAAe;IACjG,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACvC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,SAAS;YAAE,CAAC,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qGAAqG;AACrG,SAAS,SAAS,CAAC,IAAuB,EAAE,CAAS,EAAE,IAAU,EAAE,OAAe;IAChF,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,IAAI,YAAY,CAAC,KAAK,CAAC;QAAE,OAAO,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,mBAAmB,OAAO,EAAE,CAAC,CAAC;IACnG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACjE,OAAO,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACjG,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAC5B,IAAc,EACd,KAAa,EACb,IAAwB,EACxB,IAAU,EACV,OAAe;IAEf,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;QAAE,OAAO,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,OAAO,EAAE,CAAC,CAAC;IACnH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;QACzH,OAAO,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,KAAa;IAC5D,OAAO,CACL,OAAO,KAAK,aAAa,KAAK,+DAA+D;QAC7F,QAAQ,KAAK,iDAAiD,CAC/D,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,SAAS,WAAW,CAAC,QAAqB,EAAE,OAAe;IACzD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;QAClF,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,oGAAoG;AACpG,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,KAAoC,EAAE,KAAa;IAClG,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,QAAQ,GACZ,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IACrH,OAAO,CACL,OAAO,KAAK,yBAAyB,KAAK,qDAAqD,QAAQ,MAAM;QAC7G,QAAQ,KAAK,iDAAiD,CAC/D,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,IAA0B,EAAE,IAAwB;IAC5E,IAAI,IAAI,KAAK,SAAS,IAAI,YAAY,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACvD,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,qGAAqG;AACrG,SAAS,mBAAmB,CAAC,IAAY,EAAE,KAAa,EAAE,OAAe;IACvE,OAAO,CACL,OAAO,IAAI,6BAA6B,OAAO,yCAAyC,KAAK,MAAM;QACnG,wBAAwB,OAAO,0EAA0E,CAC1G,CAAC;AACJ,CAAC;AAED,wGAAwG;AACxG,SAAS,cAAc,CAAC,KAAa,EAAE,IAAU,EAAE,OAAe;IAChE,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACxH,CAAC;IACD,IAAI,CAAC,SAAS,EAAE,CAAC;IACjB,OAAO,CAAC,CAAC;AACX,CAAC;AAED,2GAA2G;AAC3G,SAAS,sBAAsB,CAAC,KAAa,EAAE,IAAU,EAAE,OAAe;IACxE,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9E,OAAO,CACL,iBAAiB,KAAK,mCAAmC,OAAO,qBAAqB,KAAK,yBAAyB;QACnH,wBAAwB,OAAO,4CAA4C,CAC5E,CAAC;AACJ,CAAC;AAED,0GAA0G;AAC1G,SAAS,eAAe,CAAC,KAAa,EAAE,OAAe;IACrD,OAAO,CACL,iBAAiB,KAAK,wDAAwD;QAC9E,oBAAoB,OAAO,wCAAwC;QACnE,wBAAwB,OAAO,iDAAiD,CACjF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CACzC,IAA4B,EAC5B,QAAqB,EACrB,OAAe;IAEf,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACvF,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,CACL,SAAS,GAAG,8DAA8D;QAC1E,sBAAsB,GAAG,YAAY,OAAO,wBAAwB;QACpE,8EAA8E,CAC/E,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAA4B,EAC5B,QAAqB,EACrB,OAAe,EACf,WAAmB;IAEnB,+FAA+F;IAC/F,6FAA6F;IAC7F,qFAAqF;IACrF,+CAA+C;IAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;QACtC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE;YAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IACjF,CAAC;IACD,2FAA2F;IAC3F,gGAAgG;IAChG,6FAA6F;IAC7F,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CACL,kBAAkB,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,CAAC;gBACpD,kBAAkB,GAAG,yBAAyB,OAAO,8BAA8B;oBACnF,GAAG,WAAW,iCAAiC,OAAO,WAAW;oBACjE,oFAAoF;oBACpF,oCAAoC,OAAO,eAAe,GAAG,KAAK;oBAClE,kCAAkC,OAAO,iDAAiD,CAC3F,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CACzB,KAA8B,EAC9B,GAAW,EACX,OAAe,EACf,WAAmB;IAEnB,MAAM,OAAO,GAAG,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;IAC1F,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,CACL,gBAAgB,OAAO,CAAC,IAAI,yBAAyB,OAAO,iCAAiC;QAC7F,GAAG,OAAO,CAAC,SAAS,8DAA8D,WAAW,MAAM;QACnG,6FAA6F;QAC7F,GAAG,OAAO,CAAC,WAAW,IAAI;QAC1B,wBAAwB,OAAO,iDAAiD,CACjF,CAAC;AACJ,CAAC"}
|
|
@@ -32,6 +32,23 @@ export declare function checkLegacyJson(args: Record<string, string>): string |
|
|
|
32
32
|
* explicit default.
|
|
33
33
|
*/
|
|
34
34
|
export declare function sourceTarget(args: Record<string, string>): string;
|
|
35
|
+
/**
|
|
36
|
+
* Guard the supplied input-file/dir flags at the CLI edge (@SCN-CLI-002). A
|
|
37
|
+
* mistyped `--vitest` / `--cucumber` / `--features` / `--ci` / `--package-json`
|
|
38
|
+
* pointing at a non-existent path used to reconcile silently against ZERO evidence —
|
|
39
|
+
* a terrifying false all-red report meaning "you forgot the reports", not "your code
|
|
40
|
+
* is broken" (the dogfooding fault). These flags are Examples of ONE boundary
|
|
41
|
+
* rule: a supplied-but-absent input path is a hard error, and a flag added to the set
|
|
42
|
+
* inherits it rather than restating it. Scope is existence only
|
|
43
|
+
* (readability / file-vs-dir type-correctness out of scope; `exists` covers the dir
|
|
44
|
+
* flag and the file flags alike).
|
|
45
|
+
*
|
|
46
|
+
* PURE and `@unit`-testable like `checkLegacyJson` / `sourceTarget`: reads the parsed
|
|
47
|
+
* args + an injected `exists` fn (no fs), returns the FIRST supplied-but-absent
|
|
48
|
+
* `(flag, path)` as a typed error naming both — routed to stderr + a non-zero exit by
|
|
49
|
+
* `refuseUnreadableInputs` (the shared typed-error surface) — else null. An OMITTED flag is not an
|
|
50
|
+
* error (legitimately optional: simply no evidence of that kind).
|
|
51
|
+
*/
|
|
35
52
|
export declare function checkInputsExist(args: Record<string, string>, exists: (path: string) => boolean): string | null;
|
|
36
53
|
/**
|
|
37
54
|
* Guard the READABILITY of the supplied JSON inputs at the CLI edge (@SCN-CLI-014).
|
|
@@ -44,7 +61,7 @@ export declare function checkInputsExist(args: Record<string, string>, exists: (
|
|
|
44
61
|
*
|
|
45
62
|
* PURE and `@unit`-testable like its sibling guards: reads the parsed args + an injected
|
|
46
63
|
* `read` fn (no fs), returns the FIRST supplied-but-unparseable `(flag, path, failure)` as
|
|
47
|
-
* a typed error naming all three — routed to stderr + exit 2 by `
|
|
64
|
+
* a typed error naming all three — routed to stderr + exit 2 by `refuseUnreadableInputs` — else null.
|
|
48
65
|
* An omitted flag is not an error, and an unreadable file (a race after the existence
|
|
49
66
|
* check) reports as the same input fault rather than escaping as a crash.
|
|
50
67
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli-balance/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli-balance/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAuDH;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAS3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAEjE;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAChC,MAAM,GAAG,IAAI,CAcf;AAYD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,GAAG,IAAI,CAef;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,GAAG,IAAI,CAcf;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoK/C"}
|