@antelopejs/interface-core 0.2.3 → 0.2.5

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.
Files changed (43) hide show
  1. package/README.md +86 -17
  2. package/dist/index.d.ts +4 -1
  3. package/dist/index.js +0 -13
  4. package/dist/index.js.map +1 -1
  5. package/dist/internal.d.ts +14 -2
  6. package/dist/internal.js +17 -1
  7. package/dist/internal.js.map +1 -1
  8. package/dist/modules.d.ts +3 -2
  9. package/dist/modules.js.map +1 -1
  10. package/dist/proxies.d.ts +25 -7
  11. package/dist/proxies.js +89 -79
  12. package/dist/proxies.js.map +1 -1
  13. package/dist/tests/module-ownership-context.test.js +3 -3
  14. package/dist/tests/module-ownership-context.test.js.map +1 -1
  15. package/dist/tests/ownership-call-chain.test.js +261 -0
  16. package/dist/tests/ownership-call-chain.test.js.map +1 -0
  17. package/docs/1.introduction.md +29 -3
  18. package/docs/2.proxies.md +101 -36
  19. package/docs/3.decorators.md +25 -1
  20. package/docs/4.metadata.md +25 -1
  21. package/docs/5.modules.md +26 -7
  22. package/docs/6.logging.md +42 -20
  23. package/docs/7.configuration.md +33 -12
  24. package/docs/8.runtime.md +15 -0
  25. package/docs/assets/proxy-lifecycles.svg +21 -0
  26. package/docs/tsconfig.json +16 -0
  27. package/package.json +11 -4
  28. package/skills/core-interface/SKILL.md +3 -4
  29. package/dist/caller-binding.d.ts +0 -12
  30. package/dist/caller-binding.js +0 -105
  31. package/dist/caller-binding.js.map +0 -1
  32. package/dist/responsible-module.d.ts +0 -23
  33. package/dist/responsible-module.js +0 -56
  34. package/dist/responsible-module.js.map +0 -1
  35. package/dist/tests/caller-context.test.js +0 -154
  36. package/dist/tests/caller-context.test.js.map +0 -1
  37. package/dist/tests/provider-context.test.d.ts +0 -1
  38. package/dist/tests/provider-context.test.js +0 -109
  39. package/dist/tests/provider-context.test.js.map +0 -1
  40. package/dist/tests/responsible-module.test.d.ts +0 -1
  41. package/dist/tests/responsible-module.test.js +0 -109
  42. package/dist/tests/responsible-module.test.js.map +0 -1
  43. /package/dist/tests/{caller-context.test.d.ts → ownership-call-chain.test.d.ts} +0 -0
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const chai_1 = require("chai");
4
+ const modules_1 = require("../modules");
5
+ const __1 = require("..");
6
+ function inModule(module, owner, callback) {
7
+ return (0, modules_1.RunWithModuleContext)({ module, owner }, callback);
8
+ }
9
+ function destroy(module, owner) {
10
+ inModule(module, owner, () => modules_1.Events.ModuleDestroyed.emit(module));
11
+ }
12
+ function attachRegistry(proxy, entries, module, owner) {
13
+ inModule(module, owner, () => proxy.onHandlers((id) => entries.add(id), (id) => entries.delete(id)));
14
+ }
15
+ function deferred() {
16
+ let resolve;
17
+ const promise = new Promise((done) => {
18
+ resolve = done;
19
+ });
20
+ return { promise, resolve };
21
+ }
22
+ function outcomeOf(promise) {
23
+ return promise.then(() => "resolved", (error) => error);
24
+ }
25
+ describe("call chain: a module serving a call owns what it registers", () => {
26
+ it("keeps a registration made by B's provider when A is destroyed, and drops it with B", async () => {
27
+ const b = new __1.AsyncProxy();
28
+ const c = new __1.RegisteringProxy();
29
+ const entries = new Set();
30
+ attachRegistry(c, entries, "c", "c#1");
31
+ inModule("b", "b#1", () => b.onCall(() => c.register("from-b")));
32
+ await inModule("a", "a#1", () => b.call());
33
+ destroy("a", "a#1");
34
+ (0, chai_1.expect)([...entries]).to.deep.equal(["from-b"]);
35
+ destroy("b", "b#1");
36
+ (0, chai_1.expect)([...entries]).to.deep.equal([]);
37
+ });
38
+ it("forwards A's registration through B, replays it to B's next generation, and removes it with A", () => {
39
+ const b = new __1.RegisteringProxy();
40
+ const c = new __1.RegisteringProxy();
41
+ const entries = new Set();
42
+ attachRegistry(c, entries, "c", "c#2");
43
+ const attachForwarder = (owner) => inModule("b", owner, () => b.onHandlers((id) => c.register(`c:${id}`), (id) => c.unregister(`c:${id}`)));
44
+ attachForwarder("b#2");
45
+ inModule("a", "a#2", () => b.register("x"));
46
+ (0, chai_1.expect)([...entries]).to.deep.equal(["c:x"]);
47
+ destroy("b", "b#2");
48
+ (0, chai_1.expect)([...entries]).to.deep.equal([]);
49
+ attachForwarder("b#3");
50
+ (0, chai_1.expect)([...entries]).to.deep.equal(["c:x"]);
51
+ destroy("a", "a#2");
52
+ (0, chai_1.expect)([...entries]).to.deep.equal([]);
53
+ });
54
+ });
55
+ describe("call chain: queued calls", () => {
56
+ it("runs a call queued before the provider attached in the provider's context", async () => {
57
+ const proxy = new __1.AsyncProxy();
58
+ const pending = inModule("a", "a#3", () => proxy.call());
59
+ inModule("b", "b#4", () => proxy.onCall(() => (0, __1.GetResponsibleModule)()));
60
+ (0, chai_1.expect)(await pending).to.equal("b");
61
+ });
62
+ it("rejects a queued call whose caller was destroyed before the provider attached", async () => {
63
+ const proxy = new __1.AsyncProxy();
64
+ let served = 0;
65
+ const pending = outcomeOf(inModule("a", "a#4", () => proxy.call()));
66
+ destroy("a", "a#4");
67
+ inModule("b", "b#5", () => proxy.onCall(() => {
68
+ served += 1;
69
+ return "served";
70
+ }));
71
+ (0, chai_1.expect)(await pending).to.be.instanceOf(__1.ModuleContextInvalidatedError);
72
+ (0, chai_1.expect)(served).to.equal(0);
73
+ });
74
+ });
75
+ describe("call chain: context at each crossing", () => {
76
+ it("runs a provider callback in the provider's context, across an await", async () => {
77
+ const proxy = new __1.AsyncProxy();
78
+ inModule("b", "b#6", () => proxy.onCall(async () => {
79
+ const before = (0, __1.GetResponsibleModule)();
80
+ await Promise.resolve();
81
+ return [before, (0, __1.GetResponsibleModule)()];
82
+ }));
83
+ const seen = await inModule("a", "a#5", () => proxy.call());
84
+ (0, chai_1.expect)(seen).to.deep.equal(["b", "b"]);
85
+ });
86
+ it("runs register, unregister and replay handlers in the provider's context", () => {
87
+ const proxy = new __1.RegisteringProxy();
88
+ const seen = [];
89
+ const attach = (owner) => inModule("b", owner, () => proxy.onHandlers(() => seen.push((0, modules_1.GetModuleContext)()?.owner), () => seen.push((0, modules_1.GetModuleContext)()?.owner)));
90
+ attach("b#7");
91
+ inModule("a", "a#6", () => proxy.register("x"));
92
+ attach("b#8");
93
+ inModule("a", "a#6", () => proxy.unregister("x"));
94
+ (0, chai_1.expect)(seen).to.deep.equal(["b#7", "b#8", "b#8"]);
95
+ });
96
+ it("runs an event handler in the context it was registered in", () => {
97
+ const event = new __1.EventProxy();
98
+ const seen = [];
99
+ inModule("a", "a#7", () => event.register(() => seen.push((0, __1.GetResponsibleModule)())));
100
+ inModule("emitter", "emitter#1", () => event.emit());
101
+ (0, chai_1.expect)(seen).to.deep.equal(["a"]);
102
+ });
103
+ it("runs a handler registered outside any context in the emitter's context", () => {
104
+ const event = new __1.EventProxy();
105
+ const seen = [];
106
+ event.register(() => seen.push((0, __1.GetResponsibleModule)()));
107
+ inModule("emitter", "emitter#2", () => event.emit());
108
+ (0, chai_1.expect)(seen).to.deep.equal(["emitter"]);
109
+ });
110
+ it("lets an unregister handler schedule work that enters a module context during the registrant's release", async () => {
111
+ const proxy = new __1.RegisteringProxy();
112
+ let scheduled;
113
+ inModule("d", "d#1", () => proxy.onHandlers(() => undefined, () => {
114
+ scheduled = new Promise((resolve) => {
115
+ setImmediate(() => {
116
+ try {
117
+ (0, modules_1.RunWithModuleContext)({ module: "d-sync" }, () => undefined);
118
+ resolve("entered");
119
+ }
120
+ catch (error) {
121
+ resolve(error);
122
+ }
123
+ });
124
+ });
125
+ }));
126
+ inModule("a", "a#8", () => proxy.register("page"));
127
+ destroy("a", "a#8");
128
+ (0, chai_1.expect)(await scheduled).to.equal("entered");
129
+ });
130
+ });
131
+ describe("call chain: an interface's own context", () => {
132
+ const INTERFACE = {
133
+ module: "interface-x",
134
+ owner: "interface-x@p#instance",
135
+ kind: "interface",
136
+ };
137
+ it("keeps the interface's context for its own timers and event handlers", async () => {
138
+ const event = new __1.EventProxy();
139
+ const handled = [];
140
+ const timer = (0, modules_1.RunWithModuleContext)(INTERFACE, () => {
141
+ event.register(() => handled.push((0, __1.GetResponsibleModule)()));
142
+ return new Promise((resolve) => {
143
+ setTimeout(() => resolve((0, modules_1.GetModuleContext)()?.owner), 0);
144
+ });
145
+ });
146
+ inModule("emitter", "emitter#3", () => event.emit());
147
+ (0, chai_1.expect)(await timer).to.equal(INTERFACE.owner);
148
+ (0, chai_1.expect)(handled).to.deep.equal(["interface-x"]);
149
+ });
150
+ it("runs callbacks it attaches in the caller's context, so what they forward is the caller's", async () => {
151
+ const call = new __1.AsyncProxy();
152
+ const handlers = new __1.RegisteringProxy();
153
+ const c = new __1.RegisteringProxy();
154
+ const entries = new Set();
155
+ attachRegistry(c, entries, "c", "c#3");
156
+ (0, modules_1.RunWithModuleContext)({ ...INTERFACE, owner: "interface-y#instance" }, () => {
157
+ call.onCall(() => (0, __1.GetResponsibleModule)());
158
+ handlers.onHandlers((id) => c.register(`c:${id}`), (id) => c.unregister(`c:${id}`));
159
+ });
160
+ (0, chai_1.expect)(await inModule("a", "a#9", () => call.call())).to.equal("a");
161
+ inModule("a", "a#9", () => handlers.register("x"));
162
+ (0, chai_1.expect)([...entries]).to.deep.equal(["c:x"]);
163
+ destroy("a", "a#9");
164
+ (0, chai_1.expect)([...entries]).to.deep.equal([]);
165
+ });
166
+ it("replays a call queued before it attaches in the caller's context, so what it forwards is the caller's", async () => {
167
+ const call = new __1.AsyncProxy();
168
+ const c = new __1.RegisteringProxy();
169
+ const entries = new Set();
170
+ attachRegistry(c, entries, "c", "c#5");
171
+ const pending = inModule("a", "a#16", () => call.call());
172
+ (0, modules_1.RunWithModuleContext)({ ...INTERFACE, owner: "interface-q#instance" }, () => call.onCall(() => {
173
+ c.register("queued");
174
+ return (0, __1.GetResponsibleModule)();
175
+ }));
176
+ (0, chai_1.expect)(await pending).to.equal("a");
177
+ (0, chai_1.expect)([...entries]).to.deep.equal(["queued"]);
178
+ destroy("a", "a#16");
179
+ (0, chai_1.expect)([...entries]).to.deep.equal([]);
180
+ });
181
+ it("replays a call queued outside any context with no context", async () => {
182
+ const call = new __1.AsyncProxy();
183
+ const pending = call.call();
184
+ (0, modules_1.RunWithModuleContext)({ ...INTERFACE, owner: "interface-r#instance" }, () => call.onCall(() => (0, __1.GetResponsibleModule)()));
185
+ (0, chai_1.expect)(await pending).to.equal(undefined);
186
+ });
187
+ it("releases only the interface's own work when its owner is released", () => {
188
+ const own = new __1.RegisteringProxy();
189
+ const handlers = new __1.RegisteringProxy();
190
+ const ownEntries = new Set();
191
+ const forwarded = new Set();
192
+ const owner = "interface-z#instance";
193
+ attachRegistry(own, ownEntries, "c", "c#4");
194
+ attachRegistry(handlers, forwarded, "c", "c#4");
195
+ (0, modules_1.RunWithModuleContext)({ ...INTERFACE, owner }, () => own.register("interface-entry"));
196
+ inModule("a", "a#10", () => handlers.register("a-entry"));
197
+ (0, modules_1.ReleaseOwner)(owner);
198
+ (0, chai_1.expect)([...ownEntries]).to.deep.equal([]);
199
+ (0, chai_1.expect)([...forwarded]).to.deep.equal(["a-entry"]);
200
+ });
201
+ });
202
+ describe("call chain: values cross unchanged", () => {
203
+ class Value {
204
+ }
205
+ const handler = () => undefined;
206
+ const object = { handler };
207
+ const array = [handler];
208
+ const values = [Value, handler, object, array];
209
+ it("hands call arguments to the provider as the very same values", async () => {
210
+ const proxy = new __1.AsyncProxy();
211
+ inModule("b", "b#9", () => proxy.onCall((...received) => received));
212
+ const received = await inModule("a", "a#11", () => proxy.call(...values));
213
+ received.forEach((value, index) => (0, chai_1.expect)(value).to.equal(values[index]));
214
+ });
215
+ it("hands register arguments to the provider as the very same values", () => {
216
+ const proxy = new __1.RegisteringProxy();
217
+ let received = [];
218
+ inModule("b", "b#10", () => proxy.onHandlers((_id, ...args) => {
219
+ received = args;
220
+ }, () => undefined));
221
+ inModule("a", "a#12", () => proxy.register("x", ...values));
222
+ received.forEach((value, index) => (0, chai_1.expect)(value).to.equal(values[index]));
223
+ });
224
+ it("unregisters an event handler by the reference it was registered with", () => {
225
+ const event = new __1.EventProxy();
226
+ const received = [];
227
+ const listener = (value) => received.push(value);
228
+ inModule("a", "a#13", () => event.register(listener));
229
+ event.emit(object);
230
+ inModule("a", "a#13", () => event.unregister(listener));
231
+ event.emit(object);
232
+ (0, chai_1.expect)(received).to.have.length(1);
233
+ (0, chai_1.expect)(received[0]).to.equal(object);
234
+ });
235
+ });
236
+ describe("call chain: fence on a destroyed generation", () => {
237
+ it("rejects a call made from a destroyed generation without throwing", async () => {
238
+ const proxy = new __1.AsyncProxy();
239
+ inModule("b", "b#11", () => proxy.onCall(() => "served"));
240
+ const gate = deferred();
241
+ const outcome = inModule("a", "a#14", async () => {
242
+ await gate.promise;
243
+ return outcomeOf(proxy.call());
244
+ });
245
+ destroy("a", "a#14");
246
+ gate.resolve();
247
+ (0, chai_1.expect)(await outcome).to.be.instanceOf(__1.ModuleContextInvalidatedError);
248
+ });
249
+ it("throws on a register made from a destroyed generation", async () => {
250
+ const proxy = new __1.RegisteringProxy();
251
+ const gate = deferred();
252
+ const outcome = inModule("a", "a#15", async () => {
253
+ await gate.promise;
254
+ proxy.register("late");
255
+ });
256
+ destroy("a", "a#15");
257
+ gate.resolve();
258
+ (0, chai_1.expect)(await outcomeOf(outcome)).to.be.instanceOf(__1.ModuleContextInvalidatedError);
259
+ });
260
+ });
261
+ //# sourceMappingURL=ownership-call-chain.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownership-call-chain.test.js","sourceRoot":"","sources":["../../src/tests/ownership-call-chain.test.ts"],"names":[],"mappings":";;AAAA,+BAA8B;AAE9B,wCAKoB;AACpB,0BAMY;AAIZ,SAAS,QAAQ,CAAI,MAAc,EAAE,KAAa,EAAE,QAAiB;IACnE,OAAO,IAAA,8BAAoB,EAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,OAAO,CAAC,MAAc,EAAE,KAAa;IAC5C,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,gBAAM,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,cAAc,CACrB,KAAiC,EACjC,OAAoB,EACpB,MAAc,EACd,KAAa;IAEb,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAC3B,KAAK,CAAC,UAAU,CACd,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EACvB,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAC3B,CACF,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ;IACf,IAAI,OAAoB,CAAC;IACzB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE;QACzC,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,SAAS,CAAC,OAAyB;IAC1C,OAAO,OAAO,CAAC,IAAI,CACjB,GAAG,EAAE,CAAC,UAAU,EAChB,CAAC,KAAc,EAAE,EAAE,CAAC,KAAK,CAC1B,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,4DAA4D,EAAE,GAAG,EAAE;IAC1E,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,CAAC,GAAG,IAAI,cAAU,EAAc,CAAC;QACvC,MAAM,CAAC,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACvC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAEjE,MAAM,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpB,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAE/C,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpB,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+FAA+F,EAAE,GAAG,EAAE;QACvG,MAAM,CAAC,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC3C,MAAM,CAAC,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,eAAe,GAAG,CAAC,KAAa,EAAE,EAAE,CACxC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CACxB,CAAC,CAAC,UAAU,CACV,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,EAC7B,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAChC,CACF,CAAC;QAEJ,eAAe,CAAC,KAAK,CAAC,CAAC;QACvB,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5C,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAE5C,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpB,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAEvC,eAAe,CAAC,KAAK,CAAC,CAAC;QACvB,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAE5C,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpB,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,KAAK,GAAG,IAAI,cAAU,EAA4B,CAAC;QACzD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAEzD,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,wBAAoB,GAAE,CAAC,CAAC,CAAC;QAEvE,IAAA,aAAM,EAAC,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,KAAK,GAAG,IAAI,cAAU,EAAgB,CAAC;QAC7C,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAEpE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpB,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CACxB,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE;YAChB,MAAM,IAAI,CAAC,CAAC;YACZ,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC,CACH,CAAC;QAEF,IAAA,aAAM,EAAC,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,iCAA6B,CAAC,CAAC;QACtE,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,KAAK,GAAG,IAAI,cAAU,EAA4B,CAAC;QACzD,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CACxB,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;YACtB,MAAM,MAAM,GAAG,IAAA,wBAAoB,GAAE,CAAC;YACtC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,CAAC,MAAM,EAAE,IAAA,wBAAoB,GAAE,CAAC,CAAC;QAC1C,CAAC,CAAC,CACH,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAE5D,IAAA,aAAM,EAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,KAAK,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC/C,MAAM,IAAI,GAA8B,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE,CAC/B,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CACxB,KAAK,CAAC,UAAU,CACd,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAA,0BAAgB,GAAE,EAAE,KAAK,CAAC,EAC1C,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAA,0BAAgB,GAAE,EAAE,KAAK,CAAC,CAC3C,CACF,CAAC;QAEJ,MAAM,CAAC,KAAK,CAAC,CAAC;QACd,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,CAAC;QACd,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAElD,IAAA,aAAM,EAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,KAAK,GAAG,IAAI,cAAU,EAAc,CAAC;QAC3C,MAAM,IAAI,GAA8B,EAAE,CAAC;QAC3C,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CACxB,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAA,wBAAoB,GAAE,CAAC,CAAC,CACxD,CAAC;QAEF,QAAQ,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAErD,IAAA,aAAM,EAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,MAAM,KAAK,GAAG,IAAI,cAAU,EAAc,CAAC;QAC3C,MAAM,IAAI,GAA8B,EAAE,CAAC;QAC3C,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAA,wBAAoB,GAAE,CAAC,CAAC,CAAC;QAExD,QAAQ,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAErD,IAAA,aAAM,EAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uGAAuG,EAAE,KAAK,IAAI,EAAE;QACrH,MAAM,KAAK,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC/C,IAAI,SAAuC,CAAC;QAC5C,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CACxB,KAAK,CAAC,UAAU,CACd,GAAG,EAAE,CAAC,SAAS,EACf,GAAG,EAAE;YACH,SAAS,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAClC,YAAY,CAAC,GAAG,EAAE;oBAChB,IAAI,CAAC;wBACH,IAAA,8BAAoB,EAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;wBAC5D,OAAO,CAAC,SAAS,CAAC,CAAC;oBACrB,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,CAAC,KAAK,CAAC,CAAC;oBACjB,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CACF,CAAC;QACF,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAEnD,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAEpB,IAAA,aAAM,EAAC,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,aAAa;QACrB,KAAK,EAAE,wBAAwB;QAC/B,IAAI,EAAE,WAAoB;KAC3B,CAAC;IAEF,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,KAAK,GAAG,IAAI,cAAU,EAAc,CAAC;QAC3C,MAAM,OAAO,GAA8B,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAA,8BAAoB,EAAC,SAAS,EAAE,GAAG,EAAE;YACjD,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAA,wBAAoB,GAAE,CAAC,CAAC,CAAC;YAC3D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAA,0BAAgB,GAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAErD,IAAA,aAAM,EAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAA,aAAM,EAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0FAA0F,EAAE,KAAK,IAAI,EAAE;QACxG,MAAM,IAAI,GAAG,IAAI,cAAU,EAA4B,CAAC;QACxD,MAAM,QAAQ,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAClD,MAAM,CAAC,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACvC,IAAA,8BAAoB,EAClB,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAC/C,GAAG,EAAE;YACH,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,wBAAoB,GAAE,CAAC,CAAC;YAC1C,QAAQ,CAAC,UAAU,CACjB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,EAC7B,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC,CAChC,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,IAAA,aAAM,EAAC,MAAM,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpE,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACnD,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QAE5C,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpB,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uGAAuG,EAAE,KAAK,IAAI,EAAE;QACrH,MAAM,IAAI,GAAG,IAAI,cAAU,EAA4B,CAAC;QACxD,MAAM,CAAC,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAEzD,IAAA,8BAAoB,EAAC,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,GAAG,EAAE,CACzE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;YACf,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACrB,OAAO,IAAA,wBAAoB,GAAE,CAAC;QAChC,CAAC,CAAC,CACH,CAAC;QAEF,IAAA,aAAM,EAAC,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACrB,IAAA,aAAM,EAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,IAAI,GAAG,IAAI,cAAU,EAA4B,CAAC;QACxD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAE5B,IAAA,8BAAoB,EAAC,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,GAAG,EAAE,CACzE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAA,wBAAoB,GAAE,CAAC,CAC1C,CAAC;QAEF,IAAA,aAAM,EAAC,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,MAAM,GAAG,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAClD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;QACpC,MAAM,KAAK,GAAG,sBAAsB,CAAC;QACrC,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5C,cAAc,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAChD,IAAA,8BAAoB,EAAC,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CACjD,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAChC,CAAC;QACF,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QAE1D,IAAA,sBAAY,EAAC,KAAK,CAAC,CAAC;QAEpB,IAAA,aAAM,EAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAA,aAAM,EAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,MAAM,KAAK;KAAG;IACd,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC;IAChC,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC;IACxB,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAE/C,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,KAAK,GAAG,IAAI,cAAU,EAAuC,CAAC;QACpE,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEpE,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;QAE1E,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,IAAA,aAAM,EAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,KAAK,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC/C,IAAI,QAAQ,GAAc,EAAE,CAAC;QAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CACzB,KAAK,CAAC,UAAU,CACd,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE;YACf,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC,EACD,GAAG,EAAE,CAAC,SAAS,CAChB,CACF,CAAC;QAEF,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;QAE5D,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,IAAA,aAAM,EAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,KAAK,GAAG,IAAI,cAAU,EAA4B,CAAC;QACzD,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1D,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEtD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEnB,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnC,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;IAC3D,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,KAAK,GAAG,IAAI,cAAU,EAAgB,CAAC;QAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,IAAI,CAAC,OAAO,CAAC;YACnB,OAAO,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACrB,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,IAAA,aAAM,EAAC,MAAM,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,iCAA6B,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,KAAK,GAAG,IAAI,oBAAgB,EAAY,CAAC;QAC/C,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,IAAI,CAAC,OAAO,CAAC;YACnB,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACrB,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,IAAA,aAAM,EAAC,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAC/C,iCAA6B,CAC9B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,8 +1,21 @@
1
- # Interface Core Documentation
1
+ # Connect modules through interfaces
2
2
 
