qfai 0.3.2 → 0.3.4
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 +7 -1
- package/assets/init/.qfai/README.md +4 -0
- package/assets/init/.qfai/prompts/README.md +6 -0
- package/assets/init/.qfai/prompts/require-to-spec.md +39 -0
- package/assets/init/.qfai/require/README.md +28 -0
- package/assets/init/.qfai/rules/pnpm.md +29 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +30 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/report.d.ts +7 -0
- package/dist/cli/commands/report.d.ts.map +1 -0
- package/dist/cli/commands/report.js +87 -0
- package/dist/cli/commands/report.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +9 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +57 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.cjs +20 -3
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.mjs +20 -3
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib/args.d.ts +18 -0
- package/dist/cli/lib/args.d.ts.map +1 -0
- package/dist/cli/lib/args.js +98 -0
- package/dist/cli/lib/args.js.map +1 -0
- package/dist/cli/lib/assets.d.ts +2 -0
- package/dist/cli/lib/assets.d.ts.map +1 -0
- package/dist/cli/lib/assets.js +24 -0
- package/dist/cli/lib/assets.js.map +1 -0
- package/dist/cli/lib/failOn.d.ts +5 -0
- package/dist/cli/lib/failOn.d.ts.map +1 -0
- package/dist/cli/lib/failOn.js +10 -0
- package/dist/cli/lib/failOn.js.map +1 -0
- package/dist/cli/lib/fs.d.ts +11 -0
- package/dist/cli/lib/fs.d.ts.map +1 -0
- package/dist/cli/lib/fs.js +91 -0
- package/dist/cli/lib/fs.js.map +1 -0
- package/dist/cli/lib/logger.d.ts +4 -0
- package/dist/cli/lib/logger.d.ts.map +1 -0
- package/dist/cli/lib/logger.js +10 -0
- package/dist/cli/lib/logger.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +66 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/core/config.d.ts +44 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +218 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/contractIndex.d.ts +13 -0
- package/dist/core/contractIndex.d.ts.map +1 -0
- package/dist/core/contractIndex.js +66 -0
- package/dist/core/contractIndex.js.map +1 -0
- package/dist/core/contracts.d.ts +5 -0
- package/dist/core/contracts.d.ts.map +1 -0
- package/dist/core/contracts.js +42 -0
- package/dist/core/contracts.js.map +1 -0
- package/dist/core/discovery.d.ts +14 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/core/discovery.js +55 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/fs.d.ts +6 -0
- package/dist/core/fs.d.ts.map +1 -0
- package/dist/core/fs.js +55 -0
- package/dist/core/fs.js.map +1 -0
- package/dist/core/gherkin/parse.d.ts +7 -0
- package/dist/core/gherkin/parse.d.ts.map +1 -0
- package/dist/core/gherkin/parse.js +25 -0
- package/dist/core/gherkin/parse.js.map +1 -0
- package/dist/core/ids.d.ts +6 -0
- package/dist/core/ids.d.ts.map +1 -0
- package/dist/core/ids.js +52 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/parse/adr.d.ts +13 -0
- package/dist/core/parse/adr.d.ts.map +1 -0
- package/dist/core/parse/adr.js +33 -0
- package/dist/core/parse/adr.js.map +1 -0
- package/dist/core/parse/gherkin.d.ts +12 -0
- package/dist/core/parse/gherkin.d.ts.map +1 -0
- package/dist/core/parse/gherkin.js +22 -0
- package/dist/core/parse/gherkin.js.map +1 -0
- package/dist/core/parse/markdown.d.ts +14 -0
- package/dist/core/parse/markdown.d.ts.map +1 -0
- package/dist/core/parse/markdown.js +45 -0
- package/dist/core/parse/markdown.js.map +1 -0
- package/dist/core/parse/spec.d.ts +28 -0
- package/dist/core/parse/spec.d.ts.map +1 -0
- package/dist/core/parse/spec.js +80 -0
- package/dist/core/parse/spec.js.map +1 -0
- package/dist/core/report.d.ts +39 -0
- package/dist/core/report.d.ts.map +1 -0
- package/dist/core/report.js +226 -0
- package/dist/core/report.js.map +1 -0
- package/dist/core/scenarioModel.d.ts +33 -0
- package/dist/core/scenarioModel.d.ts.map +1 -0
- package/dist/core/scenarioModel.js +130 -0
- package/dist/core/scenarioModel.js.map +1 -0
- package/dist/core/specLayout.d.ts +8 -0
- package/dist/core/specLayout.d.ts.map +1 -0
- package/dist/core/specLayout.js +36 -0
- package/dist/core/specLayout.js.map +1 -0
- package/dist/core/types.d.ts +27 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/validate.d.ts +4 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +36 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/core/validators/contracts.d.ts +5 -0
- package/dist/core/validators/contracts.d.ts.map +1 -0
- package/dist/core/validators/contracts.js +162 -0
- package/dist/core/validators/contracts.js.map +1 -0
- package/dist/core/validators/delta.d.ts +4 -0
- package/dist/core/validators/delta.d.ts.map +1 -0
- package/dist/core/validators/delta.js +68 -0
- package/dist/core/validators/delta.js.map +1 -0
- package/dist/core/validators/ids.d.ts +4 -0
- package/dist/core/validators/ids.d.ts.map +1 -0
- package/dist/core/validators/ids.js +88 -0
- package/dist/core/validators/ids.js.map +1 -0
- package/dist/core/validators/scenario.d.ts +5 -0
- package/dist/core/validators/scenario.d.ts.map +1 -0
- package/dist/core/validators/scenario.js +137 -0
- package/dist/core/validators/scenario.js.map +1 -0
- package/dist/core/validators/spec.d.ts +5 -0
- package/dist/core/validators/spec.d.ts.map +1 -0
- package/dist/core/validators/spec.js +94 -0
- package/dist/core/validators/spec.js.map +1 -0
- package/dist/core/validators/traceability.d.ts +4 -0
- package/dist/core/validators/traceability.d.ts.map +1 -0
- package/dist/core/validators/traceability.js +180 -0
- package/dist/core/validators/traceability.js.map +1 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +25 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +2 -133
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -2
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parse as parseYaml } from "yaml";
|
|
4
|
+
export const defaultConfig = {
|
|
5
|
+
paths: {
|
|
6
|
+
contractsDir: ".qfai/contracts",
|
|
7
|
+
specsDir: ".qfai/specs",
|
|
8
|
+
rulesDir: ".qfai/rules",
|
|
9
|
+
outDir: ".qfai/out",
|
|
10
|
+
promptsDir: ".qfai/prompts",
|
|
11
|
+
srcDir: "src",
|
|
12
|
+
testsDir: "tests",
|
|
13
|
+
},
|
|
14
|
+
validation: {
|
|
15
|
+
failOn: "error",
|
|
16
|
+
require: {
|
|
17
|
+
specSections: [
|
|
18
|
+
"背景",
|
|
19
|
+
"スコープ",
|
|
20
|
+
"非ゴール",
|
|
21
|
+
"用語",
|
|
22
|
+
"前提",
|
|
23
|
+
"決定事項",
|
|
24
|
+
"業務ルール",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
traceability: {
|
|
28
|
+
brMustHaveSc: true,
|
|
29
|
+
scMustTouchContracts: true,
|
|
30
|
+
allowOrphanContracts: false,
|
|
31
|
+
unknownContractIdSeverity: "error",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
output: {
|
|
35
|
+
validateJsonPath: ".qfai/out/validate.json",
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
export function getConfigPath(root) {
|
|
39
|
+
return path.join(root, "qfai.config.yaml");
|
|
40
|
+
}
|
|
41
|
+
export async function loadConfig(root) {
|
|
42
|
+
const configPath = getConfigPath(root);
|
|
43
|
+
const issues = [];
|
|
44
|
+
let parsed;
|
|
45
|
+
try {
|
|
46
|
+
const raw = await readFile(configPath, "utf-8");
|
|
47
|
+
parsed = parseYaml(raw);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (isMissingFile(error)) {
|
|
51
|
+
return { config: defaultConfig, issues, configPath };
|
|
52
|
+
}
|
|
53
|
+
issues.push(configIssue(configPath, formatError(error)));
|
|
54
|
+
return { config: defaultConfig, issues, configPath };
|
|
55
|
+
}
|
|
56
|
+
const normalized = normalizeConfig(parsed, configPath, issues);
|
|
57
|
+
return { config: normalized, issues, configPath };
|
|
58
|
+
}
|
|
59
|
+
export function resolvePath(root, config, key) {
|
|
60
|
+
return path.resolve(root, config.paths[key]);
|
|
61
|
+
}
|
|
62
|
+
function normalizeConfig(raw, configPath, issues) {
|
|
63
|
+
if (!isRecord(raw)) {
|
|
64
|
+
issues.push(configIssue(configPath, "設定ファイルの形式が不正です。"));
|
|
65
|
+
return defaultConfig;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
paths: normalizePaths(raw.paths, configPath, issues),
|
|
69
|
+
validation: normalizeValidation(raw.validation, configPath, issues),
|
|
70
|
+
output: normalizeOutput(raw.output, configPath, issues),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function normalizePaths(raw, configPath, issues) {
|
|
74
|
+
const base = defaultConfig.paths;
|
|
75
|
+
if (!raw) {
|
|
76
|
+
return base;
|
|
77
|
+
}
|
|
78
|
+
if (!isRecord(raw)) {
|
|
79
|
+
issues.push(configIssue(configPath, "paths はオブジェクトである必要があります。"));
|
|
80
|
+
return base;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
contractsDir: readString(raw.contractsDir, base.contractsDir, "paths.contractsDir", configPath, issues),
|
|
84
|
+
specsDir: readString(raw.specsDir, base.specsDir, "paths.specsDir", configPath, issues),
|
|
85
|
+
rulesDir: readString(raw.rulesDir, base.rulesDir, "paths.rulesDir", configPath, issues),
|
|
86
|
+
outDir: readString(raw.outDir, base.outDir, "paths.outDir", configPath, issues),
|
|
87
|
+
promptsDir: readString(raw.promptsDir, base.promptsDir, "paths.promptsDir", configPath, issues),
|
|
88
|
+
srcDir: readString(raw.srcDir, base.srcDir, "paths.srcDir", configPath, issues),
|
|
89
|
+
testsDir: readString(raw.testsDir, base.testsDir, "paths.testsDir", configPath, issues),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function normalizeValidation(raw, configPath, issues) {
|
|
93
|
+
const base = defaultConfig.validation;
|
|
94
|
+
if (!raw) {
|
|
95
|
+
return base;
|
|
96
|
+
}
|
|
97
|
+
if (!isRecord(raw)) {
|
|
98
|
+
issues.push(configIssue(configPath, "validation はオブジェクトである必要があります。"));
|
|
99
|
+
return base;
|
|
100
|
+
}
|
|
101
|
+
let requireRaw;
|
|
102
|
+
if (raw.require === undefined) {
|
|
103
|
+
requireRaw = undefined;
|
|
104
|
+
}
|
|
105
|
+
else if (isRecord(raw.require)) {
|
|
106
|
+
requireRaw = raw.require;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
issues.push(configIssue(configPath, "validation.require はオブジェクトである必要があります。"));
|
|
110
|
+
requireRaw = undefined;
|
|
111
|
+
}
|
|
112
|
+
let traceabilityRaw;
|
|
113
|
+
if (raw.traceability === undefined) {
|
|
114
|
+
traceabilityRaw = undefined;
|
|
115
|
+
}
|
|
116
|
+
else if (isRecord(raw.traceability)) {
|
|
117
|
+
traceabilityRaw = raw.traceability;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
issues.push(configIssue(configPath, "validation.traceability はオブジェクトである必要があります。"));
|
|
121
|
+
traceabilityRaw = undefined;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
failOn: readFailOn(raw.failOn, base.failOn, "validation.failOn", configPath, issues),
|
|
125
|
+
require: {
|
|
126
|
+
specSections: readStringArray(requireRaw?.specSections, base.require.specSections, "validation.require.specSections", configPath, issues),
|
|
127
|
+
},
|
|
128
|
+
traceability: {
|
|
129
|
+
brMustHaveSc: readBoolean(traceabilityRaw?.brMustHaveSc, base.traceability.brMustHaveSc, "validation.traceability.brMustHaveSc", configPath, issues),
|
|
130
|
+
scMustTouchContracts: readBoolean(traceabilityRaw?.scMustTouchContracts, base.traceability.scMustTouchContracts, "validation.traceability.scMustTouchContracts", configPath, issues),
|
|
131
|
+
allowOrphanContracts: readBoolean(traceabilityRaw?.allowOrphanContracts, base.traceability.allowOrphanContracts, "validation.traceability.allowOrphanContracts", configPath, issues),
|
|
132
|
+
unknownContractIdSeverity: readTraceabilitySeverity(traceabilityRaw?.unknownContractIdSeverity, base.traceability.unknownContractIdSeverity, "validation.traceability.unknownContractIdSeverity", configPath, issues),
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function normalizeOutput(raw, configPath, issues) {
|
|
137
|
+
const base = defaultConfig.output;
|
|
138
|
+
if (!raw) {
|
|
139
|
+
return base;
|
|
140
|
+
}
|
|
141
|
+
if (!isRecord(raw)) {
|
|
142
|
+
issues.push(configIssue(configPath, "output はオブジェクトである必要があります。"));
|
|
143
|
+
return base;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
validateJsonPath: readString(raw.validateJsonPath, base.validateJsonPath, "output.validateJsonPath", configPath, issues),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function readString(value, fallback, label, configPath, issues) {
|
|
150
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
153
|
+
if (value !== undefined) {
|
|
154
|
+
issues.push(configIssue(configPath, `${label} は文字列である必要があります。`));
|
|
155
|
+
}
|
|
156
|
+
return fallback;
|
|
157
|
+
}
|
|
158
|
+
function readStringArray(value, fallback, label, configPath, issues) {
|
|
159
|
+
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
160
|
+
return value;
|
|
161
|
+
}
|
|
162
|
+
if (value !== undefined) {
|
|
163
|
+
issues.push(configIssue(configPath, `${label} は文字列配列である必要があります。`));
|
|
164
|
+
}
|
|
165
|
+
return fallback;
|
|
166
|
+
}
|
|
167
|
+
function readBoolean(value, fallback, label, configPath, issues) {
|
|
168
|
+
if (typeof value === "boolean") {
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
if (value !== undefined) {
|
|
172
|
+
issues.push(configIssue(configPath, `${label} は真偽値である必要があります。`));
|
|
173
|
+
}
|
|
174
|
+
return fallback;
|
|
175
|
+
}
|
|
176
|
+
function readFailOn(value, fallback, label, configPath, issues) {
|
|
177
|
+
if (value === "never" || value === "warning" || value === "error") {
|
|
178
|
+
return value;
|
|
179
|
+
}
|
|
180
|
+
if (value !== undefined) {
|
|
181
|
+
issues.push(configIssue(configPath, `${label} は never|warning|error のいずれかである必要があります。`));
|
|
182
|
+
}
|
|
183
|
+
return fallback;
|
|
184
|
+
}
|
|
185
|
+
function readTraceabilitySeverity(value, fallback, label, configPath, issues) {
|
|
186
|
+
if (value === "warning" || value === "error") {
|
|
187
|
+
return value;
|
|
188
|
+
}
|
|
189
|
+
if (value !== undefined) {
|
|
190
|
+
issues.push(configIssue(configPath, `${label} は warning|error のいずれかである必要があります。`));
|
|
191
|
+
}
|
|
192
|
+
return fallback;
|
|
193
|
+
}
|
|
194
|
+
function configIssue(file, message) {
|
|
195
|
+
return {
|
|
196
|
+
code: "QFAI_CONFIG_INVALID",
|
|
197
|
+
severity: "error",
|
|
198
|
+
message,
|
|
199
|
+
file,
|
|
200
|
+
rule: "config.invalid",
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function isMissingFile(error) {
|
|
204
|
+
if (error && typeof error === "object" && "code" in error) {
|
|
205
|
+
return error.code === "ENOENT";
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
function formatError(error) {
|
|
210
|
+
if (error instanceof Error) {
|
|
211
|
+
return error.message;
|
|
212
|
+
}
|
|
213
|
+
return String(error);
|
|
214
|
+
}
|
|
215
|
+
function isRecord(value) {
|
|
216
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { QfaiConfig } from "./config.js";
|
|
2
|
+
export type ContractIndex = {
|
|
3
|
+
ids: Set<string>;
|
|
4
|
+
idToFiles: Map<string, Set<string>>;
|
|
5
|
+
files: {
|
|
6
|
+
ui: string[];
|
|
7
|
+
api: string[];
|
|
8
|
+
data: string[];
|
|
9
|
+
};
|
|
10
|
+
structuredParseFailedFiles: Set<string>;
|
|
11
|
+
};
|
|
12
|
+
export declare function buildContractIndex(root: string, config: QfaiConfig): Promise<ContractIndex>;
|
|
13
|
+
//# sourceMappingURL=contractIndex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contractIndex.d.ts","sourceRoot":"","sources":["../../src/core/contractIndex.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAc9C,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,EAAE,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACvD,0BAA0B,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzC,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,aAAa,CAAC,CAwBxB"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { resolvePath } from "./config.js";
|
|
4
|
+
import { collectApiContractFiles, collectDataContractFiles, collectUiContractFiles, } from "./discovery.js";
|
|
5
|
+
import { extractApiContractIds, extractUiContractIds, parseStructuredContract, } from "./contracts.js";
|
|
6
|
+
import { extractIds } from "./ids.js";
|
|
7
|
+
export async function buildContractIndex(root, config) {
|
|
8
|
+
const contractsRoot = resolvePath(root, config, "contractsDir");
|
|
9
|
+
const uiRoot = path.join(contractsRoot, "ui");
|
|
10
|
+
const apiRoot = path.join(contractsRoot, "api");
|
|
11
|
+
const dataRoot = path.join(contractsRoot, "db");
|
|
12
|
+
const [uiFiles, apiFiles, dataFiles] = await Promise.all([
|
|
13
|
+
collectUiContractFiles(uiRoot),
|
|
14
|
+
collectApiContractFiles(apiRoot),
|
|
15
|
+
collectDataContractFiles(dataRoot),
|
|
16
|
+
]);
|
|
17
|
+
const index = {
|
|
18
|
+
ids: new Set(),
|
|
19
|
+
idToFiles: new Map(),
|
|
20
|
+
files: { ui: uiFiles, api: apiFiles, data: dataFiles },
|
|
21
|
+
structuredParseFailedFiles: new Set(),
|
|
22
|
+
};
|
|
23
|
+
await indexUiContracts(uiFiles, index);
|
|
24
|
+
await indexApiContracts(apiFiles, index);
|
|
25
|
+
await indexDataContracts(dataFiles, index);
|
|
26
|
+
return index;
|
|
27
|
+
}
|
|
28
|
+
async function indexUiContracts(files, index) {
|
|
29
|
+
for (const file of files) {
|
|
30
|
+
const text = await readFile(file, "utf-8");
|
|
31
|
+
try {
|
|
32
|
+
const doc = parseStructuredContract(file, text);
|
|
33
|
+
extractUiContractIds(doc).forEach((id) => record(index, id, file));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
index.structuredParseFailedFiles.add(file);
|
|
37
|
+
extractIds(text, "UI").forEach((id) => record(index, id, file));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function indexApiContracts(files, index) {
|
|
42
|
+
for (const file of files) {
|
|
43
|
+
const text = await readFile(file, "utf-8");
|
|
44
|
+
try {
|
|
45
|
+
const doc = parseStructuredContract(file, text);
|
|
46
|
+
extractApiContractIds(doc).forEach((id) => record(index, id, file));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
index.structuredParseFailedFiles.add(file);
|
|
50
|
+
extractIds(text, "API").forEach((id) => record(index, id, file));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function indexDataContracts(files, index) {
|
|
55
|
+
for (const file of files) {
|
|
56
|
+
const text = await readFile(file, "utf-8");
|
|
57
|
+
extractIds(text, "DATA").forEach((id) => record(index, id, file));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function record(index, id, file) {
|
|
61
|
+
index.ids.add(id);
|
|
62
|
+
const current = index.idToFiles.get(id) ?? new Set();
|
|
63
|
+
current.add(file);
|
|
64
|
+
index.idToFiles.set(id, current);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=contractIndex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contractIndex.js","sourceRoot":"","sources":["../../src/core/contractIndex.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function parseStructuredContract(file: string, text: string): Record<string, unknown>;
|
|
2
|
+
export declare function extractUiContractIds(doc: Record<string, unknown>): string[];
|
|
3
|
+
export declare function extractApiContractIds(doc: Record<string, unknown>): string[];
|
|
4
|
+
export declare function collectOperationIds(value: unknown, out: Set<string>): void;
|
|
5
|
+
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/core/contracts.ts"],"names":[],"mappings":"AAMA,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMzB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAG3E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAS5E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAkB1E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { parse as parseYaml } from "yaml";
|
|
3
|
+
import { extractIds } from "./ids.js";
|
|
4
|
+
export function parseStructuredContract(file, text) {
|
|
5
|
+
const ext = path.extname(file).toLowerCase();
|
|
6
|
+
if (ext === ".json") {
|
|
7
|
+
return JSON.parse(text);
|
|
8
|
+
}
|
|
9
|
+
return parseYaml(text);
|
|
10
|
+
}
|
|
11
|
+
export function extractUiContractIds(doc) {
|
|
12
|
+
const id = typeof doc.id === "string" ? doc.id : "";
|
|
13
|
+
return extractIds(id, "UI");
|
|
14
|
+
}
|
|
15
|
+
export function extractApiContractIds(doc) {
|
|
16
|
+
const operationIds = new Set();
|
|
17
|
+
collectOperationIds(doc, operationIds);
|
|
18
|
+
const ids = new Set();
|
|
19
|
+
for (const operationId of operationIds) {
|
|
20
|
+
extractIds(operationId, "API").forEach((id) => ids.add(id));
|
|
21
|
+
}
|
|
22
|
+
return Array.from(ids);
|
|
23
|
+
}
|
|
24
|
+
export function collectOperationIds(value, out) {
|
|
25
|
+
if (!value || typeof value !== "object") {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
for (const item of value) {
|
|
30
|
+
collectOperationIds(item, out);
|
|
31
|
+
}
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
35
|
+
if (key === "operationId" && typeof entry === "string") {
|
|
36
|
+
out.add(entry);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
collectOperationIds(entry, out);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/core/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,UAAU,uBAAuB,CACrC,IAAY,EACZ,IAAY;IAEZ,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7C,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;IACrD,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,CAA4B,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAA4B;IAC/D,MAAM,EAAE,GAAG,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,OAAO,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAA4B;IAChE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,mBAAmB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEvC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,UAAU,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAc,EAAE,GAAgB;IAClE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,mBAAmB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACjC,CAAC;QACD,OAAO;IACT,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,GAAG,KAAK,aAAa,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvD,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACf,SAAS;QACX,CAAC;QACD,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ContractFiles = {
|
|
2
|
+
api: string[];
|
|
3
|
+
ui: string[];
|
|
4
|
+
db: string[];
|
|
5
|
+
};
|
|
6
|
+
export declare function collectSpecPackDirs(specsRoot: string): Promise<string[]>;
|
|
7
|
+
export declare function collectSpecFiles(specsRoot: string): Promise<string[]>;
|
|
8
|
+
export declare function collectDeltaFiles(specsRoot: string): Promise<string[]>;
|
|
9
|
+
export declare function collectScenarioFiles(specsRoot: string): Promise<string[]>;
|
|
10
|
+
export declare function collectUiContractFiles(uiRoot: string): Promise<string[]>;
|
|
11
|
+
export declare function collectApiContractFiles(apiRoot: string): Promise<string[]>;
|
|
12
|
+
export declare function collectDataContractFiles(dataRoot: string): Promise<string[]>;
|
|
13
|
+
export declare function collectContractFiles(uiRoot: string, apiRoot: string, dataRoot: string): Promise<ContractFiles>;
|
|
14
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,EAAE,EAAE,MAAM,EAAE,CAAC;CACd,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAG3E;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAG5E;AAED,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAOxB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { access } from "node:fs/promises";
|
|
2
|
+
import { collectFiles } from "./fs.js";
|
|
3
|
+
import { collectSpecEntries } from "./specLayout.js";
|
|
4
|
+
export async function collectSpecPackDirs(specsRoot) {
|
|
5
|
+
const entries = await collectSpecEntries(specsRoot);
|
|
6
|
+
return entries.map((entry) => entry.dir);
|
|
7
|
+
}
|
|
8
|
+
export async function collectSpecFiles(specsRoot) {
|
|
9
|
+
const entries = await collectSpecEntries(specsRoot);
|
|
10
|
+
return filterExisting(entries.map((entry) => entry.specPath));
|
|
11
|
+
}
|
|
12
|
+
export async function collectDeltaFiles(specsRoot) {
|
|
13
|
+
const entries = await collectSpecEntries(specsRoot);
|
|
14
|
+
return filterExisting(entries.map((entry) => entry.deltaPath));
|
|
15
|
+
}
|
|
16
|
+
export async function collectScenarioFiles(specsRoot) {
|
|
17
|
+
const entries = await collectSpecEntries(specsRoot);
|
|
18
|
+
return filterExisting(entries.map((entry) => entry.scenarioPath));
|
|
19
|
+
}
|
|
20
|
+
export async function collectUiContractFiles(uiRoot) {
|
|
21
|
+
return collectFiles(uiRoot, { extensions: [".yaml", ".yml"] });
|
|
22
|
+
}
|
|
23
|
+
export async function collectApiContractFiles(apiRoot) {
|
|
24
|
+
return collectFiles(apiRoot, { extensions: [".yaml", ".yml", ".json"] });
|
|
25
|
+
}
|
|
26
|
+
export async function collectDataContractFiles(dataRoot) {
|
|
27
|
+
return collectFiles(dataRoot, { extensions: [".sql"] });
|
|
28
|
+
}
|
|
29
|
+
export async function collectContractFiles(uiRoot, apiRoot, dataRoot) {
|
|
30
|
+
const [ui, api, db] = await Promise.all([
|
|
31
|
+
collectUiContractFiles(uiRoot),
|
|
32
|
+
collectApiContractFiles(apiRoot),
|
|
33
|
+
collectDataContractFiles(dataRoot),
|
|
34
|
+
]);
|
|
35
|
+
return { ui, api, db };
|
|
36
|
+
}
|
|
37
|
+
async function filterExisting(files) {
|
|
38
|
+
const existing = [];
|
|
39
|
+
for (const file of files) {
|
|
40
|
+
if (await exists(file)) {
|
|
41
|
+
existing.push(file);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return existing;
|
|
45
|
+
}
|
|
46
|
+
async function exists(target) {
|
|
47
|
+
try {
|
|
48
|
+
await access(target);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,EAAE,CAAC,CAcnB"}
|
package/dist/core/fs.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { access, readdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const DEFAULT_IGNORE_DIRS = new Set([
|
|
4
|
+
"node_modules",
|
|
5
|
+
".git",
|
|
6
|
+
"dist",
|
|
7
|
+
".pnpm",
|
|
8
|
+
"tmp",
|
|
9
|
+
".mcp-tools",
|
|
10
|
+
]);
|
|
11
|
+
export async function collectFiles(root, options = {}) {
|
|
12
|
+
const entries = [];
|
|
13
|
+
if (!(await exists(root))) {
|
|
14
|
+
return entries;
|
|
15
|
+
}
|
|
16
|
+
const ignoreDirs = new Set([
|
|
17
|
+
...DEFAULT_IGNORE_DIRS,
|
|
18
|
+
...(options.ignoreDirs ?? []),
|
|
19
|
+
]);
|
|
20
|
+
const extensions = options.extensions?.map((ext) => ext.toLowerCase()) ?? [];
|
|
21
|
+
await walk(root, root, ignoreDirs, extensions, entries);
|
|
22
|
+
return entries;
|
|
23
|
+
}
|
|
24
|
+
async function walk(base, current, ignoreDirs, extensions, out) {
|
|
25
|
+
const items = await readdir(current, { withFileTypes: true });
|
|
26
|
+
for (const item of items) {
|
|
27
|
+
const fullPath = path.join(current, item.name);
|
|
28
|
+
if (item.isDirectory()) {
|
|
29
|
+
if (ignoreDirs.has(item.name)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
await walk(base, fullPath, ignoreDirs, extensions, out);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (item.isFile()) {
|
|
36
|
+
if (extensions.length > 0) {
|
|
37
|
+
const ext = path.extname(item.name).toLowerCase();
|
|
38
|
+
if (!extensions.includes(ext)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
out.push(fullPath);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function exists(target) {
|
|
47
|
+
try {
|
|
48
|
+
await access(target);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=fs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,cAAc;IACd,MAAM;IACN,MAAM;IACN,OAAO;IACP,KAAK;IACL,YAAY;CACb,CAAC,CAAC;AAOH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,UAA+B,EAAE;IAEjC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;QACzB,GAAG,mBAAmB;QACtB,GAAG,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;KAC9B,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAE7E,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACxD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,IAAY,EACZ,OAAe,EACf,UAAuB,EACvB,UAAoB,EACpB,GAAa;IAEb,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/C,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACvB,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,SAAS;YACX,CAAC;YACD,MAAM,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YACxD,SAAS;QACX,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;YAClB,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;gBAClD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9B,SAAS;gBACX,CAAC;YACH,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,MAAc;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GherkinDocument } from "@cucumber/messages";
|
|
2
|
+
export type ParsedGherkin = {
|
|
3
|
+
gherkinDocument: GherkinDocument | null;
|
|
4
|
+
errors: string[];
|
|
5
|
+
};
|
|
6
|
+
export declare function parseGherkin(source: string, uri: string): ParsedGherkin;
|
|
7
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/core/gherkin/parse.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,MAAM,MAAM,aAAa,GAAG;IAC1B,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,CAevE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AstBuilder, GherkinClassicTokenMatcher, Parser, } from "@cucumber/gherkin";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
export function parseGherkin(source, uri) {
|
|
4
|
+
const errors = [];
|
|
5
|
+
const uuidFn = () => randomUUID();
|
|
6
|
+
const builder = new AstBuilder(uuidFn);
|
|
7
|
+
const matcher = new GherkinClassicTokenMatcher();
|
|
8
|
+
const parser = new Parser(builder, matcher);
|
|
9
|
+
try {
|
|
10
|
+
const gherkinDocument = parser.parse(source);
|
|
11
|
+
gherkinDocument.uri = uri;
|
|
12
|
+
return { gherkinDocument, errors };
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
errors.push(formatError(error));
|
|
16
|
+
return { gherkinDocument: null, errors };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function formatError(error) {
|
|
20
|
+
if (error instanceof Error) {
|
|
21
|
+
return error.message;
|
|
22
|
+
}
|
|
23
|
+
return String(error);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/core/gherkin/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,0BAA0B,EAC1B,MAAM,GACP,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOzC,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,GAAW;IACtD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,0BAA0B,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE5C,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7C,eAAe,CAAC,GAAG,GAAG,GAAG,CAAC;QAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QAChC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type IdPrefix = "SPEC" | "BR" | "SC" | "UI" | "API" | "DATA";
|
|
2
|
+
export type IdFormatPrefix = IdPrefix | "ADR";
|
|
3
|
+
export declare function extractIds(text: string, prefix: IdPrefix): string[];
|
|
4
|
+
export declare function extractAllIds(text: string): string[];
|
|
5
|
+
export declare function extractInvalidIds(text: string, prefixes: IdFormatPrefix[]): string[];
|
|
6
|
+
//# sourceMappingURL=ids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../../src/core/ids.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,KAAK,CAAC;AAwB9C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,CAInE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMpD;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,cAAc,EAAE,GACzB,MAAM,EAAE,CAWV"}
|
package/dist/core/ids.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const ID_PREFIXES = ["SPEC", "BR", "SC", "UI", "API", "DATA"];
|
|
2
|
+
const STRICT_ID_PATTERNS = {
|
|
3
|
+
SPEC: /\bSPEC-\d{4}\b/g,
|
|
4
|
+
BR: /\bBR-\d{4}\b/g,
|
|
5
|
+
SC: /\bSC-\d{4}\b/g,
|
|
6
|
+
UI: /\bUI-\d{4}\b/g,
|
|
7
|
+
API: /\bAPI-\d{4}\b/g,
|
|
8
|
+
DATA: /\bDATA-\d{4}\b/g,
|
|
9
|
+
ADR: /\bADR-\d{4}\b/g,
|
|
10
|
+
};
|
|
11
|
+
const LOOSE_ID_PATTERNS = {
|
|
12
|
+
SPEC: /\bSPEC-[A-Za-z0-9_-]+\b/gi,
|
|
13
|
+
BR: /\bBR-[A-Za-z0-9_-]+\b/gi,
|
|
14
|
+
SC: /\bSC-[A-Za-z0-9_-]+\b/gi,
|
|
15
|
+
UI: /\bUI-[A-Za-z0-9_-]+\b/gi,
|
|
16
|
+
API: /\bAPI-[A-Za-z0-9_-]+\b/gi,
|
|
17
|
+
DATA: /\bDATA-[A-Za-z0-9_-]+\b/gi,
|
|
18
|
+
ADR: /\bADR-[A-Za-z0-9_-]+\b/gi,
|
|
19
|
+
};
|
|
20
|
+
export function extractIds(text, prefix) {
|
|
21
|
+
const pattern = STRICT_ID_PATTERNS[prefix];
|
|
22
|
+
const matches = text.match(pattern);
|
|
23
|
+
return unique(matches ?? []);
|
|
24
|
+
}
|
|
25
|
+
export function extractAllIds(text) {
|
|
26
|
+
const all = [];
|
|
27
|
+
ID_PREFIXES.forEach((prefix) => {
|
|
28
|
+
all.push(...extractIds(text, prefix));
|
|
29
|
+
});
|
|
30
|
+
return unique(all);
|
|
31
|
+
}
|
|
32
|
+
export function extractInvalidIds(text, prefixes) {
|
|
33
|
+
const invalid = [];
|
|
34
|
+
for (const prefix of prefixes) {
|
|
35
|
+
const candidates = text.match(LOOSE_ID_PATTERNS[prefix]) ?? [];
|
|
36
|
+
for (const candidate of candidates) {
|
|
37
|
+
if (!isValidId(candidate, prefix)) {
|
|
38
|
+
invalid.push(candidate);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return unique(invalid);
|
|
43
|
+
}
|
|
44
|
+
function unique(values) {
|
|
45
|
+
return Array.from(new Set(values));
|
|
46
|
+
}
|
|
47
|
+
function isValidId(value, prefix) {
|
|
48
|
+
const pattern = STRICT_ID_PATTERNS[prefix];
|
|
49
|
+
const strict = new RegExp(pattern.source);
|
|
50
|
+
return strict.test(value);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=ids.js.map
|