@ddd-ts/event-tree 0.0.0-eventviz.15 → 0.0.0-eventviz.16
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/dist/engine/defaults/_utils.d.ts +15 -0
- package/dist/engine/defaults/_utils.d.ts.map +1 -1
- package/dist/engine/defaults/_utils.mjs +52 -19
- package/dist/engine/defaults/command-handler.d.ts.map +1 -1
- package/dist/engine/defaults/command-handler.mjs +39 -18
- package/dist/engine/defaults/index.d.ts.map +1 -1
- package/dist/engine/defaults/index.mjs +2 -0
- package/dist/engine/defaults/method-index.d.ts +11 -0
- package/dist/engine/defaults/method-index.d.ts.map +1 -0
- package/dist/engine/defaults/method-index.mjs +24 -0
- package/dist/engine/engine.d.ts +26 -0
- package/dist/engine/engine.d.ts.map +1 -1
- package/dist/engine/engine.mjs +47 -0
- package/package.json +2 -2
|
@@ -5,10 +5,25 @@ export declare function walkSubtree(node: Node | null | undefined, visit: (n: No
|
|
|
5
5
|
export declare function readStringLiteral(node: Node | null | undefined): string | null;
|
|
6
6
|
export declare function superGenericIdentifier(node: Class): string | null;
|
|
7
7
|
export declare function reactorEvents(decorators: Decorator[] | undefined, allowedCallees: Set<string>): string[];
|
|
8
|
+
/**
|
|
9
|
+
* Resolves the constructed type name from the ddd-ts construction idioms:
|
|
10
|
+
* `new X(...)`, `X.new(...)` and `X.parse(...)`. Events and commands are most
|
|
11
|
+
* often created through the static `.new()`/`.parse()` factories rather than
|
|
12
|
+
* the `new` operator, so both must be recognised.
|
|
13
|
+
*/
|
|
14
|
+
export declare function constructedName(node: Node | null | undefined): string | null;
|
|
8
15
|
export declare function methodEffects(method: MethodDefinition): {
|
|
9
16
|
sends: string[];
|
|
10
17
|
emits: string[];
|
|
11
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* Events applied within a method via the aggregate idiom `this.apply(Event.new(...))`
|
|
21
|
+
* (or `this.apply(new Event(...))`). Unlike `methodEffects`, this is scoped to
|
|
22
|
+
* `this.apply(...)` only, so it captures event-application methods (the
|
|
23
|
+
* behaviours a command handler delegates to) without sweeping up command
|
|
24
|
+
* dispatching or unrelated constructions.
|
|
25
|
+
*/
|
|
26
|
+
export declare function appliedEvents(method: MethodDefinition): string[];
|
|
12
27
|
export declare function classMethods(node: Class): MethodDefinition[];
|
|
13
28
|
export declare function methodName(method: MethodDefinition): string | null;
|
|
14
29
|
//# sourceMappingURL=_utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_utils.d.ts","sourceRoot":"","sources":["../../../src/engine/defaults/_utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,SAAS,EACT,gBAAgB,EAChB,IAAI,EACL,MAAM,YAAY,CAAC;AAEpB,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAM3E;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQvE;AAOD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,IAAI,QAYlF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,iBAK9D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,KAAK,iBAKjD;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EACnC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,YAc5B;AAKD,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB;;;
|
|
1
|
+
{"version":3,"file":"_utils.d.ts","sourceRoot":"","sources":["../../../src/engine/defaults/_utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,SAAS,EACT,gBAAgB,EAChB,IAAI,EACL,MAAM,YAAY,CAAC;AAEpB,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAM3E;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQvE;AAOD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,IAAI,QAYlF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,iBAK9D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,KAAK,iBAKjD;AAED,wBAAgB,aAAa,CAC3B,UAAU,EAAE,SAAS,EAAE,GAAG,SAAS,EACnC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,YAc5B;AAKD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAU5E;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB;;;EAiCrD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAWhE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,KAAK,sBAQvC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,iBAElD"}
|
|
@@ -59,40 +59,73 @@ const SEND_MEMBERS = new Set([
|
|
|
59
59
|
"dispatch",
|
|
60
60
|
"send"
|
|
61
61
|
]);
|
|
62
|
-
const EMIT_MEMBERS = new Set([
|
|
62
|
+
const EMIT_MEMBERS = new Set([
|
|
63
|
+
"publish",
|
|
64
|
+
"emit",
|
|
65
|
+
"apply"
|
|
66
|
+
]);
|
|
67
|
+
/**
|
|
68
|
+
* Resolves the constructed type name from the ddd-ts construction idioms:
|
|
69
|
+
* `new X(...)`, `X.new(...)` and `X.parse(...)`. Events and commands are most
|
|
70
|
+
* often created through the static `.new()`/`.parse()` factories rather than
|
|
71
|
+
* the `new` operator, so both must be recognised.
|
|
72
|
+
*/
|
|
73
|
+
function constructedName(node) {
|
|
74
|
+
if (!node) return null;
|
|
75
|
+
if (node.type === "NewExpression") return identifierName(node.callee);
|
|
76
|
+
if (node.type === "CallExpression" && node.callee.type === "MemberExpression") {
|
|
77
|
+
const factory = identifierName(node.callee.property);
|
|
78
|
+
if (factory === "new" || factory === "parse") return identifierName(node.callee.object);
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
63
82
|
function methodEffects(method) {
|
|
64
83
|
const sends = /* @__PURE__ */ new Set();
|
|
65
84
|
const emits = /* @__PURE__ */ new Set();
|
|
66
|
-
const
|
|
85
|
+
const consumed = /* @__PURE__ */ new WeakSet();
|
|
67
86
|
walkSubtree(method.value.body, (n) => {
|
|
68
87
|
if (n.type !== "CallExpression") return;
|
|
69
|
-
const a0 = n.arguments[0];
|
|
70
|
-
let arg0New = null;
|
|
71
|
-
if (a0?.type === "NewExpression") arg0New = identifierName(a0.callee);
|
|
72
|
-
else if (a0?.type === "Identifier") arg0New = a0.name;
|
|
73
|
-
if (!arg0New) return;
|
|
74
88
|
if (n.callee.type !== "MemberExpression") return;
|
|
75
89
|
const member = identifierName(n.callee.property);
|
|
76
90
|
if (!member) return;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
const isSend = SEND_MEMBERS.has(member);
|
|
92
|
+
const isEmit = EMIT_MEMBERS.has(member);
|
|
93
|
+
if (!isSend && !isEmit) return;
|
|
94
|
+
const a0 = n.arguments[0];
|
|
95
|
+
const name = constructedName(a0) ?? (a0?.type === "Identifier" ? a0.name : null);
|
|
96
|
+
if (!name) return;
|
|
97
|
+
(isSend ? sends : emits).add(name);
|
|
98
|
+
if (a0 && (a0.type === "NewExpression" || a0.type === "CallExpression")) consumed.add(a0);
|
|
84
99
|
});
|
|
85
100
|
walkSubtree(method.value.body, (n) => {
|
|
86
|
-
if (n
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (id) emits.add(id);
|
|
101
|
+
if (consumed.has(n)) return;
|
|
102
|
+
const name = constructedName(n);
|
|
103
|
+
if (name) emits.add(name);
|
|
90
104
|
});
|
|
91
105
|
return {
|
|
92
106
|
sends: [...sends],
|
|
93
107
|
emits: [...emits]
|
|
94
108
|
};
|
|
95
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Events applied within a method via the aggregate idiom `this.apply(Event.new(...))`
|
|
112
|
+
* (or `this.apply(new Event(...))`). Unlike `methodEffects`, this is scoped to
|
|
113
|
+
* `this.apply(...)` only, so it captures event-application methods (the
|
|
114
|
+
* behaviours a command handler delegates to) without sweeping up command
|
|
115
|
+
* dispatching or unrelated constructions.
|
|
116
|
+
*/
|
|
117
|
+
function appliedEvents(method) {
|
|
118
|
+
const events = /* @__PURE__ */ new Set();
|
|
119
|
+
walkSubtree(method.value.body, (n) => {
|
|
120
|
+
if (n.type !== "CallExpression") return;
|
|
121
|
+
if (n.callee.type !== "MemberExpression") return;
|
|
122
|
+
if (n.callee.object.type !== "ThisExpression") return;
|
|
123
|
+
if (identifierName(n.callee.property) !== "apply") return;
|
|
124
|
+
const name = constructedName(n.arguments[0]);
|
|
125
|
+
if (name) events.add(name);
|
|
126
|
+
});
|
|
127
|
+
return [...events];
|
|
128
|
+
}
|
|
96
129
|
function classMethods(node) {
|
|
97
130
|
const out = [];
|
|
98
131
|
for (const member of node.body.body) if (member.type === "MethodDefinition" || member.type === "TSAbstractMethodDefinition") out.push(member);
|
|
@@ -102,4 +135,4 @@ function methodName(method) {
|
|
|
102
135
|
return identifierName(method.key);
|
|
103
136
|
}
|
|
104
137
|
//#endregion
|
|
105
|
-
export { classMethods, identifierName, memberPath, methodEffects, methodName, reactorEvents, readStringLiteral, superGenericIdentifier, walkSubtree };
|
|
138
|
+
export { appliedEvents, classMethods, constructedName, identifierName, memberPath, methodEffects, methodName, reactorEvents, readStringLiteral, superGenericIdentifier, walkSubtree };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../../src/engine/defaults/command-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"command-handler.d.ts","sourceRoot":"","sources":["../../../src/engine/defaults/command-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAQxC,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,QAsDzD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { identifierName, superGenericIdentifier, walkSubtree } from "./_utils.mjs";
|
|
1
|
+
import { constructedName, identifierName, superGenericIdentifier, walkSubtree } from "./_utils.mjs";
|
|
2
2
|
//#region src/engine/defaults/command-handler.ts
|
|
3
3
|
function applyCommandHandlerDefaults(engine) {
|
|
4
4
|
engine.on((node, parent, ctx, file) => {
|
|
@@ -9,25 +9,46 @@ function applyCommandHandlerDefaults(engine) {
|
|
|
9
9
|
const command = superGenericIdentifier(node);
|
|
10
10
|
if (!command) return;
|
|
11
11
|
const seen = /* @__PURE__ */ new Set();
|
|
12
|
+
const invoked = /* @__PURE__ */ new Set();
|
|
12
13
|
walkSubtree(node.body, (n) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
const created = constructedName(n);
|
|
15
|
+
if (created) {
|
|
16
|
+
if (!seen.has(created)) {
|
|
17
|
+
seen.add(created);
|
|
18
|
+
engine.saveEdge({
|
|
19
|
+
from: {
|
|
20
|
+
type: "command",
|
|
21
|
+
name: command
|
|
22
|
+
},
|
|
23
|
+
to: {
|
|
24
|
+
type: "event",
|
|
25
|
+
name: created
|
|
26
|
+
},
|
|
27
|
+
source: {
|
|
28
|
+
file,
|
|
29
|
+
start: n.start
|
|
30
|
+
}
|
|
31
|
+
});
|
|
29
32
|
}
|
|
30
|
-
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (n.type === "CallExpression" && n.callee.type === "MemberExpression" && n.callee.object.type === "Identifier") {
|
|
36
|
+
const method = identifierName(n.callee.property);
|
|
37
|
+
if (method && !invoked.has(method)) {
|
|
38
|
+
invoked.add(method);
|
|
39
|
+
engine.saveInvocation({
|
|
40
|
+
from: {
|
|
41
|
+
type: "command",
|
|
42
|
+
name: command
|
|
43
|
+
},
|
|
44
|
+
method,
|
|
45
|
+
source: {
|
|
46
|
+
file,
|
|
47
|
+
start: n.start
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
31
52
|
});
|
|
32
53
|
});
|
|
33
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/defaults/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/defaults/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAUxC,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,QAS3C"}
|
|
@@ -2,6 +2,7 @@ import { applyCommandDefaults } from "./command.mjs";
|
|
|
2
2
|
import { applyCommandHandlerDefaults } from "./command-handler.mjs";
|
|
3
3
|
import { applyEsAggregateDefaults } from "./es-aggregate.mjs";
|
|
4
4
|
import { applyEventDefaults } from "./event.mjs";
|
|
5
|
+
import { applyMethodIndexDefaults } from "./method-index.mjs";
|
|
5
6
|
import { applyProjectionDefaults } from "./projection.mjs";
|
|
6
7
|
import { applySagaDefaults } from "./saga.mjs";
|
|
7
8
|
import { applyScannerDefaults } from "./scanner.mjs";
|
|
@@ -13,6 +14,7 @@ function applyDefaults(engine) {
|
|
|
13
14
|
applyEsAggregateDefaults(engine);
|
|
14
15
|
applyProjectionDefaults(engine);
|
|
15
16
|
applyCommandHandlerDefaults(engine);
|
|
17
|
+
applyMethodIndexDefaults(engine);
|
|
16
18
|
applyScannerDefaults(engine);
|
|
17
19
|
}
|
|
18
20
|
//#endregion
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Engine } from "../engine";
|
|
2
|
+
/**
|
|
3
|
+
* Indexes aggregate/entity event-application methods (`this.apply(Event.new(...))`)
|
|
4
|
+
* by method name. The engine later joins these against recorded
|
|
5
|
+
* `receiver.method(...)` calls so a caller (e.g. a command handler) is linked to
|
|
6
|
+
* the events it ultimately produces, even when the emit happens in another
|
|
7
|
+
* class. Scoped to `this.apply(...)` so command-dispatch methods (every
|
|
8
|
+
* handler's `execute`, command buses, …) don't become catch-all matches.
|
|
9
|
+
*/
|
|
10
|
+
export declare function applyMethodIndexDefaults(engine: Engine): void;
|
|
11
|
+
//# sourceMappingURL=method-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method-index.d.ts","sourceRoot":"","sources":["../../../src/engine/defaults/method-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGxC;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,QAatD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { appliedEvents, classMethods, methodName } from "./_utils.mjs";
|
|
2
|
+
//#region src/engine/defaults/method-index.ts
|
|
3
|
+
/**
|
|
4
|
+
* Indexes aggregate/entity event-application methods (`this.apply(Event.new(...))`)
|
|
5
|
+
* by method name. The engine later joins these against recorded
|
|
6
|
+
* `receiver.method(...)` calls so a caller (e.g. a command handler) is linked to
|
|
7
|
+
* the events it ultimately produces, even when the emit happens in another
|
|
8
|
+
* class. Scoped to `this.apply(...)` so command-dispatch methods (every
|
|
9
|
+
* handler's `execute`, command buses, …) don't become catch-all matches.
|
|
10
|
+
*/
|
|
11
|
+
function applyMethodIndexDefaults(engine) {
|
|
12
|
+
engine.on((node) => {
|
|
13
|
+
if (node.type !== "ClassDeclaration" || !node.id) return;
|
|
14
|
+
const owner = node.id.name;
|
|
15
|
+
for (const method of classMethods(node)) {
|
|
16
|
+
const name = methodName(method);
|
|
17
|
+
if (!name) continue;
|
|
18
|
+
const events = appliedEvents(method);
|
|
19
|
+
if (events.length) engine.indexBehaviour(name, owner, events);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { applyMethodIndexDefaults };
|
package/dist/engine/engine.d.ts
CHANGED
|
@@ -13,6 +13,32 @@ export declare class Engine {
|
|
|
13
13
|
private nodes;
|
|
14
14
|
saveNode(node: Node): void;
|
|
15
15
|
getNodes(): readonly Node[];
|
|
16
|
+
private behaviours;
|
|
17
|
+
indexBehaviour(method: string, owner: string, events: readonly string[]): void;
|
|
18
|
+
private invocations;
|
|
19
|
+
saveInvocation(invocation: {
|
|
20
|
+
from: {
|
|
21
|
+
type: "command";
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
method: string;
|
|
25
|
+
source: {
|
|
26
|
+
file: string;
|
|
27
|
+
start: number;
|
|
28
|
+
};
|
|
29
|
+
}): void;
|
|
30
|
+
/**
|
|
31
|
+
* Expands recorded `receiver.method(...)` calls into edges from the caller to
|
|
32
|
+
* whatever the callee emits/sends. This links a command handler that
|
|
33
|
+
* delegates to an aggregate method (e.g. `message.destroy()` →
|
|
34
|
+
* `this.apply(SomeEvent.new(...))`) to the events it ultimately produces.
|
|
35
|
+
* Matching is by method name only — no receiver type resolution. To stay
|
|
36
|
+
* precise we attribute a method's events only when that name is declared in a
|
|
37
|
+
* single class; a name shared across classes (e.g. `enable`/`disable` on many
|
|
38
|
+
* feature aggregates) is ambiguous and skipped. Edges to unknown targets are
|
|
39
|
+
* dropped later by resolveEdges().
|
|
40
|
+
*/
|
|
41
|
+
private resolveInvocations;
|
|
16
42
|
/**
|
|
17
43
|
* Edge targets discovered from `new X()` calls are speculative: when a walker
|
|
18
44
|
* records them it only knows the constructor name, not whether `X` is a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAGpC,KAAK,SAAS,GAAG,CACf,GAAG,IAAI,EAAE,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,KAChD,UAAU,CAAC,WAAW,CAAC,CAAC;AAE7B,qBAAa,MAAM;IACjB,OAAO,CAAC,UAAU,CAAmB;IAErC,EAAE,CAAC,MAAM,EAAE,SAAS;IAKpB,OAAO,CAAC,WAAW,CAIjB;IACF,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC,MAAM,CAAC;IAKpD,OAAO,CAAC,KAAK,CAAc;IAC3B,QAAQ,CAAC,IAAI,EAAE,IAAI;IAGnB,QAAQ,IAAI,SAAS,IAAI,EAAE;IAI3B,OAAO,CAAC,KAAK,CAAc;IAC3B,QAAQ,CAAC,IAAI,EAAE,IAAI;IAGnB,QAAQ,IAAI,SAAS,IAAI,EAAE;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAGpC,KAAK,SAAS,GAAG,CACf,GAAG,IAAI,EAAE,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,KAChD,UAAU,CAAC,WAAW,CAAC,CAAC;AAE7B,qBAAa,MAAM;IACjB,OAAO,CAAC,UAAU,CAAmB;IAErC,EAAE,CAAC,MAAM,EAAE,SAAS;IAKpB,OAAO,CAAC,WAAW,CAIjB;IACF,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC,MAAM,CAAC;IAKpD,OAAO,CAAC,KAAK,CAAc;IAC3B,QAAQ,CAAC,IAAI,EAAE,IAAI;IAGnB,QAAQ,IAAI,SAAS,IAAI,EAAE;IAI3B,OAAO,CAAC,KAAK,CAAc;IAC3B,QAAQ,CAAC,IAAI,EAAE,IAAI;IAGnB,QAAQ,IAAI,SAAS,IAAI,EAAE;IAS3B,OAAO,CAAC,UAAU,CAA+C;IACjE,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE;IAiBvE,OAAO,CAAC,WAAW,CAIV;IACT,cAAc,CAAC,UAAU,EAAE;QACzB,IAAI,EAAE;YAAE,IAAI,EAAE,SAAS,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QACxC,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;KACzC;IAID;;;;;;;;;;OAUG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,YAAY;IAiCpB,KAAK;IAOL,GAAG,CAAC,IAAI,GAAE,MAAsB;CAsBjC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,eAAO,MAAM,MAAM,QAAwB,CAAC"}
|
package/dist/engine/engine.mjs
CHANGED
|
@@ -29,6 +29,50 @@ var Engine = class {
|
|
|
29
29
|
getNodes() {
|
|
30
30
|
return this.nodes;
|
|
31
31
|
}
|
|
32
|
+
behaviours = /* @__PURE__ */ new Map();
|
|
33
|
+
indexBehaviour(method, owner, events) {
|
|
34
|
+
let byOwner = this.behaviours.get(method);
|
|
35
|
+
if (!byOwner) {
|
|
36
|
+
byOwner = /* @__PURE__ */ new Map();
|
|
37
|
+
this.behaviours.set(method, byOwner);
|
|
38
|
+
}
|
|
39
|
+
let entry = byOwner.get(owner);
|
|
40
|
+
if (!entry) {
|
|
41
|
+
entry = /* @__PURE__ */ new Set();
|
|
42
|
+
byOwner.set(owner, entry);
|
|
43
|
+
}
|
|
44
|
+
for (const e of events) entry.add(e);
|
|
45
|
+
}
|
|
46
|
+
invocations = [];
|
|
47
|
+
saveInvocation(invocation) {
|
|
48
|
+
this.invocations.push(invocation);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Expands recorded `receiver.method(...)` calls into edges from the caller to
|
|
52
|
+
* whatever the callee emits/sends. This links a command handler that
|
|
53
|
+
* delegates to an aggregate method (e.g. `message.destroy()` →
|
|
54
|
+
* `this.apply(SomeEvent.new(...))`) to the events it ultimately produces.
|
|
55
|
+
* Matching is by method name only — no receiver type resolution. To stay
|
|
56
|
+
* precise we attribute a method's events only when that name is declared in a
|
|
57
|
+
* single class; a name shared across classes (e.g. `enable`/`disable` on many
|
|
58
|
+
* feature aggregates) is ambiguous and skipped. Edges to unknown targets are
|
|
59
|
+
* dropped later by resolveEdges().
|
|
60
|
+
*/
|
|
61
|
+
resolveInvocations() {
|
|
62
|
+
for (const { from, method, source } of this.invocations) {
|
|
63
|
+
const byOwner = this.behaviours.get(method);
|
|
64
|
+
if (!byOwner || byOwner.size !== 1) continue;
|
|
65
|
+
const [events] = byOwner.values();
|
|
66
|
+
for (const name of events) this.edges.push({
|
|
67
|
+
from,
|
|
68
|
+
to: {
|
|
69
|
+
type: "event",
|
|
70
|
+
name
|
|
71
|
+
},
|
|
72
|
+
source
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
32
76
|
/**
|
|
33
77
|
* Edge targets discovered from `new X()` calls are speculative: when a walker
|
|
34
78
|
* records them it only knows the constructor name, not whether `X` is a
|
|
@@ -65,6 +109,8 @@ var Engine = class {
|
|
|
65
109
|
reset() {
|
|
66
110
|
this.edges = [];
|
|
67
111
|
this.nodes = [];
|
|
112
|
+
this.invocations = [];
|
|
113
|
+
this.behaviours = /* @__PURE__ */ new Map();
|
|
68
114
|
}
|
|
69
115
|
run(root = process.cwd()) {
|
|
70
116
|
for (const file of this.fileScanner(root)) {
|
|
@@ -78,6 +124,7 @@ var Engine = class {
|
|
|
78
124
|
}
|
|
79
125
|
} });
|
|
80
126
|
}
|
|
127
|
+
this.resolveInvocations();
|
|
81
128
|
this.resolveEdges();
|
|
82
129
|
}
|
|
83
130
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ddd-ts/event-tree",
|
|
3
|
-
"version": "0.0.0-eventviz.
|
|
3
|
+
"version": "0.0.0-eventviz.16",
|
|
4
4
|
"types": "dist/server/index.d.ts",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"oxc-walker": "^1.0.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@ddd-ts/tools": "0.0.0-eventviz.
|
|
18
|
+
"@ddd-ts/tools": "0.0.0-eventviz.16",
|
|
19
19
|
"@types/node": "^22.14.1"
|
|
20
20
|
},
|
|
21
21
|
"exports": {
|