3
3
  ## Overview
4
4
 
5
- `@antelopejs/interface-core` provides the foundational building blocks for the AntelopeJS interface system. It defines the core primitives that enable type-safe, module-aware communication between decoupled components.
5
+ `@antelopejs/interface-core` lets one module call a contract implemented by another. The caller imports the interface rather than the provider, so the runtime can connect modules and replace a provider without changing the caller's imports.
6
+
7
+ If you only need application logs, start with [logging](./6.logging.md). If you are using HTTP routes or authentication, start with those interfaces; you do not need to build a proxy first.
8
+
9
+ ## Start with your role
10
+
11
+ | You are… | Start here | You own… |
12
+ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- |
13
+ | Calling an existing interface | Its package documentation, then [connection lookup](./2.proxies.md#getinterfaceinstances-and-getinterfaceinstance) | The consuming module and its provider binding. |
14
+ | Defining a new contract | [How interfaces work](#how-interfaces-work), then [proxies](./2.proxies.md) | Typed declarations shared by consumers and providers. |
15
+ | Implementing a contract | [`ImplementInterface`](./2.proxies.md#implementinterface) | Every declared function and registration callback. |
16
+ | Integrating a module loader | [Runtime](./8.runtime.md) and [module lifecycle](./5.modules.md) | Ownership contexts, generations, and cleanup. |
17
+
18
+ Application modules normally import an existing interface rather than construct proxies themselves. The AntelopeJS runtime supplies module context and connections; these primitives do not configure a project or choose a provider for you.
6
19
 
7
20
  The package exports several key categories of functionality:
8
21
 
@@ -70,7 +83,17 @@ ImplementInterface(UserInterface, {
70
83
  });
71
84
  ```
72
85
 
73
- The proxy system ensures that calls to `GetUser` before the implementation is attached are automatically queued and resolved once the implementation becomes available. When the implementing module is unloaded, the proxy detaches and resumes queuing.
86
+ The proxy queues calls to `GetUser` until an implementation attaches. When the implementing module unloads, the proxy detaches and queues new calls again. The queue is bounded (1,000 pending calls by default), and test stub mode rejects missing providers instead of waiting. See [proxy failure modes](./2.proxies.md#other-public-errors) before relying on this behavior during startup.
87
+
88
+ ## Choose a communication primitive
89
+
90
+ | Need | Primitive | Without an attached provider or listener |
91
+ | ------------------------------------------ | ---------------------------------- | --------------------------------------------------------- |
92
+ | Ask for a result | `InterfaceFunction` / `AsyncProxy` | Calls queue, subject to the queue limit and stub mode. |
93
+ | Notify current listeners | `EventProxy` | Emissions are not retained for future listeners. |
94
+ | Keep declarations available across reloads | `RegisteringProxy` | Entries remain available for replay when handlers attach. |
95
+
96
+ Do not use an event for a registration that a replacement provider must recover. Use the registering proxy's paired `onHandlers` attachment when replay needs both registration and unregistration callbacks.
74
97
 
75
98
  ## Next steps
76
99
 
@@ -78,3 +101,6 @@ The proxy system ensures that calls to `GetUser` before the implementation is at
78
101
  - [Decorators](./3.decorators.md) - Build type-safe decorator factories
79
102
  - [Modules](./5.modules.md) - Understand module lifecycle events
80
103
  - [Logging](./6.logging.md) - Use the structured logging system
104
+ - [Metadata](./4.metadata.md) - Read inherited metadata
105
+ - [Configuration](./7.configuration.md) - Define project configuration
106
+ - [Runtime](./8.runtime.md) - Integrate ownership and loader behavior
package/docs/2.proxies.md CHANGED
@@ -2,9 +2,23 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- Proxies are the backbone of cross-module communication in AntelopeJS. They provide module-aware abstractions for function calls, event handling, and registration patterns. Each proxy type automatically tracks the module that attaches callbacks and detaches them when that module is unloaded, preventing memory leaks and dangling references.
5
+ Choose a proxy by what must survive a provider change: a pending call, nothing from a past event, or a retained registration. The proxy tracks module ownership so the runtime can remove that module's callbacks and registrations when it is destroyed. You still own resources such as sockets and timers created by those callbacks.
6
6
 
7
- A proxy has a single provider and keeps its state on the proxy object itself. When a project has several providers of one interface, the core evaluates a separate instance of the interface package for each provider, so each instance's proxies reach exactly one provider; no call selects a provider at run time.
7
+ An async or registering proxy has one provider attachment; an event proxy has multiple listeners. State lives on each proxy object. When a project has several providers of one interface, the core evaluates a separate instance of the interface package for each provider, so each instance's calls reach one provider; no call selects a provider at run time.
8
+
9
+ For an ordinary request/response contract, start with [`InterfaceFunction`](#interfacefunction) and [`ImplementInterface`](#implementinterface). Direct attachment, leases, and ownership contexts below are for provider or loader authors who need lifecycle control.
10
+
11
+ ## Read the lifecycle before choosing a proxy
12
+
13
+ ![Async calls wait for a provider, events reach only current listeners, and registrations remain available for replay after provider replacement.](./assets/proxy-lifecycles.svg){width="480"}
14
+
15
+ | Situation | Async call | Event | Registration |
16
+ | ------------------ | ---------------------- | --------------------------------------- | -------------------------------------------------------------------- |
17
+ | No attachment | Queues up to the limit | No listener receives it | Entry is retained |
18
+ | Attachment arrives | Pending calls run | Future emissions reach listeners | Stored entries replay |
19
+ | Attachment leaves | New calls queue again | Removed listener stops receiving events | Entries remain until explicitly removed or their owner is cleaned up |
20
+
21
+ This table describes normal runtime behavior. [Test stub mode](#missingprovidererror) rejects missing providers. Detaching an async callback does not cancel work already running; detaching registration callbacks does not release provider resources.
8
22
 
9
23
  ## `AsyncProxy`
10
24
 
@@ -20,7 +34,7 @@ const proxy = new AsyncProxy<(name: string) => string>();
20
34
  // Calls made before attachment are queued
21
35
  const result = proxy.call("Alice"); // returns Promise<string>
22
36
 
23
- // Attach an implementation - queued calls resolve immediately
37
+ // Attach an implementation - queued calls now invoke it
24
38
  proxy.onCall((name: string) => {
25
39
  return `Hello, ${name}!`;
26
40
  });
@@ -33,23 +47,41 @@ const greeting = await proxy.call("Bob"); // "Hello, Bob!"
33
47
 
34
48
  Attaches the provider's callback to the proxy, replacing any callback attached before, so a provider's new generation takes over from the old one. The proxy automatically tracks the calling module and detaches the callback when that module is unloaded; releasing an older generation never detaches a newer one. Pass `manualDetach: true` to disable automatic cleanup.
35
49
 
36
- When attachment occurs inside `RunWithModuleContext`, calls execute in the captured provider context rather than the consumer context. The captured module and owner generation remain available across nested calls and `await`. Calls reject with `ModuleContextInvalidatedError` if the captured owner has been destroyed.
50
+ The callback runs in the context it was attached in, the provider's, whichever module calls: `GetModuleContext` reports the provider, across nested calls and `await`, and what the callback registers belongs to the provider. A callback attached in an interface package's own context runs in the caller's context instead (see [Ownership](#ownership)).
37
51
 
38
52
  ```ts
39
53
  // Automatic cleanup (default) - detaches when the module unloads
40
54
  proxy.onCall(myHandler);
41
55
 
42
- // Manual cleanup - you are responsible for calling detach()
43
- proxy.onCall(myHandler, true);
56
+ // Manual cleanup - retain the lease for generation-safe detachment
57
+ const lease = proxy.onCall(myHandler, true);
58
+ // Later:
59
+ proxy.detach(lease);
44
60
  ```
45
61
 
62
+ `onCall` returns an `AttachmentLease` with `owner: string` and `generation: number`. Keep this handle unchanged and pass it to `detach(lease)` to remove only that attachment. A stale lease cannot detach a replacement provider. Import the type from `@antelopejs/interface-core/proxies`; it is not re-exported from the package root.
63
+
64
+ ```ts docs-check
65
+ import { AsyncProxy } from "@antelopejs/interface-core";
66
+ import type { AttachmentLease } from "@antelopejs/interface-core/proxies";
67
+
68
+ const proxy = new AsyncProxy<() => string>("greeting");
69
+ const oldLease: AttachmentLease = proxy.onCall(() => "old", true);
70
+ const currentLease = proxy.onCall(() => "current", true);
71
+ proxy.detach(oldLease); // The current provider stays attached.
72
+ const greeting: string = await proxy.call(); // "current"
73
+ proxy.detach(currentLease);
74
+ ```
75
+
76
+ Manual detachment disables automatic attachment cleanup only. A callback attached by a generation that is later destroyed still runs when invoked, in that generation's context, so reading the module context or registering from inside it throws `ModuleContextInvalidatedError`.
77
+
46
78
  ### `call(...args)`
47
79
 
48
- Invokes the attached callback. If no callback is attached, the call returns a `Promise` that resolves once a callback is provided. In test stub mode, unattached calls reject with a [`MissingProviderError`](#missingprovidererror).
80
+ Invokes the attached callback. If no callback is attached, the call returns a `Promise` that resolves once a callback is provided; the queued call then runs as if it had just been made, and rejects with `ModuleContextInvalidatedError` if the caller's generation was destroyed in the meantime. A call made from a destroyed generation rejects with `ModuleContextInvalidatedError`. In test stub mode, unattached calls reject with a [`MissingProviderError`](#missingprovidererror).
49
81
 
50
82
  ### `detach()`
51
83
 
52
- Manually removes the attached callback. After detaching, subsequent calls are queued again.
84
+ `detach()` removes the current callback unconditionally; `detach(lease)` removes it only when the lease matches. After detaching, subsequent calls are queued again. Detaching does not cancel calls already executing.
53
85
 
54
86
  ## `InterfaceFunction`
55
87
 
@@ -66,7 +98,9 @@ const GetUser =
66
98
  const user = await GetUser("user-123");
67
99
  ```
68
100
 
69
- The returned function has a `.proxy` property that exposes the underlying `AsyncProxy` for direct access when needed.
101
+ The typed return value is `(...args: Parameters<T>) => Promise<R>`, where `R` defaults to `Awaited<ReturnType<T>>`. Supply an optional identity string as `InterfaceFunction<T>("name")` for diagnostics.
102
+
103
+ The implementation attaches a `.proxy` property at runtime, but the declared return type does not expose it. Use `ImplementInterface({ GetUser }, { GetUser: handler })` for typed provider wiring. When you need direct attachment and lease control, construct an `AsyncProxy` as shown above instead of accessing `.proxy` on an interface function.
70
104
 
71
105
  ## `EventProxy`
72
106
 
@@ -90,11 +124,11 @@ onUserCreated.emit("u-1", "Alice");
90
124
 
91
125
  ### `register(func)`
92
126
 
93
- Registers a handler for the event. Duplicate handlers (same function reference) are ignored. The proxy tracks the calling module and removes the handler when that module is unloaded. The handler runs in the context of the module that registered it, whichever module emits the event.
127
+ Registers a handler for the event. Duplicate handlers (same function reference) are ignored. The proxy tracks the calling module and removes the handler when that module is unloaded. The handler runs in the context it was registered in, whichever module emits the event. A handler registered outside any context runs in the emitter's context.
94
128
 
95
129
  ### `emit(...args)`
96
130
 
97
- Calls all registered handlers with the provided arguments.
131
+ Calls all registered handlers synchronously with the provided arguments. Synchronous exceptions are reported through the runtime's error reporter without preventing later handlers from running. Emission does not await returned promises; asynchronous handlers must handle their own rejections.
98
132
 
99
133
  ### `unregister(func)`
100
134
 
@@ -117,51 +151,72 @@ const routeRegistry = new RegisteringProxy<
117
151
  routeRegistry.register("home", "/", homeHandler);
118
152
  routeRegistry.register("about", "/about", aboutHandler);
119
153
 
120
- // Attach callbacks - queued registrations replay immediately
121
- routeRegistry.onRegister((id, path, handler) => {
122
- router.addRoute(path, handler);
123
- });
124
-
125
- routeRegistry.onUnregister((id) => {
126
- router.removeRoute(id);
127
- });
154
+ // Install both callbacks before replaying stored registrations.
155
+ const lease = routeRegistry.onHandlers(
156
+ (id, path, handler) => router.addRoute(path, handler),
157
+ (id) => router.removeRoute(id),
158
+ );
128
159
 
129
160
  // Unregister by ID
130
161
  routeRegistry.unregister("about");
131
162
  ```
132
163
 
164
+ ### `onHandlers(register, unregister, manualDetach?)`
165
+
166
+ Attaches both callbacks under one lease before replaying stored registrations. Prefer this operation when replacing a provider: replay can safely call `unregister` because the matching unregister callback is already installed. It returns an `AttachmentLease` for both callbacks. `ImplementInterface` uses this operation for registering proxies.
167
+
168
+ Replay reports synchronous registration failures and continues to the next stored entry. This is not a transaction or a rollback of provider side effects. Direct `register` calls propagate synchronous callback failures to the caller.
169
+
133
170
  ### `onRegister(callback, manualDetach?)`
134
171
 
135
- Attaches the register callback. Any previously registered entries replay through this callback immediately. Automatic module-aware detachment applies unless `manualDetach` is `true`.
172
+ Attaches only the register callback and returns its own lease. Any previously registered entries replay through this callback immediately. Automatic module-aware detachment applies unless `manualDetach` is `true`. An existing unregister callback remains attached.
136
173
 
137
- Register replay and direct registration execute in the provider context captured when the callback attaches.
174
+ Direct registration and replay run in the context the callback was attached in, the provider's.
138
175
 
139
176
  ### `onUnregister(callback)`
140
177
 
141
- Attaches the unregister callback. This callback is detached at the same time as the register callback.
178
+ Attaches only the unregister callback and returns a separate lease. It shares the owner and manual-detach setting of an existing attachment belonging to the active owner when available. Without an explicit context, it uses the existing unregister attachment, then the register attachment, if present. Otherwise it resolves ownership normally and enables automatic cleanup. It does not replay registrations or replace the register callback.
142
179
 
143
- Unregistration executes in the context captured when this callback attaches.
180
+ Unregistration runs in the context this callback was attached in, also when it is triggered by the release of the module that registered the entry.
144
181
 
145
182
  ### `register(id, ...args)`
146
183
 
147
- Registers an entry with the given identifier. If a register callback is attached, it executes immediately. Otherwise, the entry is stored and replayed when a callback is attached. The calling module is tracked for automatic cleanup.
184
+ Registers an entry with the given identifier. If a register callback is attached, it executes immediately. Otherwise, the entry is stored and replayed when a callback is attached. The calling module is tracked for automatic cleanup. Registering the same ID replaces the stored arguments and ownership and calls the register callback again; it does not first call unregister. Registering from a destroyed generation throws `ModuleContextInvalidatedError`.
148
185
 
149
186
  ### `unregister(id)`
150
187
 
151
- Removes the entry with the given identifier and calls the unregister callback if one is attached.
188
+ Removes the entry with the given identifier and calls the unregister callback if one is attached. Unknown IDs are ignored. The stored entry is removed even if the callback throws.
152
189
 
153
190
  ### `detach()`
154
191
 
155
- Manually removes both the register and unregister callbacks. Registered entries remain stored.
192
+ `detach()` removes both callbacks. `detach(lease)` removes only callbacks matching the lease: both for `onHandlers`, or one for separate `onRegister`/`onUnregister` attachments. Registered entries remain stored for replay; detaching callbacks does not unregister provider resources.
193
+
194
+ ### Ownership cleanup
195
+
196
+ `RegisteringProxy` and `EventProxy` expose `unregisterModule(module)` and `unregisterOwner(owner)` to remove entries for a whole module or one generation. Normal module destruction invokes owner cleanup automatically; application consumers usually need only `unregister(id)` or `unregister(handler)`.
197
+
198
+ ## Proxy identity helpers
199
+
200
+ All three proxy constructors accept an optional identity string. `GetInterfaceProxyIdentity(proxy)` returns a diagnostic identity prefixed by the proxy kind, for example `"async:greeting"`. Without an explicit name, the runtime generates an anonymous identity. Non-proxy values return `undefined`.
201
+
202
+ `IsInterfaceProxy(value, kind?)` checks the shared runtime protocol brand, optionally restricted to `"async"`, `"registering"`, or `"event"`. It works across compatible package copies where `instanceof` is unreliable, but returns a boolean rather than narrowing a TypeScript type. Both helpers operate on proxy objects, not on the callable return value of `InterfaceFunction`.
156
203
 
157
- ## Functions passed through a proxy
204
+ ## Ownership
158
205
 
159
- A function a module hands to a proxy runs as that module's work, whoever invokes it later:
206
+ Proxies track ownership so that hot reload can detach and unregister everything a module generation left behind. The owner of an attachment, a registration or an event handler is the nearest module in the chain of work that made it, read from the async module context:
160
207
 
161
- - an event handler runs in the context of the module that registered it;
162
- - a function passed as an argument to `AsyncProxy.call` or `RegisteringProxy.register`, or held in a plain object or array passed that way, runs in the context of the module that made the call.
208
+ - **A module owns its own work**, including what it registers while serving another module's call. A provider callback runs in the provider's context, so when module A calls B and B's provider registers on C, the entry on C is B's: reloading B removes it, destroying A does not.
209
+ - **A module that forwards registrations declares a `RegisteringProxy`.** When A registers on B and B's provider forwards to C, B's next generation receives A's entry again through replay and forwards it again. When A is destroyed, its entry on B is unregistered and B's unregister callback removes the one on C.
210
+ - **Interface package code is never an owner.** Functions an interface package exports run in their caller's context, so what they forward is the caller's.
211
+ - **An interface package owns what it needs in order to work.** The core evaluates each interface package in a context of its own, of kind `"interface"`, whose owner is released only when the core discards that interface instance, never on a module reload. Code at the package's top level, and the timers, promises and event handlers it creates, run in that context. A provider callback attached there is the exception: it only carries calls and registrations forward on a caller's behalf, so it runs in the caller's context.
163
212
 
164
- Inside such a function, `GetModuleContext` and `GetResponsibleModule` report the module that passed it, and what it registers is owned by that module. Once that module's generation is destroyed, invoking the function throws `ModuleContextInvalidatedError`. Plain data, classes, class instances and proxies cross unchanged, so a class keeps the identity its metadata and registries are keyed by; a function passed twice reaches the provider as the same value, and a function passed on by another module keeps its original context.
213
+ Values cross unchanged: arguments to `AsyncProxy.call`, `RegisteringProxy.register` and `EventProxy.emit` reach the other side as the very same values, so a class keeps the identity its metadata and registries are keyed by, and a function can be unregistered by reference.
214
+
215
+ ### Limits
216
+
217
+ - A function passed as an argument and invoked later by the provider runs in the context of whoever invokes it, and what it registers belongs to that module. Callbacks that outlive the call belong in a `RegisteringProxy` entry, not in `AsyncProxy.call` arguments.
218
+ - Work an interface package starts lazily, from inside a function it exports rather than from its top level, belongs to the module that called first.
219
+ - The core enters an interface package's context only for packages loaded through `require()`. A package reached through an ECMAScript `import` is evaluated in its importer's context, so its top-level work belongs to that importer.
165
220
 
166
221
  ## `ImplementInterface`
167
222
 
@@ -200,6 +255,8 @@ ImplementInterface(ItemInterface, {
200
255
 
201
256
  `EventProxy` entries in the declaration are skipped during implementation wiring, as they are emitted from the declaring side, not implemented.
202
257
 
258
+ The synchronous overload returns `{ declaration, implementation }`. Every declared async proxy needs a function, and every registering proxy needs both `register` and `unregister`, even though the implementation type permits optional keys. Missing or malformed handlers, non-object arguments, and object cycles throw `TypeError`. Validation happens before attachment, but provider callback effects during attachment are not rolled back. Promise-like arguments use a deprecated asynchronous overload; prefer the synchronous form.
259
+
203
260
  ## `MissingProviderError`
204
261
 
205
262
  In test stub mode, using a proxy that has no provider attached fails with a `MissingProviderError`: `AsyncProxy.call` rejects with it and `RegisteringProxy.register` throws it.
@@ -222,6 +279,16 @@ try {
222
279
 
223
280
  Prefer the `isMissingProviderError` guard over `instanceof`: it checks the `code` property, so detection keeps working across realm boundaries and duplicated copies of the package where `instanceof` fails.
224
281
 
282
+ ## Other public errors
283
+
284
+ Errors are exported from the package root. Use their stable `code` values rather than parsing messages.
285
+
286
+ | Error | Code constant | Code value | When it applies |
287
+ | ------------------------------- | --------------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
288
+ | `ProviderQueueFullError` | `PROVIDER_QUEUE_FULL_CODE` | `ERR_PROVIDER_QUEUE_FULL` | An unattached async proxy reaches its pending-call limit (1,000 by default). |
289
+ | `ModuleContextInvalidatedError` | `MODULE_CONTEXT_INVALIDATED_CODE` | `ERR_MODULE_CONTEXT_INVALIDATED` | Work tries to use a destroyed ownership context. |
290
+ | `AmbiguousProviderError` | `AMBIGUOUS_PROVIDER_CODE` | `ERR_AMBIGUOUS_PROVIDER` | Exported to represent ambiguous provider routing. The current single-provider proxy classes do not themselves throw it or select between providers. |
291
+
225
292
  ## `GetInterfaceInstances` and `GetInterfaceInstance`
226
293
 
227
294
  These functions retrieve information about active interface connections for the current module.
@@ -254,7 +321,7 @@ Requiring a connection's `path` (or a subpath of it) gives the interface bound t
254
321
 
255
322
  ## `GetResponsibleModule`
256
323
 
257
- `GetResponsibleModule` inspects the call stack to determine which module is responsible for the current execution. The proxy classes use this internally for automatic cleanup tracking.
324
+ `GetResponsibleModule` returns the module of the active async module context, or `undefined` outside any context. It never inspects the call stack.
258
325
 
259
326
  ```ts
260
327
  import { GetResponsibleModule } from "@antelopejs/interface-core";
@@ -262,11 +329,9 @@ import { GetResponsibleModule } from "@antelopejs/interface-core";
262
329
  const moduleId = GetResponsibleModule();
263
330
  ```
264
331
 
265
- > **Warning:** Calling `GetResponsibleModule` from within an async context (such as `setTimeout` or `setInterval`) without explicit ownership breaks hot reloading. The system logs an error when this is detected.
266
-
267
332
  ## `RunWithResponsibleModule`
268
333
 
269
- `RunWithResponsibleModule` sets the responsible module explicitly for synchronous and asynchronous work. Proxy registrations made in the callback use this module directly instead of capturing and walking a stack. Nested contexts restore their parent when they complete, including when a callback throws.
334
+ `RunWithResponsibleModule` sets the responsible module explicitly for synchronous and asynchronous work. Proxy registrations made in the callback are owned by this module. Nested contexts restore their parent when they complete, including when a callback throws.
270
335
 
271
336
  ```ts
272
337
  import { RunWithResponsibleModule } from "@antelopejs/interface-core";
@@ -277,7 +342,7 @@ await RunWithResponsibleModule("my-module", async () => {
277
342
  });
278
343
  ```
279
344
 
280
- The module loader should wrap known module-owned entry points, including module evaluation and lifecycle hooks. Existing callers need no migration: outside an explicit context, `GetResponsibleModule` retains stack-based resolution as a backward-compatible fallback. Automatic proxy detachment and registration cleanup use the resolved module in both paths.
345
+ The module loader wraps every module-owned entry point, including module evaluation and lifecycle hooks. Work done outside any context has no owner: its attachments belong to a default owner that no module release removes, and its registrations are never released by owner.
281
346
 
282
347
  Ownership contexts are scoped to a loaded module generation. Loaders that can overlap old and replacement instances should use `RunWithModuleContext` and provide a unique `owner` for every generation. `ModuleDestroyed` invalidates and cleans only the active event context's owner while preserving the existing module ID event contract. Detached asynchronous work from that owner then receives a `ModuleContextInvalidatedError`.
283
348