domain-knowledge-kit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +94 -0
- package/README.md +266 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +40 -0
- package/dist/cli.js.map +1 -0
- package/dist/features/adr/commands/adr-related.d.ts +14 -0
- package/dist/features/adr/commands/adr-related.d.ts.map +1 -0
- package/dist/features/adr/commands/adr-related.js +146 -0
- package/dist/features/adr/commands/adr-related.js.map +1 -0
- package/dist/features/adr/commands/adr-show.d.ts +10 -0
- package/dist/features/adr/commands/adr-show.d.ts.map +1 -0
- package/dist/features/adr/commands/adr-show.js +30 -0
- package/dist/features/adr/commands/adr-show.js.map +1 -0
- package/dist/features/pipeline/commands/render.d.ts +10 -0
- package/dist/features/pipeline/commands/render.d.ts.map +1 -0
- package/dist/features/pipeline/commands/render.js +71 -0
- package/dist/features/pipeline/commands/render.js.map +1 -0
- package/dist/features/pipeline/commands/validate.d.ts +10 -0
- package/dist/features/pipeline/commands/validate.d.ts.map +1 -0
- package/dist/features/pipeline/commands/validate.js +48 -0
- package/dist/features/pipeline/commands/validate.js.map +1 -0
- package/dist/features/pipeline/indexer.d.ts +36 -0
- package/dist/features/pipeline/indexer.d.ts.map +1 -0
- package/dist/features/pipeline/indexer.js +279 -0
- package/dist/features/pipeline/indexer.js.map +1 -0
- package/dist/features/pipeline/renderer.d.ts +42 -0
- package/dist/features/pipeline/renderer.d.ts.map +1 -0
- package/dist/features/pipeline/renderer.js +239 -0
- package/dist/features/pipeline/renderer.js.map +1 -0
- package/dist/features/pipeline/tests/indexer.test.d.ts +2 -0
- package/dist/features/pipeline/tests/indexer.test.d.ts.map +1 -0
- package/dist/features/pipeline/tests/indexer.test.js +224 -0
- package/dist/features/pipeline/tests/indexer.test.js.map +1 -0
- package/dist/features/pipeline/tests/renderer.test.d.ts +2 -0
- package/dist/features/pipeline/tests/renderer.test.d.ts.map +1 -0
- package/dist/features/pipeline/tests/renderer.test.js +252 -0
- package/dist/features/pipeline/tests/renderer.test.js.map +1 -0
- package/dist/features/pipeline/tests/validate-schemas.test.d.ts +2 -0
- package/dist/features/pipeline/tests/validate-schemas.test.d.ts.map +1 -0
- package/dist/features/pipeline/tests/validate-schemas.test.js +183 -0
- package/dist/features/pipeline/tests/validate-schemas.test.js.map +1 -0
- package/dist/features/pipeline/tests/validator.test.d.ts +2 -0
- package/dist/features/pipeline/tests/validator.test.d.ts.map +1 -0
- package/dist/features/pipeline/tests/validator.test.js +371 -0
- package/dist/features/pipeline/tests/validator.test.js.map +1 -0
- package/dist/features/pipeline/validator.d.ts +44 -0
- package/dist/features/pipeline/validator.d.ts.map +1 -0
- package/dist/features/pipeline/validator.js +289 -0
- package/dist/features/pipeline/validator.js.map +1 -0
- package/dist/features/query/commands/list.d.ts +10 -0
- package/dist/features/query/commands/list.d.ts.map +1 -0
- package/dist/features/query/commands/list.js +123 -0
- package/dist/features/query/commands/list.js.map +1 -0
- package/dist/features/query/commands/related.d.ts +10 -0
- package/dist/features/query/commands/related.d.ts.map +1 -0
- package/dist/features/query/commands/related.js +61 -0
- package/dist/features/query/commands/related.js.map +1 -0
- package/dist/features/query/commands/search.d.ts +10 -0
- package/dist/features/query/commands/search.d.ts.map +1 -0
- package/dist/features/query/commands/search.js +55 -0
- package/dist/features/query/commands/search.js.map +1 -0
- package/dist/features/query/commands/show.d.ts +10 -0
- package/dist/features/query/commands/show.d.ts.map +1 -0
- package/dist/features/query/commands/show.js +96 -0
- package/dist/features/query/commands/show.js.map +1 -0
- package/dist/features/query/searcher.d.ts +58 -0
- package/dist/features/query/searcher.d.ts.map +1 -0
- package/dist/features/query/searcher.js +185 -0
- package/dist/features/query/searcher.js.map +1 -0
- package/dist/features/query/tests/searcher.test.d.ts +2 -0
- package/dist/features/query/tests/searcher.test.d.ts.map +1 -0
- package/dist/features/query/tests/searcher.test.js +320 -0
- package/dist/features/query/tests/searcher.test.js.map +1 -0
- package/dist/shared/adr-parser.d.ts +14 -0
- package/dist/shared/adr-parser.d.ts.map +1 -0
- package/dist/shared/adr-parser.js +72 -0
- package/dist/shared/adr-parser.js.map +1 -0
- package/dist/shared/errors.d.ts +43 -0
- package/dist/shared/errors.d.ts.map +1 -0
- package/dist/shared/errors.js +60 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/graph.d.ts +71 -0
- package/dist/shared/graph.d.ts.map +1 -0
- package/dist/shared/graph.js +250 -0
- package/dist/shared/graph.js.map +1 -0
- package/dist/shared/index.d.ts +16 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +24 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/item-visitor.d.ts +62 -0
- package/dist/shared/item-visitor.d.ts.map +1 -0
- package/dist/shared/item-visitor.js +95 -0
- package/dist/shared/item-visitor.js.map +1 -0
- package/dist/shared/loader.d.ts +19 -0
- package/dist/shared/loader.d.ts.map +1 -0
- package/dist/shared/loader.js +166 -0
- package/dist/shared/loader.js.map +1 -0
- package/dist/shared/paths.d.ts +32 -0
- package/dist/shared/paths.d.ts.map +1 -0
- package/dist/shared/paths.js +62 -0
- package/dist/shared/paths.js.map +1 -0
- package/dist/shared/tests/graph.test.d.ts +2 -0
- package/dist/shared/tests/graph.test.d.ts.map +1 -0
- package/dist/shared/tests/graph.test.js +291 -0
- package/dist/shared/tests/graph.test.js.map +1 -0
- package/dist/shared/tests/loader.test.d.ts +2 -0
- package/dist/shared/tests/loader.test.d.ts.map +1 -0
- package/dist/shared/tests/loader.test.js +239 -0
- package/dist/shared/tests/loader.test.js.map +1 -0
- package/dist/shared/tests/verify-collision-fix.test.d.ts +2 -0
- package/dist/shared/tests/verify-collision-fix.test.d.ts.map +1 -0
- package/dist/shared/tests/verify-collision-fix.test.js +114 -0
- package/dist/shared/tests/verify-collision-fix.test.js.map +1 -0
- package/dist/shared/types/domain.d.ts +244 -0
- package/dist/shared/types/domain.d.ts.map +1 -0
- package/dist/shared/types/domain.js +6 -0
- package/dist/shared/types/domain.js.map +1 -0
- package/dist/shared/types/index.d.ts +34 -0
- package/dist/shared/types/index.d.ts.map +1 -0
- package/dist/shared/types/index.js +9 -0
- package/dist/shared/types/index.js.map +1 -0
- package/dist/shared/yaml.d.ts +13 -0
- package/dist/shared/yaml.d.ts.map +1 -0
- package/dist/shared/yaml.js +29 -0
- package/dist/shared/yaml.js.map +1 -0
- package/package.json +48 -0
- package/tools/domain-pack/schema/.gitkeep +0 -0
- package/tools/domain-pack/schema/actors.schema.json +42 -0
- package/tools/domain-pack/schema/adr-frontmatter.schema.json +51 -0
- package/tools/domain-pack/schema/aggregate.schema.json +58 -0
- package/tools/domain-pack/schema/command.schema.json +76 -0
- package/tools/domain-pack/schema/context.schema.json +51 -0
- package/tools/domain-pack/schema/event.schema.json +66 -0
- package/tools/domain-pack/schema/glossary.schema.json +33 -0
- package/tools/domain-pack/schema/index.schema.json +76 -0
- package/tools/domain-pack/schema/policy.schema.json +53 -0
- package/tools/domain-pack/schema/read-model.schema.json +39 -0
- package/tools/domain-pack/templates/.gitkeep +0 -0
- package/tools/domain-pack/templates/context.md.hbs +89 -0
- package/tools/domain-pack/templates/index.md.hbs +60 -0
- package/tools/domain-pack/templates/item.md.hbs +85 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the domain model validator.
|
|
3
|
+
*
|
|
4
|
+
* Builds various DomainModel fixtures (valid and intentionally broken)
|
|
5
|
+
* and asserts that validateDomainModel reports the expected errors and warnings.
|
|
6
|
+
*/
|
|
7
|
+
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { loadDomainModel } from "../../../shared/loader.js";
|
|
11
|
+
import { validateDomainModel, } from "../validator.js";
|
|
12
|
+
// ── Helpers ───────────────────────────────────────────────────────────
|
|
13
|
+
const SCHEMA_DIR = join(import.meta.dirname, "../../../../tools/domain-pack/schema");
|
|
14
|
+
let passed = 0;
|
|
15
|
+
let failed = 0;
|
|
16
|
+
function assert(label, condition, detail) {
|
|
17
|
+
if (condition) {
|
|
18
|
+
console.log(` OK: ${label}`);
|
|
19
|
+
passed++;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.error(`FAIL: ${label}${detail ? ` — ${detail}` : ""}`);
|
|
23
|
+
failed++;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function hasError(result, substring) {
|
|
27
|
+
return result.errors.some((e) => e.message.includes(substring));
|
|
28
|
+
}
|
|
29
|
+
function hasWarning(result, substring) {
|
|
30
|
+
return result.warnings.some((w) => w.message.includes(substring));
|
|
31
|
+
}
|
|
32
|
+
/** Create a minimal temp domain tree and return its root path. */
|
|
33
|
+
function makeTempRoot(suffix) {
|
|
34
|
+
const root = join(tmpdir(), `dkk-validator-${suffix}-${Date.now()}`);
|
|
35
|
+
mkdirSync(join(root, "domain", "contexts"), { recursive: true });
|
|
36
|
+
mkdirSync(join(root, "docs", "adr"), { recursive: true });
|
|
37
|
+
return root;
|
|
38
|
+
}
|
|
39
|
+
/** Write a YAML string to a file. */
|
|
40
|
+
function writeYaml(path, content) {
|
|
41
|
+
writeFileSync(path, content, "utf-8");
|
|
42
|
+
}
|
|
43
|
+
/** Write an ADR Markdown file. */
|
|
44
|
+
function writeAdr(dir, filename, frontmatter) {
|
|
45
|
+
writeFileSync(join(dir, filename), `---\n${frontmatter}\n---\n\n# Title\n\nContent.\n`, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Write a per-item context directory under domain/contexts/<name>/.
|
|
49
|
+
* - contextYaml: YAML for context.yml (contains name, description, optional glossary)
|
|
50
|
+
* - items: map of sub-dir name → array of [filename, yamlContent] pairs
|
|
51
|
+
*/
|
|
52
|
+
function writeContextDir(root, contextYaml, items = {}) {
|
|
53
|
+
const nameMatch = contextYaml.match(/^name:\s*(\S+)/m);
|
|
54
|
+
const name = nameMatch[1];
|
|
55
|
+
const ctxDir = join(root, "domain", "contexts", name);
|
|
56
|
+
mkdirSync(ctxDir, { recursive: true });
|
|
57
|
+
writeYaml(join(ctxDir, "context.yml"), contextYaml);
|
|
58
|
+
for (const [subDir, files] of Object.entries(items)) {
|
|
59
|
+
mkdirSync(join(ctxDir, subDir), { recursive: true });
|
|
60
|
+
for (const [filename, content] of files) {
|
|
61
|
+
writeYaml(join(ctxDir, subDir, filename), content);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ── Test: Valid model ─────────────────────────────────────────────────
|
|
66
|
+
function testValidModel() {
|
|
67
|
+
console.log("\n=== Valid model ===");
|
|
68
|
+
const root = makeTempRoot("valid");
|
|
69
|
+
writeYaml(join(root, "domain", "index.yml"), [
|
|
70
|
+
"contexts:",
|
|
71
|
+
" - name: ordering",
|
|
72
|
+
"flows:",
|
|
73
|
+
" - name: PlaceFlow",
|
|
74
|
+
" steps:",
|
|
75
|
+
" - ref: ordering.PlaceOrder",
|
|
76
|
+
" type: command",
|
|
77
|
+
" - ref: ordering.OrderPlaced",
|
|
78
|
+
" type: event",
|
|
79
|
+
].join("\n"));
|
|
80
|
+
writeYaml(join(root, "domain", "actors.yml"), [
|
|
81
|
+
"actors:",
|
|
82
|
+
" - name: Customer",
|
|
83
|
+
" type: human",
|
|
84
|
+
' description: "A paying customer"',
|
|
85
|
+
].join("\n"));
|
|
86
|
+
writeContextDir(root, [
|
|
87
|
+
"name: ordering",
|
|
88
|
+
'description: "Handles orders"',
|
|
89
|
+
"glossary:",
|
|
90
|
+
" - term: OrderLifecycle",
|
|
91
|
+
' definition: "The lifecycle of a purchase request"',
|
|
92
|
+
].join("\n"), {
|
|
93
|
+
events: [["OrderPlaced.yml", [
|
|
94
|
+
"name: OrderPlaced",
|
|
95
|
+
'description: "Raised when order placed"',
|
|
96
|
+
"fields:",
|
|
97
|
+
" - name: orderId",
|
|
98
|
+
" type: UUID",
|
|
99
|
+
"raised_by: Order",
|
|
100
|
+
].join("\n")]],
|
|
101
|
+
commands: [["PlaceOrder.yml", [
|
|
102
|
+
"name: PlaceOrder",
|
|
103
|
+
'description: "Submit a new order"',
|
|
104
|
+
"actor: Customer",
|
|
105
|
+
"handled_by: Order",
|
|
106
|
+
"fields:",
|
|
107
|
+
" - name: items",
|
|
108
|
+
" type: array",
|
|
109
|
+
].join("\n")]],
|
|
110
|
+
aggregates: [["Order.yml", [
|
|
111
|
+
"name: Order",
|
|
112
|
+
'description: "Order aggregate root"',
|
|
113
|
+
"handles:",
|
|
114
|
+
" commands:",
|
|
115
|
+
" - PlaceOrder",
|
|
116
|
+
"emits:",
|
|
117
|
+
" events:",
|
|
118
|
+
" - OrderPlaced",
|
|
119
|
+
].join("\n")]],
|
|
120
|
+
});
|
|
121
|
+
writeAdr(join(root, "docs", "adr"), "0001-use-yaml.md", [
|
|
122
|
+
"id: adr-0001",
|
|
123
|
+
"title: Use YAML for domain models",
|
|
124
|
+
"status: accepted",
|
|
125
|
+
"date: 2026-01-15",
|
|
126
|
+
"domain_refs:",
|
|
127
|
+
" - ordering.OrderPlaced",
|
|
128
|
+
].join("\n"));
|
|
129
|
+
const model = loadDomainModel({ root });
|
|
130
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
131
|
+
assert("valid model has no errors", result.valid, `errors: ${result.errors.map((e) => e.message).join("; ")}`);
|
|
132
|
+
assert("valid model has no warnings", result.warnings.length === 0);
|
|
133
|
+
rmSync(root, { recursive: true, force: true });
|
|
134
|
+
}
|
|
135
|
+
// ── Test: Broken ADR refs ─────────────────────────────────────────────
|
|
136
|
+
function testBrokenAdrRefs() {
|
|
137
|
+
console.log("\n=== Broken ADR refs ===");
|
|
138
|
+
const root = makeTempRoot("brokenadr");
|
|
139
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts:\n - name: ordering\n");
|
|
140
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
141
|
+
writeContextDir(root, [
|
|
142
|
+
"name: ordering",
|
|
143
|
+
'description: "Orders"',
|
|
144
|
+
].join("\n"), {
|
|
145
|
+
events: [["OrderPlaced.yml", [
|
|
146
|
+
"name: OrderPlaced",
|
|
147
|
+
'description: "Placed"',
|
|
148
|
+
"adr_refs:",
|
|
149
|
+
" - adr-9999",
|
|
150
|
+
].join("\n")]],
|
|
151
|
+
});
|
|
152
|
+
const model = loadDomainModel({ root });
|
|
153
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
154
|
+
assert("detects unresolved adr_ref", hasError(result, "adr-9999"));
|
|
155
|
+
assert("result is invalid", !result.valid);
|
|
156
|
+
rmSync(root, { recursive: true, force: true });
|
|
157
|
+
}
|
|
158
|
+
// ── Test: Broken domain_refs on ADR ───────────────────────────────────
|
|
159
|
+
function testBrokenDomainRefs() {
|
|
160
|
+
console.log("\n=== Broken ADR domain_refs ===");
|
|
161
|
+
const root = makeTempRoot("brokendomainref");
|
|
162
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts: []\n");
|
|
163
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
164
|
+
writeAdr(join(root, "docs", "adr"), "0001-test.md", [
|
|
165
|
+
"id: adr-0001",
|
|
166
|
+
"title: Test",
|
|
167
|
+
"status: accepted",
|
|
168
|
+
"date: 2026-02-20",
|
|
169
|
+
"domain_refs:",
|
|
170
|
+
" - nonexistent.Thing",
|
|
171
|
+
].join("\n"));
|
|
172
|
+
const model = loadDomainModel({ root });
|
|
173
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
174
|
+
assert("detects unresolved ADR domain_ref", hasError(result, "nonexistent.Thing"));
|
|
175
|
+
assert("result is invalid", !result.valid);
|
|
176
|
+
rmSync(root, { recursive: true, force: true });
|
|
177
|
+
}
|
|
178
|
+
// ── Test: Broken intra-context references ─────────────────────────────
|
|
179
|
+
function testBrokenIntraContextRefs() {
|
|
180
|
+
console.log("\n=== Broken intra-context refs ===");
|
|
181
|
+
const root = makeTempRoot("brokenintra");
|
|
182
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts:\n - name: sales\n");
|
|
183
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors:\n - name: Admin\n type: human\n description: Admin user\n");
|
|
184
|
+
writeContextDir(root, "name: sales\ndescription: \"Sales context\"", {
|
|
185
|
+
events: [["SaleCompleted.yml", [
|
|
186
|
+
"name: SaleCompleted",
|
|
187
|
+
'description: "A sale was completed"',
|
|
188
|
+
"raised_by: NonExistentAggregate",
|
|
189
|
+
].join("\n")]],
|
|
190
|
+
commands: [["CompleteSale.yml", [
|
|
191
|
+
"name: CompleteSale",
|
|
192
|
+
'description: "Complete a sale"',
|
|
193
|
+
"handled_by: GhostAggregate",
|
|
194
|
+
"actor: GhostActor",
|
|
195
|
+
].join("\n")]],
|
|
196
|
+
aggregates: [["Sale.yml", [
|
|
197
|
+
"name: Sale",
|
|
198
|
+
'description: "Sale aggregate"',
|
|
199
|
+
"handles:",
|
|
200
|
+
" commands:",
|
|
201
|
+
" - NonExistentCommand",
|
|
202
|
+
"emits:",
|
|
203
|
+
" events:",
|
|
204
|
+
" - NonExistentEvent",
|
|
205
|
+
].join("\n")]],
|
|
206
|
+
policies: [["NotifyOnSale.yml", [
|
|
207
|
+
"name: NotifyOnSale",
|
|
208
|
+
'description: "Notify on sale"',
|
|
209
|
+
"when:",
|
|
210
|
+
" events:",
|
|
211
|
+
" - GhostEvent",
|
|
212
|
+
"then:",
|
|
213
|
+
" commands:",
|
|
214
|
+
" - GhostCommand",
|
|
215
|
+
].join("\n")]],
|
|
216
|
+
"read-models": [["SaleDashboard.yml", [
|
|
217
|
+
"name: SaleDashboard",
|
|
218
|
+
'description: "Dashboard"',
|
|
219
|
+
"subscribes_to:",
|
|
220
|
+
" - GhostEvent",
|
|
221
|
+
"used_by:",
|
|
222
|
+
" - GhostActor",
|
|
223
|
+
].join("\n")]],
|
|
224
|
+
});
|
|
225
|
+
const model = loadDomainModel({ root });
|
|
226
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
227
|
+
assert("detects event raised_by unknown aggregate", hasError(result, "raised_by") && hasError(result, "NonExistentAggregate"));
|
|
228
|
+
assert("detects command handled_by unknown aggregate", hasError(result, "handled_by") && hasError(result, "GhostAggregate"));
|
|
229
|
+
assert("detects command actor unknown", hasError(result, "actor") && hasError(result, "GhostActor"));
|
|
230
|
+
assert("detects aggregate handles unknown command", hasError(result, "NonExistentCommand"));
|
|
231
|
+
assert("detects aggregate emits unknown event", hasError(result, "NonExistentEvent"));
|
|
232
|
+
assert("detects policy triggers unknown event", hasError(result, 'when.events "GhostEvent"'));
|
|
233
|
+
assert("detects policy emits unknown command", hasError(result, 'then.commands "GhostCommand"'));
|
|
234
|
+
assert("detects read_model subscribes_to unknown event", hasError(result, 'subscribes_to "GhostEvent"'));
|
|
235
|
+
assert("detects read_model used_by unknown actor", hasError(result, 'used_by "GhostActor"'));
|
|
236
|
+
rmSync(root, { recursive: true, force: true });
|
|
237
|
+
}
|
|
238
|
+
// ── Test: Duplicate names ─────────────────────────────────────────────
|
|
239
|
+
function testDuplicateNames() {
|
|
240
|
+
console.log("\n=== Duplicate names ===");
|
|
241
|
+
const root = makeTempRoot("dupes");
|
|
242
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts:\n - name: ctx\n");
|
|
243
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
244
|
+
writeContextDir(root, "name: ctx\ndescription: \"Test context\"", {
|
|
245
|
+
events: [["Clash.yml", "name: Clash\ndescription: \"Event\""]],
|
|
246
|
+
commands: [["Clash.yml", "name: Clash\ndescription: \"Command\""]],
|
|
247
|
+
});
|
|
248
|
+
const model = loadDomainModel({ root });
|
|
249
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
250
|
+
assert("detects duplicate name", hasError(result, 'Duplicate name "Clash"'));
|
|
251
|
+
rmSync(root, { recursive: true, force: true });
|
|
252
|
+
}
|
|
253
|
+
// ── Test: Glossary-aggregate name collision ───────────────────────────
|
|
254
|
+
function testGlossaryAggregateCollision() {
|
|
255
|
+
console.log("\n=== Glossary-aggregate collision ===");
|
|
256
|
+
const root = makeTempRoot("glosscoll");
|
|
257
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts:\n - name: ctx\n");
|
|
258
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
259
|
+
writeContextDir(root, [
|
|
260
|
+
"name: ctx",
|
|
261
|
+
'description: "Test context"',
|
|
262
|
+
"glossary:",
|
|
263
|
+
" - term: Order",
|
|
264
|
+
' definition: "A purchase"',
|
|
265
|
+
].join("\n"), {
|
|
266
|
+
aggregates: [["Order.yml", "name: Order\ndescription: \"Root\""]],
|
|
267
|
+
});
|
|
268
|
+
const model = loadDomainModel({ root });
|
|
269
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
270
|
+
assert("detects glossary-aggregate collision", hasError(result, 'Duplicate name "Order"'));
|
|
271
|
+
rmSync(root, { recursive: true, force: true });
|
|
272
|
+
}
|
|
273
|
+
// ── Test: Missing context file ────────────────────────────────────────
|
|
274
|
+
function testMissingContextFile() {
|
|
275
|
+
console.log("\n=== Missing context file ===");
|
|
276
|
+
const root = makeTempRoot("missingctx");
|
|
277
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts:\n - name: phantom\n");
|
|
278
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
279
|
+
const model = loadDomainModel({ root });
|
|
280
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
281
|
+
assert("detects missing context file", hasError(result, "phantom"));
|
|
282
|
+
rmSync(root, { recursive: true, force: true });
|
|
283
|
+
}
|
|
284
|
+
// ── Test: Broken flow step refs ───────────────────────────────────────
|
|
285
|
+
function testBrokenFlowSteps() {
|
|
286
|
+
console.log("\n=== Broken flow step refs ===");
|
|
287
|
+
const root = makeTempRoot("brokenflow");
|
|
288
|
+
writeYaml(join(root, "domain", "index.yml"), [
|
|
289
|
+
"contexts: []",
|
|
290
|
+
"flows:",
|
|
291
|
+
" - name: BadFlow",
|
|
292
|
+
" steps:",
|
|
293
|
+
" - ref: ghost.DoThing",
|
|
294
|
+
" type: command",
|
|
295
|
+
].join("\n"));
|
|
296
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
297
|
+
const model = loadDomainModel({ root });
|
|
298
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
299
|
+
assert("detects unresolved flow step ref", hasError(result, "ghost.DoThing"));
|
|
300
|
+
rmSync(root, { recursive: true, force: true });
|
|
301
|
+
}
|
|
302
|
+
// ── Test: ADR superseded_by unresolved ────────────────────────────────
|
|
303
|
+
function testBrokenSupersededBy() {
|
|
304
|
+
console.log("\n=== ADR superseded_by unresolved ===");
|
|
305
|
+
const root = makeTempRoot("superseded");
|
|
306
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts: []\n");
|
|
307
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
308
|
+
writeAdr(join(root, "docs", "adr"), "0001-old.md", [
|
|
309
|
+
"id: adr-0001",
|
|
310
|
+
"title: Old decision",
|
|
311
|
+
"status: superseded",
|
|
312
|
+
"date: 2026-02-20",
|
|
313
|
+
"superseded_by: adr-9999",
|
|
314
|
+
].join("\n"));
|
|
315
|
+
const model = loadDomainModel({ root });
|
|
316
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
317
|
+
assert("detects unresolved superseded_by", hasError(result, "adr-9999"));
|
|
318
|
+
rmSync(root, { recursive: true, force: true });
|
|
319
|
+
}
|
|
320
|
+
// ── Test: warnMissingFields ───────────────────────────────────────────
|
|
321
|
+
function testWarnMissingFields() {
|
|
322
|
+
console.log("\n=== warnMissingFields ===");
|
|
323
|
+
const root = makeTempRoot("warnfields");
|
|
324
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts:\n - name: ctx\n");
|
|
325
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
326
|
+
writeContextDir(root, 'name: ctx\ndescription: "Test"', {
|
|
327
|
+
events: [["NoFieldsEvent.yml", 'name: NoFieldsEvent\ndescription: "Event with no fields"']],
|
|
328
|
+
commands: [["NoFieldsCommand.yml", 'name: NoFieldsCommand\ndescription: "Command with no fields"']],
|
|
329
|
+
});
|
|
330
|
+
const model = loadDomainModel({ root });
|
|
331
|
+
// Without the option — no warnings
|
|
332
|
+
const r1 = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
333
|
+
assert("no warnings when warnMissingFields is off", r1.warnings.length === 0);
|
|
334
|
+
// With the option — warnings
|
|
335
|
+
const r2 = validateDomainModel(model, { schemaDir: SCHEMA_DIR, warnMissingFields: true });
|
|
336
|
+
assert("warns about event without fields", hasWarning(r2, "NoFieldsEvent"));
|
|
337
|
+
assert("warns about command without fields", hasWarning(r2, "NoFieldsCommand"));
|
|
338
|
+
assert("warnings are non-blocking", r2.valid);
|
|
339
|
+
rmSync(root, { recursive: true, force: true });
|
|
340
|
+
}
|
|
341
|
+
// ── Test: Empty model (should be valid) ───────────────────────────────
|
|
342
|
+
function testEmptyModel() {
|
|
343
|
+
console.log("\n=== Empty model ===");
|
|
344
|
+
const root = makeTempRoot("empty");
|
|
345
|
+
writeYaml(join(root, "domain", "index.yml"), "contexts: []\n");
|
|
346
|
+
writeYaml(join(root, "domain", "actors.yml"), "actors: []\n");
|
|
347
|
+
const model = loadDomainModel({ root });
|
|
348
|
+
const result = validateDomainModel(model, { schemaDir: SCHEMA_DIR });
|
|
349
|
+
assert("empty model is valid", result.valid);
|
|
350
|
+
assert("no errors", result.errors.length === 0);
|
|
351
|
+
assert("no warnings", result.warnings.length === 0);
|
|
352
|
+
rmSync(root, { recursive: true, force: true });
|
|
353
|
+
}
|
|
354
|
+
// ── Run all ───────────────────────────────────────────────────────────
|
|
355
|
+
testValidModel();
|
|
356
|
+
testBrokenAdrRefs();
|
|
357
|
+
testBrokenDomainRefs();
|
|
358
|
+
testBrokenIntraContextRefs();
|
|
359
|
+
testDuplicateNames();
|
|
360
|
+
testGlossaryAggregateCollision();
|
|
361
|
+
testMissingContextFile();
|
|
362
|
+
testBrokenFlowSteps();
|
|
363
|
+
testBrokenSupersededBy();
|
|
364
|
+
testWarnMissingFields();
|
|
365
|
+
testEmptyModel();
|
|
366
|
+
// ── Summary ───────────────────────────────────────────────────────────
|
|
367
|
+
console.log(`\n${"=".repeat(40)}`);
|
|
368
|
+
console.log(`Results: ${passed} passed, ${failed} failed`);
|
|
369
|
+
if (failed > 0)
|
|
370
|
+
process.exit(1);
|
|
371
|
+
//# sourceMappingURL=validator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.test.js","sourceRoot":"","sources":["../../../../src/features/pipeline/tests/validator.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EACL,mBAAmB,GAEpB,MAAM,iBAAiB,CAAC;AAEzB,yEAAyE;AAEzE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,sCAAsC,CAAC,CAAC;AAErF,IAAI,MAAM,GAAG,CAAC,CAAC;AACf,IAAI,MAAM,GAAG,CAAC,CAAC;AAEf,SAAS,MAAM,CAAC,KAAa,EAAE,SAAkB,EAAE,MAAe;IAChE,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;QAC9B,MAAM,EAAE,CAAC;IACX,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,SAAS,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,CAAC;IACX,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,MAAwB,EAAE,SAAiB;IAC3D,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,UAAU,CAAC,MAAwB,EAAE,SAAiB;IAC7D,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,kEAAkE;AAClE,SAAS,YAAY,CAAC,MAAc;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qCAAqC;AACrC,SAAS,SAAS,CAAC,IAAY,EAAE,OAAe;IAC9C,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC;AAED,kCAAkC;AAClC,SAAS,QAAQ,CAAC,GAAW,EAAE,QAAgB,EAAE,WAAmB;IAClE,aAAa,CACX,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,EACnB,QAAQ,WAAW,gCAAgC,EACnD,OAAO,CACR,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CACtB,IAAY,EACZ,WAAmB,EACnB,QAAiD,EAAE;IAEnD,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,SAAU,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACtD,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,WAAW,CAAC,CAAC;IACpD,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC;YACxC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;AACH,CAAC;AAED,yEAAyE;AAEzE,SAAS,cAAc;IACrB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAEnC,SAAS,CACP,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EACjC;QACE,WAAW;QACX,oBAAoB;QACpB,QAAQ;QACR,qBAAqB;QACrB,YAAY;QACZ,kCAAkC;QAClC,uBAAuB;QACvB,mCAAmC;QACnC,qBAAqB;KACtB,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,SAAS,CACP,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAClC;QACE,SAAS;QACT,oBAAoB;QACpB,iBAAiB;QACjB,sCAAsC;KACvC,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,eAAe,CAAC,IAAI,EAAE;QACpB,gBAAgB;QAChB,+BAA+B;QAC/B,WAAW;QACX,0BAA0B;QAC1B,uDAAuD;KACxD,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACZ,MAAM,EAAE,CAAC,CAAC,iBAAiB,EAAE;oBAC3B,mBAAmB;oBACnB,yCAAyC;oBACzC,SAAS;oBACT,mBAAmB;oBACnB,gBAAgB;oBAChB,kBAAkB;iBACnB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC,CAAC,gBAAgB,EAAE;oBAC5B,kBAAkB;oBAClB,mCAAmC;oBACnC,iBAAiB;oBACjB,mBAAmB;oBACnB,SAAS;oBACT,iBAAiB;oBACjB,iBAAiB;iBAClB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,UAAU,EAAE,CAAC,CAAC,WAAW,EAAE;oBACzB,aAAa;oBACb,qCAAqC;oBACrC,UAAU;oBACV,aAAa;oBACb,kBAAkB;oBAClB,QAAQ;oBACR,WAAW;oBACX,mBAAmB;iBACpB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;KACf,CAAC,CAAC;IAEH,QAAQ,CACN,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EACzB,kBAAkB,EAClB;QACE,cAAc;QACd,mCAAmC;QACnC,kBAAkB;QAClB,kBAAkB;QAClB,cAAc;QACd,0BAA0B;KAC3B,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,2BAA2B,EAAE,MAAM,CAAC,KAAK,EAAE,WAAW,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/G,MAAM,CAAC,6BAA6B,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IAEpE,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,iBAAiB;IACxB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAEvC,SAAS,CACP,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EACjC,iCAAiC,CAClC,CAAC;IACF,SAAS,CACP,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAClC,cAAc,CACf,CAAC;IACF,eAAe,CAAC,IAAI,EAAE;QACpB,gBAAgB;QAChB,uBAAuB;KACxB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACZ,MAAM,EAAE,CAAC,CAAC,iBAAiB,EAAE;oBAC3B,mBAAmB;oBACnB,uBAAuB;oBACvB,WAAW;oBACX,cAAc;iBACf,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;KACf,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,4BAA4B,EAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACnE,MAAM,CAAC,mBAAmB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE3C,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,oBAAoB;IAC3B,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAE7C,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC/D,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAC9D,QAAQ,CACN,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EACzB,cAAc,EACd;QACE,cAAc;QACd,aAAa;QACb,kBAAkB;QAClB,kBAAkB;QAClB,cAAc;QACd,uBAAuB;KACxB,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,mCAAmC,EAAE,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACnF,MAAM,CAAC,mBAAmB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE3C,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,0BAA0B;IACjC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;IAEzC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,8BAA8B,CAAC,CAAC;IAC7E,SAAS,CACP,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAClC,0EAA0E,CAC3E,CAAC;IACF,eAAe,CAAC,IAAI,EAAE,6CAA6C,EAAE;QACnE,MAAM,EAAE,CAAC,CAAC,mBAAmB,EAAE;oBAC7B,qBAAqB;oBACrB,qCAAqC;oBACrC,iCAAiC;iBAClC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC,CAAC,kBAAkB,EAAE;oBAC9B,oBAAoB;oBACpB,gCAAgC;oBAChC,4BAA4B;oBAC5B,mBAAmB;iBACpB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE;oBACxB,YAAY;oBACZ,+BAA+B;oBAC/B,UAAU;oBACV,aAAa;oBACb,0BAA0B;oBAC1B,QAAQ;oBACR,WAAW;oBACX,wBAAwB;iBACzB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC,CAAC,kBAAkB,EAAE;oBAC9B,oBAAoB;oBACpB,+BAA+B;oBAC/B,OAAO;oBACP,WAAW;oBACX,kBAAkB;oBAClB,OAAO;oBACP,aAAa;oBACb,oBAAoB;iBACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,aAAa,EAAE,CAAC,CAAC,mBAAmB,EAAE;oBACpC,qBAAqB;oBACrB,0BAA0B;oBAC1B,gBAAgB;oBAChB,gBAAgB;oBAChB,UAAU;oBACV,gBAAgB;iBACjB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;KACf,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,2CAA2C,EAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAC/H,MAAM,CAAC,8CAA8C,EAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC7H,MAAM,CAAC,+BAA+B,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACrG,MAAM,CAAC,2CAA2C,EAAE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC5F,MAAM,CAAC,uCAAuC,EAAE,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACtF,MAAM,CAAC,uCAAuC,EAAE,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC;IAC9F,MAAM,CAAC,sCAAsC,EAAE,QAAQ,CAAC,MAAM,EAAE,8BAA8B,CAAC,CAAC,CAAC;IACjG,MAAM,CAAC,gDAAgD,EAAE,QAAQ,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC,CAAC;IACzG,MAAM,CAAC,0CAA0C,EAAE,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAE7F,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,kBAAkB;IACzB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAEnC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAC3E,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAC9D,eAAe,CAAC,IAAI,EAAE,0CAA0C,EAAE;QAChE,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,qCAAqC,CAAC,CAAC;QAC9D,QAAQ,EAAE,CAAC,CAAC,WAAW,EAAE,uCAAuC,CAAC,CAAC;KACnE,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,wBAAwB,EAAE,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAE7E,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,8BAA8B;IACrC,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAEvC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAC3E,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAC9D,eAAe,CAAC,IAAI,EAAE;QACpB,WAAW;QACX,6BAA6B;QAC7B,WAAW;QACX,iBAAiB;QACjB,8BAA8B;KAC/B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACZ,UAAU,EAAE,CAAC,CAAC,WAAW,EAAE,oCAAoC,CAAC,CAAC;KAClE,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CACJ,sCAAsC,EACtC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAC3C,CAAC;IAEF,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,sBAAsB;IAC7B,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAExC,SAAS,CACP,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EACjC,gCAAgC,CACjC,CAAC;IACF,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAE9D,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,8BAA8B,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAEpE,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,mBAAmB;IAC1B,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAExC,SAAS,CACP,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EACjC;QACE,cAAc;QACd,QAAQ;QACR,mBAAmB;QACnB,YAAY;QACZ,4BAA4B;QAC5B,uBAAuB;KACxB,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACF,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAE9D,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,kCAAkC,EAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;IAE9E,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,sBAAsB;IAC7B,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAExC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC/D,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAC9D,QAAQ,CACN,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EACzB,aAAa,EACb;QACE,cAAc;QACd,qBAAqB;QACrB,oBAAoB;QACpB,kBAAkB;QAClB,yBAAyB;KAC1B,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IAEF,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,kCAAkC,EAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAEzE,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,qBAAqB;IAC5B,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAExC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,4BAA4B,CAAC,CAAC;IAC3E,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAC9D,eAAe,CAAC,IAAI,EAAE,gCAAgC,EAAE;QACtD,MAAM,EAAE,CAAC,CAAC,mBAAmB,EAAE,0DAA0D,CAAC,CAAC;QAC3F,QAAQ,EAAE,CAAC,CAAC,qBAAqB,EAAE,8DAA8D,CAAC,CAAC;KACpG,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAExC,mCAAmC;IACnC,MAAM,EAAE,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IACjE,MAAM,CAAC,2CAA2C,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IAE9E,6BAA6B;IAC7B,MAAM,EAAE,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1F,MAAM,CAAC,kCAAkC,EAAE,UAAU,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAC5E,MAAM,CAAC,oCAAoC,EAAE,UAAU,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAChF,MAAM,CAAC,2BAA2B,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;IAE9C,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,SAAS,cAAc;IACrB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAEnC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC/D,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAE9D,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IAEpD,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,yEAAyE;AAEzE,cAAc,EAAE,CAAC;AACjB,iBAAiB,EAAE,CAAC;AACpB,oBAAoB,EAAE,CAAC;AACvB,0BAA0B,EAAE,CAAC;AAC7B,kBAAkB,EAAE,CAAC;AACrB,8BAA8B,EAAE,CAAC;AACjC,sBAAsB,EAAE,CAAC;AACzB,mBAAmB,EAAE,CAAC;AACtB,sBAAsB,EAAE,CAAC;AACzB,qBAAqB,EAAE,CAAC;AACxB,cAAc,EAAE,CAAC;AAEjB,yEAAyE;AACzE,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AACnC,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,YAAY,MAAM,SAAS,CAAC,CAAC;AAC3D,IAAI,MAAM,GAAG,CAAC;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { DomainModel } from "../../shared/types/domain.js";
|
|
2
|
+
/** Severity of a validation finding. */
|
|
3
|
+
export type Severity = "error" | "warning";
|
|
4
|
+
/** A single validation finding. */
|
|
5
|
+
export interface ValidationIssue {
|
|
6
|
+
/** error = blocking (fail), warning = informational. */
|
|
7
|
+
severity: Severity;
|
|
8
|
+
/** Human-readable problem description. */
|
|
9
|
+
message: string;
|
|
10
|
+
/** Location hint (e.g. "context:ordering", "adr:adr-0001"). */
|
|
11
|
+
path?: string;
|
|
12
|
+
}
|
|
13
|
+
/** Complete validation result. */
|
|
14
|
+
export interface ValidationResult {
|
|
15
|
+
/** True when there are zero errors (warnings are OK). */
|
|
16
|
+
valid: boolean;
|
|
17
|
+
/** All findings grouped for convenience. */
|
|
18
|
+
errors: ValidationIssue[];
|
|
19
|
+
warnings: ValidationIssue[];
|
|
20
|
+
}
|
|
21
|
+
/** Options that control validator behaviour. */
|
|
22
|
+
export interface ValidatorOptions {
|
|
23
|
+
/**
|
|
24
|
+
* Absolute path to the schema directory.
|
|
25
|
+
* Defaults to `<repoRoot>/tools/domain-pack/schema`.
|
|
26
|
+
*/
|
|
27
|
+
schemaDir?: string;
|
|
28
|
+
/**
|
|
29
|
+
* When true, emit warnings for events and commands that have no
|
|
30
|
+
* `fields` array defined. Default: `false`.
|
|
31
|
+
*/
|
|
32
|
+
warnMissingFields?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Validate a loaded {@link DomainModel}.
|
|
36
|
+
*
|
|
37
|
+
* Runs JSON Schema validation followed by cross-reference checks.
|
|
38
|
+
* Returns a {@link ValidationResult} containing errors and warnings.
|
|
39
|
+
*
|
|
40
|
+
* @param model - The domain model to validate (from `loadDomainModel()`).
|
|
41
|
+
* @param options - Optional validator configuration.
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateDomainModel(model: DomainModel, options?: ValidatorOptions): ValidationResult;
|
|
44
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../src/features/pipeline/validator.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,WAAW,EAMZ,MAAM,8BAA8B,CAAC;AAYtC,wCAAwC;AACxC,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3C,mCAAmC;AACnC,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,QAAQ,EAAE,QAAQ,CAAC;IACnB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,kCAAkC;AAClC,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,KAAK,EAAE,OAAO,CAAC;IACf,4CAA4C;IAC5C,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,gDAAgD;AAChD,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AA4VD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,gBAAqB,GAC7B,gBAAgB,CAgBlB"}
|