domain-knowledge-kit 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -27
- package/dist/cli.js +23 -0
- package/dist/cli.js.map +1 -1
- package/dist/features/agent/commands/init.d.ts.map +1 -1
- package/dist/features/agent/commands/init.js +3 -2
- package/dist/features/agent/commands/init.js.map +1 -1
- package/dist/features/agent/commands/prime.d.ts +4 -1
- package/dist/features/agent/commands/prime.d.ts.map +1 -1
- package/dist/features/agent/commands/prime.js +213 -61
- package/dist/features/agent/commands/prime.js.map +1 -1
- package/dist/features/audit/commands/stats.d.ts +3 -0
- package/dist/features/audit/commands/stats.d.ts.map +1 -0
- package/dist/features/audit/commands/stats.js +90 -0
- package/dist/features/audit/commands/stats.js.map +1 -0
- package/dist/features/pipeline/commands/validate.d.ts.map +1 -1
- package/dist/features/pipeline/commands/validate.js +32 -13
- package/dist/features/pipeline/commands/validate.js.map +1 -1
- package/dist/features/pipeline/renderer.js +1 -1
- package/dist/features/pipeline/renderer.js.map +1 -1
- package/dist/features/pipeline/tests/indexer.test.js +5 -5
- package/dist/features/pipeline/tests/indexer.test.js.map +1 -1
- package/dist/features/pipeline/tests/validator.test.js +25 -25
- package/dist/features/pipeline/tests/validator.test.js.map +1 -1
- package/dist/features/query/commands/graph.d.ts +3 -0
- package/dist/features/query/commands/graph.d.ts.map +1 -0
- package/dist/features/query/commands/graph.js +86 -0
- package/dist/features/query/commands/graph.js.map +1 -0
- package/dist/features/query/commands/search.d.ts +3 -0
- package/dist/features/query/commands/search.d.ts.map +1 -1
- package/dist/features/query/commands/search.js +29 -8
- package/dist/features/query/commands/search.js.map +1 -1
- package/dist/features/query/commands/summary.d.ts +7 -0
- package/dist/features/query/commands/summary.d.ts.map +1 -0
- package/dist/features/query/commands/summary.js +43 -0
- package/dist/features/query/commands/summary.js.map +1 -0
- package/dist/features/query/tests/searcher.test.js +5 -5
- package/dist/features/query/tests/searcher.test.js.map +1 -1
- package/dist/features/refactor/commands/rename.d.ts +3 -0
- package/dist/features/refactor/commands/rename.d.ts.map +1 -0
- package/dist/features/refactor/commands/rename.js +152 -0
- package/dist/features/refactor/commands/rename.js.map +1 -0
- package/dist/features/refactor/commands/rm.d.ts +3 -0
- package/dist/features/refactor/commands/rm.d.ts.map +1 -0
- package/dist/features/refactor/commands/rm.js +93 -0
- package/dist/features/refactor/commands/rm.js.map +1 -0
- package/dist/features/scaffold/commands/add-item.d.ts +26 -0
- package/dist/features/scaffold/commands/add-item.d.ts.map +1 -0
- package/dist/features/scaffold/commands/add-item.js +221 -0
- package/dist/features/scaffold/commands/add-item.js.map +1 -0
- package/dist/features/scaffold/commands/new-adr.d.ts +12 -0
- package/dist/features/scaffold/commands/new-adr.d.ts.map +1 -0
- package/dist/features/scaffold/commands/new-adr.js +112 -0
- package/dist/features/scaffold/commands/new-adr.js.map +1 -0
- package/dist/features/scaffold/commands/new-context.d.ts +17 -0
- package/dist/features/scaffold/commands/new-context.d.ts.map +1 -0
- package/dist/features/scaffold/commands/new-context.js +77 -0
- package/dist/features/scaffold/commands/new-context.js.map +1 -0
- package/dist/features/scaffold/commands/new-domain.d.ts +14 -0
- package/dist/features/scaffold/commands/new-domain.d.ts.map +1 -0
- package/dist/features/scaffold/commands/new-domain.js +95 -0
- package/dist/features/scaffold/commands/new-domain.js.map +1 -0
- package/dist/shared/errors.js +1 -1
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/loader.js +2 -2
- package/dist/shared/paths.d.ts +32 -11
- package/dist/shared/paths.d.ts.map +1 -1
- package/dist/shared/paths.js +49 -19
- package/dist/shared/paths.js.map +1 -1
- package/dist/shared/tests/graph.test.js +9 -9
- package/dist/shared/tests/graph.test.js.map +1 -1
- package/dist/shared/tests/loader.test.js +20 -20
- package/dist/shared/tests/loader.test.js.map +1 -1
- package/dist/shared/tests/verify-collision-fix.test.js +1 -1
- package/dist/shared/tests/verify-collision-fix.test.js.map +1 -1
- package/dist/shared/types/domain.d.ts +4 -4
- package/dist/shared/types/domain.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rm.js","sourceRoot":"","sources":["../../../../src/features/refactor/commands/rm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dkk add <type> <name> --context <ctx>` command — scaffold individual domain items.
|
|
3
|
+
*
|
|
4
|
+
* Supported types: event, command, aggregate, policy, read-model, glossary
|
|
5
|
+
*
|
|
6
|
+
* For file-based types (event, command, aggregate, policy, read-model):
|
|
7
|
+
* Creates `.dkk/domain/contexts/<ctx>/<type-plural>/<Name>.yml`
|
|
8
|
+
*
|
|
9
|
+
* For glossary:
|
|
10
|
+
* Appends entry to `.dkk/domain/contexts/<ctx>/context.yml` glossary array
|
|
11
|
+
* (glossary entries are stored inline in context.yml, not as separate files).
|
|
12
|
+
*/
|
|
13
|
+
import type { Command as Cmd } from "commander";
|
|
14
|
+
export interface AddItemRelations {
|
|
15
|
+
raisedBy?: string;
|
|
16
|
+
handledBy?: string;
|
|
17
|
+
actor?: string;
|
|
18
|
+
triggers?: string[];
|
|
19
|
+
emits?: string[];
|
|
20
|
+
handles?: string[];
|
|
21
|
+
subscribesTo?: string[];
|
|
22
|
+
usedBy?: string[];
|
|
23
|
+
fromObj?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
export declare function registerAddItem(program: Cmd): void;
|
|
26
|
+
//# sourceMappingURL=add-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-item.d.ts","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/add-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAyBhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAwFD,wBAAgB,eAAe,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CA8JlD"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { contextsDir } from "../../../shared/paths.js";
|
|
4
|
+
import { parseYaml, stringifyYaml } from "../../../shared/yaml.js";
|
|
5
|
+
import { loadDomainModel } from "../../../shared/loader.js";
|
|
6
|
+
import { DomainGraph } from "../../../shared/graph.js";
|
|
7
|
+
// ── Constants ─────────────────────────────────────────────────────────
|
|
8
|
+
/** Supported item types and their plural directory names. */
|
|
9
|
+
const TYPE_DIR_MAP = {
|
|
10
|
+
event: "events",
|
|
11
|
+
command: "commands",
|
|
12
|
+
aggregate: "aggregates",
|
|
13
|
+
policy: "policies",
|
|
14
|
+
"read-model": "read-models",
|
|
15
|
+
};
|
|
16
|
+
/** All supported item types (including glossary which is handled differently). */
|
|
17
|
+
const SUPPORTED_TYPES = [...Object.keys(TYPE_DIR_MAP), "glossary"];
|
|
18
|
+
function eventYaml(name, description, rel) {
|
|
19
|
+
let out = `name: ${name}\ndescription: "${description}"\n`;
|
|
20
|
+
if (rel.fromObj?.fields)
|
|
21
|
+
out += `fields:\n${stringifyYaml(rel.fromObj.fields).trimEnd().split('\n').map(l => ` ${l}`).join('\n')}\n`;
|
|
22
|
+
if (rel.raisedBy)
|
|
23
|
+
out += `raised_by: ${rel.raisedBy}\n`;
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
function commandYaml(name, description, rel) {
|
|
27
|
+
let out = `name: ${name}\ndescription: "${description}"\n`;
|
|
28
|
+
if (rel.fromObj?.fields)
|
|
29
|
+
out += `fields:\n${stringifyYaml(rel.fromObj.fields).trimEnd().split('\n').map(l => ` ${l}`).join('\n')}\n`;
|
|
30
|
+
if (rel.actor)
|
|
31
|
+
out += `actor: ${rel.actor}\n`;
|
|
32
|
+
if (rel.handledBy)
|
|
33
|
+
out += `handled_by: ${rel.handledBy}\n`;
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
function aggregateYaml(name, description, rel) {
|
|
37
|
+
const handles = rel.handles?.length ? rel.handles.map(h => ` - ${h}`).join('\n') : " []";
|
|
38
|
+
const emits = rel.emits?.length ? rel.emits.map(e => ` - ${e}`).join('\n') : " []";
|
|
39
|
+
return [
|
|
40
|
+
`name: ${name}`,
|
|
41
|
+
`description: "${description}"`,
|
|
42
|
+
"handles:",
|
|
43
|
+
` commands:\n${handles === " []" ? " []" : handles}`,
|
|
44
|
+
"emits:",
|
|
45
|
+
` events:\n${emits === " []" ? " []" : emits}`,
|
|
46
|
+
"",
|
|
47
|
+
].join("\n");
|
|
48
|
+
}
|
|
49
|
+
function policyYaml(name, description, rel) {
|
|
50
|
+
const triggers = rel.triggers?.length ? rel.triggers.map(t => ` - ${t}`).join('\n') : " []";
|
|
51
|
+
const emits = rel.emits?.length ? rel.emits.map(e => ` - ${e}`).join('\n') : " []";
|
|
52
|
+
return [
|
|
53
|
+
`name: ${name}`,
|
|
54
|
+
`description: "${description}"`,
|
|
55
|
+
"when:",
|
|
56
|
+
` events:\n${triggers === " []" ? " []" : triggers}`,
|
|
57
|
+
"then:",
|
|
58
|
+
` commands:\n${emits === " []" ? " []" : emits}`,
|
|
59
|
+
"",
|
|
60
|
+
].join("\n");
|
|
61
|
+
}
|
|
62
|
+
function readModelYaml(name, description, rel) {
|
|
63
|
+
const subs = rel.subscribesTo?.length ? rel.subscribesTo.map(s => ` - ${s}`).join('\n') : " []";
|
|
64
|
+
const users = rel.usedBy?.length ? rel.usedBy.map(u => ` - ${u}`).join('\n') : " []";
|
|
65
|
+
return [
|
|
66
|
+
`name: ${name}`,
|
|
67
|
+
`description: "${description}"`,
|
|
68
|
+
`subscribes_to:\n${subs === " []" ? " []" : subs}`,
|
|
69
|
+
`used_by:\n${users === " []" ? " []" : users}`,
|
|
70
|
+
"",
|
|
71
|
+
].join("\n");
|
|
72
|
+
}
|
|
73
|
+
/** Return YAML content for a file-based item type. */
|
|
74
|
+
function generateYaml(type, name, description, rel) {
|
|
75
|
+
switch (type) {
|
|
76
|
+
case "event":
|
|
77
|
+
return eventYaml(name, description, rel);
|
|
78
|
+
case "command":
|
|
79
|
+
return commandYaml(name, description, rel);
|
|
80
|
+
case "aggregate":
|
|
81
|
+
return aggregateYaml(name, description, rel);
|
|
82
|
+
case "policy":
|
|
83
|
+
return policyYaml(name, description, rel);
|
|
84
|
+
case "read-model":
|
|
85
|
+
return readModelYaml(name, description, rel);
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Unknown type: ${type}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ── Validation ────────────────────────────────────────────────────────
|
|
91
|
+
/** Validate item name is PascalCase per schema: ^[A-Za-z][A-Za-z0-9]*$ */
|
|
92
|
+
function isValidItemName(name) {
|
|
93
|
+
return /^[A-Za-z][A-Za-z0-9]*$/.test(name);
|
|
94
|
+
}
|
|
95
|
+
// ── Registration ──────────────────────────────────────────────────────
|
|
96
|
+
function parseCsv(val) {
|
|
97
|
+
return val.split(',').map(s => s.trim()).filter(Boolean);
|
|
98
|
+
}
|
|
99
|
+
export function registerAddItem(program) {
|
|
100
|
+
program
|
|
101
|
+
.command("add <type> <name>")
|
|
102
|
+
.description(`Scaffold a domain item. Types: ${SUPPORTED_TYPES.join(", ")}`)
|
|
103
|
+
.requiredOption("-c, --context <ctx>", "Target bounded context (kebab-case)")
|
|
104
|
+
.option("-d, --description <text>", "Description of the item")
|
|
105
|
+
.option("--raised-by <id>", "Aggregate that raises this event")
|
|
106
|
+
.option("--handled-by <id>", "Aggregate that handles this command")
|
|
107
|
+
.option("--actor <id>", "Actor that initiates this command")
|
|
108
|
+
.option("--triggers <ids>", "Events that trigger this policy (comma-separated)", parseCsv)
|
|
109
|
+
.option("--emits <ids>", "Commands emitted by policy / events emitted by aggregate (comma-separated)", parseCsv)
|
|
110
|
+
.option("--handles <ids>", "Commands handled by aggregate (comma-separated)", parseCsv)
|
|
111
|
+
.option("--subscribes-to <ids>", "Events subscribed to by read-model (comma-separated)", parseCsv)
|
|
112
|
+
.option("--used-by <ids>", "Actors that use this read-model (comma-separated)", parseCsv)
|
|
113
|
+
.option("--from <id>", "Clone structure from existing item ID")
|
|
114
|
+
.option("--json", "Output as JSON")
|
|
115
|
+
.option("--minify", "Minify JSON output")
|
|
116
|
+
.option("-r, --root <path>", "Override repository root")
|
|
117
|
+
.action((type, name, opts) => {
|
|
118
|
+
// Validate type
|
|
119
|
+
if (!SUPPORTED_TYPES.includes(type)) {
|
|
120
|
+
console.error(`Error: Unknown item type "${type}". Supported types: ${SUPPORTED_TYPES.join(", ")}`);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
// Validate name
|
|
124
|
+
if (!isValidItemName(name)) {
|
|
125
|
+
console.error(`Error: Item name "${name}" is invalid. Use PascalCase (e.g. "OrderPlaced").`);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
const ctxBase = contextsDir(opts.root);
|
|
129
|
+
const ctxDir = join(ctxBase, opts.context);
|
|
130
|
+
const contextYmlPath = join(ctxDir, "context.yml");
|
|
131
|
+
// Validate context exists
|
|
132
|
+
if (!existsSync(contextYmlPath)) {
|
|
133
|
+
console.error(`Error: Context "${opts.context}" does not exist. No context.yml found at ${contextYmlPath}.`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
let description = opts.description ?? `TODO: describe ${name}`;
|
|
137
|
+
// Handle glossary separately — append to context.yml
|
|
138
|
+
if (type === "glossary") {
|
|
139
|
+
const raw = readFileSync(contextYmlPath, "utf-8");
|
|
140
|
+
const meta = parseYaml(raw);
|
|
141
|
+
// Check for duplicate
|
|
142
|
+
if (meta.glossary?.some((g) => g.term === name)) {
|
|
143
|
+
console.error(`Error: Glossary entry "${name}" already exists in context "${opts.context}".`);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
if (!meta.glossary) {
|
|
147
|
+
meta.glossary = [];
|
|
148
|
+
}
|
|
149
|
+
meta.glossary.push({ term: name, definition: description });
|
|
150
|
+
writeFileSync(contextYmlPath, stringifyYaml(meta), "utf-8");
|
|
151
|
+
console.log(`Added glossary entry "${name}" to context "${opts.context}" in context.yml.`);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// Handle --from templating
|
|
155
|
+
let fromObj = undefined;
|
|
156
|
+
if (opts.from) {
|
|
157
|
+
const model = loadDomainModel({ root: opts.root });
|
|
158
|
+
const graph = DomainGraph.from(model);
|
|
159
|
+
if (!graph.hasNode(opts.from)) {
|
|
160
|
+
console.error(`Error: --from target '${opts.from}' not found.`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
// For cloning fields, we need the actual Yaml representation
|
|
164
|
+
// We can re-use the load function but doing it manually is tedious.
|
|
165
|
+
// Since we know the context and name, we can just parse the file directly:
|
|
166
|
+
const [fromCtx, fromName] = opts.from.split('.');
|
|
167
|
+
const fromKind = graph.nodes.get(opts.from)?.kind ?? 'event';
|
|
168
|
+
if (TYPE_DIR_MAP[fromKind]) {
|
|
169
|
+
const fromPath = join(ctxBase, fromCtx, TYPE_DIR_MAP[fromKind], `${fromName}.yml`);
|
|
170
|
+
if (existsSync(fromPath)) {
|
|
171
|
+
fromObj = parseYaml(readFileSync(fromPath, 'utf-8'));
|
|
172
|
+
if (!opts.description && fromObj.description) {
|
|
173
|
+
description = fromObj.description;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// File-based types
|
|
179
|
+
const dirName = TYPE_DIR_MAP[type];
|
|
180
|
+
const typeDir = join(ctxDir, dirName);
|
|
181
|
+
const filePath = join(typeDir, `${name}.yml`);
|
|
182
|
+
// Check if item already exists
|
|
183
|
+
if (existsSync(filePath)) {
|
|
184
|
+
if (opts.json) {
|
|
185
|
+
console.log(JSON.stringify({ error: `${type} "${name}" already exists at ${filePath}` }, null, opts.minify ? 0 : 2));
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
console.error(`Error: ${type} "${name}" already exists at ${filePath}.`);
|
|
189
|
+
}
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
// Create type subdirectory if needed
|
|
193
|
+
mkdirSync(typeDir, { recursive: true });
|
|
194
|
+
const rel = {
|
|
195
|
+
raisedBy: opts.raisedBy,
|
|
196
|
+
handledBy: opts.handledBy,
|
|
197
|
+
actor: opts.actor,
|
|
198
|
+
triggers: opts.triggers,
|
|
199
|
+
emits: opts.emits,
|
|
200
|
+
handles: opts.handles,
|
|
201
|
+
subscribesTo: opts.subscribesTo,
|
|
202
|
+
usedBy: opts.usedBy,
|
|
203
|
+
fromObj: fromObj
|
|
204
|
+
};
|
|
205
|
+
// Write YAML file
|
|
206
|
+
const yaml = generateYaml(type, name, description, rel);
|
|
207
|
+
writeFileSync(filePath, yaml, "utf-8");
|
|
208
|
+
if (opts.json) {
|
|
209
|
+
console.log(JSON.stringify({
|
|
210
|
+
id: `${opts.context}.${name}`,
|
|
211
|
+
path: filePath,
|
|
212
|
+
type,
|
|
213
|
+
name
|
|
214
|
+
}, null, opts.minify ? 0 : 2));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
console.log(`Created ${type} "${name}" in context "${opts.context}":`);
|
|
218
|
+
console.log(` ${filePath}`);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=add-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-item.js","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/add-item.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dkk new adr <title>` command — scaffold a new ADR file.
|
|
3
|
+
*
|
|
4
|
+
* Creates `.dkk/adr/adr-NNNN.md` with YAML frontmatter template.
|
|
5
|
+
* Automatically determines the next ADR number by scanning existing files.
|
|
6
|
+
*
|
|
7
|
+
* Flags:
|
|
8
|
+
* --status accepted|proposed|deprecated (default: proposed)
|
|
9
|
+
*/
|
|
10
|
+
import type { Command as Cmd } from "commander";
|
|
11
|
+
export declare function registerNewAdr(program: Cmd): void;
|
|
12
|
+
//# sourceMappingURL=new-adr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-adr.d.ts","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-adr.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AA+ChD,wBAAgB,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CA+EjD"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { adrDir } from "../../../shared/paths.js";
|
|
4
|
+
/** Scan existing adr-NNNN.md files and return the next number. */
|
|
5
|
+
function nextAdrNumber(dir) {
|
|
6
|
+
if (!existsSync(dir))
|
|
7
|
+
return 1;
|
|
8
|
+
const files = readdirSync(dir);
|
|
9
|
+
let max = 0;
|
|
10
|
+
for (const f of files) {
|
|
11
|
+
const m = f.match(/^adr-(\d{4})\.md$/);
|
|
12
|
+
if (m) {
|
|
13
|
+
const n = parseInt(m[1], 10);
|
|
14
|
+
if (n > max)
|
|
15
|
+
max = n;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return max + 1;
|
|
19
|
+
}
|
|
20
|
+
/** Pad a number to 4 digits. */
|
|
21
|
+
function pad4(n) {
|
|
22
|
+
return String(n).padStart(4, "0");
|
|
23
|
+
}
|
|
24
|
+
/** Get today's date as YYYY-MM-DD. */
|
|
25
|
+
function today() {
|
|
26
|
+
const d = new Date();
|
|
27
|
+
const year = d.getFullYear();
|
|
28
|
+
const month = String(d.getMonth() + 1).padStart(2, "0");
|
|
29
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
30
|
+
return `${year}-${month}-${day}`;
|
|
31
|
+
}
|
|
32
|
+
/** Convert a title to a kebab-case slug for the filename hint. */
|
|
33
|
+
function slugify(title) {
|
|
34
|
+
return title
|
|
35
|
+
.toLowerCase()
|
|
36
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
37
|
+
.replace(/^-|-$/g, "");
|
|
38
|
+
}
|
|
39
|
+
function parseCsv(val) {
|
|
40
|
+
return val.split(',').map(s => s.trim()).filter(Boolean);
|
|
41
|
+
}
|
|
42
|
+
export function registerNewAdr(program) {
|
|
43
|
+
program
|
|
44
|
+
.command("adr <title>")
|
|
45
|
+
.description("Scaffold a new ADR file with frontmatter template")
|
|
46
|
+
.option("-r, --root <path>", "Override repository root")
|
|
47
|
+
.option("-s, --status <status>", "ADR status (proposed, accepted, deprecated)", "proposed")
|
|
48
|
+
.option("--domain-refs <ids>", "Domain references (comma-separated)", parseCsv)
|
|
49
|
+
.option("--deciders <names>", "Deciders (comma-separated)", parseCsv)
|
|
50
|
+
.option("--json", "Output as JSON")
|
|
51
|
+
.option("--minify", "Minify JSON")
|
|
52
|
+
.action((title, opts) => {
|
|
53
|
+
const status = opts.status ?? "proposed";
|
|
54
|
+
const validStatuses = ["proposed", "accepted", "deprecated", "superseded"];
|
|
55
|
+
if (!validStatuses.includes(status)) {
|
|
56
|
+
console.error(`Error: Invalid status "${status}". Must be one of: ${validStatuses.join(", ")}`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const dir = adrDir(opts.root);
|
|
60
|
+
mkdirSync(dir, { recursive: true });
|
|
61
|
+
const num = nextAdrNumber(dir);
|
|
62
|
+
const id = `adr-${pad4(num)}`;
|
|
63
|
+
const filename = `${id}.md`;
|
|
64
|
+
const filePath = join(dir, filename);
|
|
65
|
+
// Guard: should not happen with auto-numbering, but be safe
|
|
66
|
+
if (existsSync(filePath)) {
|
|
67
|
+
console.error(`Error: ${filePath} already exists.`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const _slug = slugify(title);
|
|
71
|
+
const decidersStr = opts.deciders?.length ? opts.deciders.map(d => `\n - "${d}"`).join('') : " []";
|
|
72
|
+
const domainRefsStr = opts.domainRefs?.length ? opts.domainRefs.map(r => `\n - ${r}`).join('') : " []";
|
|
73
|
+
const content = `---
|
|
74
|
+
id: ${id}
|
|
75
|
+
title: ${title}
|
|
76
|
+
status: ${status}
|
|
77
|
+
date: ${today()}
|
|
78
|
+
deciders:${decidersStr}
|
|
79
|
+
domain_refs:${domainRefsStr}
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
# ${id.toUpperCase()} — ${title}
|
|
83
|
+
|
|
84
|
+
**Status:** ${status.charAt(0).toUpperCase() + status.slice(1)}
|
|
85
|
+
**Date:** ${today()}
|
|
86
|
+
|
|
87
|
+
## Context
|
|
88
|
+
|
|
89
|
+
<!-- What is the issue that we're seeing that is motivating this decision? -->
|
|
90
|
+
|
|
91
|
+
## Decision
|
|
92
|
+
|
|
93
|
+
<!-- What is the change that we're proposing and/or doing? -->
|
|
94
|
+
|
|
95
|
+
## Consequences
|
|
96
|
+
|
|
97
|
+
<!-- What becomes easier or harder as a result of this decision? -->
|
|
98
|
+
`;
|
|
99
|
+
writeFileSync(filePath, content, "utf-8");
|
|
100
|
+
if (opts.json) {
|
|
101
|
+
console.log(JSON.stringify({
|
|
102
|
+
id,
|
|
103
|
+
path: filePath,
|
|
104
|
+
title
|
|
105
|
+
}, null, opts.minify ? 0 : 2));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
console.log(`Created ${filename}`);
|
|
109
|
+
console.log(` .dkk/adr/${filename}`);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=new-adr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-adr.js","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-adr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dkk new context <name>` command — scaffold a new bounded context.
|
|
3
|
+
*
|
|
4
|
+
* Creates:
|
|
5
|
+
* .dkk/domain/contexts/<name>/context.yml
|
|
6
|
+
* .dkk/domain/contexts/<name>/events/
|
|
7
|
+
* .dkk/domain/contexts/<name>/commands/
|
|
8
|
+
* .dkk/domain/contexts/<name>/aggregates/
|
|
9
|
+
* .dkk/domain/contexts/<name>/policies/
|
|
10
|
+
* .dkk/domain/contexts/<name>/read-models/
|
|
11
|
+
*
|
|
12
|
+
* Registers the context in `.dkk/domain/index.yml`.
|
|
13
|
+
* Errors if the context already exists.
|
|
14
|
+
*/
|
|
15
|
+
import type { Command as Cmd } from "commander";
|
|
16
|
+
export declare function registerNewContext(program: Cmd): void;
|
|
17
|
+
//# sourceMappingURL=new-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-context.d.ts","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AAYhD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CA+ErD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { contextsDir, indexFile } from "../../../shared/paths.js";
|
|
4
|
+
import { parseYaml, stringifyYaml } from "../../../shared/yaml.js";
|
|
5
|
+
/** Validate context name is kebab-case per schema: ^[a-z][a-z0-9-]*$ */
|
|
6
|
+
function isValidContextName(name) {
|
|
7
|
+
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
8
|
+
}
|
|
9
|
+
export function registerNewContext(program) {
|
|
10
|
+
program
|
|
11
|
+
.command("context <name>")
|
|
12
|
+
.description("Scaffold a new bounded context directory and register it in index.yml")
|
|
13
|
+
.option("-r, --root <path>", "Override repository root")
|
|
14
|
+
.option("-d, --description <text>", "Description of the bounded context")
|
|
15
|
+
.option("--json", "Output as JSON")
|
|
16
|
+
.option("--minify", "Minify JSON")
|
|
17
|
+
.action((name, opts) => {
|
|
18
|
+
// Validate name
|
|
19
|
+
if (!isValidContextName(name)) {
|
|
20
|
+
console.error(`Error: Context name "${name}" is invalid. Use kebab-case (e.g. "order-management").`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const ctxDir = join(contextsDir(opts.root), name);
|
|
24
|
+
// Guard: refuse if context directory already exists
|
|
25
|
+
if (existsSync(ctxDir)) {
|
|
26
|
+
console.error(`Error: Context "${name}" already exists at ${ctxDir}.`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const description = opts.description ?? `The ${name} bounded context`;
|
|
30
|
+
// Create directory structure
|
|
31
|
+
const subDirs = ["events", "commands", "aggregates", "policies", "read-models"];
|
|
32
|
+
for (const sub of subDirs) {
|
|
33
|
+
mkdirSync(join(ctxDir, sub), { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
// Write context.yml
|
|
36
|
+
const contextYaml = `# Bounded context metadata and glossary.
|
|
37
|
+
name: ${name}
|
|
38
|
+
description: ${description}
|
|
39
|
+
`;
|
|
40
|
+
writeFileSync(join(ctxDir, "context.yml"), contextYaml, "utf-8");
|
|
41
|
+
// Register in index.yml
|
|
42
|
+
const idxPath = indexFile(opts.root);
|
|
43
|
+
let index;
|
|
44
|
+
if (existsSync(idxPath)) {
|
|
45
|
+
const raw = readFileSync(idxPath, "utf-8");
|
|
46
|
+
index = parseYaml(raw);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Create index.yml if it doesn't exist
|
|
50
|
+
mkdirSync(join(idxPath, ".."), { recursive: true });
|
|
51
|
+
index = { contexts: [], flows: [] };
|
|
52
|
+
}
|
|
53
|
+
// Check if already registered
|
|
54
|
+
const alreadyRegistered = index.contexts.some((c) => c.name === name);
|
|
55
|
+
if (!alreadyRegistered) {
|
|
56
|
+
index.contexts.push({ name, description });
|
|
57
|
+
writeFileSync(idxPath, stringifyYaml(index), "utf-8");
|
|
58
|
+
}
|
|
59
|
+
if (opts.json) {
|
|
60
|
+
console.log(JSON.stringify({
|
|
61
|
+
name,
|
|
62
|
+
path: ctxDir,
|
|
63
|
+
indexUpdated: !alreadyRegistered
|
|
64
|
+
}, null, opts.minify ? 0 : 2));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
console.log(`Created context "${name}":`);
|
|
68
|
+
console.log(` contexts/${name}/context.yml`);
|
|
69
|
+
for (const sub of subDirs) {
|
|
70
|
+
console.log(` contexts/${name}/${sub}/`);
|
|
71
|
+
}
|
|
72
|
+
if (!alreadyRegistered) {
|
|
73
|
+
console.log(`\nRegistered "${name}" in index.yml.`);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=new-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-context.js","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dkk new domain` command — scaffold a complete `.dkk/domain/` structure.
|
|
3
|
+
*
|
|
4
|
+
* Creates:
|
|
5
|
+
* .dkk/domain/index.yml — domain index with one sample context
|
|
6
|
+
* .dkk/domain/actors.yml — actors file with one sample actor
|
|
7
|
+
* .dkk/domain/contexts/sample/ — example bounded context with:
|
|
8
|
+
* context.yml, events/, commands/, aggregates/, policies/, read-models/
|
|
9
|
+
*
|
|
10
|
+
* Errors if `.dkk/domain/` already exists (use `--force` to overwrite).
|
|
11
|
+
*/
|
|
12
|
+
import type { Command as Cmd } from "commander";
|
|
13
|
+
export declare function registerNewDomain(program: Cmd): void;
|
|
14
|
+
//# sourceMappingURL=new-domain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"new-domain.d.ts","sourceRoot":"","sources":["../../../../src/features/scaffold/commands/new-domain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC;AA0DhD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI,CAoDpD"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { domainDir } from "../../../shared/paths.js";
|
|
4
|
+
// ── Template content ──────────────────────────────────────────────────
|
|
5
|
+
const INDEX_YML = `# Domain index — registered bounded contexts and cross-context flows.
|
|
6
|
+
contexts:
|
|
7
|
+
- name: sample
|
|
8
|
+
description: Example bounded context (replace with your own)
|
|
9
|
+
flows: []
|
|
10
|
+
`;
|
|
11
|
+
const ACTORS_YML = `# Actors — people and systems that interact with the domain.
|
|
12
|
+
actors:
|
|
13
|
+
- name: User
|
|
14
|
+
type: human
|
|
15
|
+
description: A person who interacts with the system
|
|
16
|
+
`;
|
|
17
|
+
const CONTEXT_YML = `# Bounded context metadata and glossary.
|
|
18
|
+
name: sample
|
|
19
|
+
description: Example bounded context (replace with your own)
|
|
20
|
+
glossary:
|
|
21
|
+
- term: Example
|
|
22
|
+
definition: A sample glossary term to demonstrate the structure
|
|
23
|
+
`;
|
|
24
|
+
const SAMPLE_EVENT = `# Domain event — something that happened in the domain.
|
|
25
|
+
name: SampleCreated
|
|
26
|
+
description: Raised when a new sample entity is created
|
|
27
|
+
fields:
|
|
28
|
+
- name: sampleId
|
|
29
|
+
type: UUID
|
|
30
|
+
raised_by: Sample
|
|
31
|
+
`;
|
|
32
|
+
const SAMPLE_COMMAND = `# Command — an instruction to change domain state.
|
|
33
|
+
name: CreateSample
|
|
34
|
+
description: Create a new sample entity
|
|
35
|
+
actor: User
|
|
36
|
+
handled_by: Sample
|
|
37
|
+
`;
|
|
38
|
+
const SAMPLE_AGGREGATE = `# Aggregate — a consistency boundary that handles commands and emits events.
|
|
39
|
+
name: Sample
|
|
40
|
+
description: Sample aggregate root
|
|
41
|
+
handles:
|
|
42
|
+
commands:
|
|
43
|
+
- CreateSample
|
|
44
|
+
emits:
|
|
45
|
+
events:
|
|
46
|
+
- SampleCreated
|
|
47
|
+
`;
|
|
48
|
+
// ── Registration ──────────────────────────────────────────────────────
|
|
49
|
+
export function registerNewDomain(program) {
|
|
50
|
+
program
|
|
51
|
+
.command("domain")
|
|
52
|
+
.description("Scaffold a complete .dkk/domain/ structure with sample content")
|
|
53
|
+
.option("-r, --root <path>", "Override repository root")
|
|
54
|
+
.option("--force", "Overwrite existing .dkk/domain/ directory")
|
|
55
|
+
.option("--json", "Output as JSON")
|
|
56
|
+
.option("--minify", "Minify JSON")
|
|
57
|
+
.action((opts) => {
|
|
58
|
+
const dir = domainDir(opts.root);
|
|
59
|
+
// Guard: refuse to overwrite unless --force
|
|
60
|
+
if (existsSync(dir) && !opts.force) {
|
|
61
|
+
console.error(`Error: ${dir} already exists. Use --force to overwrite.`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
// Create directory structure
|
|
65
|
+
const contextsBase = join(dir, "contexts", "sample");
|
|
66
|
+
const subDirs = ["events", "commands", "aggregates", "policies", "read-models"];
|
|
67
|
+
for (const sub of subDirs) {
|
|
68
|
+
mkdirSync(join(contextsBase, sub), { recursive: true });
|
|
69
|
+
}
|
|
70
|
+
// Write files
|
|
71
|
+
writeFileSync(join(dir, "index.yml"), INDEX_YML, "utf-8");
|
|
72
|
+
writeFileSync(join(dir, "actors.yml"), ACTORS_YML, "utf-8");
|
|
73
|
+
writeFileSync(join(contextsBase, "context.yml"), CONTEXT_YML, "utf-8");
|
|
74
|
+
writeFileSync(join(contextsBase, "events", "SampleCreated.yml"), SAMPLE_EVENT, "utf-8");
|
|
75
|
+
writeFileSync(join(contextsBase, "commands", "CreateSample.yml"), SAMPLE_COMMAND, "utf-8");
|
|
76
|
+
writeFileSync(join(contextsBase, "aggregates", "Sample.yml"), SAMPLE_AGGREGATE, "utf-8");
|
|
77
|
+
if (opts.json) {
|
|
78
|
+
console.log(JSON.stringify({
|
|
79
|
+
path: dir,
|
|
80
|
+
success: true
|
|
81
|
+
}, null, opts.minify ? 0 : 2));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log("Created .dkk/domain/ with sample content:");
|
|
85
|
+
console.log(" index.yml");
|
|
86
|
+
console.log(" actors.yml");
|
|
87
|
+
console.log(" contexts/sample/");
|
|
88
|
+
console.log(" context.yml");
|
|
89
|
+
console.log(" events/SampleCreated.yml");
|
|
90
|
+
console.log(" commands/CreateSample.yml");
|
|
91
|
+
console.log(" aggregates/Sample.yml");
|
|
92
|
+
console.log("\nRun `dkk render` to validate and generate documentation.");
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=new-domain.js.map
|