spec-controller 0.1.0-alpha.25 → 0.1.0-alpha.27
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/dist/host.d.ts +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +14 -0
- package/dist/host.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 -2
package/dist/host.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export interface HostInvocation {
|
|
|
37
37
|
* --features f` yields the store + `balance` + `[--features, f]`, while `balance --store
|
|
38
38
|
* /s` leaves `--store` in the command's args (a `--store` AFTER the command is the
|
|
39
39
|
* command's own arg, never a host store directive) — the "global before command" contract.
|
|
40
|
+
* A modifier with nothing after it is refused (@SCN-CLI-067); an empty argv is the bare help.
|
|
40
41
|
*/
|
|
41
42
|
export declare function parseHostInvocation(argv: readonly string[], globalFlags?: readonly FlagSpec[], commands?: readonly string[]): HostInvocation;
|
|
42
43
|
/**
|
package/dist/host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE/D,6FAA6F;AAC7F,MAAM,WAAW,cAAc;IAC7B,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2FAA2F;IAC3F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE/D,6FAA6F;AAC7F,MAAM,WAAW,cAAc;IAC7B,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2FAA2F;IAC3F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,WAAW,GAAE,SAAS,QAAQ,EAAuB,EACrD,QAAQ,GAAE,SAAS,MAAM,EAAwD,GAChF,cAAc,CA2BhB;AAyFD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,EAAE,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAExG;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASlF;AAED,4FAA4F;AAC5F,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAKxF"}
|
package/dist/host.js
CHANGED
|
@@ -22,6 +22,7 @@ import { cliRegistry } from "./cli-registry.js";
|
|
|
22
22
|
* --features f` yields the store + `balance` + `[--features, f]`, while `balance --store
|
|
23
23
|
* /s` leaves `--store` in the command's args (a `--store` AFTER the command is the
|
|
24
24
|
* command's own arg, never a host store directive) — the "global before command" contract.
|
|
25
|
+
* A modifier with nothing after it is refused (@SCN-CLI-067); an empty argv is the bare help.
|
|
25
26
|
*/
|
|
26
27
|
export function parseHostInvocation(argv, globalFlags = cliRegistry.global, commands = cliRegistry.commands.map((command) => command.name)) {
|
|
27
28
|
// The modifiers and the values they take are the registry's global scope, never a list kept here
|
|
@@ -45,6 +46,8 @@ export function parseHostInvocation(argv, globalFlags = cliRegistry.global, comm
|
|
|
45
46
|
values.set(modifier.name, value ?? "");
|
|
46
47
|
i++;
|
|
47
48
|
}
|
|
49
|
+
if (i === argv.length && values.size > 0)
|
|
50
|
+
return { commandArgs: [], refusal: noCommandRefusal([...values.keys()]) };
|
|
48
51
|
return {
|
|
49
52
|
store: values.get("--store"),
|
|
50
53
|
runId: values.get("--run-id"),
|
|
@@ -71,6 +74,17 @@ function modifierRefusal(token, modifier, [value, after], read) {
|
|
|
71
74
|
}
|
|
72
75
|
return undefined;
|
|
73
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* The refusal for host modifiers with nothing after them: every modifier given, in one line, and the
|
|
79
|
+
* fix (@SCN-CLI-067). Given last, `--store <root>` used to answer the top-level help at exit 0 having
|
|
80
|
+
* run nothing, a false green for a CI step that lost its command word (3F-3686). Help after a
|
|
81
|
+
* modifier is a command here, and a bare `spec-controller` never reaches this.
|
|
82
|
+
*/
|
|
83
|
+
function noCommandRefusal(given) {
|
|
84
|
+
return (`No command followed the host modifiers given (${given.join(", ")}), so nothing ran: ` +
|
|
85
|
+
`a host modifier needs a command after it, or --help.\n` +
|
|
86
|
+
`Run 'spec-controller --help' to see the commands and host modifiers this version accepts.`);
|
|
87
|
+
}
|
|
74
88
|
/** The refusal for a modifier that took the command as its value: the modifier, the command, and the fix. */
|
|
75
89
|
function commandAsValueRefusal(token, modifier, command) {
|
|
76
90
|
return (`The ${token} host modifier took '${command}', a command, as its value, and left no command to run.\n` +
|
package/dist/host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAiB,MAAM,mBAAmB,CAAC;AAmB/D
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ingest the target's feature files — the IMPURE reader that walks features/ on disk
|
|
3
|
-
* and
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the `scnId → feature-code` grammar helper is engine-side (packages/core/src/lib/
|
|
3
|
+
* and reads each file's header code into DiscoveredFeature records (split out of the old
|
|
4
|
+
* spec/featureCodes.ts). The pure header parser (extractFeatureCode) lives here with its sole
|
|
5
|
+
* consumer; the `scnId → feature-code` grammar helper is engine-side (packages/core/src/lib/
|
|
7
6
|
* featureCode.ts); the duplicate-code lint is engine-side too since 3F-3313, as @SCN-STG-010 in
|
|
8
|
-
* parse/
|
|
7
|
+
* parse/scenarioCodeErrors.ts, and no longer a private check under tests/checks/.
|
|
8
|
+
*
|
|
9
|
+
* NO PER-FILE LIST OF SCENARIO CODES (3F-3636). One used to ride here, read by a copy of the
|
|
10
|
+
* @SCN grammar of its own, and nothing but its own test read it; a scenario's code is read by the
|
|
11
|
+
* engine's scenario walk, which is the reading the ledger's accounts are minted from.
|
|
9
12
|
*
|
|
10
13
|
* The foundation, folded into the @LDG runtime spine.
|
|
11
14
|
*/
|
|
@@ -16,8 +19,6 @@ export interface DiscoveredFeature {
|
|
|
16
19
|
/** Absolute path to the feature file. */
|
|
17
20
|
path: string;
|
|
18
21
|
featureCode: string | null;
|
|
19
|
-
/** Every @SCN-<FFF>-<NNN> scenario code in the file, in order, duplicates kept. */
|
|
20
|
-
scenarioCodes: string[];
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
24
|
* Read the Feature-level @<FFF> header tag from a feature file's source — the
|
|
@@ -25,13 +26,6 @@ export interface DiscoveredFeature {
|
|
|
25
26
|
* or a recognised evidence/routing tag. Returns null if absent.
|
|
26
27
|
*/
|
|
27
28
|
export declare function extractFeatureCode(source: string): string | null;
|
|
28
|
-
/**
|
|
29
|
-
* Parse every @SCN-<FFF>-<NNN> scenario code in a feature file's source, in
|
|
30
|
-
* document order, duplicates preserved. Only genuine TAG LINES are scanned (a
|
|
31
|
-
* line whose first non-blank character is `@` and whose every whitespace-
|
|
32
|
-
* separated token is a tag) — prose that merely mentions a code is skipped.
|
|
33
|
-
*/
|
|
34
|
-
export declare function parseScenarioCodes(source: string): string[];
|
|
35
29
|
/**
|
|
36
30
|
* Discover every feature file on disk and its header code — REFUSING a corpus the Gherkin
|
|
37
31
|
* parser rejects (@SCN-GPG-001, 3F-2817).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingestScenarios.d.ts","sourceRoot":"","sources":["../../src/ingest/ingestScenarios.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ingestScenarios.d.ts","sourceRoot":"","sources":["../../src/ingest/ingestScenarios.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAeH,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKhE;AA8DD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAsB,GAAG,iBAAiB,EAAE,CAiBjF"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ingest the target's feature files — the IMPURE reader that walks features/ on disk
|
|
3
|
-
* and
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the `scnId → feature-code` grammar helper is engine-side (packages/core/src/lib/
|
|
3
|
+
* and reads each file's header code into DiscoveredFeature records (split out of the old
|
|
4
|
+
* spec/featureCodes.ts). The pure header parser (extractFeatureCode) lives here with its sole
|
|
5
|
+
* consumer; the `scnId → feature-code` grammar helper is engine-side (packages/core/src/lib/
|
|
7
6
|
* featureCode.ts); the duplicate-code lint is engine-side too since 3F-3313, as @SCN-STG-010 in
|
|
8
|
-
* parse/
|
|
7
|
+
* parse/scenarioCodeErrors.ts, and no longer a private check under tests/checks/.
|
|
8
|
+
*
|
|
9
|
+
* NO PER-FILE LIST OF SCENARIO CODES (3F-3636). One used to ride here, read by a copy of the
|
|
10
|
+
* @SCN grammar of its own, and nothing but its own test read it; a scenario's code is read by the
|
|
11
|
+
* engine's scenario walk, which is the reading the ledger's accounts are minted from.
|
|
9
12
|
*
|
|
10
13
|
* The foundation, folded into the @LDG runtime spine.
|
|
11
14
|
*/
|
|
@@ -21,56 +24,32 @@ const CODE_PATTERN = /^[A-Z0-9]{2,5}$/;
|
|
|
21
24
|
*/
|
|
22
25
|
export function extractFeatureCode(source) {
|
|
23
26
|
const lines = source.split(/\r?\n/);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
break;
|
|
35
|
-
const tags = prev.split(/\s+/).filter((t) => t.startsWith("@"));
|
|
36
|
-
for (const tag of tags) {
|
|
37
|
-
const bare = tag.slice(1);
|
|
38
|
-
if (bare.startsWith("SCN-"))
|
|
39
|
-
continue;
|
|
40
|
-
if (["unit", "integration", "e2e", "performance", "smoke"].includes(bare))
|
|
41
|
-
continue;
|
|
42
|
-
if (CODE_PATTERN.test(bare))
|
|
43
|
-
return bare;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return null;
|
|
27
|
+
const featureLine = lines.findIndex((line) => line.trim().startsWith("Feature:"));
|
|
28
|
+
if (featureLine < 0)
|
|
29
|
+
return null;
|
|
30
|
+
return headerTagsAbove(lines, featureLine).find(isHeaderCode) ?? null;
|
|
31
|
+
}
|
|
32
|
+
/** The tags a tier or routing concern owns, which are never a file's header code. */
|
|
33
|
+
const NON_CODE_TAGS = ["unit", "integration", "e2e", "performance", "smoke"];
|
|
34
|
+
/** Is this bare tag the file's header code — not an @SCN id, not a tier tag, and code-shaped? */
|
|
35
|
+
function isHeaderCode(bare) {
|
|
36
|
+
return !bare.startsWith("SCN-") && !NON_CODE_TAGS.includes(bare) && CODE_PATTERN.test(bare);
|
|
50
37
|
}
|
|
51
38
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* line whose first non-blank character is `@` and whose every whitespace-
|
|
55
|
-
* separated token is a tag) — prose that merely mentions a code is skipped.
|
|
39
|
+
* The bare tags on the tag lines directly above the `Feature:` line, nearest line first and each
|
|
40
|
+
* line left to right. Blank lines are passed over; the first line that is not a tag line ends it.
|
|
56
41
|
*/
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!line.startsWith("@"))
|
|
63
|
-
continue;
|
|
64
|
-
const tokens = line.split(/\s+/);
|
|
65
|
-
if (!tokens.every((t) => t.startsWith("@")))
|
|
42
|
+
function headerTagsAbove(lines, featureLine) {
|
|
43
|
+
const tags = [];
|
|
44
|
+
for (let j = featureLine - 1; j >= 0; j--) {
|
|
45
|
+
const prev = lines[j].trim();
|
|
46
|
+
if (prev === "")
|
|
66
47
|
continue;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
codes.push(bare);
|
|
71
|
-
}
|
|
48
|
+
if (!prev.startsWith("@"))
|
|
49
|
+
break;
|
|
50
|
+
tags.push(...prev.split(/\s+/).filter((t) => t.startsWith("@")).map((t) => t.slice(1)));
|
|
72
51
|
}
|
|
73
|
-
return
|
|
52
|
+
return tags;
|
|
74
53
|
}
|
|
75
54
|
/**
|
|
76
55
|
* Locate the default features/ directory — `./features` under the current
|
|
@@ -88,10 +67,9 @@ function featuresDir() {
|
|
|
88
67
|
*
|
|
89
68
|
* Absence stays a REFUSAL AT THE READER — what changed is that it is typed, so a caller can decide.
|
|
90
69
|
* `balance` opts in to reporting on a target that has no corpus (most targets have no `features/`
|
|
91
|
-
* at all, and `new-client` is a supported adoption state)
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* into `tags: OK …` at exit 0.
|
|
70
|
+
* at all, and `new-client` is a supported adoption state) by catching `MissingFeatureCorpusError` by
|
|
71
|
+
* name. Returning `[]` here instead would make that decision for every caller, and one that
|
|
72
|
+
* certifies a corpus would certify an absent one as empty.
|
|
95
73
|
*
|
|
96
74
|
* ONLY `ENOENT`. A `features` path that exists but is a FILE, or one the process may not read, is
|
|
97
75
|
* a different fault and is not ours to reinterpret — it rethrows.
|
|
@@ -142,7 +120,6 @@ export function discoverFeatures(dir = featuresDir()) {
|
|
|
142
120
|
slug: name.replace(/\.feature$/, ""),
|
|
143
121
|
path,
|
|
144
122
|
featureCode: extractFeatureCode(source),
|
|
145
|
-
scenarioCodes: parseScenarioCodes(source),
|
|
146
123
|
}));
|
|
147
124
|
}
|
|
148
125
|
//# sourceMappingURL=ingestScenarios.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingestScenarios.js","sourceRoot":"","sources":["../../src/ingest/ingestScenarios.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ingestScenarios.js","sourceRoot":"","sources":["../../src/ingest/ingestScenarios.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spec-controller",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.27",
|
|
4
4
|
"description": "Reconcile the behaviour your scenarios name against the evidence that actually ran — the deterministic `balance` CLI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"reconciliation",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@cucumber/gherkin": "^41.0.0",
|
|
26
26
|
"@cucumber/messages": "^34.0.1",
|
|
27
27
|
"yaml": "^2.9.0",
|
|
28
|
-
"@3f-consulting/spec-controller-core": "0.1.0-alpha.
|
|
28
|
+
"@3f-consulting/spec-controller-core": "0.1.0-alpha.27"
|
|
29
29
|
},
|
|
30
30
|
"publishConfig": {
|
|
31
31
|
"access": "public"
|