@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.
- package/README.md +86 -17
- package/dist/index.d.ts +4 -1
- package/dist/index.js +0 -13
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +14 -2
- package/dist/internal.js +17 -1
- package/dist/internal.js.map +1 -1
- package/dist/modules.d.ts +3 -2
- package/dist/modules.js.map +1 -1
- package/dist/proxies.d.ts +25 -7
- package/dist/proxies.js +89 -79
- package/dist/proxies.js.map +1 -1
- package/dist/tests/module-ownership-context.test.js +3 -3
- package/dist/tests/module-ownership-context.test.js.map +1 -1
- package/dist/tests/ownership-call-chain.test.js +261 -0
- package/dist/tests/ownership-call-chain.test.js.map +1 -0
- package/docs/1.introduction.md +29 -3
- package/docs/2.proxies.md +101 -36
- package/docs/3.decorators.md +25 -1
- package/docs/4.metadata.md +25 -1
- package/docs/5.modules.md +26 -7
- package/docs/6.logging.md +42 -20
- package/docs/7.configuration.md +33 -12
- package/docs/8.runtime.md +15 -0
- package/docs/assets/proxy-lifecycles.svg +21 -0
- package/docs/tsconfig.json +16 -0
- package/package.json +11 -4
- package/skills/core-interface/SKILL.md +3 -4
- package/dist/caller-binding.d.ts +0 -12
- package/dist/caller-binding.js +0 -105
- package/dist/caller-binding.js.map +0 -1
- package/dist/responsible-module.d.ts +0 -23
- package/dist/responsible-module.js +0 -56
- package/dist/responsible-module.js.map +0 -1
- package/dist/tests/caller-context.test.js +0 -154
- package/dist/tests/caller-context.test.js.map +0 -1
- package/dist/tests/provider-context.test.d.ts +0 -1
- package/dist/tests/provider-context.test.js +0 -109
- package/dist/tests/provider-context.test.js.map +0 -1
- package/dist/tests/responsible-module.test.d.ts +0 -1
- package/dist/tests/responsible-module.test.js +0 -109
- package/dist/tests/responsible-module.test.js.map +0 -1
- /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":"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"}
|
package/docs/1.introduction.md
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Connect modules through interfaces
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
`@antelopejs/interface-core`
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
{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
|
|
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
|
-
|
|
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 -
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
//
|
|
121
|
-
routeRegistry.
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
##
|
|
204
|
+
## Ownership
|
|
158
205
|
|
|
159
|
-
|
|
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
|
-
-
|
|
162
|
-
- a
|
|
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
|
-
|
|
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`
|
|
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
|
|
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
|
|
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
|
|