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,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the SQLite FTS5 searcher.
|
|
3
|
+
*
|
|
4
|
+
* Builds a DomainModel in a temp directory, indexes it, then runs
|
|
5
|
+
* search queries and verifies results.
|
|
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 { DomainGraph } from "../../../shared/graph.js";
|
|
12
|
+
import { buildIndex } from "../../pipeline/indexer.js";
|
|
13
|
+
import { search } from "../searcher.js";
|
|
14
|
+
// ── Fixture setup ─────────────────────────────────────────────────────
|
|
15
|
+
const TMP = join(tmpdir(), `dkk-search-test-${Date.now()}`);
|
|
16
|
+
const DOMAIN = join(TMP, "domain");
|
|
17
|
+
const CONTEXTS = join(DOMAIN, "contexts");
|
|
18
|
+
const ADR_DIR = join(TMP, "docs", "adr");
|
|
19
|
+
const DB_PATH = join(TMP, ".domain-pack", "index.db");
|
|
20
|
+
function setup() {
|
|
21
|
+
mkdirSync(join(CONTEXTS, "ordering", "events"), { recursive: true });
|
|
22
|
+
mkdirSync(join(CONTEXTS, "ordering", "commands"), { recursive: true });
|
|
23
|
+
mkdirSync(join(CONTEXTS, "ordering", "policies"), { recursive: true });
|
|
24
|
+
mkdirSync(join(CONTEXTS, "ordering", "aggregates"), { recursive: true });
|
|
25
|
+
mkdirSync(join(CONTEXTS, "ordering", "read-models"), { recursive: true });
|
|
26
|
+
mkdirSync(join(CONTEXTS, "shipping", "events"), { recursive: true });
|
|
27
|
+
mkdirSync(join(CONTEXTS, "shipping", "commands"), { recursive: true });
|
|
28
|
+
mkdirSync(join(CONTEXTS, "shipping", "aggregates"), { recursive: true });
|
|
29
|
+
mkdirSync(join(CONTEXTS, "shipping", "read-models"), { recursive: true });
|
|
30
|
+
mkdirSync(ADR_DIR, { recursive: true });
|
|
31
|
+
// domain/index.yml
|
|
32
|
+
writeFileSync(join(DOMAIN, "index.yml"), [
|
|
33
|
+
"contexts:",
|
|
34
|
+
" - name: ordering",
|
|
35
|
+
' description: "Order management"',
|
|
36
|
+
" - name: shipping",
|
|
37
|
+
' description: "Shipping logistics"',
|
|
38
|
+
"flows:",
|
|
39
|
+
" - name: PlaceAndShip",
|
|
40
|
+
' description: "Order to shipment"',
|
|
41
|
+
" steps:",
|
|
42
|
+
" - ref: ordering.PlaceOrder",
|
|
43
|
+
" type: command",
|
|
44
|
+
" - ref: ordering.OrderPlaced",
|
|
45
|
+
" type: event",
|
|
46
|
+
" - ref: shipping.ShipOrder",
|
|
47
|
+
" type: command",
|
|
48
|
+
].join("\n"));
|
|
49
|
+
// domain/actors.yml
|
|
50
|
+
writeFileSync(join(DOMAIN, "actors.yml"), [
|
|
51
|
+
"actors:",
|
|
52
|
+
" - name: Customer",
|
|
53
|
+
" type: human",
|
|
54
|
+
' description: "A paying customer who places orders"',
|
|
55
|
+
" - name: WarehouseBot",
|
|
56
|
+
" type: system",
|
|
57
|
+
' description: "Automated warehouse robot"',
|
|
58
|
+
].join("\n"));
|
|
59
|
+
// domain/contexts/ordering/ — per-item directory
|
|
60
|
+
writeFileSync(join(CONTEXTS, "ordering", "context.yml"), [
|
|
61
|
+
"name: ordering",
|
|
62
|
+
'description: "Handles the order lifecycle"',
|
|
63
|
+
"glossary:",
|
|
64
|
+
" - term: Order",
|
|
65
|
+
' definition: "A customer purchase request"',
|
|
66
|
+
" aliases:",
|
|
67
|
+
" - Purchase",
|
|
68
|
+
" - Booking",
|
|
69
|
+
" adr_refs:",
|
|
70
|
+
" - adr-0001",
|
|
71
|
+
].join("\n"));
|
|
72
|
+
writeFileSync(join(CONTEXTS, "ordering", "events", "OrderPlaced.yml"), [
|
|
73
|
+
"name: OrderPlaced",
|
|
74
|
+
'description: "Raised when an order is placed"',
|
|
75
|
+
"fields:",
|
|
76
|
+
" - name: orderId",
|
|
77
|
+
" type: UUID",
|
|
78
|
+
"raised_by: Order",
|
|
79
|
+
].join("\n"));
|
|
80
|
+
writeFileSync(join(CONTEXTS, "ordering", "events", "OrderCancelled.yml"), [
|
|
81
|
+
"name: OrderCancelled",
|
|
82
|
+
'description: "Raised when an order is cancelled"',
|
|
83
|
+
"raised_by: Order",
|
|
84
|
+
].join("\n"));
|
|
85
|
+
writeFileSync(join(CONTEXTS, "ordering", "commands", "PlaceOrder.yml"), [
|
|
86
|
+
"name: PlaceOrder",
|
|
87
|
+
'description: "Submit a new order"',
|
|
88
|
+
"actor: Customer",
|
|
89
|
+
"handled_by: Order",
|
|
90
|
+
].join("\n"));
|
|
91
|
+
writeFileSync(join(CONTEXTS, "ordering", "commands", "CancelOrder.yml"), [
|
|
92
|
+
"name: CancelOrder",
|
|
93
|
+
'description: "Cancel an existing order"',
|
|
94
|
+
"handled_by: Order",
|
|
95
|
+
].join("\n"));
|
|
96
|
+
writeFileSync(join(CONTEXTS, "ordering", "policies", "NotifyOnCancel.yml"), [
|
|
97
|
+
"name: NotifyOnCancel",
|
|
98
|
+
'description: "Notify customer when order is cancelled"',
|
|
99
|
+
"when:",
|
|
100
|
+
" events:",
|
|
101
|
+
" - OrderCancelled",
|
|
102
|
+
"then:",
|
|
103
|
+
" commands:",
|
|
104
|
+
" - SendNotification",
|
|
105
|
+
].join("\n"));
|
|
106
|
+
writeFileSync(join(CONTEXTS, "ordering", "aggregates", "Order.yml"), [
|
|
107
|
+
"name: Order",
|
|
108
|
+
'description: "Order aggregate root"',
|
|
109
|
+
"handles:",
|
|
110
|
+
" commands:",
|
|
111
|
+
" - PlaceOrder",
|
|
112
|
+
" - CancelOrder",
|
|
113
|
+
"emits:",
|
|
114
|
+
" events:",
|
|
115
|
+
" - OrderPlaced",
|
|
116
|
+
" - OrderCancelled",
|
|
117
|
+
].join("\n"));
|
|
118
|
+
writeFileSync(join(CONTEXTS, "ordering", "read-models", "OrderSummary.yml"), [
|
|
119
|
+
"name: OrderSummary",
|
|
120
|
+
'description: "Summary view of all orders"',
|
|
121
|
+
"subscribes_to:",
|
|
122
|
+
" - OrderPlaced",
|
|
123
|
+
" - OrderCancelled",
|
|
124
|
+
"used_by:",
|
|
125
|
+
" - Customer",
|
|
126
|
+
].join("\n"));
|
|
127
|
+
// domain/contexts/shipping/ — per-item directory
|
|
128
|
+
writeFileSync(join(CONTEXTS, "shipping", "context.yml"), [
|
|
129
|
+
"name: shipping",
|
|
130
|
+
'description: "Handles shipment tracking"',
|
|
131
|
+
].join("\n"));
|
|
132
|
+
writeFileSync(join(CONTEXTS, "shipping", "commands", "ShipOrder.yml"), [
|
|
133
|
+
"name: ShipOrder",
|
|
134
|
+
'description: "Initiate shipment for an order"',
|
|
135
|
+
"handled_by: Shipment",
|
|
136
|
+
].join("\n"));
|
|
137
|
+
writeFileSync(join(CONTEXTS, "shipping", "events", "ShipmentDispatched.yml"), [
|
|
138
|
+
"name: ShipmentDispatched",
|
|
139
|
+
'description: "Raised when a shipment is dispatched"',
|
|
140
|
+
"raised_by: Shipment",
|
|
141
|
+
].join("\n"));
|
|
142
|
+
writeFileSync(join(CONTEXTS, "shipping", "read-models", "ShipmentStatus.yml"), [
|
|
143
|
+
"name: ShipmentStatus",
|
|
144
|
+
'description: "Current status of a shipment"',
|
|
145
|
+
"subscribes_to:",
|
|
146
|
+
" - ShipmentDispatched",
|
|
147
|
+
"used_by:",
|
|
148
|
+
" - Customer",
|
|
149
|
+
].join("\n"));
|
|
150
|
+
writeFileSync(join(CONTEXTS, "shipping", "aggregates", "Shipment.yml"), [
|
|
151
|
+
"name: Shipment",
|
|
152
|
+
'description: "Shipment aggregate"',
|
|
153
|
+
"handles:",
|
|
154
|
+
" commands:",
|
|
155
|
+
" - ShipOrder",
|
|
156
|
+
"emits:",
|
|
157
|
+
" events:",
|
|
158
|
+
" - ShipmentDispatched",
|
|
159
|
+
].join("\n"));
|
|
160
|
+
// docs/adr/0001-use-yaml.md
|
|
161
|
+
writeFileSync(join(ADR_DIR, "0001-use-yaml.md"), [
|
|
162
|
+
"---",
|
|
163
|
+
"id: adr-0001",
|
|
164
|
+
"title: Use YAML for domain models",
|
|
165
|
+
"status: accepted",
|
|
166
|
+
"date: 2026-01-15",
|
|
167
|
+
"deciders:",
|
|
168
|
+
" - Alice",
|
|
169
|
+
"domain_refs:",
|
|
170
|
+
" - ordering.Order",
|
|
171
|
+
"---",
|
|
172
|
+
"",
|
|
173
|
+
"# ADR-0001 — Use YAML for domain models",
|
|
174
|
+
"",
|
|
175
|
+
"## Context",
|
|
176
|
+
"",
|
|
177
|
+
"We evaluated serialization formats including JSON, TOML, and YAML.",
|
|
178
|
+
"YAML provides the best human-readability for domain modeling artifacts.",
|
|
179
|
+
"",
|
|
180
|
+
"## Decision",
|
|
181
|
+
"",
|
|
182
|
+
"Adopt YAML as the canonical serialization format for all domain definitions.",
|
|
183
|
+
"",
|
|
184
|
+
"## Consequences",
|
|
185
|
+
"",
|
|
186
|
+
"Domain experts can directly read and edit model files without specialized tooling.",
|
|
187
|
+
].join("\n"));
|
|
188
|
+
writeFileSync(join(ADR_DIR, "README.md"), "# ADRs\n");
|
|
189
|
+
}
|
|
190
|
+
function teardown() {
|
|
191
|
+
rmSync(TMP, { recursive: true, force: true });
|
|
192
|
+
}
|
|
193
|
+
// ── Assertions ────────────────────────────────────────────────────────
|
|
194
|
+
let passed = 0;
|
|
195
|
+
let failed = 0;
|
|
196
|
+
function assert(label, condition, detail) {
|
|
197
|
+
if (condition) {
|
|
198
|
+
console.log(` OK: ${label}`);
|
|
199
|
+
passed++;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
console.error(`FAIL: ${label}${detail ? ` — ${detail}` : ""}`);
|
|
203
|
+
failed++;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// ── Run tests ─────────────────────────────────────────────────────────
|
|
207
|
+
setup();
|
|
208
|
+
try {
|
|
209
|
+
const model = loadDomainModel({ root: TMP });
|
|
210
|
+
const graph = DomainGraph.from(model);
|
|
211
|
+
// Build index (setup for search tests)
|
|
212
|
+
buildIndex(model, { root: TMP, dbPath: DB_PATH });
|
|
213
|
+
// ── Basic FTS search ──────────────────────────────────────────────
|
|
214
|
+
console.log("\n=== Basic search ===");
|
|
215
|
+
const orderResults = search("order", {}, { dbPath: DB_PATH });
|
|
216
|
+
assert("search 'order' returns results", orderResults.length > 0);
|
|
217
|
+
assert("search 'order' includes OrderPlaced", orderResults.some((r) => r.id === "ordering.OrderPlaced"));
|
|
218
|
+
assert("search 'order' includes PlaceOrder", orderResults.some((r) => r.id === "ordering.PlaceOrder"));
|
|
219
|
+
// Verify result shape
|
|
220
|
+
const first = orderResults[0];
|
|
221
|
+
assert("result has id", typeof first.id === "string" && first.id.length > 0);
|
|
222
|
+
assert("result has type", typeof first.type === "string");
|
|
223
|
+
assert("result has name", typeof first.name === "string");
|
|
224
|
+
assert("result has excerpt", typeof first.excerpt === "string");
|
|
225
|
+
assert("result has score", typeof first.score === "number" && first.score > 0);
|
|
226
|
+
assert("result has relatedIds array", Array.isArray(first.relatedIds));
|
|
227
|
+
assert("result has adrIds array", Array.isArray(first.adrIds));
|
|
228
|
+
// ── Search actors ─────────────────────────────────────────────────
|
|
229
|
+
console.log("\n=== Search actors ===");
|
|
230
|
+
const customerResults = search("customer", {}, { dbPath: DB_PATH });
|
|
231
|
+
assert("search 'customer' returns results", customerResults.length > 0);
|
|
232
|
+
assert("search 'customer' includes actor.Customer", customerResults.some((r) => r.id === "actor.Customer"));
|
|
233
|
+
// ── Search ADRs ───────────────────────────────────────────────────
|
|
234
|
+
console.log("\n=== Search ADRs ===");
|
|
235
|
+
const yamlResults = search("YAML", {}, { dbPath: DB_PATH });
|
|
236
|
+
assert("search 'YAML' returns results", yamlResults.length > 0);
|
|
237
|
+
assert("search 'YAML' includes adr-0001", yamlResults.some((r) => r.id === "adr-0001"));
|
|
238
|
+
// ── Search ADR body content ─────────────────────────────────────
|
|
239
|
+
console.log("\n=== Search ADR body content ===");
|
|
240
|
+
const serializationResults = search("serialization", {}, { dbPath: DB_PATH });
|
|
241
|
+
assert("search 'serialization' returns results", serializationResults.length > 0);
|
|
242
|
+
assert("search 'serialization' finds adr-0001 via body content", serializationResults.some((r) => r.id === "adr-0001"));
|
|
243
|
+
const readabilityResults = search("human-readability", {}, { dbPath: DB_PATH });
|
|
244
|
+
assert("search 'human-readability' returns results", readabilityResults.length > 0);
|
|
245
|
+
assert("search 'human-readability' finds adr-0001 via body content", readabilityResults.some((r) => r.id === "adr-0001"));
|
|
246
|
+
const toolingResults = search("tooling", {}, { dbPath: DB_PATH });
|
|
247
|
+
assert("search 'tooling' returns results", toolingResults.length > 0);
|
|
248
|
+
assert("search 'tooling' finds adr-0001 via Consequences section", toolingResults.some((r) => r.id === "adr-0001"));
|
|
249
|
+
// ── Search glossary (aliases) ─────────────────────────────────────
|
|
250
|
+
console.log("\n=== Search glossary aliases ===");
|
|
251
|
+
const purchaseResults = search("purchase", {}, { dbPath: DB_PATH });
|
|
252
|
+
assert("search 'purchase' returns results", purchaseResults.length > 0);
|
|
253
|
+
assert("search 'purchase' finds glossary Order via alias", purchaseResults.some((r) => r.id === "ordering.Order" && r.type === "glossary"));
|
|
254
|
+
// ── Filter by context ─────────────────────────────────────────────
|
|
255
|
+
console.log("\n=== Filter by context ===");
|
|
256
|
+
const shippingOnly = search("shipment", { context: "shipping" }, { dbPath: DB_PATH });
|
|
257
|
+
assert("filter context=shipping returns results", shippingOnly.length > 0);
|
|
258
|
+
assert("all results are in shipping context", shippingOnly.every((r) => r.context === "shipping"));
|
|
259
|
+
// ── Filter by type ────────────────────────────────────────────────
|
|
260
|
+
console.log("\n=== Filter by type ===");
|
|
261
|
+
const eventsOnly = search("order", { type: "event" }, { dbPath: DB_PATH });
|
|
262
|
+
assert("filter type=event returns results", eventsOnly.length > 0);
|
|
263
|
+
assert("all results are events", eventsOnly.every((r) => r.type === "event"));
|
|
264
|
+
// ── Filter by tag ─────────────────────────────────────────────────
|
|
265
|
+
console.log("\n=== Filter by tag ===");
|
|
266
|
+
const humanActors = search("customer", { tag: "human" }, { dbPath: DB_PATH });
|
|
267
|
+
assert("filter tag=human returns results", humanActors.length > 0);
|
|
268
|
+
assert("tagged results include actor.Customer", humanActors.some((r) => r.id === "actor.Customer"));
|
|
269
|
+
// ── Scoring: exact ID match gets highest score ────────────────────
|
|
270
|
+
console.log("\n=== Scoring ===");
|
|
271
|
+
const exactResults = search("ordering.OrderPlaced", {}, { dbPath: DB_PATH });
|
|
272
|
+
if (exactResults.length > 0) {
|
|
273
|
+
assert("exact ID match has highest score", exactResults[0].id === "ordering.OrderPlaced" ||
|
|
274
|
+
exactResults[0].score >= exactResults[exactResults.length - 1].score);
|
|
275
|
+
}
|
|
276
|
+
// ── Graph expansion ───────────────────────────────────────────────
|
|
277
|
+
console.log("\n=== Graph expansion ===");
|
|
278
|
+
const expandedResults = search("PlaceOrder", {}, { dbPath: DB_PATH, graph, expandTopN: 3 });
|
|
279
|
+
assert("expanded search returns results", expandedResults.length > 0);
|
|
280
|
+
const placeOrderResult = expandedResults.find((r) => r.id === "ordering.PlaceOrder");
|
|
281
|
+
if (placeOrderResult) {
|
|
282
|
+
assert("expanded result has relatedIds from graph", placeOrderResult.relatedIds.length > 0);
|
|
283
|
+
assert("expanded result includes Order aggregate in relatedIds", placeOrderResult.relatedIds.includes("ordering.Order"));
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
assert("PlaceOrder found in expanded results", false);
|
|
287
|
+
}
|
|
288
|
+
// ── Empty query ───────────────────────────────────────────────────
|
|
289
|
+
console.log("\n=== Edge cases ===");
|
|
290
|
+
const emptyResults = search("", {}, { dbPath: DB_PATH });
|
|
291
|
+
assert("empty query returns empty array", emptyResults.length === 0);
|
|
292
|
+
const whitespaceResults = search(" ", {}, { dbPath: DB_PATH });
|
|
293
|
+
assert("whitespace query returns empty array", whitespaceResults.length === 0);
|
|
294
|
+
// ── Missing index ─────────────────────────────────────────────────
|
|
295
|
+
let missingThrew = false;
|
|
296
|
+
try {
|
|
297
|
+
search("order", {}, { dbPath: join(TMP, "nonexistent.db") });
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
missingThrew = true;
|
|
301
|
+
}
|
|
302
|
+
assert("search with missing DB throws", missingThrew);
|
|
303
|
+
// ── Search flows ──────────────────────────────────────────────────
|
|
304
|
+
console.log("\n=== Search flows ===");
|
|
305
|
+
const flowResults = search("PlaceAndShip", {}, { dbPath: DB_PATH });
|
|
306
|
+
assert("search for flow name returns results", flowResults.length > 0);
|
|
307
|
+
assert("flow result found", flowResults.some((r) => r.id === "flow.PlaceAndShip"));
|
|
308
|
+
// ── Limit ─────────────────────────────────────────────────────────
|
|
309
|
+
console.log("\n=== Limit ===");
|
|
310
|
+
const limitResults = search("order", {}, { dbPath: DB_PATH, limit: 2 });
|
|
311
|
+
assert("limit caps results", limitResults.length <= 2);
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
teardown();
|
|
315
|
+
}
|
|
316
|
+
// ── Summary ───────────────────────────────────────────────────────────
|
|
317
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
318
|
+
if (failed > 0)
|
|
319
|
+
process.exit(1);
|
|
320
|
+
//# sourceMappingURL=searcher.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searcher.test.js","sourceRoot":"","sources":["../../../../src/features/query/tests/searcher.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AdrRecord } from "./types/domain.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse YAML frontmatter from a Markdown string.
|
|
4
|
+
*
|
|
5
|
+
* @returns The parsed `AdrRecord`, or `null` if no frontmatter is found.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseAdrFrontmatter(markdown: string): AdrRecord | null;
|
|
8
|
+
/**
|
|
9
|
+
* Read an ADR Markdown file from disk and return its frontmatter.
|
|
10
|
+
*
|
|
11
|
+
* @returns The parsed `AdrRecord`, or `null` if the file has no valid frontmatter.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseAdrFile(filePath: string): AdrRecord | null;
|
|
14
|
+
//# sourceMappingURL=adr-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr-parser.d.ts","sourceRoot":"","sources":["../../src/shared/adr-parser.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAgCnD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAwBtE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAG/D"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR frontmatter parser.
|
|
3
|
+
*
|
|
4
|
+
* Reads Markdown files from `docs/adr/` and extracts the YAML
|
|
5
|
+
* frontmatter block (delimited by `---`) into typed `AdrRecord` objects.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { parseYaml } from "./yaml.js";
|
|
9
|
+
/** Regex that captures the YAML block between the opening and closing `---`. */
|
|
10
|
+
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
11
|
+
/**
|
|
12
|
+
* Strip Markdown formatting from body text for cleaner search indexing.
|
|
13
|
+
*
|
|
14
|
+
* Removes heading markers, link syntax, emphasis, inline code, and
|
|
15
|
+
* fenced code-block delimiters while preserving the readable content.
|
|
16
|
+
*/
|
|
17
|
+
function stripMarkdown(md) {
|
|
18
|
+
return md
|
|
19
|
+
// Remove fenced code-block delimiters (``` or ~~~)
|
|
20
|
+
.replace(/^(`{3,}|~{3,}).*$/gm, "")
|
|
21
|
+
// Remove heading markers
|
|
22
|
+
.replace(/^#{1,6}\s+/gm, "")
|
|
23
|
+
// Remove images 
|
|
24
|
+
.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1")
|
|
25
|
+
// Remove links [text](url)
|
|
26
|
+
.replace(/\[([^\]]*)\]\([^)]*\)/g, "$1")
|
|
27
|
+
// Remove bold/italic markers
|
|
28
|
+
.replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1")
|
|
29
|
+
.replace(/_{1,3}([^_]+)_{1,3}/g, "$1")
|
|
30
|
+
// Remove inline code backticks
|
|
31
|
+
.replace(/`([^`]*)`/g, "$1")
|
|
32
|
+
// Collapse multiple whitespace into single space
|
|
33
|
+
.replace(/\s+/g, " ")
|
|
34
|
+
.trim();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse YAML frontmatter from a Markdown string.
|
|
38
|
+
*
|
|
39
|
+
* @returns The parsed `AdrRecord`, or `null` if no frontmatter is found.
|
|
40
|
+
*/
|
|
41
|
+
export function parseAdrFrontmatter(markdown) {
|
|
42
|
+
const match = FRONTMATTER_RE.exec(markdown);
|
|
43
|
+
if (!match)
|
|
44
|
+
return null;
|
|
45
|
+
const raw = parseYaml(match[1]);
|
|
46
|
+
// The frontmatter must at minimum contain `id`, `title`, `status`, `date`.
|
|
47
|
+
if (!raw.id || !raw.title || !raw.status || !raw.date)
|
|
48
|
+
return null;
|
|
49
|
+
// js-yaml auto-converts ISO date strings to Date objects; normalise back.
|
|
50
|
+
if (raw.date instanceof Date) {
|
|
51
|
+
raw.date = raw.date.toISOString().slice(0, 10);
|
|
52
|
+
}
|
|
53
|
+
// Extract body text after the closing ---
|
|
54
|
+
const closingIndex = markdown.indexOf("---", match.index + 3);
|
|
55
|
+
if (closingIndex !== -1) {
|
|
56
|
+
const bodyRaw = markdown.slice(closingIndex + 3).trim();
|
|
57
|
+
if (bodyRaw.length > 0) {
|
|
58
|
+
raw.body = stripMarkdown(bodyRaw);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return raw;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Read an ADR Markdown file from disk and return its frontmatter.
|
|
65
|
+
*
|
|
66
|
+
* @returns The parsed `AdrRecord`, or `null` if the file has no valid frontmatter.
|
|
67
|
+
*/
|
|
68
|
+
export function parseAdrFile(filePath) {
|
|
69
|
+
const content = readFileSync(filePath, "utf-8");
|
|
70
|
+
return parseAdrFrontmatter(content);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=adr-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr-parser.js","sourceRoot":"","sources":["../../src/shared/adr-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,gFAAgF;AAChF,MAAM,cAAc,GAAG,6BAA6B,CAAC;AAErD;;;;;GAKG;AACH,SAAS,aAAa,CAAC,EAAU;IAC/B,OAAO,EAAE;QACP,mDAAmD;SAClD,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC;QACnC,yBAAyB;SACxB,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC;QAC5B,4BAA4B;SAC3B,OAAO,CAAC,yBAAyB,EAAE,IAAI,CAAC;QACzC,2BAA2B;SAC1B,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC;QACxC,6BAA6B;SAC5B,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC;SACvC,OAAO,CAAC,sBAAsB,EAAE,IAAI,CAAC;QACtC,+BAA+B;SAC9B,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC;QAC5B,iDAAiD;SAChD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,GAAG,GAAG,SAAS,CAA0B,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzD,2EAA2E;IAC3E,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEnE,0EAA0E;IAC1E,IAAI,GAAG,CAAC,IAAI,YAAY,IAAI,EAAE,CAAC;QAC7B,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,0CAA0C;IAC1C,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9D,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACxD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,GAA2B,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI error-formatting helpers.
|
|
3
|
+
*
|
|
4
|
+
* These are presentation-infrastructure utilities used by the CLI entry
|
|
5
|
+
* point to turn raw errors into user-friendly messages.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Node.js system error shape (ENOENT, EACCES, EPERM, etc.).
|
|
9
|
+
* Not all Error objects carry these, so we use a type guard.
|
|
10
|
+
*/
|
|
11
|
+
interface NodeSystemError extends Error {
|
|
12
|
+
code: string;
|
|
13
|
+
path?: string;
|
|
14
|
+
syscall?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function isNodeSystemError(err: unknown): err is NodeSystemError;
|
|
17
|
+
/**
|
|
18
|
+
* js-yaml YAMLException shape.
|
|
19
|
+
* We detect by `name` rather than importing the class to keep coupling low.
|
|
20
|
+
*/
|
|
21
|
+
interface YAMLExceptionLike extends Error {
|
|
22
|
+
name: "YAMLException";
|
|
23
|
+
reason?: string;
|
|
24
|
+
mark?: {
|
|
25
|
+
name?: string | null;
|
|
26
|
+
line?: number;
|
|
27
|
+
column?: number;
|
|
28
|
+
snippet?: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export declare function isYAMLException(err: unknown): err is YAMLExceptionLike;
|
|
32
|
+
/**
|
|
33
|
+
* Format an error into a user-friendly CLI message.
|
|
34
|
+
*
|
|
35
|
+
* Categories handled:
|
|
36
|
+
* - YAML parse errors → clean "Failed to parse YAML" with location
|
|
37
|
+
* - ENOENT → "File not found" with path
|
|
38
|
+
* - EACCES / EPERM → "Permission denied" with path
|
|
39
|
+
* - Everything else → the error message without a stack trace
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatCliError(err: unknown): string;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,UAAU,eAAgB,SAAQ,KAAK;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,eAAe,CAEtE;AAED;;;GAGG;AACH,UAAU,iBAAkB,SAAQ,KAAK;IACvC,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnF;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,iBAAiB,CAEtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAwCnD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI error-formatting helpers.
|
|
3
|
+
*
|
|
4
|
+
* These are presentation-infrastructure utilities used by the CLI entry
|
|
5
|
+
* point to turn raw errors into user-friendly messages.
|
|
6
|
+
*/
|
|
7
|
+
export function isNodeSystemError(err) {
|
|
8
|
+
return err instanceof Error && typeof err.code === "string";
|
|
9
|
+
}
|
|
10
|
+
export function isYAMLException(err) {
|
|
11
|
+
return err instanceof Error && err.name === "YAMLException";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Format an error into a user-friendly CLI message.
|
|
15
|
+
*
|
|
16
|
+
* Categories handled:
|
|
17
|
+
* - YAML parse errors → clean "Failed to parse YAML" with location
|
|
18
|
+
* - ENOENT → "File not found" with path
|
|
19
|
+
* - EACCES / EPERM → "Permission denied" with path
|
|
20
|
+
* - Everything else → the error message without a stack trace
|
|
21
|
+
*/
|
|
22
|
+
export function formatCliError(err) {
|
|
23
|
+
// 1. YAML parse errors
|
|
24
|
+
if (isYAMLException(err)) {
|
|
25
|
+
const reason = err.reason ?? "invalid YAML syntax";
|
|
26
|
+
const mark = err.mark;
|
|
27
|
+
if (mark && mark.line != null) {
|
|
28
|
+
const file = mark.name ? `${mark.name} ` : "";
|
|
29
|
+
// js-yaml lines are 0-based; display as 1-based
|
|
30
|
+
const location = `line ${mark.line + 1}, column ${(mark.column ?? 0) + 1}`;
|
|
31
|
+
let msg = `Failed to parse YAML — ${reason} (${file}${location})`;
|
|
32
|
+
if (mark.snippet) {
|
|
33
|
+
msg += `\n${mark.snippet}`;
|
|
34
|
+
}
|
|
35
|
+
return msg;
|
|
36
|
+
}
|
|
37
|
+
return `Failed to parse YAML — ${reason}`;
|
|
38
|
+
}
|
|
39
|
+
// 2. Node.js filesystem / system errors
|
|
40
|
+
if (isNodeSystemError(err)) {
|
|
41
|
+
const filePath = err.path ? ` "${err.path}"` : "";
|
|
42
|
+
switch (err.code) {
|
|
43
|
+
case "ENOENT":
|
|
44
|
+
return `File not found:${filePath}. Check that the path exists and the domain/ directory is present.`;
|
|
45
|
+
case "EACCES":
|
|
46
|
+
case "EPERM":
|
|
47
|
+
return `Permission denied:${filePath}. Check file permissions.`;
|
|
48
|
+
case "EISDIR":
|
|
49
|
+
return `Expected a file but found a directory:${filePath}.`;
|
|
50
|
+
default:
|
|
51
|
+
return `System error (${err.code}):${filePath} — ${err.message}`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// 3. Generic errors — just the message, no stack trace
|
|
55
|
+
if (err instanceof Error) {
|
|
56
|
+
return err.message;
|
|
57
|
+
}
|
|
58
|
+
return String(err);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,OAAO,GAAG,YAAY,KAAK,IAAI,OAAQ,GAAuB,CAAC,IAAI,KAAK,QAAQ,CAAC;AACnF,CAAC;AAYD,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,OAAO,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,CAAC;AAC9D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,uBAAuB;IACvB,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,qBAAqB,CAAC;QACnD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QACtB,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,gDAAgD;YAChD,MAAM,QAAQ,GAAG,QAAQ,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3E,IAAI,GAAG,GAAG,0BAA0B,MAAM,KAAK,IAAI,GAAG,QAAQ,GAAG,CAAC;YAClE,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBACjB,GAAG,IAAI,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QACD,OAAO,0BAA0B,MAAM,EAAE,CAAC;IAC5C,CAAC;IAED,wCAAwC;IACxC,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,QAAQ;gBACX,OAAO,kBAAkB,QAAQ,oEAAoE,CAAC;YACxG,KAAK,QAAQ,CAAC;YACd,KAAK,OAAO;gBACV,OAAO,qBAAqB,QAAQ,2BAA2B,CAAC;YAClE,KAAK,QAAQ;gBACX,OAAO,yCAAyC,QAAQ,GAAG,CAAC;YAC9D;gBACE,OAAO,iBAAiB,GAAG,CAAC,IAAI,KAAK,QAAQ,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;QACrE,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain graph — adjacency-list representation of domain model relationships.
|
|
3
|
+
*
|
|
4
|
+
* Nodes represent every domain item (event, command, policy, aggregate,
|
|
5
|
+
* read-model, actor, ADR, flow). Edges capture the structural
|
|
6
|
+
* relationships declared in the YAML model (handles, emits, triggers,
|
|
7
|
+
* subscribes_to, actor, used_by, adr_refs, domain_refs, flow steps).
|
|
8
|
+
*
|
|
9
|
+
* The primary query surface is {@link DomainGraph.getRelated} which
|
|
10
|
+
* performs a breadth-first traversal up to a specified depth.
|
|
11
|
+
*/
|
|
12
|
+
import type { DomainModel } from "./types/domain.js";
|
|
13
|
+
/** The kind of domain item a node represents. */
|
|
14
|
+
export type NodeKind = "context" | "event" | "command" | "policy" | "aggregate" | "read_model" | "actor" | "adr" | "glossary" | "flow";
|
|
15
|
+
/** A single node in the domain graph. */
|
|
16
|
+
export interface GraphNode {
|
|
17
|
+
/** Unique identifier (e.g. "ordering.OrderPlaced", "actor.Customer"). */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Kind of domain item. */
|
|
20
|
+
kind: NodeKind;
|
|
21
|
+
/** Human-readable display name. */
|
|
22
|
+
name: string;
|
|
23
|
+
/** Bounded-context name, when applicable. */
|
|
24
|
+
context?: string;
|
|
25
|
+
}
|
|
26
|
+
/** An undirected edge between two nodes. */
|
|
27
|
+
export interface GraphEdge {
|
|
28
|
+
/** Source node id. */
|
|
29
|
+
from: string;
|
|
30
|
+
/** Target node id. */
|
|
31
|
+
to: string;
|
|
32
|
+
/** Describes the relationship (e.g. "handles", "emits", "adr_ref"). */
|
|
33
|
+
label: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Adjacency-list graph over every item in a {@link DomainModel}.
|
|
37
|
+
*
|
|
38
|
+
* Construct via the static factory {@link DomainGraph.from}.
|
|
39
|
+
*/
|
|
40
|
+
export declare class DomainGraph {
|
|
41
|
+
/** All nodes keyed by id. */
|
|
42
|
+
readonly nodes: ReadonlyMap<string, GraphNode>;
|
|
43
|
+
/** All edges. */
|
|
44
|
+
readonly edges: readonly GraphEdge[];
|
|
45
|
+
/** Adjacency list: node id → set of neighbour ids. */
|
|
46
|
+
private readonly adj;
|
|
47
|
+
private constructor();
|
|
48
|
+
/**
|
|
49
|
+
* Build a domain graph from a loaded {@link DomainModel}.
|
|
50
|
+
*/
|
|
51
|
+
static from(model: DomainModel): DomainGraph;
|
|
52
|
+
/**
|
|
53
|
+
* Return the set of node ids reachable from `startId` within `depth`
|
|
54
|
+
* hops (BFS). The start node itself is **not** included unless it is
|
|
55
|
+
* reachable via a cycle within the depth limit.
|
|
56
|
+
*
|
|
57
|
+
* @param startId The id of the node to start from.
|
|
58
|
+
* @param depth Maximum traversal depth (default: 1).
|
|
59
|
+
* @returns A set of related node ids.
|
|
60
|
+
*/
|
|
61
|
+
getRelated(startId: string, depth?: number): Set<string>;
|
|
62
|
+
/**
|
|
63
|
+
* Return direct neighbours of a node (shorthand for depth-1 traversal).
|
|
64
|
+
*/
|
|
65
|
+
getNeighbours(nodeId: string): Set<string>;
|
|
66
|
+
/**
|
|
67
|
+
* Check whether a node id exists in the graph.
|
|
68
|
+
*/
|
|
69
|
+
hasNode(id: string): boolean;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../src/shared/graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAsD,MAAM,mBAAmB,CAAC;AAMzG,iDAAiD;AACjD,MAAM,MAAM,QAAQ,GAChB,SAAS,GACT,OAAO,GACP,SAAS,GACT,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,OAAO,GACP,KAAK,GACL,UAAU,GACV,MAAM,CAAC;AAEX,yCAAyC;AACzC,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,4CAA4C;AAC5C,MAAM,WAAW,SAAS;IACxB,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;CACf;AAqBD;;;;GAIG;AACH,qBAAa,WAAW;IACtB,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC/C,iBAAiB;IACjB,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;IAErC,sDAAsD;IACtD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA2B;IAE/C,OAAO;IAYP;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW;IAkL5C;;;;;;;;OAQG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,GAAG,CAAC,MAAM,CAAC;IAwB3D;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAI1C;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;CAG7B"}
|