@labostack/typebridge 0.1.0
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 +62 -0
- package/dist/adapters/decorators.d.ts +11 -0
- package/dist/adapters/decorators.d.ts.map +1 -0
- package/dist/adapters/decorators.js +20 -0
- package/dist/adapters/decorators.js.map +1 -0
- package/dist/adapters/deepkit-adapter.d.ts +11 -0
- package/dist/adapters/deepkit-adapter.d.ts.map +1 -0
- package/dist/adapters/deepkit-adapter.js +39 -0
- package/dist/adapters/deepkit-adapter.js.map +1 -0
- package/dist/adapters/generic-adapter.d.ts +12 -0
- package/dist/adapters/generic-adapter.d.ts.map +1 -0
- package/dist/adapters/generic-adapter.js +28 -0
- package/dist/adapters/generic-adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +5 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/nest-adapter.d.ts +14 -0
- package/dist/adapters/nest-adapter.d.ts.map +1 -0
- package/dist/adapters/nest-adapter.js +33 -0
- package/dist/adapters/nest-adapter.js.map +1 -0
- package/dist/adapters/tsed-adapter.d.ts +10 -0
- package/dist/adapters/tsed-adapter.d.ts.map +1 -0
- package/dist/adapters/tsed-adapter.js +31 -0
- package/dist/adapters/tsed-adapter.js.map +1 -0
- package/dist/autobarrel/index.d.ts +2 -0
- package/dist/autobarrel/index.d.ts.map +1 -0
- package/dist/autobarrel/index.js +2 -0
- package/dist/autobarrel/index.js.map +1 -0
- package/dist/autobarrel/scanner.d.ts +14 -0
- package/dist/autobarrel/scanner.d.ts.map +1 -0
- package/dist/autobarrel/scanner.js +93 -0
- package/dist/autobarrel/scanner.js.map +1 -0
- package/dist/bridge.d.ts +54 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +151 -0
- package/dist/bridge.js.map +1 -0
- package/dist/discovery/dns.d.ts +10 -0
- package/dist/discovery/dns.d.ts.map +1 -0
- package/dist/discovery/dns.js +19 -0
- package/dist/discovery/dns.js.map +1 -0
- package/dist/discovery/index.d.ts +4 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +4 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/mdns.d.ts +18 -0
- package/dist/discovery/mdns.d.ts.map +1 -0
- package/dist/discovery/mdns.js +49 -0
- package/dist/discovery/mdns.js.map +1 -0
- package/dist/discovery/resolver.d.ts +16 -0
- package/dist/discovery/resolver.d.ts.map +1 -0
- package/dist/discovery/resolver.js +36 -0
- package/dist/discovery/resolver.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/mesh/index.d.ts +2 -0
- package/dist/mesh/index.d.ts.map +1 -0
- package/dist/mesh/index.js +2 -0
- package/dist/mesh/index.js.map +1 -0
- package/dist/mesh/mesh-manager.d.ts +55 -0
- package/dist/mesh/mesh-manager.d.ts.map +1 -0
- package/dist/mesh/mesh-manager.js +179 -0
- package/dist/mesh/mesh-manager.js.map +1 -0
- package/dist/proxy/client-proxy.d.ts +20 -0
- package/dist/proxy/client-proxy.d.ts.map +1 -0
- package/dist/proxy/client-proxy.js +69 -0
- package/dist/proxy/client-proxy.js.map +1 -0
- package/dist/proxy/index.d.ts +2 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +2 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/reflection/extractor.d.ts +13 -0
- package/dist/reflection/extractor.d.ts.map +1 -0
- package/dist/reflection/extractor.js +62 -0
- package/dist/reflection/extractor.js.map +1 -0
- package/dist/reflection/index.d.ts +2 -0
- package/dist/reflection/index.d.ts.map +1 -0
- package/dist/reflection/index.js +2 -0
- package/dist/reflection/index.js.map +1 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +2 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/method-registry.d.ts +56 -0
- package/dist/registry/method-registry.d.ts.map +1 -0
- package/dist/registry/method-registry.js +84 -0
- package/dist/registry/method-registry.js.map +1 -0
- package/dist/serialization/error-ext.d.ts +38 -0
- package/dist/serialization/error-ext.d.ts.map +1 -0
- package/dist/serialization/error-ext.js +76 -0
- package/dist/serialization/error-ext.js.map +1 -0
- package/dist/serialization/index.d.ts +4 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/serialization/index.js +3 -0
- package/dist/serialization/index.js.map +1 -0
- package/dist/serialization/msgpack.d.ts +30 -0
- package/dist/serialization/msgpack.d.ts.map +1 -0
- package/dist/serialization/msgpack.js +76 -0
- package/dist/serialization/msgpack.js.map +1 -0
- package/dist/serialization/serializer.d.ts +15 -0
- package/dist/serialization/serializer.d.ts.map +1 -0
- package/dist/serialization/serializer.js +2 -0
- package/dist/serialization/serializer.js.map +1 -0
- package/dist/transport/client.d.ts +38 -0
- package/dist/transport/client.d.ts.map +1 -0
- package/dist/transport/client.js +57 -0
- package/dist/transport/client.js.map +1 -0
- package/dist/transport/connection.d.ts +57 -0
- package/dist/transport/connection.d.ts.map +1 -0
- package/dist/transport/connection.js +212 -0
- package/dist/transport/connection.js.map +1 -0
- package/dist/transport/constants.d.ts +2 -0
- package/dist/transport/constants.d.ts.map +1 -0
- package/dist/transport/constants.js +2 -0
- package/dist/transport/constants.js.map +1 -0
- package/dist/transport/framing.d.ts +54 -0
- package/dist/transport/framing.d.ts.map +1 -0
- package/dist/transport/framing.js +107 -0
- package/dist/transport/framing.js.map +1 -0
- package/dist/transport/index.d.ts +7 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +7 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/peer-manager.d.ts +67 -0
- package/dist/transport/peer-manager.d.ts.map +1 -0
- package/dist/transport/peer-manager.js +172 -0
- package/dist/transport/peer-manager.js.map +1 -0
- package/dist/transport/server.d.ts +37 -0
- package/dist/transport/server.d.ts.map +1 -0
- package/dist/transport/server.js +88 -0
- package/dist/transport/server.js.map +1 -0
- package/dist/types/adapter.d.ts +33 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +2 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/types/descriptor.d.ts +35 -0
- package/dist/types/descriptor.d.ts.map +1 -0
- package/dist/types/descriptor.js +2 -0
- package/dist/types/descriptor.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/options.d.ts +55 -0
- package/dist/types/options.d.ts.map +1 -0
- package/dist/types/options.js +6 -0
- package/dist/types/options.js.map +1 -0
- package/dist/types/protocol.d.ts +94 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +43 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types/type-descriptor.d.ts +64 -0
- package/dist/types/type-descriptor.d.ts.map +1 -0
- package/dist/types/type-descriptor.js +2 -0
- package/dist/types/type-descriptor.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { TransportClient } from "../transport/client.js";
|
|
3
|
+
/**
|
|
4
|
+
* MeshManager — automatic peer discovery, connection, and controller routing.
|
|
5
|
+
*
|
|
6
|
+
* Each TypeBridge node has a MeshManager that:
|
|
7
|
+
* 1. Browses for other nodes via mDNS
|
|
8
|
+
* 2. Auto-connects and exchanges catalogs
|
|
9
|
+
* 3. Maintains a routing table: controllerName → Connection
|
|
10
|
+
* 4. Routes method calls to the right peer
|
|
11
|
+
*/
|
|
12
|
+
export class MeshManager extends EventEmitter {
|
|
13
|
+
localName;
|
|
14
|
+
localRegistry;
|
|
15
|
+
/** peerName → Connection */
|
|
16
|
+
peers = new Map();
|
|
17
|
+
/** controllerName → peerName */
|
|
18
|
+
routes = new Map();
|
|
19
|
+
/** Clients we created (for cleanup) */
|
|
20
|
+
clients = [];
|
|
21
|
+
/** mDNS browser stop handle */
|
|
22
|
+
stopBrowsing = null;
|
|
23
|
+
constructor(localName, localRegistry) {
|
|
24
|
+
super();
|
|
25
|
+
this.localName = localName;
|
|
26
|
+
this.localRegistry = localRegistry;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Start browsing for other TypeBridge nodes via mDNS.
|
|
30
|
+
*/
|
|
31
|
+
async startBrowsing() {
|
|
32
|
+
try {
|
|
33
|
+
const bonjourModule = await import("bonjour-service");
|
|
34
|
+
const Bonjour = bonjourModule.default ?? bonjourModule;
|
|
35
|
+
const bonjour = typeof Bonjour === "function" ? new Bonjour() : Bonjour;
|
|
36
|
+
const browser = bonjour.find({ type: "typebridge" });
|
|
37
|
+
browser.on("up", (service) => {
|
|
38
|
+
// Skip self
|
|
39
|
+
if (service.name === this.localName)
|
|
40
|
+
return;
|
|
41
|
+
// Skip already connected
|
|
42
|
+
if (this.peers.has(service.name))
|
|
43
|
+
return;
|
|
44
|
+
const host = service.addresses?.[0] ?? service.host ?? "127.0.0.1";
|
|
45
|
+
const port = service.port;
|
|
46
|
+
this.connectToPeer(service.name, host, port).catch(() => {
|
|
47
|
+
// Connection failed — will retry on next mDNS event
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
this.stopBrowsing = () => {
|
|
51
|
+
browser.stop();
|
|
52
|
+
bonjour.destroy();
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// mDNS not available — that's fine, peers can still connect to us
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Connect to a discovered peer, exchange catalogs.
|
|
61
|
+
*/
|
|
62
|
+
async connectToPeer(name, host, port) {
|
|
63
|
+
if (this.peers.has(name))
|
|
64
|
+
return; // already connected
|
|
65
|
+
const client = new TransportClient({ host, port });
|
|
66
|
+
this.clients.push(client);
|
|
67
|
+
const connection = await client.connect();
|
|
68
|
+
// Send handshake WITH our catalog
|
|
69
|
+
connection.sendHandshake({
|
|
70
|
+
name: this.localName,
|
|
71
|
+
version: 1,
|
|
72
|
+
catalog: this.localRegistry.toCatalog(),
|
|
73
|
+
});
|
|
74
|
+
// Wait for handshake ack with their catalog
|
|
75
|
+
const peerCatalog = await new Promise((resolve, reject) => {
|
|
76
|
+
const timer = setTimeout(() => reject(new Error("Handshake timeout")), 10_000);
|
|
77
|
+
connection.on("handshake-ack", (data) => {
|
|
78
|
+
clearTimeout(timer);
|
|
79
|
+
resolve(data.catalog ?? {});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
// Register the peer
|
|
83
|
+
this.registerPeer(name, connection, peerCatalog);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Register an incoming peer (called from server-side handshake handler).
|
|
87
|
+
*/
|
|
88
|
+
registerIncomingPeer(name, connection, catalog) {
|
|
89
|
+
if (this.peers.has(name))
|
|
90
|
+
return; // already connected
|
|
91
|
+
this.registerPeer(name, connection, catalog);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Register a peer and its controllers in the routing table.
|
|
95
|
+
*/
|
|
96
|
+
registerPeer(name, connection, catalog) {
|
|
97
|
+
this.peers.set(name, connection);
|
|
98
|
+
// Build routing table: controllerName → peerName
|
|
99
|
+
for (const controllerName of Object.keys(catalog)) {
|
|
100
|
+
this.routes.set(controllerName, name);
|
|
101
|
+
}
|
|
102
|
+
// Wire incoming requests (bidirectional — peer calls our controllers)
|
|
103
|
+
connection.on("request", async (reqId, method, args) => {
|
|
104
|
+
try {
|
|
105
|
+
const [controllerName, methodName] = method.split(".");
|
|
106
|
+
if (!controllerName || !methodName) {
|
|
107
|
+
throw new Error(`Invalid method format: "${method}"`);
|
|
108
|
+
}
|
|
109
|
+
const result = await this.localRegistry.invoke(controllerName, methodName, args);
|
|
110
|
+
connection.sendResponse(reqId, result);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
connection.sendError(reqId, error);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
// Handle disconnection — remove from routing table
|
|
117
|
+
connection.on("close", () => {
|
|
118
|
+
this.peers.delete(name);
|
|
119
|
+
for (const [ctrl, peer] of this.routes) {
|
|
120
|
+
if (peer === name)
|
|
121
|
+
this.routes.delete(ctrl);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
// Notify waiters that a new peer is available
|
|
125
|
+
this.emit("peer-available", name);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get the connection for a controller.
|
|
129
|
+
* If the controller isn't found yet, waits for discovery (with timeout).
|
|
130
|
+
*/
|
|
131
|
+
async getConnection(controllerName, timeout = 10_000) {
|
|
132
|
+
// Already known?
|
|
133
|
+
const peerName = this.routes.get(controllerName);
|
|
134
|
+
if (peerName) {
|
|
135
|
+
const conn = this.peers.get(peerName);
|
|
136
|
+
if (conn && conn.isOpen)
|
|
137
|
+
return conn;
|
|
138
|
+
}
|
|
139
|
+
// Wait for a peer with this controller to appear
|
|
140
|
+
return new Promise((resolve, reject) => {
|
|
141
|
+
const timer = setTimeout(() => {
|
|
142
|
+
this.off("peer-available", check);
|
|
143
|
+
reject(new Error(`Controller "${controllerName}" not found on any peer (timeout ${timeout}ms). ` +
|
|
144
|
+
`Make sure the service exposing it is running.`));
|
|
145
|
+
}, timeout);
|
|
146
|
+
const check = () => {
|
|
147
|
+
const peerName = this.routes.get(controllerName);
|
|
148
|
+
if (peerName) {
|
|
149
|
+
const conn = this.peers.get(peerName);
|
|
150
|
+
if (conn && conn.isOpen) {
|
|
151
|
+
clearTimeout(timer);
|
|
152
|
+
this.off("peer-available", check);
|
|
153
|
+
resolve(conn);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
this.on("peer-available", check);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check if a controller is available on any peer.
|
|
162
|
+
*/
|
|
163
|
+
hasController(controllerName) {
|
|
164
|
+
return this.routes.has(controllerName);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Close all peer connections and stop browsing.
|
|
168
|
+
*/
|
|
169
|
+
async close() {
|
|
170
|
+
this.stopBrowsing?.();
|
|
171
|
+
for (const client of this.clients) {
|
|
172
|
+
client.close();
|
|
173
|
+
}
|
|
174
|
+
this.clients = [];
|
|
175
|
+
this.peers.clear();
|
|
176
|
+
this.routes.clear();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=mesh-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mesh-manager.js","sourceRoot":"","sources":["../../src/mesh/mesh-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAIzD;;;;;;;;GAQG;AACH,MAAM,OAAO,WAAY,SAAQ,YAAY;IAWxB;IACA;IAXnB,4BAA4B;IACpB,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC9C,gCAAgC;IACxB,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,uCAAuC;IAC/B,OAAO,GAAsB,EAAE,CAAC;IACxC,+BAA+B;IACvB,YAAY,GAAwB,IAAI,CAAC;IAEjD,YACmB,SAAiB,EACjB,aAA6B;QAE9C,KAAK,EAAE,CAAC;QAHS,cAAS,GAAT,SAAS,CAAQ;QACjB,kBAAa,GAAb,aAAa,CAAgB;IAGhD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;YACtD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,aAAa,CAAC;YACvD,MAAM,OAAO,GAAG,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,IAAK,OAAe,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAEjF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;YAErD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,OAAY,EAAE,EAAE;gBAChC,YAAY;gBACZ,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,SAAS;oBAAE,OAAO;gBAC5C,yBAAyB;gBACzB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;oBAAE,OAAO;gBAEzC,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;gBACnE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;gBAE1B,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBACtD,oDAAoD;gBACtD,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,YAAY,GAAG,GAAG,EAAE;gBACvB,OAAO,CAAC,IAAI,EAAE,CAAC;gBACf,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;QACpE,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,IAAY,EAAE,IAAY,EAAE,IAAY;QAC1D,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,oBAAoB;QAEtD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE1B,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QAE1C,kCAAkC;QAClC,UAAU,CAAC,aAAa,CAAC;YACvB,IAAI,EAAE,IAAI,CAAC,SAAS;YACpB,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE;SACxC,CAAC,CAAC;QAEH,4CAA4C;QAC5C,MAAM,WAAW,GAAG,MAAM,IAAI,OAAO,CAAuC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC9F,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YAC/E,UAAU,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,IAAS,EAAE,EAAE;gBAC3C,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,oBAAoB;QACpB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,oBAAoB,CAClB,IAAY,EACZ,UAAsB,EACtB,OAA6C;QAE7C,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,oBAAoB;QACtD,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACK,YAAY,CAClB,IAAY,EACZ,UAAsB,EACtB,OAA6C;QAE7C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEjC,iDAAiD;QACjD,KAAK,MAAM,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;QACxC,CAAC;QAED,sEAAsE;QACtE,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,KAAa,EAAE,MAAc,EAAE,IAAe,EAAE,EAAE;YAChF,IAAI,CAAC;gBACH,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACvD,IAAI,CAAC,cAAc,IAAI,CAAC,UAAU,EAAE,CAAC;oBACnC,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,GAAG,CAAC,CAAC;gBACxD,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,cAAc,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;gBACjF,UAAU,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,mDAAmD;QACnD,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBACvC,IAAI,IAAI,KAAK,IAAI;oBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,8CAA8C;QAC9C,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,cAAsB,EAAE,OAAO,GAAG,MAAM;QAC1D,iBAAiB;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACtC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;QACvC,CAAC;QAED,iDAAiD;QACjD,OAAO,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACjD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;gBAClC,MAAM,CAAC,IAAI,KAAK,CACd,eAAe,cAAc,oCAAoC,OAAO,OAAO;oBAC/E,+CAA+C,CAChD,CAAC,CAAC;YACL,CAAC,EAAE,OAAO,CAAC,CAAC;YAEZ,MAAM,KAAK,GAAG,GAAG,EAAE;gBACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACjD,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACtC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBACxB,YAAY,CAAC,KAAK,CAAC,CAAC;wBACpB,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;wBAClC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAChB,CAAC;gBACH,CAAC;YACH,CAAC,CAAC;YAEF,IAAI,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,cAAsB;QAClC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QACtB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MethodRegistry } from "../registry/method-registry.js";
|
|
2
|
+
import type { MeshManager } from "../mesh/mesh-manager.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a smart mesh proxy.
|
|
5
|
+
*
|
|
6
|
+
* This proxy routes method calls to the right place:
|
|
7
|
+
* - Local controllers → invoke directly via MethodRegistry
|
|
8
|
+
* - Remote controllers → route via MeshManager (auto-discovered)
|
|
9
|
+
*
|
|
10
|
+
* The proxy is what TypeBridge.create() returns. It IS the API:
|
|
11
|
+
*
|
|
12
|
+
* const api = await TypeBridge.create(adapter, { controllers });
|
|
13
|
+
* api.userController.findById("abc"); // local or remote — just works
|
|
14
|
+
*
|
|
15
|
+
* @param localRegistry - local controllers
|
|
16
|
+
* @param meshManager - handles remote controller routing
|
|
17
|
+
* @param ownProps - own properties (close, port, name, etc.)
|
|
18
|
+
*/
|
|
19
|
+
export declare function createMeshProxy<T = unknown>(localRegistry: MethodRegistry, meshManager: MeshManager, ownProps?: Record<string, unknown>): T;
|
|
20
|
+
//# sourceMappingURL=client-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-proxy.d.ts","sourceRoot":"","sources":["../../src/proxy/client-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,CAAC,GAAG,OAAO,EACzC,aAAa,EAAE,cAAc,EAC7B,WAAW,EAAE,WAAW,EACxB,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACrC,CAAC,CA0BH"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a smart mesh proxy.
|
|
3
|
+
*
|
|
4
|
+
* This proxy routes method calls to the right place:
|
|
5
|
+
* - Local controllers → invoke directly via MethodRegistry
|
|
6
|
+
* - Remote controllers → route via MeshManager (auto-discovered)
|
|
7
|
+
*
|
|
8
|
+
* The proxy is what TypeBridge.create() returns. It IS the API:
|
|
9
|
+
*
|
|
10
|
+
* const api = await TypeBridge.create(adapter, { controllers });
|
|
11
|
+
* api.userController.findById("abc"); // local or remote — just works
|
|
12
|
+
*
|
|
13
|
+
* @param localRegistry - local controllers
|
|
14
|
+
* @param meshManager - handles remote controller routing
|
|
15
|
+
* @param ownProps - own properties (close, port, name, etc.)
|
|
16
|
+
*/
|
|
17
|
+
export function createMeshProxy(localRegistry, meshManager, ownProps = {}) {
|
|
18
|
+
return new Proxy(ownProps, {
|
|
19
|
+
get(target, prop) {
|
|
20
|
+
if (typeof prop === "symbol")
|
|
21
|
+
return undefined;
|
|
22
|
+
if (prop === "then" || prop === "catch" || prop === "finally")
|
|
23
|
+
return undefined;
|
|
24
|
+
// Own properties (close, port, name, __controllers) take priority
|
|
25
|
+
if (prop in target) {
|
|
26
|
+
return target[prop];
|
|
27
|
+
}
|
|
28
|
+
// Return a controller proxy — will route to local or remote
|
|
29
|
+
return createControllerProxy(localRegistry, meshManager, prop);
|
|
30
|
+
},
|
|
31
|
+
ownKeys(target) {
|
|
32
|
+
return Object.keys(target);
|
|
33
|
+
},
|
|
34
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
35
|
+
if (prop in target) {
|
|
36
|
+
return { configurable: true, enumerable: true, value: target[prop] };
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Controller-level proxy — intercepts method calls and routes them.
|
|
44
|
+
*/
|
|
45
|
+
function createControllerProxy(localRegistry, meshManager, controllerName) {
|
|
46
|
+
return new Proxy(() => { }, {
|
|
47
|
+
get(_target, methodName) {
|
|
48
|
+
if (typeof methodName === "symbol")
|
|
49
|
+
return undefined;
|
|
50
|
+
if (methodName === "then" || methodName === "catch" || methodName === "finally")
|
|
51
|
+
return undefined;
|
|
52
|
+
// Return a function that routes the call
|
|
53
|
+
return async (...args) => {
|
|
54
|
+
// 1. Local? Call directly — no network involved
|
|
55
|
+
if (localRegistry.hasController(controllerName)) {
|
|
56
|
+
return localRegistry.invoke(controllerName, String(methodName), args);
|
|
57
|
+
}
|
|
58
|
+
// 2. Remote? Route via mesh (waits for discovery if needed)
|
|
59
|
+
const conn = await meshManager.getConnection(controllerName);
|
|
60
|
+
return conn.request(`${controllerName}.${String(methodName)}`, args);
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
apply() {
|
|
64
|
+
throw new Error(`Cannot call controller "${controllerName}" directly. ` +
|
|
65
|
+
`Access a method: api.${controllerName}.methodName(args)`);
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=client-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-proxy.js","sourceRoot":"","sources":["../../src/proxy/client-proxy.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAC7B,aAA6B,EAC7B,WAAwB,EACxB,WAAoC,EAAE;IAEtC,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE;QACzB,GAAG,CAAC,MAAM,EAAE,IAAqB;YAC/B,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAC;YAC/C,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAEhF,kEAAkE;YAClE,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;gBACnB,OAAQ,MAAkC,CAAC,IAAI,CAAC,CAAC;YACnD,CAAC;YAED,4DAA4D;YAC5D,OAAO,qBAAqB,CAAC,aAAa,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;QACjE,CAAC;QAED,OAAO,CAAC,MAAM;YACZ,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QAED,wBAAwB,CAAC,MAAM,EAAE,IAAI;YACnC,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;gBACnB,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAG,MAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAChF,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAM,CAAC;AACV,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAC5B,aAA6B,EAC7B,WAAwB,EACxB,cAAsB;IAEtB,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE;QACzB,GAAG,CAAC,OAAO,EAAE,UAA2B;YACtC,IAAI,OAAO,UAAU,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAC;YACrD,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAElG,yCAAyC;YACzC,OAAO,KAAK,EAAE,GAAG,IAAe,EAAE,EAAE;gBAClC,gDAAgD;gBAChD,IAAI,aAAa,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,CAAC;oBAChD,OAAO,aAAa,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;gBACxE,CAAC;gBAED,4DAA4D;gBAC5D,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;gBAC7D,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,cAAc,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACvE,CAAC,CAAC;QACJ,CAAC;QAED,KAAK;YACH,MAAM,IAAI,KAAK,CACb,2BAA2B,cAAc,cAAc;gBACvD,wBAAwB,cAAc,mBAAmB,CAC1D,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proxy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/proxy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MethodDescriptor } from "../types/descriptor.js";
|
|
2
|
+
/**
|
|
3
|
+
* Extract method descriptors from a plain class by inspecting its prototype.
|
|
4
|
+
*
|
|
5
|
+
* This is the fallback/generic extractor used when no adapter-specific
|
|
6
|
+
* metadata is available. It produces basic descriptors by inspecting
|
|
7
|
+
* the class prototype's own methods.
|
|
8
|
+
*
|
|
9
|
+
* Framework-specific adapters (NestAdapter, TsedAdapter, etc.) may
|
|
10
|
+
* override this with richer metadata from decorator reflection.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractMethodsFromPrototype(controllerName: string, controllerClass: new (...args: unknown[]) => unknown): MethodDescriptor[];
|
|
13
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/reflection/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,wBAAwB,CAAC;AAGpF;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GACnD,gBAAgB,EAAE,CAkCpB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract method descriptors from a plain class by inspecting its prototype.
|
|
3
|
+
*
|
|
4
|
+
* This is the fallback/generic extractor used when no adapter-specific
|
|
5
|
+
* metadata is available. It produces basic descriptors by inspecting
|
|
6
|
+
* the class prototype's own methods.
|
|
7
|
+
*
|
|
8
|
+
* Framework-specific adapters (NestAdapter, TsedAdapter, etc.) may
|
|
9
|
+
* override this with richer metadata from decorator reflection.
|
|
10
|
+
*/
|
|
11
|
+
export function extractMethodsFromPrototype(controllerName, controllerClass) {
|
|
12
|
+
const prototype = controllerClass.prototype;
|
|
13
|
+
const methods = [];
|
|
14
|
+
const ownMethodNames = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor" && typeof prototype[name] === "function");
|
|
15
|
+
for (const methodName of ownMethodNames) {
|
|
16
|
+
const method = prototype[methodName];
|
|
17
|
+
// Try to extract parameter names from function source (best-effort)
|
|
18
|
+
const paramNames = extractParamNames(method);
|
|
19
|
+
const parameters = paramNames.map((name, index) => ({
|
|
20
|
+
name,
|
|
21
|
+
index,
|
|
22
|
+
type: { kind: "unknown" },
|
|
23
|
+
isOptional: false,
|
|
24
|
+
}));
|
|
25
|
+
const descriptor = {
|
|
26
|
+
controllerName,
|
|
27
|
+
methodName,
|
|
28
|
+
parameters,
|
|
29
|
+
returnType: { kind: "unknown" },
|
|
30
|
+
isAsync: method.constructor.name === "AsyncFunction",
|
|
31
|
+
decorators: [],
|
|
32
|
+
};
|
|
33
|
+
methods.push(descriptor);
|
|
34
|
+
}
|
|
35
|
+
return methods;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract parameter names from a function's toString() representation.
|
|
39
|
+
* Best-effort — works for simple cases. Complex destructuring or
|
|
40
|
+
* compiled code may not parse correctly.
|
|
41
|
+
*/
|
|
42
|
+
function extractParamNames(fn) {
|
|
43
|
+
const source = fn.toString();
|
|
44
|
+
const match = source.match(/\(([^)]*)\)/);
|
|
45
|
+
if (!match || !match[1])
|
|
46
|
+
return [];
|
|
47
|
+
return match[1]
|
|
48
|
+
.split(",")
|
|
49
|
+
.map((param) => param.trim())
|
|
50
|
+
.filter((param) => param.length > 0)
|
|
51
|
+
.map((param) => {
|
|
52
|
+
// Handle default values: "name = 'default'" → "name"
|
|
53
|
+
const eqIdx = param.indexOf("=");
|
|
54
|
+
if (eqIdx > 0)
|
|
55
|
+
return param.substring(0, eqIdx).trim();
|
|
56
|
+
// Handle rest params: "...args" → "args"
|
|
57
|
+
if (param.startsWith("..."))
|
|
58
|
+
return param.substring(3);
|
|
59
|
+
return param;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/reflection/extractor.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B,CACzC,cAAsB,EACtB,eAAoD;IAEpD,MAAM,SAAS,GAAG,eAAe,CAAC,SAAoC,CAAC;IACvE,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,MAAM,cAAc,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,MAAM,CACjE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,UAAU,CAC1E,CAAC;IAEF,KAAK,MAAM,UAAU,IAAI,cAAc,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAa,CAAC;QAEjD,oEAAoE;QACpE,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAE7C,MAAM,UAAU,GAA0B,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACzE,IAAI;YACJ,KAAK;YACL,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAoB;YAC3C,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC,CAAC;QAEJ,MAAM,UAAU,GAAqB;YACnC,cAAc;YACd,UAAU;YACV,UAAU;YACV,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAoB;YACjD,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe;YACpD,UAAU,EAAE,EAAE;SACf,CAAC;QAEF,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CAAC,EAAY;IACrC,MAAM,MAAM,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,OAAO,KAAK,CAAC,CAAC,CAAC;SACZ,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;SACnC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,qDAAqD;QACrD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,yCAAyC;QACzC,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reflection/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reflection/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { MethodDescriptor } from "../types/descriptor.js";
|
|
2
|
+
/**
|
|
3
|
+
* MethodRegistry — stores all registered controllers and their methods.
|
|
4
|
+
*
|
|
5
|
+
* Each controller is registered with a key name (e.g., "userController")
|
|
6
|
+
* and its instance + extracted method descriptors.
|
|
7
|
+
*/
|
|
8
|
+
export declare class MethodRegistry {
|
|
9
|
+
/** controller name → method descriptors */
|
|
10
|
+
private readonly methods;
|
|
11
|
+
/** controller name → controller instance (for invoking methods) */
|
|
12
|
+
private readonly instances;
|
|
13
|
+
/**
|
|
14
|
+
* Register a controller with its method descriptors and instance.
|
|
15
|
+
*/
|
|
16
|
+
register(controllerName: string, instance: unknown, methods: MethodDescriptor[]): void;
|
|
17
|
+
/**
|
|
18
|
+
* Get all method descriptors for a controller.
|
|
19
|
+
*/
|
|
20
|
+
getMethods(controllerName: string): MethodDescriptor[] | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Get a specific method descriptor.
|
|
23
|
+
*/
|
|
24
|
+
getMethod(controllerName: string, methodName: string): MethodDescriptor | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Get the instance for a controller (used to actually call methods).
|
|
27
|
+
*/
|
|
28
|
+
getInstance(controllerName: string): unknown | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Check if a controller is registered.
|
|
31
|
+
*/
|
|
32
|
+
hasController(controllerName: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Get all registered controller names.
|
|
35
|
+
*/
|
|
36
|
+
getControllerNames(): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Invoke a method on a registered controller.
|
|
39
|
+
*/
|
|
40
|
+
invoke(controllerName: string, methodName: string, args: unknown[]): Promise<unknown>;
|
|
41
|
+
/**
|
|
42
|
+
* Generate a serializable type catalog for the handshake.
|
|
43
|
+
* Contains all controllers, methods, and their parameter info.
|
|
44
|
+
*/
|
|
45
|
+
toCatalog(): Record<string, MethodCatalogEntry[]>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Single method entry in the serializable catalog.
|
|
49
|
+
*/
|
|
50
|
+
export interface MethodCatalogEntry {
|
|
51
|
+
methodName: string;
|
|
52
|
+
parameterNames: string[];
|
|
53
|
+
parameterCount: number;
|
|
54
|
+
isAsync: boolean;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=method-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method-registry.d.ts","sourceRoot":"","sources":["../../src/registry/method-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,2CAA2C;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IACjE,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8B;IAExD;;OAEG;IACH,QAAQ,CACN,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,IAAI;IAKP;;OAEG;IACH,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,SAAS;IAIlE;;OAEG;IACH,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAMnF;;OAEG;IACH,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIxD;;OAEG;IACH,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO;IAI9C;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAI9B;;OAEG;IACG,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAe3F;;;OAGG;IACH,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC;CAclD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MethodRegistry — stores all registered controllers and their methods.
|
|
3
|
+
*
|
|
4
|
+
* Each controller is registered with a key name (e.g., "userController")
|
|
5
|
+
* and its instance + extracted method descriptors.
|
|
6
|
+
*/
|
|
7
|
+
export class MethodRegistry {
|
|
8
|
+
/** controller name → method descriptors */
|
|
9
|
+
methods = new Map();
|
|
10
|
+
/** controller name → controller instance (for invoking methods) */
|
|
11
|
+
instances = new Map();
|
|
12
|
+
/**
|
|
13
|
+
* Register a controller with its method descriptors and instance.
|
|
14
|
+
*/
|
|
15
|
+
register(controllerName, instance, methods) {
|
|
16
|
+
this.methods.set(controllerName, methods);
|
|
17
|
+
this.instances.set(controllerName, instance);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get all method descriptors for a controller.
|
|
21
|
+
*/
|
|
22
|
+
getMethods(controllerName) {
|
|
23
|
+
return this.methods.get(controllerName);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get a specific method descriptor.
|
|
27
|
+
*/
|
|
28
|
+
getMethod(controllerName, methodName) {
|
|
29
|
+
const methods = this.methods.get(controllerName);
|
|
30
|
+
if (!methods)
|
|
31
|
+
return undefined;
|
|
32
|
+
return methods.find((m) => m.methodName === methodName);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get the instance for a controller (used to actually call methods).
|
|
36
|
+
*/
|
|
37
|
+
getInstance(controllerName) {
|
|
38
|
+
return this.instances.get(controllerName);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Check if a controller is registered.
|
|
42
|
+
*/
|
|
43
|
+
hasController(controllerName) {
|
|
44
|
+
return this.methods.has(controllerName);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get all registered controller names.
|
|
48
|
+
*/
|
|
49
|
+
getControllerNames() {
|
|
50
|
+
return Array.from(this.methods.keys());
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Invoke a method on a registered controller.
|
|
54
|
+
*/
|
|
55
|
+
async invoke(controllerName, methodName, args) {
|
|
56
|
+
const instance = this.instances.get(controllerName);
|
|
57
|
+
if (!instance) {
|
|
58
|
+
throw new Error(`Controller not found: ${controllerName}`);
|
|
59
|
+
}
|
|
60
|
+
const method = instance[methodName];
|
|
61
|
+
if (typeof method !== "function") {
|
|
62
|
+
throw new Error(`Method not found: ${controllerName}.${methodName}`);
|
|
63
|
+
}
|
|
64
|
+
// Call the method on the instance with the provided args
|
|
65
|
+
return method.call(instance, ...args);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate a serializable type catalog for the handshake.
|
|
69
|
+
* Contains all controllers, methods, and their parameter info.
|
|
70
|
+
*/
|
|
71
|
+
toCatalog() {
|
|
72
|
+
const catalog = {};
|
|
73
|
+
for (const [controllerName, methods] of this.methods) {
|
|
74
|
+
catalog[controllerName] = methods.map((m) => ({
|
|
75
|
+
methodName: m.methodName,
|
|
76
|
+
parameterNames: m.parameters.map((p) => p.name),
|
|
77
|
+
parameterCount: m.parameters.length,
|
|
78
|
+
isAsync: m.isAsync,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
return catalog;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=method-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method-registry.js","sourceRoot":"","sources":["../../src/registry/method-registry.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IACzB,2CAA2C;IAC1B,OAAO,GAAG,IAAI,GAAG,EAA8B,CAAC;IACjE,mEAAmE;IAClD,SAAS,GAAG,IAAI,GAAG,EAAmB,CAAC;IAExD;;OAEG;IACH,QAAQ,CACN,cAAsB,EACtB,QAAiB,EACjB,OAA2B;QAE3B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,cAAsB;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,cAAsB,EAAE,UAAkB;QAClD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,cAAsB;QAChC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,cAAsB;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,cAAsB,EAAE,UAAkB,EAAE,IAAe;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACpD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,cAAc,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,MAAM,GAAI,QAAoC,CAAC,UAAU,CAAC,CAAC;QACjE,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,qBAAqB,cAAc,IAAI,UAAU,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,yDAAyD;QACzD,OAAQ,MAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,SAAS;QACP,MAAM,OAAO,GAAyC,EAAE,CAAC;QAEzD,KAAK,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACrD,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC5C,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,cAAc,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC/C,cAAc,EAAE,CAAC,CAAC,UAAU,CAAC,MAAM;gBACnC,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAC,CAAC,CAAC;QACN,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Error serialization/deserialization.
|
|
3
|
+
*
|
|
4
|
+
* Errors are fully serialized as-is:
|
|
5
|
+
* - name, message, stack (exact)
|
|
6
|
+
* - cause chains (recursive)
|
|
7
|
+
* - All enumerable custom properties (statusCode, details, etc.)
|
|
8
|
+
*
|
|
9
|
+
* The client receives the exact same error the server threw. Period.
|
|
10
|
+
*/
|
|
11
|
+
/** Marker to identify serialized Error objects in MessagePack payload */
|
|
12
|
+
export declare const ERROR_MARKER = "__typebridge_error__";
|
|
13
|
+
/**
|
|
14
|
+
* Serialized representation of an Error.
|
|
15
|
+
*/
|
|
16
|
+
export interface SerializedError {
|
|
17
|
+
[ERROR_MARKER]: true;
|
|
18
|
+
name: string;
|
|
19
|
+
message: string;
|
|
20
|
+
stack: string | undefined;
|
|
21
|
+
cause?: SerializedError;
|
|
22
|
+
properties: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Serialize an Error object into a plain object that can be encoded by MessagePack.
|
|
26
|
+
* Recursively serializes `cause` chains and captures all enumerable properties.
|
|
27
|
+
*/
|
|
28
|
+
export declare function serializeError(error: unknown): SerializedError;
|
|
29
|
+
/**
|
|
30
|
+
* Deserialize a SerializedError back into an Error object.
|
|
31
|
+
* Reconstructs cause chains and restores all custom properties.
|
|
32
|
+
*/
|
|
33
|
+
export declare function deserializeError(data: SerializedError): Error;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a value is a serialized TypeBridge Error.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isSerializedError(value: unknown): value is SerializedError;
|
|
38
|
+
//# sourceMappingURL=error-ext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-ext.d.ts","sourceRoot":"","sources":["../../src/serialization/error-ext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,yEAAyE;AACzE,eAAO,MAAM,YAAY,yBAAyB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAiC9D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,KAAK,CAmB7D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAO1E"}
|