domain-knowledge-kit 0.2.15 → 0.2.19
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 +4 -0
- package/dist/cli.js +24 -1
- package/dist/cli.js.map +1 -1
- package/dist/features/agent/commands/init.d.ts +90 -1
- package/dist/features/agent/commands/init.d.ts.map +1 -1
- package/dist/features/agent/commands/init.js +328 -32
- package/dist/features/agent/commands/init.js.map +1 -1
- package/dist/features/agent/commands/prime.d.ts +11 -0
- package/dist/features/agent/commands/prime.d.ts.map +1 -1
- package/dist/features/agent/commands/prime.js +105 -8
- package/dist/features/agent/commands/prime.js.map +1 -1
- package/dist/features/agent/commands/update.d.ts +27 -0
- package/dist/features/agent/commands/update.d.ts.map +1 -0
- package/dist/features/agent/commands/update.js +316 -0
- package/dist/features/agent/commands/update.js.map +1 -0
- package/dist/features/agent/dkk-artifacts.d.ts +76 -0
- package/dist/features/agent/dkk-artifacts.d.ts.map +1 -0
- package/dist/features/agent/dkk-artifacts.js +328 -0
- package/dist/features/agent/dkk-artifacts.js.map +1 -0
- package/dist/features/agent/install-mode.d.ts +34 -0
- package/dist/features/agent/install-mode.d.ts.map +1 -0
- package/dist/features/agent/install-mode.js +78 -0
- package/dist/features/agent/install-mode.js.map +1 -0
- package/dist/features/agent/mcp-register.d.ts +20 -0
- package/dist/features/agent/mcp-register.d.ts.map +1 -0
- package/dist/features/agent/mcp-register.js +116 -0
- package/dist/features/agent/mcp-register.js.map +1 -0
- package/dist/features/agent/settings-prune.d.ts +29 -0
- package/dist/features/agent/settings-prune.d.ts.map +1 -0
- package/dist/features/agent/settings-prune.js +70 -0
- package/dist/features/agent/settings-prune.js.map +1 -0
- package/dist/features/agent/tests/settings-prune.test.d.ts +2 -0
- package/dist/features/agent/tests/settings-prune.test.d.ts.map +1 -0
- package/dist/features/agent/tests/settings-prune.test.js +118 -0
- package/dist/features/agent/tests/settings-prune.test.js.map +1 -0
- package/dist/features/federation/commands/consumers.d.ts +40 -0
- package/dist/features/federation/commands/consumers.d.ts.map +1 -0
- package/dist/features/federation/commands/consumers.js +126 -0
- package/dist/features/federation/commands/consumers.js.map +1 -0
- package/dist/features/federation/commands/peers-add.d.ts +14 -0
- package/dist/features/federation/commands/peers-add.d.ts.map +1 -0
- package/dist/features/federation/commands/peers-add.js +79 -0
- package/dist/features/federation/commands/peers-add.js.map +1 -0
- package/dist/features/federation/commands/peers-list.d.ts +8 -0
- package/dist/features/federation/commands/peers-list.d.ts.map +1 -0
- package/dist/features/federation/commands/peers-list.js +51 -0
- package/dist/features/federation/commands/peers-list.js.map +1 -0
- package/dist/features/federation/commands/peers-status.d.ts +8 -0
- package/dist/features/federation/commands/peers-status.d.ts.map +1 -0
- package/dist/features/federation/commands/peers-status.js +78 -0
- package/dist/features/federation/commands/peers-status.js.map +1 -0
- package/dist/features/federation/commands/pull.d.ts +18 -0
- package/dist/features/federation/commands/pull.d.ts.map +1 -0
- package/dist/features/federation/commands/pull.js +153 -0
- package/dist/features/federation/commands/pull.js.map +1 -0
- package/dist/features/federation/git-fetcher.d.ts +45 -0
- package/dist/features/federation/git-fetcher.d.ts.map +1 -0
- package/dist/features/federation/git-fetcher.js +70 -0
- package/dist/features/federation/git-fetcher.js.map +1 -0
- package/dist/features/federation/loader.d.ts +60 -0
- package/dist/features/federation/loader.d.ts.map +1 -0
- package/dist/features/federation/loader.js +193 -0
- package/dist/features/federation/loader.js.map +1 -0
- package/dist/features/federation/lock.d.ts +12 -0
- package/dist/features/federation/lock.d.ts.map +1 -0
- package/dist/features/federation/lock.js +48 -0
- package/dist/features/federation/lock.js.map +1 -0
- package/dist/features/federation/tests/git-fetcher.test.d.ts +2 -0
- package/dist/features/federation/tests/git-fetcher.test.d.ts.map +1 -0
- package/dist/features/federation/tests/git-fetcher.test.js +167 -0
- package/dist/features/federation/tests/git-fetcher.test.js.map +1 -0
- package/dist/features/federation/tests/loader.test.d.ts +2 -0
- package/dist/features/federation/tests/loader.test.d.ts.map +1 -0
- package/dist/features/federation/tests/loader.test.js +144 -0
- package/dist/features/federation/tests/loader.test.js.map +1 -0
- package/dist/features/federation/tests/phase5.test.d.ts +2 -0
- package/dist/features/federation/tests/phase5.test.d.ts.map +1 -0
- package/dist/features/federation/tests/phase5.test.js +137 -0
- package/dist/features/federation/tests/phase5.test.js.map +1 -0
- package/dist/features/federation/tests/schema-load.test.d.ts +2 -0
- package/dist/features/federation/tests/schema-load.test.d.ts.map +1 -0
- package/dist/features/federation/tests/schema-load.test.js +97 -0
- package/dist/features/federation/tests/schema-load.test.js.map +1 -0
- package/dist/features/federation/tests/validator.test.d.ts +2 -0
- package/dist/features/federation/tests/validator.test.d.ts.map +1 -0
- package/dist/features/federation/tests/validator.test.js +319 -0
- package/dist/features/federation/tests/validator.test.js.map +1 -0
- package/dist/features/mcp/commands/serve.d.ts +10 -0
- package/dist/features/mcp/commands/serve.d.ts.map +1 -0
- package/dist/features/mcp/commands/serve.js +12 -0
- package/dist/features/mcp/commands/serve.js.map +1 -0
- package/dist/features/mcp/server.d.ts +15 -0
- package/dist/features/mcp/server.d.ts.map +1 -0
- package/dist/features/mcp/server.js +438 -0
- package/dist/features/mcp/server.js.map +1 -0
- package/dist/features/pipeline/commands/validate.d.ts.map +1 -1
- package/dist/features/pipeline/commands/validate.js +7 -0
- package/dist/features/pipeline/commands/validate.js.map +1 -1
- package/dist/features/pipeline/indexer.d.ts +28 -2
- package/dist/features/pipeline/indexer.d.ts.map +1 -1
- package/dist/features/pipeline/indexer.js +82 -27
- package/dist/features/pipeline/indexer.js.map +1 -1
- package/dist/features/pipeline/validator.d.ts +10 -0
- package/dist/features/pipeline/validator.d.ts.map +1 -1
- package/dist/features/pipeline/validator.js +274 -27
- package/dist/features/pipeline/validator.js.map +1 -1
- package/dist/features/query/commands/list.d.ts +10 -0
- package/dist/features/query/commands/list.d.ts.map +1 -1
- package/dist/features/query/commands/list.js +1 -1
- package/dist/features/query/commands/list.js.map +1 -1
- package/dist/features/query/commands/locate.d.ts +1 -0
- package/dist/features/query/commands/locate.d.ts.map +1 -1
- package/dist/features/query/commands/locate.js +1 -1
- package/dist/features/query/commands/locate.js.map +1 -1
- package/dist/features/query/commands/search.d.ts.map +1 -1
- package/dist/features/query/commands/search.js +2 -0
- package/dist/features/query/commands/search.js.map +1 -1
- package/dist/features/query/commands/show.d.ts +15 -0
- package/dist/features/query/commands/show.d.ts.map +1 -1
- package/dist/features/query/commands/show.js +116 -58
- package/dist/features/query/commands/show.js.map +1 -1
- package/dist/features/query/commands/story.d.ts +70 -0
- package/dist/features/query/commands/story.d.ts.map +1 -1
- package/dist/features/query/commands/story.js +2 -2
- package/dist/features/query/commands/story.js.map +1 -1
- package/dist/features/query/commands/summary.d.ts +3 -0
- package/dist/features/query/commands/summary.d.ts.map +1 -1
- package/dist/features/query/commands/summary.js +1 -1
- package/dist/features/query/commands/summary.js.map +1 -1
- package/dist/features/query/searcher.d.ts +18 -1
- package/dist/features/query/searcher.d.ts.map +1 -1
- package/dist/features/query/searcher.js +11 -2
- package/dist/features/query/searcher.js.map +1 -1
- package/dist/features/scaffold/commands/new-domain.d.ts +22 -0
- package/dist/features/scaffold/commands/new-domain.d.ts.map +1 -1
- package/dist/features/scaffold/commands/new-domain.js +44 -28
- package/dist/features/scaffold/commands/new-domain.js.map +1 -1
- package/dist/features/scaffold/commands/service-init.d.ts +12 -0
- package/dist/features/scaffold/commands/service-init.d.ts.map +1 -0
- package/dist/features/scaffold/commands/service-init.js +69 -0
- package/dist/features/scaffold/commands/service-init.js.map +1 -0
- package/dist/shared/graph.d.ts +8 -0
- package/dist/shared/graph.d.ts.map +1 -1
- package/dist/shared/graph.js +180 -112
- package/dist/shared/graph.js.map +1 -1
- package/dist/shared/index.d.ts +4 -1
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +6 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/loader.d.ts +22 -0
- package/dist/shared/loader.d.ts.map +1 -1
- package/dist/shared/loader.js +31 -1
- package/dist/shared/loader.js.map +1 -1
- package/dist/shared/paths.d.ts +59 -7
- package/dist/shared/paths.d.ts.map +1 -1
- package/dist/shared/paths.js +93 -11
- package/dist/shared/paths.js.map +1 -1
- package/dist/shared/refs.d.ts +96 -0
- package/dist/shared/refs.d.ts.map +1 -0
- package/dist/shared/refs.js +182 -0
- package/dist/shared/refs.js.map +1 -0
- package/dist/shared/service-id.d.ts +11 -0
- package/dist/shared/service-id.d.ts.map +1 -0
- package/dist/shared/service-id.js +64 -0
- package/dist/shared/service-id.js.map +1 -0
- package/dist/shared/tests/paths.test.d.ts +2 -0
- package/dist/shared/tests/paths.test.d.ts.map +1 -0
- package/dist/shared/tests/paths.test.js +111 -0
- package/dist/shared/tests/paths.test.js.map +1 -0
- package/dist/shared/tests/refs.test.d.ts +2 -0
- package/dist/shared/tests/refs.test.d.ts.map +1 -0
- package/dist/shared/tests/refs.test.js +104 -0
- package/dist/shared/tests/refs.test.js.map +1 -0
- package/dist/shared/types/domain.d.ts +14 -0
- package/dist/shared/types/domain.d.ts.map +1 -1
- package/dist/shared/types/federation.d.ts +60 -0
- package/dist/shared/types/federation.d.ts.map +1 -0
- package/dist/shared/types/federation.js +12 -0
- package/dist/shared/types/federation.js.map +1 -0
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +15 -0
- package/dist/version.js.map +1 -0
- package/package.json +8 -5
- package/tools/dkk/claude/agents/dkk-domain-reviewer.md +69 -0
- package/tools/dkk/claude/commands/dkk-adr.md +11 -0
- package/tools/dkk/claude/commands/dkk-impact.md +34 -0
- package/tools/dkk/claude/commands/dkk-implement.md +12 -0
- package/tools/dkk/claude/commands/dkk-prime.md +6 -0
- package/tools/dkk/claude/commands/dkk-review.md +12 -0
- package/tools/dkk/claude/commands/dkk-story.md +12 -0
- package/tools/dkk/claude/hooks/post-edit-validate.mjs +68 -0
- package/tools/dkk/claude/hooks/pre-edit-block-generated.mjs +39 -0
- package/tools/dkk/claude/hooks/session-start-prime.mjs +20 -0
- package/tools/dkk/claude/hooks/stop-validate.mjs +67 -0
- package/tools/dkk/claude/settings.json +62 -0
- package/tools/dkk/claude/skills/dkk-adr-author/SKILL.md +54 -0
- package/tools/dkk/claude/skills/dkk-flow-implementer/SKILL.md +51 -0
- package/tools/dkk/claude/skills/dkk-story-analyst/SKILL.md +108 -0
- package/tools/dkk/schema/actors.schema.json +1 -1
- package/tools/dkk/schema/adr-frontmatter.schema.json +4 -4
- package/tools/dkk/schema/aggregate.schema.json +1 -1
- package/tools/dkk/schema/command.schema.json +1 -1
- package/tools/dkk/schema/event.schema.json +1 -1
- package/tools/dkk/schema/federation.schema.json +71 -0
- package/tools/dkk/schema/glossary.schema.json +1 -1
- package/tools/dkk/schema/index.schema.json +2 -2
- package/tools/dkk/schema/policy.schema.json +1 -1
- package/tools/dkk/schema/read-model.schema.json +1 -1
- package/tools/dkk/schema/service.schema.json +30 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Federation loader — resolves peer services declared in
|
|
3
|
+
* `.dkk/federation.yml` and loads each peer's `.dkk/` as a read-only
|
|
4
|
+
* sub-model attached at `model.peers.get(serviceName)`.
|
|
5
|
+
*
|
|
6
|
+
* Peer loading is exactly one level deep: a peer's own `federation.yml`
|
|
7
|
+
* is intentionally NOT followed. Peers are loaded in lenient mode so
|
|
8
|
+
* that DKK schema drift across services (peer YAML using fields the
|
|
9
|
+
* local DKK version doesn't understand) degrades to a warning rather
|
|
10
|
+
* than failing the consumer's load.
|
|
11
|
+
*
|
|
12
|
+
* Two source types are supported:
|
|
13
|
+
* - `local`: a filesystem path (absolute or relative to repo root).
|
|
14
|
+
* - `git`: resolved against the cache at `.dkk/imports/<service>/`
|
|
15
|
+
* populated by `dkk pull` (Phase 3).
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
18
|
+
import { isAbsolute, resolve, join } from "node:path";
|
|
19
|
+
import { createRequire } from "node:module";
|
|
20
|
+
import { parseYaml } from "../../shared/yaml.js";
|
|
21
|
+
import { federationFile, importedServiceDir, schemaDir, repoRoot } from "../../shared/paths.js";
|
|
22
|
+
import { loadDomainModel, setFederationHook } from "../../shared/loader.js";
|
|
23
|
+
// ajv is a CJS package — use createRequire for ESM interop.
|
|
24
|
+
const require = createRequire(import.meta.url);
|
|
25
|
+
const Ajv = require("ajv").default;
|
|
26
|
+
const addFormats = require("ajv-formats").default;
|
|
27
|
+
/** Cached Ajv instance for federation.yml validation. */
|
|
28
|
+
let cachedAjv = null;
|
|
29
|
+
function getAjv() {
|
|
30
|
+
if (cachedAjv)
|
|
31
|
+
return cachedAjv;
|
|
32
|
+
const ajv = new Ajv({ allErrors: true, strict: true });
|
|
33
|
+
addFormats(ajv);
|
|
34
|
+
const dir = schemaDir();
|
|
35
|
+
for (const f of readdirSync(dir).filter((n) => n.endsWith(".schema.json"))) {
|
|
36
|
+
const schema = JSON.parse(readFileSync(join(dir, f), "utf-8"));
|
|
37
|
+
ajv.addSchema(schema, schema.$id);
|
|
38
|
+
}
|
|
39
|
+
cachedAjv = ajv;
|
|
40
|
+
return ajv;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read `.dkk/federation.yml` (if present), validate it against
|
|
44
|
+
* `federation.schema.json`, and return the parsed manifest. Returns
|
|
45
|
+
* `null` for unfederated repos.
|
|
46
|
+
*
|
|
47
|
+
* Throws when the file exists but does not conform to the schema —
|
|
48
|
+
* the message includes Ajv's error list so the user can fix the
|
|
49
|
+
* manifest directly.
|
|
50
|
+
*/
|
|
51
|
+
export function loadFederation(root) {
|
|
52
|
+
const path = federationFile(root);
|
|
53
|
+
if (!existsSync(path))
|
|
54
|
+
return null;
|
|
55
|
+
const text = readFileSync(path, "utf-8");
|
|
56
|
+
const parsed = parseYaml(text);
|
|
57
|
+
const ajv = getAjv();
|
|
58
|
+
const valid = ajv.validate("federation.schema.json", parsed);
|
|
59
|
+
if (!valid) {
|
|
60
|
+
const details = (ajv.errors ?? [])
|
|
61
|
+
.map((e) => ` - ${e.instancePath || "/"}: ${e.message ?? "invalid"}`)
|
|
62
|
+
.join("\n");
|
|
63
|
+
throw new Error(`Invalid ${path}:\n${details}\n\nExpected shape: { peers: [{ name, source: { type: "local" | "git", ... } }] }`);
|
|
64
|
+
}
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resolve a single peer spec into an absolute repo-root path on disk.
|
|
69
|
+
*
|
|
70
|
+
* - `local` sources resolve relative to the local repo root (so
|
|
71
|
+
* `../order-svc` in `billing-svc/.dkk/federation.yml` points at the
|
|
72
|
+
* sibling directory regardless of `cwd`). Env-var override
|
|
73
|
+
* `DKK_PEER_<SERVICE_NAME_UPPER>` (uppercase, hyphens → underscores)
|
|
74
|
+
* takes precedence over the manifest's `source.path`.
|
|
75
|
+
* - `git` sources resolve to the cache directory
|
|
76
|
+
* `.dkk/imports/<service>/` populated by `dkk pull`.
|
|
77
|
+
*
|
|
78
|
+
* The returned `peerRoot` points at the peer's repository root (so
|
|
79
|
+
* `<peerRoot>/.dkk/` is where the peer's domain lives).
|
|
80
|
+
*/
|
|
81
|
+
export function resolvePeerRoot(spec, localRepoRoot) {
|
|
82
|
+
const source = spec.source;
|
|
83
|
+
// Env-var override: applies to any source type for the convenience of
|
|
84
|
+
// developers who want to point at a local checkout regardless of
|
|
85
|
+
// what the committed manifest says.
|
|
86
|
+
const envKey = `DKK_PEER_${spec.name.toUpperCase().replace(/-/g, "_")}`;
|
|
87
|
+
const envOverride = process.env[envKey];
|
|
88
|
+
if (envOverride && envOverride.length > 0) {
|
|
89
|
+
const peerRoot = isAbsolute(envOverride)
|
|
90
|
+
? envOverride
|
|
91
|
+
: resolve(localRepoRoot, envOverride);
|
|
92
|
+
const reachable = existsSync(peerRoot + "/.dkk");
|
|
93
|
+
return {
|
|
94
|
+
peerRoot,
|
|
95
|
+
reachable,
|
|
96
|
+
reason: reachable ? undefined : `env override ${envKey} points at ${peerRoot} but it has no .dkk/`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (source.type === "local") {
|
|
100
|
+
const peerRoot = isAbsolute(source.path)
|
|
101
|
+
? source.path
|
|
102
|
+
: resolve(localRepoRoot, source.path);
|
|
103
|
+
const reachable = existsSync(peerRoot + "/.dkk");
|
|
104
|
+
return {
|
|
105
|
+
peerRoot,
|
|
106
|
+
reachable,
|
|
107
|
+
reason: reachable ? undefined : `local path ${peerRoot} has no .dkk/`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (source.type === "git") {
|
|
111
|
+
const cacheRoot = importedServiceDir(spec.name, localRepoRoot);
|
|
112
|
+
// When the peer's `.dkk/` lives in a sub-directory of its repo
|
|
113
|
+
// (monorepo case), the manifest's `source.path` names that
|
|
114
|
+
// sub-directory; the sparse-checkout pulls it into the cache at
|
|
115
|
+
// the same relative location.
|
|
116
|
+
const peerRoot = source.path
|
|
117
|
+
? `${cacheRoot}/${source.path.replace(/\/$/, "")}`
|
|
118
|
+
: cacheRoot;
|
|
119
|
+
const reachable = existsSync(peerRoot + "/.dkk");
|
|
120
|
+
return {
|
|
121
|
+
peerRoot,
|
|
122
|
+
reachable,
|
|
123
|
+
reason: reachable ? undefined : `git cache empty for "${spec.name}" — run \`dkk pull ${spec.name}\``,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// Exhaustiveness check — future source types should be added here.
|
|
127
|
+
const exhaustive = source;
|
|
128
|
+
return { peerRoot: null, reachable: false, reason: `unknown source type: ${JSON.stringify(exhaustive)}` };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Load a peer's domain model in "peer mode": one level deep (peer's
|
|
132
|
+
* own `federation.yml` is skipped) and resilient to minor schema
|
|
133
|
+
* drift. The peer's model is structurally identical to a local model
|
|
134
|
+
* so the same `loadDomainModel` is reused; the federation pass is
|
|
135
|
+
* suppressed via the `followPeers: false` option.
|
|
136
|
+
*/
|
|
137
|
+
export function loadPeerModel(peerRoot) {
|
|
138
|
+
return loadDomainModel({ root: peerRoot, followPeers: false });
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Resolve and load every peer declared in the manifest. Unreachable
|
|
142
|
+
* peers are reported via `warnings` (each line is one peer) but never
|
|
143
|
+
* abort the load — the caller (typically the main loader) attaches
|
|
144
|
+
* the resulting map to `model.peers`.
|
|
145
|
+
*/
|
|
146
|
+
export function loadAllPeers(localRepoRoot, manifest) {
|
|
147
|
+
const peers = new Map();
|
|
148
|
+
const warnings = [];
|
|
149
|
+
for (const spec of manifest.peers ?? []) {
|
|
150
|
+
const resolution = resolvePeerRoot(spec, localRepoRoot);
|
|
151
|
+
if (!resolution.reachable || !resolution.peerRoot) {
|
|
152
|
+
warnings.push(`peer "${spec.name}" unreachable: ${resolution.reason ?? "unknown"}`);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
const model = loadPeerModel(resolution.peerRoot);
|
|
157
|
+
peers.set(spec.name, model);
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
161
|
+
warnings.push(`peer "${spec.name}" failed to load: ${msg}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return { peers, warnings };
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Build the env-var key used to override a peer's source path.
|
|
168
|
+
* Exposed for tests and for the `peers status` command.
|
|
169
|
+
*/
|
|
170
|
+
export function peerEnvKey(serviceName) {
|
|
171
|
+
return `DKK_PEER_${serviceName.toUpperCase().replace(/-/g, "_")}`;
|
|
172
|
+
}
|
|
173
|
+
// ── Hook registration ────────────────────────────────────────────────
|
|
174
|
+
//
|
|
175
|
+
// Register the peer-hydration hook with the shared loader at module
|
|
176
|
+
// initialisation. Any CLI command that imports this slice (directly or
|
|
177
|
+
// transitively via the federation commands wired in cli.ts) will cause
|
|
178
|
+
// `loadDomainModel` to start populating `model.peers`. Scripts that
|
|
179
|
+
// import the shared loader without the federation slice get plain
|
|
180
|
+
// unfederated behaviour — no surprises, no cycles.
|
|
181
|
+
setFederationHook((root, model) => {
|
|
182
|
+
const manifest = loadFederation(root);
|
|
183
|
+
if (!manifest)
|
|
184
|
+
return;
|
|
185
|
+
const resolvedRoot = repoRoot(root);
|
|
186
|
+
const { peers, warnings } = loadAllPeers(resolvedRoot, manifest);
|
|
187
|
+
if (peers.size > 0)
|
|
188
|
+
model.peers = peers;
|
|
189
|
+
for (const w of warnings) {
|
|
190
|
+
console.warn(`dkk: ${w}`);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/features/federation/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FederationLock, LockEntry } from "../../shared/types/federation.js";
|
|
2
|
+
/**
|
|
3
|
+
* Read the lockfile from disk. Returns an empty record when the file
|
|
4
|
+
* is absent. Malformed JSON throws (the file is committed, so a parse
|
|
5
|
+
* failure should be loud).
|
|
6
|
+
*/
|
|
7
|
+
export declare function readLock(root?: string): FederationLock;
|
|
8
|
+
/** Write the lockfile to disk with stable formatting. */
|
|
9
|
+
export declare function writeLock(lock: FederationLock, root?: string): void;
|
|
10
|
+
/** Build a fresh lock entry from a fetch result. */
|
|
11
|
+
export declare function makeEntry(source: LockEntry["source"], sha: string | undefined): LockEntry;
|
|
12
|
+
//# sourceMappingURL=lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../src/features/federation/lock.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAElF;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAMtD;AAED,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CASnE;AAED,oDAAoD;AACpD,wBAAgB,SAAS,CACvB,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,EAC3B,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,SAAS,CAKX"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Federation lockfile (.dkk/federation.lock.json).
|
|
3
|
+
*
|
|
4
|
+
* Records the resolved commit SHA each git-source peer was fetched at,
|
|
5
|
+
* along with a snapshot of the source spec used. Committing the
|
|
6
|
+
* lockfile means two developers running `dkk pull` see the same peer
|
|
7
|
+
* state until someone explicitly re-pulls with `--refresh`.
|
|
8
|
+
*
|
|
9
|
+
* Local-source peers have no lockfile entry — they're always live from
|
|
10
|
+
* disk.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
13
|
+
import { dirname } from "node:path";
|
|
14
|
+
import { federationLockFile } from "../../shared/paths.js";
|
|
15
|
+
/**
|
|
16
|
+
* Read the lockfile from disk. Returns an empty record when the file
|
|
17
|
+
* is absent. Malformed JSON throws (the file is committed, so a parse
|
|
18
|
+
* failure should be loud).
|
|
19
|
+
*/
|
|
20
|
+
export function readLock(root) {
|
|
21
|
+
const path = federationLockFile(root);
|
|
22
|
+
if (!existsSync(path))
|
|
23
|
+
return {};
|
|
24
|
+
const text = readFileSync(path, "utf-8");
|
|
25
|
+
if (text.trim().length === 0)
|
|
26
|
+
return {};
|
|
27
|
+
return JSON.parse(text);
|
|
28
|
+
}
|
|
29
|
+
/** Write the lockfile to disk with stable formatting. */
|
|
30
|
+
export function writeLock(lock, root) {
|
|
31
|
+
const path = federationLockFile(root);
|
|
32
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
33
|
+
// Stable key ordering (sorted by service name) keeps diffs minimal.
|
|
34
|
+
const sorted = {};
|
|
35
|
+
for (const key of Object.keys(lock).sort()) {
|
|
36
|
+
sorted[key] = lock[key];
|
|
37
|
+
}
|
|
38
|
+
writeFileSync(path, JSON.stringify(sorted, null, 2) + "\n", "utf-8");
|
|
39
|
+
}
|
|
40
|
+
/** Build a fresh lock entry from a fetch result. */
|
|
41
|
+
export function makeEntry(source, sha) {
|
|
42
|
+
const entry = { source };
|
|
43
|
+
if (sha)
|
|
44
|
+
entry.sha = sha;
|
|
45
|
+
entry.fetchedAt = new Date().toISOString();
|
|
46
|
+
return entry;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/features/federation/lock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAG3D;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAa;IACpC,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC;AAC5C,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,SAAS,CAAC,IAAoB,EAAE,IAAa;IAC3D,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,oEAAoE;IACpE,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACvE,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,SAAS,CACvB,MAA2B,EAC3B,GAAuB;IAEvB,MAAM,KAAK,GAAc,EAAE,MAAM,EAAE,CAAC;IACpC,IAAI,GAAG;QAAE,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;IACzB,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-fetcher.test.d.ts","sourceRoot":"","sources":["../../../../src/features/federation/tests/git-fetcher.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the sparse-checkout git fetcher.
|
|
3
|
+
*
|
|
4
|
+
* Uses a local bare repository as the "remote" so the test runs
|
|
5
|
+
* fully offline. Verifies that:
|
|
6
|
+
* - sparseFetch clones with a `.dkk/` sparse pattern.
|
|
7
|
+
* - Only `.dkk/` content is materialised; other top-level files are
|
|
8
|
+
* excluded by the sparse rule.
|
|
9
|
+
* - The returned SHA matches `HEAD` of the configured branch.
|
|
10
|
+
* - `dkk pull` populates the cache and writes a lockfile entry.
|
|
11
|
+
* - A subsequent `dkk pull` is a no-op (the SHA in the lock matches).
|
|
12
|
+
* - `dkk pull --refresh` re-fetches.
|
|
13
|
+
*
|
|
14
|
+
* If `git` is not available on PATH, the test is skipped (we don't
|
|
15
|
+
* fail CI on environments without git).
|
|
16
|
+
*/
|
|
17
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
18
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, realpathSync } from "node:fs";
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
import { tmpdir } from "node:os";
|
|
21
|
+
import { sparseFetch } from "../git-fetcher.js";
|
|
22
|
+
let passed = 0;
|
|
23
|
+
let failed = 0;
|
|
24
|
+
let skipped = false;
|
|
25
|
+
function assert(label, condition, detail) {
|
|
26
|
+
if (condition) {
|
|
27
|
+
console.log(` OK: ${label}`);
|
|
28
|
+
passed++;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
console.error(`FAIL: ${label}${detail ? ` — ${detail}` : ""}`);
|
|
32
|
+
failed++;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function gitAvailable() {
|
|
36
|
+
try {
|
|
37
|
+
execFileSync("git", ["--version"], { stdio: "ignore" });
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!gitAvailable()) {
|
|
45
|
+
console.log("git not available on PATH — skipping git-fetcher tests");
|
|
46
|
+
skipped = true;
|
|
47
|
+
}
|
|
48
|
+
if (!skipped) {
|
|
49
|
+
const RAW_TMP = join(tmpdir(), `dkk-git-${Date.now()}`);
|
|
50
|
+
mkdirSync(RAW_TMP, { recursive: true });
|
|
51
|
+
const TMP = realpathSync(RAW_TMP);
|
|
52
|
+
// Layout:
|
|
53
|
+
// <TMP>/remote/ — a bare git repo (the "remote")
|
|
54
|
+
// <TMP>/source/ — a regular repo we'll push from
|
|
55
|
+
// .dkk/ — the only content sparseFetch should pull
|
|
56
|
+
// service.yml
|
|
57
|
+
// domain/.../OrderPlaced.yml
|
|
58
|
+
// README.md — should NOT appear in the cache
|
|
59
|
+
// <TMP>/local/.dkk/imports/ordering/ — destination cache
|
|
60
|
+
const REMOTE = join(TMP, "remote");
|
|
61
|
+
const SOURCE = join(TMP, "source");
|
|
62
|
+
const LOCAL = join(TMP, "local");
|
|
63
|
+
const CACHE_DIR = join(LOCAL, ".dkk", "imports", "ordering");
|
|
64
|
+
function run(args, cwd) {
|
|
65
|
+
const result = spawnSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
|
|
66
|
+
if (result.status !== 0) {
|
|
67
|
+
throw new Error(`git ${args.join(" ")} failed in ${cwd}\nstderr: ${result.stderr}`);
|
|
68
|
+
}
|
|
69
|
+
return result.stdout.trim();
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
// Create the bare remote.
|
|
73
|
+
mkdirSync(REMOTE, { recursive: true });
|
|
74
|
+
run(["init", "--bare", "--initial-branch=main"], REMOTE);
|
|
75
|
+
// Create the source repo with .dkk/ content + a noise file.
|
|
76
|
+
mkdirSync(join(SOURCE, ".dkk", "domain", "contexts", "ordering", "events"), {
|
|
77
|
+
recursive: true,
|
|
78
|
+
});
|
|
79
|
+
writeFileSync(join(SOURCE, ".dkk", "service.yml"), "name: ordering\nexports:\n - ordering\n");
|
|
80
|
+
writeFileSync(join(SOURCE, ".dkk", "domain", "index.yml"), "contexts:\n - name: ordering\n description: Ordering context\nflows: []\n");
|
|
81
|
+
writeFileSync(join(SOURCE, ".dkk", "domain", "actors.yml"), "actors: []\n");
|
|
82
|
+
writeFileSync(join(SOURCE, ".dkk", "domain", "contexts", "ordering", "context.yml"), "name: ordering\ndescription: Ordering bounded context\n");
|
|
83
|
+
writeFileSync(join(SOURCE, ".dkk", "domain", "contexts", "ordering", "events", "OrderPlaced.yml"), "name: OrderPlaced\ndescription: Raised when an order is placed.\n");
|
|
84
|
+
writeFileSync(join(SOURCE, "README.md"), "# Should NOT be in the sparse checkout\n");
|
|
85
|
+
run(["init", "--initial-branch=main"], SOURCE);
|
|
86
|
+
run(["config", "user.email", "test@example.com"], SOURCE);
|
|
87
|
+
run(["config", "user.name", "Test"], SOURCE);
|
|
88
|
+
run(["config", "commit.gpgsign", "false"], SOURCE);
|
|
89
|
+
run(["add", "."], SOURCE);
|
|
90
|
+
run(["commit", "-m", "initial"], SOURCE);
|
|
91
|
+
run(["remote", "add", "origin", REMOTE], SOURCE);
|
|
92
|
+
run(["push", "-u", "origin", "main"], SOURCE);
|
|
93
|
+
const sourceHead = run(["rev-parse", "HEAD"], SOURCE);
|
|
94
|
+
// ── sparseFetch pulls only .dkk/ ──────────────────────────────────
|
|
95
|
+
console.log("\n=== sparseFetch ===");
|
|
96
|
+
const result = sparseFetch({
|
|
97
|
+
url: REMOTE,
|
|
98
|
+
branch: "main",
|
|
99
|
+
subpath: "",
|
|
100
|
+
dest: CACHE_DIR,
|
|
101
|
+
});
|
|
102
|
+
assert("returned SHA matches source HEAD", result.sha === sourceHead);
|
|
103
|
+
assert(".dkk/ exists in cache", existsSync(join(CACHE_DIR, ".dkk")));
|
|
104
|
+
assert("service.yml present", existsSync(join(CACHE_DIR, ".dkk", "service.yml")));
|
|
105
|
+
assert("OrderPlaced.yml present", existsSync(join(CACHE_DIR, ".dkk", "domain", "contexts", "ordering", "events", "OrderPlaced.yml")));
|
|
106
|
+
assert("README.md NOT in cache (sparse rule excluded it)", !existsSync(join(CACHE_DIR, "README.md")));
|
|
107
|
+
// ── dkk pull integrates the fetcher + lockfile ────────────────────
|
|
108
|
+
console.log("\n=== dkk pull (CLI integration) ===");
|
|
109
|
+
// Set up a `local` repo with a federation manifest pointing at the
|
|
110
|
+
// bare remote. Wipe the cache from the previous step so `pull` has
|
|
111
|
+
// to re-fetch.
|
|
112
|
+
rmSync(join(LOCAL, ".dkk"), { recursive: true, force: true });
|
|
113
|
+
mkdirSync(join(LOCAL, ".dkk", "domain"), { recursive: true });
|
|
114
|
+
writeFileSync(join(LOCAL, ".dkk", "service.yml"), "name: billing\nexports:\n - billing\n");
|
|
115
|
+
writeFileSync(join(LOCAL, ".dkk", "federation.yml"), [
|
|
116
|
+
"peers:",
|
|
117
|
+
" - name: ordering",
|
|
118
|
+
" source:",
|
|
119
|
+
" type: git",
|
|
120
|
+
` url: ${REMOTE}`,
|
|
121
|
+
" branch: main",
|
|
122
|
+
].join("\n") + "\n");
|
|
123
|
+
const cliEntry = join(process.cwd(), "src", "cli.ts");
|
|
124
|
+
const pullResult = spawnSync("npx", ["tsx", cliEntry, "pull", "--root", LOCAL, "--json"], { encoding: "utf-8" });
|
|
125
|
+
if (pullResult.status !== 0) {
|
|
126
|
+
throw new Error(`dkk pull failed: ${pullResult.stderr}\n${pullResult.stdout}`);
|
|
127
|
+
}
|
|
128
|
+
const pullReport = JSON.parse(pullResult.stdout);
|
|
129
|
+
assert("pull report has one peer", pullReport.peers.length === 1);
|
|
130
|
+
assert("ordering peer fetched", pullReport.peers[0].name === "ordering" && pullReport.peers[0].outcome === "fetched");
|
|
131
|
+
assert("lockfile sha matches source HEAD", pullReport.peers[0].sha === sourceHead);
|
|
132
|
+
assert("lockfile written to disk", existsSync(join(LOCAL, ".dkk", "federation.lock.json")));
|
|
133
|
+
// Subsequent pull is a no-op.
|
|
134
|
+
const pullAgain = spawnSync("npx", ["tsx", cliEntry, "pull", "--root", LOCAL, "--json"], { encoding: "utf-8" });
|
|
135
|
+
const pullAgainReport = JSON.parse(pullAgain.stdout);
|
|
136
|
+
assert("second pull is cached (no-op)", pullAgainReport.peers[0].outcome === "cached");
|
|
137
|
+
// --refresh forces re-fetch even when cached.
|
|
138
|
+
const pullRefresh = spawnSync("npx", ["tsx", cliEntry, "pull", "--root", LOCAL, "--refresh", "--json"], { encoding: "utf-8" });
|
|
139
|
+
const pullRefreshReport = JSON.parse(pullRefresh.stdout);
|
|
140
|
+
assert("--refresh re-fetches even when cached", pullRefreshReport.peers[0].outcome === "fetched");
|
|
141
|
+
// --offline with cache present is a no-op.
|
|
142
|
+
const pullOffline = spawnSync("npx", ["tsx", cliEntry, "pull", "--root", LOCAL, "--offline", "--json"], { encoding: "utf-8" });
|
|
143
|
+
const pullOfflineReport = JSON.parse(pullOffline.stdout);
|
|
144
|
+
assert("--offline with cache returns skipped-offline-cached", pullOfflineReport.peers[0].outcome === "skipped-offline-cached");
|
|
145
|
+
// Verify lockfile contents.
|
|
146
|
+
const lock = JSON.parse(readFileSync(join(LOCAL, ".dkk", "federation.lock.json"), "utf-8"));
|
|
147
|
+
assert("lockfile has ordering entry", lock.ordering !== undefined);
|
|
148
|
+
assert("lockfile entry has git source", lock.ordering.source.type === "git");
|
|
149
|
+
assert("lockfile entry has sha", typeof lock.ordering.sha === "string" && lock.ordering.sha.length > 0);
|
|
150
|
+
// ── Federation loader sees the cached peer ────────────────────────
|
|
151
|
+
console.log("\n=== loader sees cached peer ===");
|
|
152
|
+
const showResult = spawnSync("npx", ["tsx", cliEntry, "show", "ordering:OrderPlaced", "--root", LOCAL, "--json"], { encoding: "utf-8" });
|
|
153
|
+
if (showResult.status !== 0) {
|
|
154
|
+
throw new Error(`dkk show failed: ${showResult.stderr}\n${showResult.stdout}`);
|
|
155
|
+
}
|
|
156
|
+
const shown = JSON.parse(showResult.stdout);
|
|
157
|
+
assert("peer item resolved via cache", shown.data?.name === "OrderPlaced");
|
|
158
|
+
assert("peer label includes [peer: ordering]", shown.label.includes("peer: ordering"));
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
rmSync(RAW_TMP, { recursive: true, force: true });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
console.log(`\n${passed} passed, ${failed} failed${skipped ? " (test suite skipped)" : ""}`);
|
|
165
|
+
if (failed > 0)
|
|
166
|
+
process.exit(1);
|
|
167
|
+
//# sourceMappingURL=git-fetcher.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-fetcher.test.js","sourceRoot":"","sources":["../../../../src/features/federation/tests/git-fetcher.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.test.d.ts","sourceRoot":"","sources":["../../../../src/features/federation/tests/loader.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the federation loader.
|
|
3
|
+
*
|
|
4
|
+
* Verifies two-repo local-path federation:
|
|
5
|
+
* - Local peer is reachable, its items are loaded into model.peers
|
|
6
|
+
* - Unreachable peer becomes a warning, not an error
|
|
7
|
+
* - DKK_PEER_<NAME> env override redirects a peer to a different path
|
|
8
|
+
* - Peer loading is one level deep (a peer's own federation.yml is ignored)
|
|
9
|
+
*/
|
|
10
|
+
import { mkdirSync, writeFileSync, rmSync, realpathSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { loadDomainModel } from "../../../shared/loader.js";
|
|
14
|
+
import { loadFederation, resolvePeerRoot, peerEnvKey } from "../loader.js";
|
|
15
|
+
let passed = 0;
|
|
16
|
+
let failed = 0;
|
|
17
|
+
function assert(label, condition, detail) {
|
|
18
|
+
if (condition) {
|
|
19
|
+
console.log(` OK: ${label}`);
|
|
20
|
+
passed++;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
console.error(`FAIL: ${label}${detail ? ` — ${detail}` : ""}`);
|
|
24
|
+
failed++;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const RAW_TMP = join(tmpdir(), `dkk-fed-${Date.now()}`);
|
|
28
|
+
mkdirSync(RAW_TMP, { recursive: true });
|
|
29
|
+
const TMP = realpathSync(RAW_TMP);
|
|
30
|
+
// Two-repo fixture layout:
|
|
31
|
+
// <TMP>/order-svc/.dkk/ — peer service "ordering" with one event
|
|
32
|
+
// <TMP>/billing-svc/.dkk/ — local service "billing" with federation.yml pointing at order-svc
|
|
33
|
+
const ORDER = join(TMP, "order-svc");
|
|
34
|
+
const BILLING = join(TMP, "billing-svc");
|
|
35
|
+
const ALT_ORDER = join(TMP, "alt-order-svc"); // for env override test
|
|
36
|
+
function writeServiceRepo(root, opts) {
|
|
37
|
+
const dkk = join(root, ".dkk");
|
|
38
|
+
const domain = join(dkk, "domain");
|
|
39
|
+
const ctx = join(domain, "contexts", opts.contextName);
|
|
40
|
+
mkdirSync(join(ctx, "events"), { recursive: true });
|
|
41
|
+
mkdirSync(join(dkk, "adr"), { recursive: true });
|
|
42
|
+
// service.yml
|
|
43
|
+
writeFileSync(join(dkk, "service.yml"), [`name: ${opts.serviceName}`, `exports:`, ` - ${opts.exportName}`].join("\n"));
|
|
44
|
+
// domain/index.yml
|
|
45
|
+
writeFileSync(join(domain, "index.yml"), [`contexts:`, ` - name: ${opts.contextName}`, ` description: ${opts.contextName} context`].join("\n"));
|
|
46
|
+
// domain/actors.yml
|
|
47
|
+
writeFileSync(join(domain, "actors.yml"), "actors: []\n");
|
|
48
|
+
// contexts/<name>/context.yml
|
|
49
|
+
writeFileSync(join(ctx, "context.yml"), [`name: ${opts.contextName}`, `description: ${opts.contextName} bounded context`].join("\n"));
|
|
50
|
+
if (opts.eventName) {
|
|
51
|
+
writeFileSync(join(ctx, "events", `${opts.eventName}.yml`), [`name: ${opts.eventName}`, `description: Raised when ${opts.eventName.toLowerCase()}.`].join("\n"));
|
|
52
|
+
}
|
|
53
|
+
if (opts.federationYml) {
|
|
54
|
+
writeFileSync(join(dkk, "federation.yml"), opts.federationYml);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
writeServiceRepo(ORDER, {
|
|
58
|
+
serviceName: "ordering",
|
|
59
|
+
exportName: "ordering",
|
|
60
|
+
contextName: "ordering",
|
|
61
|
+
eventName: "OrderPlaced",
|
|
62
|
+
});
|
|
63
|
+
writeServiceRepo(BILLING, {
|
|
64
|
+
serviceName: "billing",
|
|
65
|
+
exportName: "billing",
|
|
66
|
+
contextName: "billing",
|
|
67
|
+
federationYml: [
|
|
68
|
+
"peers:",
|
|
69
|
+
" - name: ordering",
|
|
70
|
+
" source:",
|
|
71
|
+
" type: local",
|
|
72
|
+
" path: ../order-svc",
|
|
73
|
+
].join("\n"),
|
|
74
|
+
});
|
|
75
|
+
// Alt peer for env override
|
|
76
|
+
writeServiceRepo(ALT_ORDER, {
|
|
77
|
+
serviceName: "ordering",
|
|
78
|
+
exportName: "ordering",
|
|
79
|
+
contextName: "ordering",
|
|
80
|
+
eventName: "OrderShipped",
|
|
81
|
+
});
|
|
82
|
+
try {
|
|
83
|
+
// ── loadFederation reads the manifest ─────────────────────────────────
|
|
84
|
+
console.log("\n=== loadFederation ===");
|
|
85
|
+
const manifest = loadFederation(BILLING);
|
|
86
|
+
assert("federation manifest loaded", manifest !== null);
|
|
87
|
+
assert("manifest has one peer", manifest?.peers.length === 1);
|
|
88
|
+
assert("peer name is ordering", manifest?.peers[0].name === "ordering");
|
|
89
|
+
assert("peer source type is local", manifest?.peers[0].source.type === "local");
|
|
90
|
+
// unfederated repo returns null
|
|
91
|
+
const noFed = loadFederation(ORDER);
|
|
92
|
+
assert("unfederated repo returns null", noFed === null);
|
|
93
|
+
// ── resolvePeerRoot for local source ──────────────────────────────────
|
|
94
|
+
console.log("\n=== resolvePeerRoot (local) ===");
|
|
95
|
+
const resolved = resolvePeerRoot(manifest.peers[0], BILLING);
|
|
96
|
+
assert("local peer is reachable", resolved.reachable);
|
|
97
|
+
assert("peerRoot resolves to order-svc", resolved.peerRoot === ORDER);
|
|
98
|
+
// ── resolvePeerRoot for unreachable local source ─────────────────────
|
|
99
|
+
console.log("\n=== resolvePeerRoot (unreachable local) ===");
|
|
100
|
+
const unreachable = resolvePeerRoot({
|
|
101
|
+
name: "missing",
|
|
102
|
+
source: { type: "local", path: "../does-not-exist" },
|
|
103
|
+
}, BILLING);
|
|
104
|
+
assert("unreachable peer not reachable", !unreachable.reachable);
|
|
105
|
+
assert("unreachable peer has reason", typeof unreachable.reason === "string");
|
|
106
|
+
// ── End-to-end: loadDomainModel from billing hydrates ordering peer ──
|
|
107
|
+
console.log("\n=== loadDomainModel with federation ===");
|
|
108
|
+
const model = loadDomainModel({ root: BILLING });
|
|
109
|
+
assert("model.service is billing", model.service?.name === "billing");
|
|
110
|
+
assert("model.peers exists", model.peers !== undefined);
|
|
111
|
+
assert("model.peers has ordering", model.peers?.has("ordering") === true);
|
|
112
|
+
const peer = model.peers?.get("ordering");
|
|
113
|
+
assert("peer has service identity", peer?.service?.name === "ordering");
|
|
114
|
+
assert("peer has ordering context", peer?.contexts.has("ordering") === true);
|
|
115
|
+
assert("peer has OrderPlaced event", (peer?.contexts.get("ordering")?.events ?? []).some((e) => e.name === "OrderPlaced"));
|
|
116
|
+
// ── One level deep: peer.peers stays undefined ────────────────────────
|
|
117
|
+
console.log("\n=== peer-of-peer not followed ===");
|
|
118
|
+
assert("peer.peers is undefined (no transitive)", peer?.peers === undefined);
|
|
119
|
+
// ── Env override redirects peer to a different path ──────────────────
|
|
120
|
+
console.log("\n=== env override ===");
|
|
121
|
+
const envKey = peerEnvKey("ordering");
|
|
122
|
+
assert("env key formatted correctly", envKey === "DKK_PEER_ORDERING");
|
|
123
|
+
const originalEnv = process.env[envKey];
|
|
124
|
+
process.env[envKey] = ALT_ORDER;
|
|
125
|
+
try {
|
|
126
|
+
const altModel = loadDomainModel({ root: BILLING });
|
|
127
|
+
const altPeer = altModel.peers?.get("ordering");
|
|
128
|
+
assert("env override points peer at alt-order-svc", (altPeer?.contexts.get("ordering")?.events ?? []).some((e) => e.name === "OrderShipped"));
|
|
129
|
+
assert("env override drops OrderPlaced (different repo)", !(altPeer?.contexts.get("ordering")?.events ?? []).some((e) => e.name === "OrderPlaced"));
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
if (originalEnv === undefined)
|
|
133
|
+
delete process.env[envKey];
|
|
134
|
+
else
|
|
135
|
+
process.env[envKey] = originalEnv;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
rmSync(RAW_TMP, { recursive: true, force: true });
|
|
140
|
+
}
|
|
141
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
142
|
+
if (failed > 0)
|
|
143
|
+
process.exit(1);
|
|
144
|
+
//# sourceMappingURL=loader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.test.js","sourceRoot":"","sources":["../../../../src/features/federation/tests/loader.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase5.test.d.ts","sourceRoot":"","sources":["../../../../src/features/federation/tests/phase5.test.ts"],"names":[],"mappings":""}
|