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,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain model validator.
|
|
3
|
+
*
|
|
4
|
+
* Validates the loaded {@link DomainModel} in two phases:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Schema validation** — Each YAML file is checked against its
|
|
7
|
+
* corresponding JSON Schema (via ajv).
|
|
8
|
+
* 2. **Cross-reference validation** — All inter-item references are
|
|
9
|
+
* resolved: context names, adr_refs, domain_refs, handles/emits,
|
|
10
|
+
* when/then (policy), subscribes_to, used_by, raised_by, handled_by, actor.
|
|
11
|
+
*
|
|
12
|
+
* Results are returned as arrays of errors (blocking, should exit 1)
|
|
13
|
+
* and warnings (non-blocking, informational).
|
|
14
|
+
*/
|
|
15
|
+
import { createRequire } from "node:module";
|
|
16
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { forEachItem, itemAdrRefs } from "../../shared/item-visitor.js";
|
|
19
|
+
// ajv & ajv-formats are CJS packages; use createRequire for clean interop
|
|
20
|
+
// under both tsc (Node16 resolution) and tsx (ESM runtime).
|
|
21
|
+
const require = createRequire(import.meta.url);
|
|
22
|
+
const Ajv = require("ajv").default;
|
|
23
|
+
const addFormats = require("ajv-formats").default;
|
|
24
|
+
// ── Schema bootstrap ──────────────────────────────────────────────────
|
|
25
|
+
/** Load all `*.schema.json` files from a directory into an Ajv instance. */
|
|
26
|
+
function buildAjv(schemaDir) {
|
|
27
|
+
const ajv = new Ajv({ allErrors: true, strict: true });
|
|
28
|
+
addFormats(ajv);
|
|
29
|
+
const files = readdirSync(schemaDir).filter((f) => f.endsWith(".schema.json"));
|
|
30
|
+
for (const file of files) {
|
|
31
|
+
const schema = JSON.parse(readFileSync(join(schemaDir, file), "utf-8"));
|
|
32
|
+
ajv.addSchema(schema, schema.$id);
|
|
33
|
+
}
|
|
34
|
+
return ajv;
|
|
35
|
+
}
|
|
36
|
+
// ── Helper: push issue ────────────────────────────────────────────────
|
|
37
|
+
function err(issues, message, path) {
|
|
38
|
+
issues.push({ severity: "error", message, path });
|
|
39
|
+
}
|
|
40
|
+
function warn(issues, message, path) {
|
|
41
|
+
issues.push({ severity: "warning", message, path });
|
|
42
|
+
}
|
|
43
|
+
// ── Phase 1: Schema validation ────────────────────────────────────────
|
|
44
|
+
function validateSchemas(model, ajv, issues) {
|
|
45
|
+
// Helper: validate a single value against a schema id
|
|
46
|
+
function check(schemaId, data, path) {
|
|
47
|
+
const validate = ajv.getSchema(schemaId);
|
|
48
|
+
if (!validate) {
|
|
49
|
+
err(issues, `Schema "${schemaId}" not found in ajv`, path);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (!validate(data)) {
|
|
53
|
+
for (const e of validate.errors ?? []) {
|
|
54
|
+
const loc = e.instancePath ? ` ${e.instancePath}` : "";
|
|
55
|
+
err(issues, `Schema "${schemaId}"${loc}: ${e.message}`, path);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Index
|
|
60
|
+
check("index.schema.json", model.index, "index");
|
|
61
|
+
// Actors
|
|
62
|
+
check("actors.schema.json", { actors: model.actors }, "actors");
|
|
63
|
+
// Bounded contexts (validate the full context object)
|
|
64
|
+
for (const [name, ctx] of model.contexts) {
|
|
65
|
+
check("context.schema.json", ctx, `context:${name}`);
|
|
66
|
+
}
|
|
67
|
+
// ADR frontmatter (strip runtime-only `body` field before validation)
|
|
68
|
+
for (const [id, adr] of model.adrs) {
|
|
69
|
+
const { body: _, ...frontmatter } = adr;
|
|
70
|
+
check("adr-frontmatter.schema.json", frontmatter, `adr:${id}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// ── Phase 2: Cross-reference validation ───────────────────────────────
|
|
74
|
+
function validateCrossRefs(model, options, issues) {
|
|
75
|
+
// ─ Build lookup sets ────────────────────────────────────────────────
|
|
76
|
+
/** All ADR ids (e.g. "adr-0001"). */
|
|
77
|
+
const adrIds = new Set(model.adrs.keys());
|
|
78
|
+
/** All context names. */
|
|
79
|
+
const contextNames = new Set(model.contexts.keys());
|
|
80
|
+
/** All actor names. */
|
|
81
|
+
const actorNames = new Set(model.actors.map((a) => a.name));
|
|
82
|
+
/**
|
|
83
|
+
* All named domain items keyed as "context.Name".
|
|
84
|
+
* Used to verify domain_refs from ADRs and flow step refs.
|
|
85
|
+
*/
|
|
86
|
+
const domainItemIds = new Set();
|
|
87
|
+
/**
|
|
88
|
+
* Per-context lookup sets for events, commands, aggregates,
|
|
89
|
+
* read models, policies, and glossary terms.
|
|
90
|
+
*/
|
|
91
|
+
const perContext = new Map();
|
|
92
|
+
for (const [ctxName, ctx] of model.contexts) {
|
|
93
|
+
const sets = {
|
|
94
|
+
events: new Set(),
|
|
95
|
+
commands: new Set(),
|
|
96
|
+
aggregates: new Set(),
|
|
97
|
+
readModels: new Set(),
|
|
98
|
+
policies: new Set(),
|
|
99
|
+
glossaryTerms: new Set(),
|
|
100
|
+
};
|
|
101
|
+
const typeToSet = {
|
|
102
|
+
event: sets.events,
|
|
103
|
+
command: sets.commands,
|
|
104
|
+
aggregate: sets.aggregates,
|
|
105
|
+
read_model: sets.readModels,
|
|
106
|
+
policy: sets.policies,
|
|
107
|
+
glossary: sets.glossaryTerms,
|
|
108
|
+
};
|
|
109
|
+
forEachItem(ctx, (type, name) => {
|
|
110
|
+
typeToSet[type].add(name);
|
|
111
|
+
domainItemIds.add(`${ctxName}.${name}`);
|
|
112
|
+
});
|
|
113
|
+
perContext.set(ctxName, sets);
|
|
114
|
+
}
|
|
115
|
+
// ─ 1. Global ID uniqueness ─────────────────────────────────────────
|
|
116
|
+
// Check for duplicate names within a context (e.g. an event and command
|
|
117
|
+
// with the same name). Glossary terms share the same ID namespace
|
|
118
|
+
// (context.Name), so they must also be unique.
|
|
119
|
+
for (const [ctxName, ctx] of model.contexts) {
|
|
120
|
+
const seen = new Map(); // name → first-seen kind
|
|
121
|
+
forEachItem(ctx, (kind, name) => {
|
|
122
|
+
if (seen.has(name)) {
|
|
123
|
+
err(issues, `Duplicate name "${name}" in context "${ctxName}" (first seen as ${seen.get(name)}, duplicate as ${kind})`, `context:${ctxName}`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
seen.set(name, kind);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// ─ 2. Context references in index ──────────────────────────────────
|
|
131
|
+
for (const entry of model.index.contexts) {
|
|
132
|
+
if (!contextNames.has(entry.name)) {
|
|
133
|
+
err(issues, `Index references context "${entry.name}" but no context file was loaded`, "index");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// ─ 3. ADR ref resolution ───────────────────────────────────────────
|
|
137
|
+
// Every adr_refs entry on any domain item must resolve to an ADR.
|
|
138
|
+
function checkAdrRefs(refs, path) {
|
|
139
|
+
for (const ref of refs ?? []) {
|
|
140
|
+
if (!adrIds.has(ref)) {
|
|
141
|
+
err(issues, `adr_ref "${ref}" does not resolve to any ADR`, path);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
for (const actor of model.actors) {
|
|
146
|
+
checkAdrRefs(actor.adr_refs, `actor:${actor.name}`);
|
|
147
|
+
}
|
|
148
|
+
for (const [ctxName, ctx] of model.contexts) {
|
|
149
|
+
forEachItem(ctx, (type, name, item) => {
|
|
150
|
+
checkAdrRefs(itemAdrRefs(item), `context:${ctxName}.${type}:${name}`);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
// ─ 4. ADR domain_refs resolution ───────────────────────────────────
|
|
154
|
+
for (const [id, adr] of model.adrs) {
|
|
155
|
+
for (const ref of adr.domain_refs ?? []) {
|
|
156
|
+
if (!domainItemIds.has(ref)) {
|
|
157
|
+
err(issues, `ADR domain_ref "${ref}" does not resolve to any domain item`, `adr:${id}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// superseded_by must resolve
|
|
161
|
+
if (adr.superseded_by && !adrIds.has(adr.superseded_by)) {
|
|
162
|
+
err(issues, `ADR superseded_by "${adr.superseded_by}" does not resolve to any ADR`, `adr:${id}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// ─ 5. Intra-context reference resolution ───────────────────────────
|
|
166
|
+
for (const [ctxName, ctx] of model.contexts) {
|
|
167
|
+
const sets = perContext.get(ctxName);
|
|
168
|
+
const path = (kind, name) => `context:${ctxName}.${kind}:${name}`;
|
|
169
|
+
forEachItem(ctx, (type, name, item) => {
|
|
170
|
+
switch (type) {
|
|
171
|
+
case "event": {
|
|
172
|
+
const e = item;
|
|
173
|
+
if (e.raised_by && !sets.aggregates.has(e.raised_by)) {
|
|
174
|
+
err(issues, `Event "${e.name}" raised_by "${e.raised_by}" does not match any aggregate in context "${ctxName}"`, path("event", e.name));
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case "command": {
|
|
179
|
+
const c = item;
|
|
180
|
+
if (c.handled_by && !sets.aggregates.has(c.handled_by)) {
|
|
181
|
+
err(issues, `Command "${c.name}" handled_by "${c.handled_by}" does not match any aggregate in context "${ctxName}"`, path("command", c.name));
|
|
182
|
+
}
|
|
183
|
+
if (c.actor && !actorNames.has(c.actor)) {
|
|
184
|
+
err(issues, `Command "${c.name}" actor "${c.actor}" does not match any actor`, path("command", c.name));
|
|
185
|
+
}
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
case "aggregate": {
|
|
189
|
+
const a = item;
|
|
190
|
+
for (const h of a.handles?.commands ?? []) {
|
|
191
|
+
if (!sets.commands.has(h)) {
|
|
192
|
+
err(issues, `Aggregate "${a.name}" handles "${h}" but no such command in context "${ctxName}"`, path("aggregate", a.name));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (const e of a.emits?.events ?? []) {
|
|
196
|
+
if (!sets.events.has(e)) {
|
|
197
|
+
err(issues, `Aggregate "${a.name}" emits "${e}" but no such event in context "${ctxName}"`, path("aggregate", a.name));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
case "policy": {
|
|
203
|
+
const p = item;
|
|
204
|
+
for (const t of p.when?.events ?? []) {
|
|
205
|
+
if (!sets.events.has(t)) {
|
|
206
|
+
err(issues, `Policy "${p.name}" when.events "${t}" but no such event in context "${ctxName}"`, path("policy", p.name));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
for (const e of p.then?.commands ?? []) {
|
|
210
|
+
if (!sets.commands.has(e)) {
|
|
211
|
+
err(issues, `Policy "${p.name}" then.commands "${e}" but no such command in context "${ctxName}"`, path("policy", p.name));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
case "read_model": {
|
|
217
|
+
const r = item;
|
|
218
|
+
for (const s of r.subscribes_to ?? []) {
|
|
219
|
+
if (!sets.events.has(s)) {
|
|
220
|
+
err(issues, `ReadModel "${r.name}" subscribes_to "${s}" but no such event in context "${ctxName}"`, path("read_model", r.name));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
for (const u of r.used_by ?? []) {
|
|
224
|
+
if (!actorNames.has(u)) {
|
|
225
|
+
err(issues, `ReadModel "${r.name}" used_by "${u}" but no such actor`, path("read_model", r.name));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
case "glossary":
|
|
231
|
+
// Glossary entries have no intra-context references to validate.
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
// ─ 6. Flow step resolution ─────────────────────────────────────────
|
|
237
|
+
for (const flow of model.index.flows ?? []) {
|
|
238
|
+
for (const step of flow.steps) {
|
|
239
|
+
if (!domainItemIds.has(step.ref)) {
|
|
240
|
+
err(issues, `Flow "${flow.name}" step ref "${step.ref}" does not resolve to any domain item`, `flow:${flow.name}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// ─ 7. Configurable warnings ────────────────────────────────────────
|
|
245
|
+
if (options.warnMissingFields) {
|
|
246
|
+
for (const [ctxName, ctx] of model.contexts) {
|
|
247
|
+
forEachItem(ctx, (type, name, item) => {
|
|
248
|
+
if (type === "event" || type === "command") {
|
|
249
|
+
const typed = item;
|
|
250
|
+
if (!typed.fields || typed.fields.length === 0) {
|
|
251
|
+
warn(issues, `${type === "event" ? "Event" : "Command"} "${name}" has no fields defined`, `context:${ctxName}.${type}:${name}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// ── Public API ────────────────────────────────────────────────────────
|
|
259
|
+
/**
|
|
260
|
+
* Default schema directory, resolved relative to this module.
|
|
261
|
+
* Works both from source (`src/core/`) and compiled (`dist/core/`).
|
|
262
|
+
*/
|
|
263
|
+
function defaultSchemaDir() {
|
|
264
|
+
return join(import.meta.dirname, "../../../tools/domain-pack/schema");
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Validate a loaded {@link DomainModel}.
|
|
268
|
+
*
|
|
269
|
+
* Runs JSON Schema validation followed by cross-reference checks.
|
|
270
|
+
* Returns a {@link ValidationResult} containing errors and warnings.
|
|
271
|
+
*
|
|
272
|
+
* @param model - The domain model to validate (from `loadDomainModel()`).
|
|
273
|
+
* @param options - Optional validator configuration.
|
|
274
|
+
*/
|
|
275
|
+
export function validateDomainModel(model, options = {}) {
|
|
276
|
+
const schemaDir = options.schemaDir ?? defaultSchemaDir();
|
|
277
|
+
const ajv = buildAjv(schemaDir);
|
|
278
|
+
const issues = [];
|
|
279
|
+
validateSchemas(model, ajv, issues);
|
|
280
|
+
validateCrossRefs(model, options, issues);
|
|
281
|
+
const errors = issues.filter((i) => i.severity === "error");
|
|
282
|
+
const warnings = issues.filter((i) => i.severity === "warning");
|
|
283
|
+
return {
|
|
284
|
+
valid: errors.length === 0,
|
|
285
|
+
errors,
|
|
286
|
+
warnings,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/features/pipeline/validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `domain list` command — list domain items with optional filters.
|
|
3
|
+
*
|
|
4
|
+
* Displays a table of domain items filtered by bounded context
|
|
5
|
+
* and/or item type.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command as Cmd } from "commander";
|
|
8
|
+
/** Register the `list` subcommand. */
|
|
9
|
+
export declare function registerList(program: Cmd): void;
|
|
10
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/features/query/commands/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAqHhD,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CA6B/C"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { loadDomainModel } from "../../../shared/loader.js";
|
|
2
|
+
import { forEachItem, itemDescription } from "../../../shared/item-visitor.js";
|
|
3
|
+
/** Collect all domain items into flat rows. */
|
|
4
|
+
function collectRows(root) {
|
|
5
|
+
const model = loadDomainModel({ root });
|
|
6
|
+
const rows = [];
|
|
7
|
+
// Actors
|
|
8
|
+
for (const actor of model.actors) {
|
|
9
|
+
rows.push({
|
|
10
|
+
id: `actor.${actor.name}`,
|
|
11
|
+
type: "actor",
|
|
12
|
+
context: "",
|
|
13
|
+
name: actor.name,
|
|
14
|
+
description: actor.description,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
// Bounded contexts and their items
|
|
18
|
+
for (const [ctxName, ctx] of model.contexts) {
|
|
19
|
+
rows.push({
|
|
20
|
+
id: `context.${ctxName}`,
|
|
21
|
+
type: "context",
|
|
22
|
+
context: ctxName,
|
|
23
|
+
name: ctxName,
|
|
24
|
+
description: ctx.description,
|
|
25
|
+
});
|
|
26
|
+
forEachItem(ctx, (type, name, item) => {
|
|
27
|
+
rows.push({
|
|
28
|
+
id: `${ctxName}.${name}`,
|
|
29
|
+
type,
|
|
30
|
+
context: ctxName,
|
|
31
|
+
name,
|
|
32
|
+
description: itemDescription(item),
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// ADRs
|
|
37
|
+
for (const [id, adr] of model.adrs) {
|
|
38
|
+
rows.push({
|
|
39
|
+
id,
|
|
40
|
+
type: "adr",
|
|
41
|
+
context: "",
|
|
42
|
+
name: adr.title,
|
|
43
|
+
description: `[${adr.status}] ${adr.date}`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// Flows
|
|
47
|
+
for (const flow of model.index.flows ?? []) {
|
|
48
|
+
rows.push({
|
|
49
|
+
id: `flow.${flow.name}`,
|
|
50
|
+
type: "flow",
|
|
51
|
+
context: "",
|
|
52
|
+
name: flow.name,
|
|
53
|
+
description: flow.description ?? `${flow.steps.length} steps`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return rows;
|
|
57
|
+
}
|
|
58
|
+
/** Truncate a string to `max` characters, adding "…" if truncated. */
|
|
59
|
+
function truncate(s, max) {
|
|
60
|
+
if (s.length <= max)
|
|
61
|
+
return s;
|
|
62
|
+
return s.slice(0, max - 1) + "…";
|
|
63
|
+
}
|
|
64
|
+
/** Pad a string to exactly `width` characters. */
|
|
65
|
+
function pad(s, width) {
|
|
66
|
+
return s.padEnd(width);
|
|
67
|
+
}
|
|
68
|
+
/** Print rows as an aligned text table. */
|
|
69
|
+
function printTable(rows) {
|
|
70
|
+
if (rows.length === 0) {
|
|
71
|
+
console.log("No items found.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const maxDesc = 60;
|
|
75
|
+
const header = { id: "ID", type: "TYPE", context: "CONTEXT", name: "NAME", description: "DESCRIPTION" };
|
|
76
|
+
const allRows = [header, ...rows.map((r) => ({ ...r, description: truncate(r.description, maxDesc) }))];
|
|
77
|
+
const widths = {
|
|
78
|
+
id: Math.max(...allRows.map((r) => r.id.length)),
|
|
79
|
+
type: Math.max(...allRows.map((r) => r.type.length)),
|
|
80
|
+
context: Math.max(...allRows.map((r) => r.context.length), 7),
|
|
81
|
+
name: Math.max(...allRows.map((r) => r.name.length)),
|
|
82
|
+
description: Math.max(...allRows.map((r) => r.description.length)),
|
|
83
|
+
};
|
|
84
|
+
for (const row of allRows) {
|
|
85
|
+
const line = [
|
|
86
|
+
pad(row.id, widths.id),
|
|
87
|
+
pad(row.type, widths.type),
|
|
88
|
+
pad(row.context, widths.context),
|
|
89
|
+
pad(row.name, widths.name),
|
|
90
|
+
row.description,
|
|
91
|
+
].join(" ");
|
|
92
|
+
console.log(line);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Register the `list` subcommand. */
|
|
96
|
+
export function registerList(program) {
|
|
97
|
+
program
|
|
98
|
+
.command("list")
|
|
99
|
+
.description("List domain items with optional filters")
|
|
100
|
+
.option("-c, --context <name>", "Filter by bounded context")
|
|
101
|
+
.option("-t, --type <type>", "Filter by item type (event, command, policy, aggregate, read_model, glossary, actor, adr, flow, context)")
|
|
102
|
+
.option("--json", "Output as JSON")
|
|
103
|
+
.option("-r, --root <path>", "Override repository root")
|
|
104
|
+
.action((opts) => {
|
|
105
|
+
let rows = collectRows(opts.root);
|
|
106
|
+
if (opts.context) {
|
|
107
|
+
const ctx = opts.context.toLowerCase();
|
|
108
|
+
rows = rows.filter((r) => r.context.toLowerCase() === ctx);
|
|
109
|
+
}
|
|
110
|
+
if (opts.type) {
|
|
111
|
+
const t = opts.type.toLowerCase();
|
|
112
|
+
rows = rows.filter((r) => r.type.toLowerCase() === t);
|
|
113
|
+
}
|
|
114
|
+
if (opts.json) {
|
|
115
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
console.log(`\n${rows.length} item(s) found:\n`);
|
|
119
|
+
printTable(rows);
|
|
120
|
+
console.log();
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/features/query/commands/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `domain related <id>` command — graph traversal to find related items.
|
|
3
|
+
*
|
|
4
|
+
* Performs a BFS traversal from a given item ID in the domain graph
|
|
5
|
+
* and lists all reachable items within the specified depth.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command as Cmd } from "commander";
|
|
8
|
+
/** Register the `related` subcommand. */
|
|
9
|
+
export declare function registerRelated(program: Cmd): void;
|
|
10
|
+
//# sourceMappingURL=related.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"related.d.ts","sourceRoot":"","sources":["../../../../src/features/query/commands/related.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAIhD,yCAAyC;AACzC,wBAAgB,eAAe,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CA6DlD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { loadDomainModel } from "../../../shared/loader.js";
|
|
2
|
+
import { DomainGraph } from "../../../shared/graph.js";
|
|
3
|
+
/** Register the `related` subcommand. */
|
|
4
|
+
export function registerRelated(program) {
|
|
5
|
+
program
|
|
6
|
+
.command("related <id>")
|
|
7
|
+
.description("Show items related to a domain item via graph traversal (BFS)")
|
|
8
|
+
.option("-d, --depth <n>", "Maximum traversal depth", "1")
|
|
9
|
+
.option("--json", "Output as JSON")
|
|
10
|
+
.option("-r, --root <path>", "Override repository root")
|
|
11
|
+
.action((id, opts) => {
|
|
12
|
+
const depth = parseInt(opts.depth ?? "1", 10);
|
|
13
|
+
const model = loadDomainModel({ root: opts.root });
|
|
14
|
+
const graph = DomainGraph.from(model);
|
|
15
|
+
if (!graph.hasNode(id)) {
|
|
16
|
+
if (opts.json) {
|
|
17
|
+
console.log(JSON.stringify({ error: `Node "${id}" not found in the domain graph` }, null, 2));
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
console.error(`Error: Node "${id}" not found in the domain graph.`);
|
|
21
|
+
}
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const related = graph.getRelated(id, depth);
|
|
25
|
+
// Group by kind for readability
|
|
26
|
+
const grouped = new Map();
|
|
27
|
+
for (const nId of related) {
|
|
28
|
+
const node = graph.nodes.get(nId);
|
|
29
|
+
const kind = node?.kind ?? "unknown";
|
|
30
|
+
if (!grouped.has(kind))
|
|
31
|
+
grouped.set(kind, []);
|
|
32
|
+
grouped.get(kind).push({
|
|
33
|
+
id: nId,
|
|
34
|
+
name: node?.name ?? nId,
|
|
35
|
+
...(node?.context ? { context: node.context } : {}),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (opts.json) {
|
|
39
|
+
const result = {};
|
|
40
|
+
for (const [kind, items] of [...grouped.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
41
|
+
result[kind] = items.sort((a, b) => a.id.localeCompare(b.id));
|
|
42
|
+
}
|
|
43
|
+
console.log(JSON.stringify({ id, depth, related: result }, null, 2));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (related.size === 0) {
|
|
47
|
+
console.log(`\nNo related items found for "${id}" within depth ${depth}.\n`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
console.log(`\n${related.size} item(s) related to "${id}" (depth=${depth}):\n`);
|
|
51
|
+
for (const [kind, items] of [...grouped.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
52
|
+
console.log(` ${kind}:`);
|
|
53
|
+
for (const item of items.sort((a, b) => a.id.localeCompare(b.id))) {
|
|
54
|
+
const label = `${item.name}${item.context ? ` [${item.context}]` : ""}`;
|
|
55
|
+
console.log(` - ${item.id} (${label})`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
console.log();
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=related.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"related.js","sourceRoot":"","sources":["../../../../src/features/query/commands/related.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `domain search <query>` command — FTS5 keyword search over domain items.
|
|
3
|
+
*
|
|
4
|
+
* Runs a full-text search against the SQLite FTS5 index and displays
|
|
5
|
+
* ranked results with optional context/type/tag filters.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command as Cmd } from "commander";
|
|
8
|
+
/** Register the `search` subcommand. */
|
|
9
|
+
export declare function registerSearch(program: Cmd): void;
|
|
10
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../src/features/query/commands/search.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAKhD,wCAAwC;AACxC,wBAAgB,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CA+DjD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { search } from "../searcher.js";
|
|
2
|
+
import { DomainGraph } from "../../../shared/graph.js";
|
|
3
|
+
import { loadDomainModel } from "../../../shared/loader.js";
|
|
4
|
+
/** Register the `search` subcommand. */
|
|
5
|
+
export function registerSearch(program) {
|
|
6
|
+
program
|
|
7
|
+
.command("search <query>")
|
|
8
|
+
.description("Full-text search across domain items (requires index; run 'domain-knowledge-kit render' first)")
|
|
9
|
+
.option("-c, --context <name>", "Filter results to a bounded context")
|
|
10
|
+
.option("-t, --type <type>", "Filter results by item type")
|
|
11
|
+
.option("--tag <tag>", "Filter results by tag/keyword")
|
|
12
|
+
.option("--limit <n>", "Maximum results to return", "20")
|
|
13
|
+
.option("--expand", "Expand top results with graph neighbours")
|
|
14
|
+
.option("--json", "Output as JSON")
|
|
15
|
+
.option("-r, --root <path>", "Override repository root")
|
|
16
|
+
.action((query, opts) => {
|
|
17
|
+
const filters = {
|
|
18
|
+
context: opts.context,
|
|
19
|
+
type: opts.type,
|
|
20
|
+
tag: opts.tag,
|
|
21
|
+
};
|
|
22
|
+
let graph;
|
|
23
|
+
if (opts.expand) {
|
|
24
|
+
const model = loadDomainModel({ root: opts.root });
|
|
25
|
+
graph = DomainGraph.from(model);
|
|
26
|
+
}
|
|
27
|
+
const results = search(query, filters, {
|
|
28
|
+
root: opts.root,
|
|
29
|
+
limit: parseInt(opts.limit ?? "20", 10),
|
|
30
|
+
graph,
|
|
31
|
+
});
|
|
32
|
+
if (opts.json) {
|
|
33
|
+
console.log(JSON.stringify(results, null, 2));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (results.length === 0) {
|
|
37
|
+
console.log(`\nNo results for "${query}".\n`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log(`\n${results.length} result(s) for "${query}":\n`);
|
|
41
|
+
for (const r of results) {
|
|
42
|
+
const ctx = r.context ? ` [${r.context}]` : "";
|
|
43
|
+
console.log(` ${r.id} (${r.type})${ctx} score=${r.score}`);
|
|
44
|
+
console.log(` ${r.excerpt}`);
|
|
45
|
+
if (r.adrIds.length > 0) {
|
|
46
|
+
console.log(` ADRs: ${r.adrIds.join(", ")}`);
|
|
47
|
+
}
|
|
48
|
+
if (r.relatedIds.length > 0) {
|
|
49
|
+
console.log(` Related: ${r.relatedIds.join(", ")}`);
|
|
50
|
+
}
|
|
51
|
+
console.log();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../src/features/query/commands/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `domain show <id>` command — display the full YAML for a domain item.
|
|
3
|
+
*
|
|
4
|
+
* Looks up an item by its composite ID (e.g. "ordering.OrderPlaced",
|
|
5
|
+
* "actor.Customer", "adr-0001") and prints its full YAML representation.
|
|
6
|
+
*/
|
|
7
|
+
import type { Command as Cmd } from "commander";
|
|
8
|
+
/** Register the `show` subcommand. */
|
|
9
|
+
export declare function registerShow(program: Cmd): void;
|
|
10
|
+
//# sourceMappingURL=show.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../../../src/features/query/commands/show.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAwEhD,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CA2B/C"}
|