wenay-common2 1.0.46 → 1.0.49
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 +51 -37
- package/lib/Common/Color.d.ts +3 -0
- package/lib/Common/Color.js +4 -0
- package/lib/Common/ObserveAll2/index.d.ts +2 -0
- package/lib/Common/ObserveAll2/index.js +18 -0
- package/lib/Common/ObserveAll2/reactive2.d.ts +33 -0
- package/lib/Common/ObserveAll2/reactive2.js +254 -0
- package/lib/Common/ObserveAll2/store.d.ts +98 -0
- package/lib/Common/ObserveAll2/store.js +381 -0
- package/lib/Common/Time.d.ts +8 -0
- package/lib/Common/Time.js +41 -14
- package/lib/Common/async/PromiseArrayListen.d.ts +3 -3
- package/lib/Common/async/PromiseArrayListen.js +10 -13
- package/lib/Common/async/createIterableObject.js +1 -1
- package/lib/Common/async/waitRun.d.ts +11 -4
- package/lib/Common/async/waitRun.js +74 -44
- package/lib/Common/core/Decorator.d.ts +3 -1
- package/lib/Common/core/Decorator.js +5 -2
- package/lib/Common/core/common.d.ts +25 -7
- package/lib/Common/core/common.js +114 -34
- package/lib/Common/data/ByteStream.d.ts +1 -1
- package/lib/Common/data/ByteStream.js +21 -8
- package/lib/Common/data/List.d.ts +5 -0
- package/lib/Common/data/List.js +13 -4
- package/lib/Common/data/ListNodeAnd.js +2 -2
- package/lib/Common/data/objectPath.d.ts +4 -0
- package/lib/Common/data/objectPath.js +8 -3
- package/lib/Common/events/Listen.d.ts +1 -55
- package/lib/Common/events/Listen.js +15 -154
- package/lib/Common/events/Listen2.d.ts +1 -0
- package/lib/Common/events/Listen2.js +17 -0
- package/lib/Common/events/Listen3.d.ts +197 -0
- package/lib/Common/events/Listen3.js +249 -0
- package/lib/Common/events/SocketBuffer.d.ts +14 -9
- package/lib/Common/events/SocketServerHook.d.ts +26 -13
- package/lib/Common/events/SocketServerHook.js +2 -1
- package/lib/Common/events/UseListenTransform.d.ts +10 -5
- package/lib/Common/events/event.d.ts +12 -0
- package/lib/Common/events/event.js +10 -6
- package/lib/Common/events/joinListens.d.ts +2 -0
- package/lib/Common/events/joinListens.js +13 -12
- package/lib/Common/funcTimeWait.d.ts +28 -0
- package/lib/Common/funcTimeWait.js +18 -1
- package/lib/Common/isProxy.d.ts +1 -0
- package/lib/Common/isProxy.js +2 -0
- package/lib/Common/node_console.d.ts +2 -0
- package/lib/Common/node_console.js +3 -76
- package/lib/Common/rcp/createRpcServerAutoWithProtocolDetection.d.ts +2 -0
- package/lib/Common/rcp/createRpcServerAutoWithProtocolDetection.js +63 -30
- package/lib/Common/rcp/listen-deep.d.ts +13 -5
- package/lib/Common/rcp/listen-socket.d.ts +21 -3
- package/lib/Common/rcp/listen-socket.js +126 -17
- package/lib/Common/rcp/oldCommonsServer.d.ts +1 -1
- package/lib/Common/rcp/oldCommonsServer.js +15 -1
- package/lib/Common/rcp/old/320/241ommonsServerMini.js +1 -0
- package/lib/Common/rcp/rpc-caps.d.ts +10 -0
- package/lib/Common/rcp/rpc-caps.js +16 -0
- package/lib/Common/rcp/rpc-client.d.ts +23 -1
- package/lib/Common/rcp/rpc-client.js +306 -25
- package/lib/Common/rcp/rpc-clientHub.d.ts +7 -1
- package/lib/Common/rcp/rpc-clientHub.js +25 -2
- package/lib/Common/rcp/rpc-index.d.ts +3 -0
- package/lib/Common/rcp/rpc-index.js +3 -0
- package/lib/Common/rcp/rpc-inproc.d.ts +17 -0
- package/lib/Common/rcp/rpc-inproc.js +30 -0
- package/lib/Common/rcp/rpc-off.d.ts +10 -0
- package/lib/Common/rcp/rpc-off.js +22 -0
- package/lib/Common/rcp/rpc-protocol.d.ts +6 -0
- package/lib/Common/rcp/rpc-protocol.js +4 -2
- package/lib/Common/rcp/rpc-server-auto.d.ts +14 -3
- package/lib/Common/rcp/rpc-server-auto.js +81 -6
- package/lib/Common/rcp/rpc-server.d.ts +17 -2
- package/lib/Common/rcp/rpc-server.js +127 -31
- package/lib/Common/rcp/rpc-shape.d.ts +17 -0
- package/lib/Common/rcp/rpc-shape.js +42 -0
- package/lib/Common/rcp/rpc-walk.js +29 -11
- package/lib/Exchange/Bars.d.ts +3 -0
- package/lib/Exchange/Bars.js +4 -1
- package/lib/Exchange/CParams.d.ts +2 -0
- package/lib/Exchange/CParams.js +21 -14
- package/lib/Exchange/MarketData.d.ts +6 -0
- package/lib/Exchange/MarketData.js +4 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +3 -1
- package/lib/server/WebHook3.js +22 -9
- package/package.json +3 -1
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { type SocketTmpl } from "./rpc-protocol";
|
|
2
|
+
import { type RpcLimits } from "./rpc-limits";
|
|
3
|
+
import { makeOff } from "./rpc-off";
|
|
4
|
+
import { type RpcOpt } from "./rpc-caps";
|
|
2
5
|
type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;
|
|
3
6
|
export type DeepDataOnly<T> = T extends Function ? never : T extends Array<infer U> ? Array<DeepDataOnly<U>> : T extends object ? {
|
|
4
7
|
[K in keyof T as T[K] extends Function ? never : K]: DeepDataOnly<T[K]>;
|
|
@@ -24,6 +27,10 @@ type ClientApiHandle = {
|
|
|
24
27
|
clearCallbacks: () => void;
|
|
25
28
|
remove: (fn: Function) => void;
|
|
26
29
|
end: (fn: Function) => void;
|
|
30
|
+
subscriptions: () => {
|
|
31
|
+
key: string;
|
|
32
|
+
consumers: number;
|
|
33
|
+
}[];
|
|
27
34
|
};
|
|
28
35
|
export type RpcClientReturn<T extends object> = {
|
|
29
36
|
func: ClientAPIAll<T>;
|
|
@@ -34,13 +41,28 @@ export type RpcClientReturn<T extends object> = {
|
|
|
34
41
|
strict: ClientAPIStrict<T>;
|
|
35
42
|
api: ClientApiHandle;
|
|
36
43
|
abortAll: (reason: string) => void;
|
|
44
|
+
dispose: (reason?: string, opts?: {
|
|
45
|
+
socketAlive?: boolean;
|
|
46
|
+
}) => void;
|
|
47
|
+
close: (reason?: string, opts?: {
|
|
48
|
+
socketAlive?: boolean;
|
|
49
|
+
}) => void;
|
|
37
50
|
schema: () => any;
|
|
38
51
|
readyStrict: () => Promise<void>;
|
|
52
|
+
ready: () => Promise<void>;
|
|
39
53
|
initStrict: (obj?: object) => Promise<void>;
|
|
54
|
+
init: (obj?: object) => Promise<void>;
|
|
55
|
+
reauth: (token: any) => Promise<any>;
|
|
56
|
+
auth: () => Promise<any>;
|
|
57
|
+
onDisconnect: (cb: (reason: string) => void) => ReturnType<typeof makeOff>;
|
|
40
58
|
};
|
|
41
|
-
export declare function createRpcClient<T extends object>({ socket, socketKey: key, limit }: {
|
|
59
|
+
export declare function createRpcClient<T extends object>({ socket, socketKey: key, limit, limits, dedupeListen, token, opt }: {
|
|
42
60
|
socket: SocketTmpl;
|
|
43
61
|
socketKey: string;
|
|
44
62
|
limit?: number;
|
|
63
|
+
limits?: RpcLimits;
|
|
64
|
+
dedupeListen?: boolean;
|
|
65
|
+
token?: any;
|
|
66
|
+
opt?: RpcOpt;
|
|
45
67
|
}): RpcClientReturn<T>;
|
|
46
68
|
export type { ClientApiHandle };
|
|
@@ -4,46 +4,192 @@ exports.createRpcClient = createRpcClient;
|
|
|
4
4
|
const rpc_protocol_1 = require("./rpc-protocol");
|
|
5
5
|
const id_pool_1 = require("../id-pool");
|
|
6
6
|
const rpc_walk_1 = require("./rpc-walk");
|
|
7
|
+
const rpc_limits_1 = require("./rpc-limits");
|
|
8
|
+
const myThrow_1 = require("../../toError/myThrow");
|
|
9
|
+
const rpc_off_1 = require("./rpc-off");
|
|
10
|
+
const rpc_caps_1 = require("./rpc-caps");
|
|
11
|
+
const SHARED_POOLS = new WeakMap();
|
|
12
|
+
function sharedPool(socket, key) {
|
|
13
|
+
let byKey = SHARED_POOLS.get(socket);
|
|
14
|
+
if (!byKey) {
|
|
15
|
+
byKey = new Map();
|
|
16
|
+
SHARED_POOLS.set(socket, byKey);
|
|
17
|
+
}
|
|
18
|
+
let pool = byKey.get(key);
|
|
19
|
+
if (!pool) {
|
|
20
|
+
pool = (0, id_pool_1.createIdPool)();
|
|
21
|
+
byKey.set(key, pool);
|
|
22
|
+
}
|
|
23
|
+
return pool;
|
|
24
|
+
}
|
|
25
|
+
const reviveErr = (o) => {
|
|
26
|
+
if (o == null || typeof o != "object" || typeof o.message != "string" || typeof o.name != "string")
|
|
27
|
+
return o;
|
|
28
|
+
const o2 = o.data !== undefined ? { ...o, data: (0, rpc_walk_1.unpackResult)(o.data) } : o;
|
|
29
|
+
const err = myThrow_1.MyError.fromWire(o2);
|
|
30
|
+
if (o.cause !== undefined)
|
|
31
|
+
err.cause = reviveErr(o.cause);
|
|
32
|
+
return err;
|
|
33
|
+
};
|
|
34
|
+
function listenKeyArg(a) {
|
|
35
|
+
if (typeof a == "function")
|
|
36
|
+
return "@fn";
|
|
37
|
+
if (typeof a == "bigint")
|
|
38
|
+
return { $_b: a.toString() };
|
|
39
|
+
if (a instanceof Date)
|
|
40
|
+
return { $_d: a.valueOf() };
|
|
41
|
+
if (a instanceof Map)
|
|
42
|
+
return { $_m: [...a.entries()].map(([k, v]) => [listenKeyArg(k), listenKeyArg(v)]) };
|
|
43
|
+
if (a instanceof Set)
|
|
44
|
+
return { $_s: [...a.values()].map(listenKeyArg) };
|
|
45
|
+
if (Array.isArray(a))
|
|
46
|
+
return a.map(listenKeyArg);
|
|
47
|
+
if (a && typeof a == "object") {
|
|
48
|
+
const out = {};
|
|
49
|
+
for (const k of Object.keys(a).sort())
|
|
50
|
+
out[k] = listenKeyArg(a[k]);
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
return a;
|
|
54
|
+
}
|
|
7
55
|
const IS_RPC_PIPE = Symbol.for("isRpcPipe");
|
|
8
56
|
function createClient(socket, key, opts) {
|
|
9
57
|
const limit = opts?.limit ?? 10000;
|
|
10
|
-
const
|
|
58
|
+
const lim = opts?.limits ? (0, rpc_limits_1.resolveLimits)(opts.limits) : undefined;
|
|
59
|
+
const pool = sharedPool(socket, key);
|
|
11
60
|
const pending = new Map();
|
|
12
61
|
const callbacks = new Map();
|
|
62
|
+
const compactShapes = new Map();
|
|
63
|
+
let capsSent = false;
|
|
64
|
+
const clientCaps = (0, rpc_caps_1.optToCaps)(opts?.opt);
|
|
65
|
+
let peerServerCaps = 0;
|
|
66
|
+
const zombies = new Set();
|
|
67
|
+
const retire = (id) => { zombies.add(id); };
|
|
68
|
+
let disposed = false;
|
|
69
|
+
let disconnectCbs = [];
|
|
70
|
+
let disconnectResolve = () => { };
|
|
71
|
+
const disconnectPromise = new Promise(res => { disconnectResolve = res; });
|
|
72
|
+
function onDisconnect(cb) {
|
|
73
|
+
disconnectCbs.push(cb);
|
|
74
|
+
function offDisconnect() { const i = disconnectCbs.indexOf(cb); if (i >= 0)
|
|
75
|
+
disconnectCbs.splice(i, 1); }
|
|
76
|
+
return (0, rpc_off_1.makeOff)(disconnectPromise, offDisconnect);
|
|
77
|
+
}
|
|
13
78
|
const routeCache = {};
|
|
14
79
|
let strictData = {};
|
|
15
80
|
let strictWaiters = [];
|
|
16
81
|
let debug = false;
|
|
82
|
+
let authToken = opts?.token ?? null;
|
|
83
|
+
let authStatus = undefined;
|
|
84
|
+
let authWaiters = [];
|
|
85
|
+
let authPending = false;
|
|
86
|
+
const drainAuth = (s) => { authPending = false; const w = authWaiters; authWaiters = []; for (const r of w)
|
|
87
|
+
r(s); };
|
|
88
|
+
const setAuthStatus = (s) => { authStatus = s; drainAuth(s); };
|
|
17
89
|
socket.on(key, (msg) => {
|
|
18
90
|
if (!Array.isArray(msg))
|
|
19
91
|
return;
|
|
92
|
+
if (disposed) {
|
|
93
|
+
if ((msg[0] == rpc_protocol_1.Pkt.RESP || msg[0] == rpc_protocol_1.Pkt.CB_END) && zombies.delete(msg[1]))
|
|
94
|
+
pool.release(msg[1]);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
20
97
|
switch (msg[0]) {
|
|
21
98
|
case rpc_protocol_1.Pkt.RESP: {
|
|
22
99
|
const req = pending.get(msg[1]);
|
|
23
|
-
if (!req)
|
|
100
|
+
if (!req) {
|
|
101
|
+
if (zombies.delete(msg[1]))
|
|
102
|
+
pool.release(msg[1]);
|
|
24
103
|
break;
|
|
104
|
+
}
|
|
25
105
|
pending.delete(msg[1]);
|
|
26
106
|
pool.release(msg[1]);
|
|
27
107
|
for (const cbId of req.cbs) {
|
|
28
|
-
callbacks.delete(cbId)
|
|
29
|
-
|
|
108
|
+
if (callbacks.delete(cbId))
|
|
109
|
+
pool.release(cbId);
|
|
110
|
+
}
|
|
111
|
+
if (msg[3])
|
|
112
|
+
req.fail(reviveErr(msg[3]));
|
|
113
|
+
else {
|
|
114
|
+
try {
|
|
115
|
+
req.ok((0, rpc_walk_1.unpackResult)(msg[2], lim));
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
req.fail(e);
|
|
119
|
+
}
|
|
30
120
|
}
|
|
31
|
-
msg[3] ? req.fail(msg[3]) : req.ok((0, rpc_walk_1.unpackResult)(msg[2]));
|
|
32
121
|
break;
|
|
33
122
|
}
|
|
34
123
|
case rpc_protocol_1.Pkt.CB: {
|
|
35
|
-
callbacks.get(msg[1])
|
|
124
|
+
const cb = callbacks.get(msg[1]);
|
|
125
|
+
if (!cb)
|
|
126
|
+
break;
|
|
127
|
+
let cbArgs;
|
|
128
|
+
try {
|
|
129
|
+
cbArgs = (msg[2] || []).map((a) => (0, rpc_walk_1.unpackResult)(a, lim));
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
if (debug)
|
|
133
|
+
console.log("[RPC CB] dropped:", e);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
cb(...cbArgs);
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case rpc_protocol_1.Pkt.SHAPE: {
|
|
140
|
+
let m = compactShapes.get(msg[1]);
|
|
141
|
+
if (!m) {
|
|
142
|
+
m = [];
|
|
143
|
+
compactShapes.set(msg[1], m);
|
|
144
|
+
}
|
|
145
|
+
m[msg[2]] = msg[3];
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
case rpc_protocol_1.Pkt.CBV: {
|
|
149
|
+
const cb = callbacks.get(msg[1]);
|
|
150
|
+
if (!cb)
|
|
151
|
+
break;
|
|
152
|
+
const keys = compactShapes.get(msg[1])?.[msg[2]];
|
|
153
|
+
if (!keys)
|
|
154
|
+
break;
|
|
155
|
+
const vals = msg[3] || [];
|
|
156
|
+
let obj;
|
|
157
|
+
try {
|
|
158
|
+
obj = {};
|
|
159
|
+
keys.forEach((k, i) => { obj[k] = (0, rpc_walk_1.unpackResult)(vals[i], lim); });
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
if (debug)
|
|
163
|
+
console.log("[RPC CBV] dropped:", e);
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
cb(obj);
|
|
36
167
|
break;
|
|
37
168
|
}
|
|
38
169
|
case rpc_protocol_1.Pkt.CB_END: {
|
|
39
170
|
const cbId = msg[1];
|
|
40
|
-
|
|
41
|
-
|
|
171
|
+
compactShapes.delete(cbId);
|
|
172
|
+
if (callbacks.delete(cbId))
|
|
173
|
+
pool.release(cbId);
|
|
174
|
+
else if (zombies.delete(cbId))
|
|
175
|
+
pool.release(cbId);
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case rpc_protocol_1.Pkt.CAPS: {
|
|
179
|
+
peerServerCaps = typeof msg[1] === "number" ? msg[1] : 0;
|
|
42
180
|
break;
|
|
43
181
|
}
|
|
44
182
|
case rpc_protocol_1.Pkt.MAP: {
|
|
45
|
-
if (msg[1])
|
|
183
|
+
if (msg[1]) {
|
|
184
|
+
for (const k of Object.keys(routeCache))
|
|
185
|
+
delete routeCache[k];
|
|
46
186
|
Object.assign(routeCache, msg[1]);
|
|
187
|
+
}
|
|
188
|
+
if (Array.isArray(msg[3])) {
|
|
189
|
+
declaredListens ??= new Set();
|
|
190
|
+
for (const p of msg[3])
|
|
191
|
+
declaredListens.add(p);
|
|
192
|
+
}
|
|
47
193
|
if (msg[2]) {
|
|
48
194
|
for (const k of Object.keys(strictData))
|
|
49
195
|
delete strictData[k];
|
|
@@ -52,11 +198,20 @@ function createClient(socket, key, opts) {
|
|
|
52
198
|
r(undefined);
|
|
53
199
|
strictWaiters = [];
|
|
54
200
|
}
|
|
201
|
+
if (msg.length > 4)
|
|
202
|
+
setAuthStatus(msg[4]);
|
|
203
|
+
if (!capsSent) {
|
|
204
|
+
capsSent = true;
|
|
205
|
+
if (clientCaps)
|
|
206
|
+
socket.emit(key, [rpc_protocol_1.Pkt.CAPS, clientCaps]);
|
|
207
|
+
}
|
|
55
208
|
break;
|
|
56
209
|
}
|
|
57
210
|
}
|
|
58
211
|
});
|
|
59
212
|
const sendPipe = (path, steps, wait) => {
|
|
213
|
+
if (disposed)
|
|
214
|
+
return wait ? Promise.reject(new Error("RPC client disposed")) : Promise.resolve();
|
|
60
215
|
const cbIds = [];
|
|
61
216
|
const cleanSteps = steps.map(step => {
|
|
62
217
|
if (step.type === 'call') {
|
|
@@ -120,7 +275,9 @@ function createClient(socket, key, opts) {
|
|
|
120
275
|
});
|
|
121
276
|
return proxy;
|
|
122
277
|
};
|
|
123
|
-
const
|
|
278
|
+
const sendCallWire = (path, args, wait) => {
|
|
279
|
+
if (disposed)
|
|
280
|
+
return wait ? Promise.reject(new Error("RPC client disposed")) : Promise.resolve();
|
|
124
281
|
const cbIds = [];
|
|
125
282
|
const clean = (0, rpc_walk_1.pack)(args, pool, callbacks, cbIds);
|
|
126
283
|
const ref = routeCache[path.join(".")] ?? path;
|
|
@@ -138,6 +295,70 @@ function createClient(socket, key, opts) {
|
|
|
138
295
|
socket.emit(key, [rpc_protocol_1.Pkt.CALL, reqId, ref, clean]);
|
|
139
296
|
});
|
|
140
297
|
};
|
|
298
|
+
const dedupe = opts?.dedupeListen ?? true;
|
|
299
|
+
const wireSubs = new Map();
|
|
300
|
+
let declaredListens = null;
|
|
301
|
+
function subscribeShared(path, args) {
|
|
302
|
+
if (disposed)
|
|
303
|
+
return Promise.reject(new Error("RPC client disposed"));
|
|
304
|
+
const skey = path.slice(0, -1).join(".") + "::" + JSON.stringify(args.map(listenKeyArg));
|
|
305
|
+
let sub = wireSubs.get(skey);
|
|
306
|
+
if (!sub) {
|
|
307
|
+
const created = { consumers: new Set(), stop: () => { } };
|
|
308
|
+
wireSubs.set(skey, created);
|
|
309
|
+
let fnPos = 0;
|
|
310
|
+
const realArgs = args.map(a => {
|
|
311
|
+
if (typeof a != "function")
|
|
312
|
+
return a;
|
|
313
|
+
const i = fnPos++;
|
|
314
|
+
return (...ev) => {
|
|
315
|
+
let err;
|
|
316
|
+
created.consumers.forEach(c => {
|
|
317
|
+
try {
|
|
318
|
+
c.fns[i]?.(...ev);
|
|
319
|
+
}
|
|
320
|
+
catch (e) {
|
|
321
|
+
err ??= e;
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
if (err !== undefined)
|
|
325
|
+
setTimeout(() => { throw err; }, 0);
|
|
326
|
+
};
|
|
327
|
+
});
|
|
328
|
+
const finish = () => {
|
|
329
|
+
if (wireSubs.get(skey) == created)
|
|
330
|
+
wireSubs.delete(skey);
|
|
331
|
+
created.consumers.forEach(c => c.resolve());
|
|
332
|
+
created.consumers.clear();
|
|
333
|
+
};
|
|
334
|
+
created.stop = () => {
|
|
335
|
+
sendCallWire([...path.slice(0, -1), "removeCallback"], [], false);
|
|
336
|
+
finish();
|
|
337
|
+
};
|
|
338
|
+
sendCallWire(path, realArgs, true).then(finish, finish);
|
|
339
|
+
sub = created;
|
|
340
|
+
}
|
|
341
|
+
const consumer = { fns: args.filter(a => typeof a == "function"), resolve: () => { } };
|
|
342
|
+
sub.consumers.add(consumer);
|
|
343
|
+
const p = new Promise(res => { consumer.resolve = res; });
|
|
344
|
+
const unsub = function unsubscribe() {
|
|
345
|
+
if (!sub.consumers.delete(consumer))
|
|
346
|
+
return;
|
|
347
|
+
consumer.resolve();
|
|
348
|
+
if (sub.consumers.size == 0)
|
|
349
|
+
sub.stop();
|
|
350
|
+
};
|
|
351
|
+
return (0, rpc_off_1.makeOff)(p, unsub, { unsubscribe: unsub, removeCallback: unsub });
|
|
352
|
+
}
|
|
353
|
+
const sendCall = (path, args, wait) => {
|
|
354
|
+
const last = path[path.length - 1];
|
|
355
|
+
if (dedupe && wait && path.length > 1 && (last == "callback" || last == "on") && args.some(a => typeof a == "function")) {
|
|
356
|
+
const isListen = declaredListens ? declaredListens.has(path.slice(0, -1).join(".")) : true;
|
|
357
|
+
if (isListen)
|
|
358
|
+
return subscribeShared(path, args);
|
|
359
|
+
}
|
|
360
|
+
return sendCallWire(path, args, wait);
|
|
361
|
+
};
|
|
141
362
|
const buildProxy = (path, wait) => new Proxy(function () { }, {
|
|
142
363
|
get(_, p) {
|
|
143
364
|
if (p == "then" || p == "catch" || p == Symbol.toPrimitive)
|
|
@@ -184,20 +405,65 @@ function createClient(socket, key, opts) {
|
|
|
184
405
|
const releaseCbs = (fn) => {
|
|
185
406
|
callbacks.forEach((cb, id) => { if (cb == fn) {
|
|
186
407
|
callbacks.delete(id);
|
|
187
|
-
|
|
408
|
+
retire(id);
|
|
188
409
|
} });
|
|
189
410
|
};
|
|
411
|
+
function abortAll(reason) {
|
|
412
|
+
const err = { error: { name: "RPC_ABORT", message: reason } };
|
|
413
|
+
pending.forEach((p, id) => { retire(id); p.fail(err); });
|
|
414
|
+
pending.clear();
|
|
415
|
+
callbacks.forEach((_, id) => retire(id));
|
|
416
|
+
callbacks.clear();
|
|
417
|
+
}
|
|
418
|
+
function drainWireSubs(socketAlive) {
|
|
419
|
+
const subs = Array.from(wireSubs.values());
|
|
420
|
+
wireSubs.clear();
|
|
421
|
+
for (const s of subs) {
|
|
422
|
+
if (socketAlive)
|
|
423
|
+
s.stop();
|
|
424
|
+
else {
|
|
425
|
+
s.consumers.forEach(c => c.resolve());
|
|
426
|
+
s.consumers.clear();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function dispose(reason = "RPC client disposed", opts) {
|
|
431
|
+
if (disposed)
|
|
432
|
+
return;
|
|
433
|
+
const socketAlive = opts?.socketAlive ?? true;
|
|
434
|
+
abortAll(reason);
|
|
435
|
+
drainWireSubs(socketAlive);
|
|
436
|
+
disposed = true;
|
|
437
|
+
authPending = false;
|
|
438
|
+
const sw = strictWaiters;
|
|
439
|
+
strictWaiters = [];
|
|
440
|
+
for (const r of sw)
|
|
441
|
+
r(undefined);
|
|
442
|
+
const aw = authWaiters;
|
|
443
|
+
authWaiters = [];
|
|
444
|
+
for (const r of aw)
|
|
445
|
+
r({ ok: false, reason });
|
|
446
|
+
const dc = disconnectCbs;
|
|
447
|
+
disconnectCbs = [];
|
|
448
|
+
for (const cb of dc)
|
|
449
|
+
try {
|
|
450
|
+
cb(reason);
|
|
451
|
+
}
|
|
452
|
+
catch { }
|
|
453
|
+
disconnectResolve(reason);
|
|
454
|
+
}
|
|
190
455
|
const api = {
|
|
191
456
|
log: s => { debug = s; },
|
|
192
457
|
pending: () => pending.size,
|
|
193
458
|
callbacks: () => callbacks.size,
|
|
194
459
|
clearPromises: (rej = true) => {
|
|
195
|
-
pending.forEach((p, id) => {
|
|
460
|
+
pending.forEach((p, id) => { retire(id); rej ? p.fail("promiseDeleteAll") : p.ok(undefined); });
|
|
196
461
|
pending.clear();
|
|
197
462
|
},
|
|
198
|
-
clearCallbacks: () => { callbacks.forEach((_, id) =>
|
|
463
|
+
clearCallbacks: () => { callbacks.forEach((_, id) => retire(id)); callbacks.clear(); },
|
|
199
464
|
remove: releaseCbs,
|
|
200
465
|
end: releaseCbs,
|
|
466
|
+
subscriptions: () => Array.from(wireSubs, ([k, s]) => ({ key: k, consumers: s.consumers.size })),
|
|
201
467
|
};
|
|
202
468
|
const func = buildProxy([], true);
|
|
203
469
|
const pipe = buildPipeProxy([], [], true);
|
|
@@ -207,12 +473,26 @@ function createClient(socket, key, opts) {
|
|
|
207
473
|
const init = async (obj) => {
|
|
208
474
|
if (obj) {
|
|
209
475
|
strictData = obj;
|
|
476
|
+
return;
|
|
210
477
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
478
|
+
if (authToken != null) {
|
|
479
|
+
authPending = true;
|
|
480
|
+
socket.emit(key, [rpc_protocol_1.Pkt.HELLO, authToken]);
|
|
214
481
|
}
|
|
482
|
+
socket.emit(key, rpc_protocol_1.Pkt.STRICT);
|
|
483
|
+
await new Promise(r => { strictWaiters.push(r); });
|
|
215
484
|
};
|
|
485
|
+
function reauth(token) {
|
|
486
|
+
if (disposed)
|
|
487
|
+
return Promise.resolve({ ok: false, reason: "RPC client disposed" });
|
|
488
|
+
authToken = token;
|
|
489
|
+
authPending = true;
|
|
490
|
+
socket.emit(key, [rpc_protocol_1.Pkt.HELLO, token]);
|
|
491
|
+
return new Promise(res => authWaiters.push(res));
|
|
492
|
+
}
|
|
493
|
+
const auth = () => disposed
|
|
494
|
+
? Promise.resolve(authStatus !== undefined ? authStatus : { ok: false, reason: "RPC client disposed" })
|
|
495
|
+
: (authStatus !== undefined && !authPending) ? Promise.resolve(authStatus) : new Promise(res => authWaiters.push(res));
|
|
216
496
|
return {
|
|
217
497
|
func,
|
|
218
498
|
pipe,
|
|
@@ -221,18 +501,19 @@ function createClient(socket, key, opts) {
|
|
|
221
501
|
all: func,
|
|
222
502
|
strict: buildStrict([], true),
|
|
223
503
|
api,
|
|
224
|
-
abortAll
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
pending.clear();
|
|
228
|
-
callbacks.forEach((_, id) => pool.release(id));
|
|
229
|
-
callbacks.clear();
|
|
230
|
-
},
|
|
504
|
+
abortAll,
|
|
505
|
+
dispose,
|
|
506
|
+
close: dispose,
|
|
231
507
|
schema: () => strictData,
|
|
232
508
|
readyStrict: ready,
|
|
509
|
+
ready,
|
|
233
510
|
initStrict: init,
|
|
511
|
+
init,
|
|
512
|
+
reauth,
|
|
513
|
+
auth,
|
|
514
|
+
onDisconnect,
|
|
234
515
|
};
|
|
235
516
|
}
|
|
236
|
-
function createRpcClient({ socket, socketKey: key, limit }) {
|
|
237
|
-
return createClient(socket, key, { limit });
|
|
517
|
+
function createRpcClient({ socket, socketKey: key, limit, limits, dedupeListen, token, opt }) {
|
|
518
|
+
return createClient(socket, key, { limit, limits, dedupeListen, token, opt });
|
|
238
519
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SocketTmpl } from "./rpc-protocol";
|
|
2
2
|
import { DeepSocketListenSmart } from "./listen-deep";
|
|
3
|
+
import { type RpcOpt } from "./rpc-caps";
|
|
3
4
|
export interface RpcHubSocket extends SocketTmpl {
|
|
4
5
|
disconnect?: () => void;
|
|
5
6
|
}
|
|
@@ -8,11 +9,16 @@ export type RpcDescriptor<T extends object> = {
|
|
|
8
9
|
__type?: T;
|
|
9
10
|
};
|
|
10
11
|
export declare function rpc<T extends object>(socketKey?: string): RpcDescriptor<T>;
|
|
11
|
-
export declare function createRpcClientHub<T extends Record<string, RpcDescriptor<any>>, T2 extends RpcHubSocket>(createSocket: (token: string | null) => T2, schemaBuilder: (helper: typeof rpc) => T
|
|
12
|
+
export declare function createRpcClientHub<T extends Record<string, RpcDescriptor<any>>, T2 extends RpcHubSocket>(createSocket: (token: string | null) => T2, schemaBuilder: (helper: typeof rpc) => T, hubOpts?: {
|
|
13
|
+
opt?: RpcOpt;
|
|
14
|
+
}): {
|
|
12
15
|
readonly promise: Promise<{ [K_1 in keyof { [K in keyof T]: T[K] extends RpcDescriptor<infer U extends object> ? import("./rpc-client").RpcClientReturn<DeepSocketListenSmart<U>> : never; }]: { [K in keyof T]: T[K] extends RpcDescriptor<infer U extends object> ? import("./rpc-client").RpcClientReturn<DeepSocketListenSmart<U>> : never; }[K_1]; }>;
|
|
13
16
|
facade: { [K_1 in keyof { [K in keyof T]: T[K] extends RpcDescriptor<infer U extends object> ? import("./rpc-client").RpcClientReturn<DeepSocketListenSmart<U>> : never; }]: { [K in keyof T]: T[K] extends RpcDescriptor<infer U extends object> ? import("./rpc-client").RpcClientReturn<DeepSocketListenSmart<U>> : never; }[K_1]; };
|
|
14
17
|
setToken: (token: string | null) => Promise<{ [K_1 in keyof { [K in keyof T]: T[K] extends RpcDescriptor<infer U extends object> ? import("./rpc-client").RpcClientReturn<DeepSocketListenSmart<U>> : never; }]: { [K in keyof T]: T[K] extends RpcDescriptor<infer U extends object> ? import("./rpc-client").RpcClientReturn<DeepSocketListenSmart<U>> : never; }[K_1]; }>;
|
|
18
|
+
connect: (token: string | null) => Promise<{ [K_1 in keyof { [K in keyof T]: T[K] extends RpcDescriptor<infer U extends object> ? import("./rpc-client").RpcClientReturn<DeepSocketListenSmart<U>> : never; }]: { [K in keyof T]: T[K] extends RpcDescriptor<infer U extends object> ? import("./rpc-client").RpcClientReturn<DeepSocketListenSmart<U>> : never; }[K_1]; }>;
|
|
19
|
+
reauth: (token: string | null) => Promise<any[]>;
|
|
15
20
|
readonly socket: T2;
|
|
16
21
|
onConnect: (func?: ((count: number) => void) | null) => void;
|
|
22
|
+
onDisconnect: (func?: ((reason: string) => void) | null) => void;
|
|
17
23
|
connectCount: () => number;
|
|
18
24
|
};
|
|
@@ -6,22 +6,32 @@ const rpc_client_1 = require("./rpc-client");
|
|
|
6
6
|
function rpc(socketKey) {
|
|
7
7
|
return { socketKey };
|
|
8
8
|
}
|
|
9
|
-
function createRpcClientHub(createSocket, schemaBuilder) {
|
|
9
|
+
function createRpcClientHub(createSocket, schemaBuilder, hubOpts) {
|
|
10
10
|
const schema = schemaBuilder(rpc);
|
|
11
11
|
const facade = {};
|
|
12
12
|
let socket = null;
|
|
13
|
+
let currentToken = null;
|
|
13
14
|
let connectCount = 0;
|
|
14
15
|
let onConnectCb = null;
|
|
16
|
+
let onDisconnectCb = null;
|
|
15
17
|
let resolveFunc = null;
|
|
16
18
|
let promise = new Promise((resolve) => {
|
|
17
19
|
resolveFunc = resolve;
|
|
18
20
|
});
|
|
19
21
|
function setToken(token) {
|
|
22
|
+
const hadSocket = socket != null;
|
|
20
23
|
socket?.disconnect?.();
|
|
24
|
+
for (const key in schema)
|
|
25
|
+
facade[key]?.dispose?.("token rotated", { socketAlive: false });
|
|
26
|
+
if (hadSocket)
|
|
27
|
+
onDisconnectCb?.("token rotated");
|
|
28
|
+
if (!resolveFunc)
|
|
29
|
+
promise = new Promise((resolve) => { resolveFunc = resolve; });
|
|
30
|
+
currentToken = token;
|
|
21
31
|
socket = createSocket(token);
|
|
22
32
|
for (const key in schema) {
|
|
23
33
|
const targetSocketKey = schema[key].socketKey || key;
|
|
24
|
-
const client = (0, rpc_client_1.createRpcClient)({ socketKey: targetSocketKey, socket });
|
|
34
|
+
const client = (0, rpc_client_1.createRpcClient)({ socketKey: targetSocketKey, socket, token, opt: hubOpts?.opt });
|
|
25
35
|
facade[key] = client;
|
|
26
36
|
}
|
|
27
37
|
function hi() {
|
|
@@ -44,12 +54,25 @@ function createRpcClientHub(createSocket, schemaBuilder) {
|
|
|
44
54
|
});
|
|
45
55
|
return promise;
|
|
46
56
|
}
|
|
57
|
+
function reauth(token) {
|
|
58
|
+
currentToken = token;
|
|
59
|
+
const ps = [];
|
|
60
|
+
for (const key in schema) {
|
|
61
|
+
const client = facade[key];
|
|
62
|
+
if (client && typeof client.reauth === "function")
|
|
63
|
+
ps.push(client.reauth(token));
|
|
64
|
+
}
|
|
65
|
+
return Promise.all(ps);
|
|
66
|
+
}
|
|
47
67
|
const result = {
|
|
48
68
|
get promise() { return promise; },
|
|
49
69
|
facade,
|
|
50
70
|
setToken,
|
|
71
|
+
connect: setToken,
|
|
72
|
+
reauth,
|
|
51
73
|
get socket() { return socket; },
|
|
52
74
|
onConnect: (func) => { onConnectCb = func ?? null; },
|
|
75
|
+
onDisconnect: (func) => { onDisconnectCb = func ?? null; },
|
|
53
76
|
connectCount: () => connectCount,
|
|
54
77
|
};
|
|
55
78
|
return result;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from "./listen-socket";
|
|
2
|
+
export * from "./rpc-off";
|
|
2
3
|
export * from "./listen-deep";
|
|
3
4
|
export * from "./rpc-dynamic";
|
|
4
5
|
export * from "./rpc-protocol";
|
|
6
|
+
export * from "./rpc-caps";
|
|
5
7
|
export * from "./rpc-limits";
|
|
6
8
|
export * from "./rpc-walk";
|
|
7
9
|
export * from "./rpc-client";
|
|
@@ -10,3 +12,4 @@ export * from "./rpc-client-auto";
|
|
|
10
12
|
export * from "./rpc-server-auto";
|
|
11
13
|
export * from "./rpc-clientHub";
|
|
12
14
|
export { createRpcServerAuto2 } from "./createRpcServerAutoWithProtocolDetection";
|
|
15
|
+
export * from "./rpc-inproc";
|
|
@@ -16,9 +16,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.createRpcServerAuto2 = void 0;
|
|
18
18
|
__exportStar(require("./listen-socket"), exports);
|
|
19
|
+
__exportStar(require("./rpc-off"), exports);
|
|
19
20
|
__exportStar(require("./listen-deep"), exports);
|
|
20
21
|
__exportStar(require("./rpc-dynamic"), exports);
|
|
21
22
|
__exportStar(require("./rpc-protocol"), exports);
|
|
23
|
+
__exportStar(require("./rpc-caps"), exports);
|
|
22
24
|
__exportStar(require("./rpc-limits"), exports);
|
|
23
25
|
__exportStar(require("./rpc-walk"), exports);
|
|
24
26
|
__exportStar(require("./rpc-client"), exports);
|
|
@@ -28,3 +30,4 @@ __exportStar(require("./rpc-server-auto"), exports);
|
|
|
28
30
|
__exportStar(require("./rpc-clientHub"), exports);
|
|
29
31
|
var createRpcServerAutoWithProtocolDetection_1 = require("./createRpcServerAutoWithProtocolDetection");
|
|
30
32
|
Object.defineProperty(exports, "createRpcServerAuto2", { enumerable: true, get: function () { return createRpcServerAutoWithProtocolDetection_1.createRpcServerAuto2; } });
|
|
33
|
+
__exportStar(require("./rpc-inproc"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type RpcLimits, type RpcServerAuth, type RpcOpt } from './rpc-server';
|
|
2
|
+
import type { SocketTmpl } from './rpc-protocol';
|
|
3
|
+
import type { DeepSocketListen } from './listen-deep';
|
|
4
|
+
export declare function createInProcSocketPair(): [SocketTmpl, SocketTmpl];
|
|
5
|
+
export declare function createRpcInProc<T extends object>({ object: target, socketKey, listen, debug, hooks, limits, auth, token, throttle, maxPerListen, opt, }: {
|
|
6
|
+
object: T;
|
|
7
|
+
socketKey?: string;
|
|
8
|
+
listen?: boolean;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
hooks?: any;
|
|
11
|
+
limits?: RpcLimits;
|
|
12
|
+
auth?: RpcServerAuth;
|
|
13
|
+
token?: any;
|
|
14
|
+
throttle?: number;
|
|
15
|
+
maxPerListen?: number;
|
|
16
|
+
opt?: RpcOpt;
|
|
17
|
+
}): import("./rpc-client").RpcClientReturn<DeepSocketListen<T>>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createInProcSocketPair = createInProcSocketPair;
|
|
4
|
+
exports.createRpcInProc = createRpcInProc;
|
|
5
|
+
const rpc_server_1 = require("./rpc-server");
|
|
6
|
+
const rpc_server_auto_1 = require("./rpc-server-auto");
|
|
7
|
+
const rpc_client_1 = require("./rpc-client");
|
|
8
|
+
function createInProcSocketPair() {
|
|
9
|
+
const A = {};
|
|
10
|
+
const B = {};
|
|
11
|
+
const make = (mine, theirs) => ({
|
|
12
|
+
on: (e, cb) => { (mine[e] ??= []).push(cb); },
|
|
13
|
+
emit: (e, d) => {
|
|
14
|
+
const wire = d === undefined ? undefined : JSON.parse(JSON.stringify(d));
|
|
15
|
+
for (const cb of (theirs[e] ?? []))
|
|
16
|
+
queueMicrotask(() => cb(wire));
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
return [make(A, B), make(B, A)];
|
|
20
|
+
}
|
|
21
|
+
function createRpcInProc({ object: target, socketKey = 'rpc', listen = true, debug, hooks, limits, auth, token, throttle, maxPerListen, opt, }) {
|
|
22
|
+
const [clientSocket, serverSocket] = createInProcSocketPair();
|
|
23
|
+
if (listen) {
|
|
24
|
+
(0, rpc_server_auto_1.createRpcServerAuto)({ socket: serverSocket, object: target, socketKey, debug, hooks, limits, auth, throttle, maxPerListen, opt });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
(0, rpc_server_1.createRpcServer)({ socket: serverSocket, object: target, socketKey, debug, hooks: hooks, limits, auth, opt });
|
|
28
|
+
}
|
|
29
|
+
return (0, rpc_client_1.createRpcClient)({ socket: clientSocket, socketKey, limits, token, opt });
|
|
30
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { rpcEndCallback } from "./rpc-walk";
|
|
2
|
+
export declare const endCallback: typeof rpcEndCallback;
|
|
3
|
+
type tThenable<V> = {
|
|
4
|
+
then: Promise<V>['then'];
|
|
5
|
+
catch: Promise<V>['catch'];
|
|
6
|
+
finally: Promise<V>['finally'];
|
|
7
|
+
};
|
|
8
|
+
export type Off<V = void, X extends object = {}> = (() => void) & tThenable<V> & X;
|
|
9
|
+
export declare function makeOff<V, X extends object = {}>(promise: Promise<V>, stop: () => void, extra?: X): Off<V, X>;
|
|
10
|
+
export {};
|