wenay-common2 1.0.50 → 1.0.53
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/lib/Common/ObserveAll2/reactive2.d.ts +28 -0
- package/lib/Common/ObserveAll2/reactive2.js +108 -18
- package/lib/Common/ObserveAll2/store.d.ts +36 -7
- package/lib/Common/ObserveAll2/store.js +145 -20
- package/lib/Common/events/Listen3.d.ts +13 -4
- package/lib/Common/events/Listen3.js +7 -3
- package/lib/Common/events/SocketBuffer.d.ts +1 -0
- package/lib/Common/events/SocketServerHook.d.ts +3 -0
- package/lib/Common/events/UseListenTransform.d.ts +1 -0
- package/lib/Common/rcp/createRpcServerAutoWithProtocolDetection.js +6 -6
- package/lib/Common/rcp/listen-socket.d.ts +6 -1
- package/lib/Common/rcp/listen-socket.js +23 -14
- package/lib/Common/rcp/rpc-client.js +1 -1
- package/lib/Common/rcp/rpc-server-auto.js +8 -8
- package/lib/Common/rcp/rpc-server.js +3 -2
- package/package.json +1 -1
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
type Fn = () => void;
|
|
2
|
+
export type ReactiveChange = {
|
|
3
|
+
paths: PropertyKey[][];
|
|
4
|
+
};
|
|
5
|
+
type PathUpdateFn = (change: ReactiveChange) => void;
|
|
2
6
|
type Drain = 'micro' | 'immediate' | number | ((flush: Fn) => void);
|
|
3
7
|
export type Opts = {
|
|
4
8
|
drain?: Drain;
|
|
@@ -7,7 +11,9 @@ export type Opts = {
|
|
|
7
11
|
};
|
|
8
12
|
export declare function reactive<T extends object>(root: T, opts?: Opts): T;
|
|
9
13
|
export declare function isReactive(p: any): boolean;
|
|
14
|
+
export declare function toRaw<T>(p: T): T;
|
|
10
15
|
export declare function onUpdate(p: any, cb: Fn): () => void;
|
|
16
|
+
export declare function onUpdatePaths(p: any, cb: PathUpdateFn): () => void;
|
|
11
17
|
export declare function flushReactive(p: any): Promise<void>;
|
|
12
18
|
export declare function listenUpdate(p: any): {
|
|
13
19
|
func: import("../events/Listen3").Listener<[]>;
|
|
@@ -18,6 +24,7 @@ export declare function listenUpdate(p: any): {
|
|
|
18
24
|
onClose: (cb: () => void) => () => void;
|
|
19
25
|
removeEventClose: (cb: () => void) => void;
|
|
20
26
|
on: import("../events/Listen3").ListenOn<[]>;
|
|
27
|
+
off: (k: (string | symbol) | import("../events/Listen3").Listener<[]> | null) => void;
|
|
21
28
|
addListen: (cb: import("../events/Listen3").Listener<[]>, opts?: {
|
|
22
29
|
cbClose?: () => void;
|
|
23
30
|
key?: string | symbol;
|
|
@@ -29,5 +36,26 @@ export declare function listenUpdate(p: any): {
|
|
|
29
36
|
count: () => number;
|
|
30
37
|
readonly getAllKeys: (string | symbol)[];
|
|
31
38
|
};
|
|
39
|
+
export declare function listenUpdatePaths(p: any): {
|
|
40
|
+
func: import("../events/Listen3").Listener<[ReactiveChange]>;
|
|
41
|
+
isRun: () => boolean;
|
|
42
|
+
run: () => void;
|
|
43
|
+
close: () => void;
|
|
44
|
+
eventClose: (cb: () => void) => () => void;
|
|
45
|
+
onClose: (cb: () => void) => () => void;
|
|
46
|
+
removeEventClose: (cb: () => void) => void;
|
|
47
|
+
on: import("../events/Listen3").ListenOn<[ReactiveChange]>;
|
|
48
|
+
off: (k: (string | symbol) | import("../events/Listen3").Listener<[ReactiveChange]> | null) => void;
|
|
49
|
+
addListen: (cb: import("../events/Listen3").Listener<[ReactiveChange]>, opts?: {
|
|
50
|
+
cbClose?: () => void;
|
|
51
|
+
key?: string | symbol;
|
|
52
|
+
}) => () => void;
|
|
53
|
+
removeListen: (k: (string | symbol) | import("../events/Listen3").Listener<[ReactiveChange]> | null) => void;
|
|
54
|
+
once: (cb: import("../events/Listen3").Listener<[ReactiveChange]>, opts?: {
|
|
55
|
+
key?: string | symbol;
|
|
56
|
+
}) => () => void;
|
|
57
|
+
count: () => number;
|
|
58
|
+
readonly getAllKeys: (string | symbol)[];
|
|
59
|
+
};
|
|
32
60
|
export type Reactive<T extends object> = T;
|
|
33
61
|
export {};
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.reactive = reactive;
|
|
4
4
|
exports.isReactive = isReactive;
|
|
5
|
+
exports.toRaw = toRaw;
|
|
5
6
|
exports.onUpdate = onUpdate;
|
|
7
|
+
exports.onUpdatePaths = onUpdatePaths;
|
|
6
8
|
exports.flushReactive = flushReactive;
|
|
7
9
|
exports.listenUpdate = listenUpdate;
|
|
10
|
+
exports.listenUpdatePaths = listenUpdatePaths;
|
|
8
11
|
const Listen_1 = require("../events/Listen");
|
|
9
12
|
const NODE = Symbol('reactive2.node');
|
|
10
13
|
const isObj = (v) => v != null && typeof v == 'object';
|
|
@@ -30,7 +33,7 @@ function reactive(root, opts = {}) {
|
|
|
30
33
|
const { drain = 'immediate', depth = Infinity, eager = false } = opts;
|
|
31
34
|
const fire = scheduler(drain);
|
|
32
35
|
const eng = {
|
|
33
|
-
live: 0, dirty: new Set(), scheduled: false, waiters: new Set(), depth,
|
|
36
|
+
live: 0, pathLive: 0, dirty: new Set(), dirtyPaths: [], scheduled: false, waiters: new Set(), depth,
|
|
34
37
|
schedule() {
|
|
35
38
|
if (eng.scheduled)
|
|
36
39
|
return;
|
|
@@ -39,8 +42,10 @@ function reactive(root, opts = {}) {
|
|
|
39
42
|
eng.scheduled = false;
|
|
40
43
|
const batch = [...eng.dirty];
|
|
41
44
|
eng.dirty.clear();
|
|
45
|
+
const dirtyPaths = eng.dirtyPaths;
|
|
46
|
+
eng.dirtyPaths = [];
|
|
42
47
|
let err;
|
|
43
|
-
for (const n of batch)
|
|
48
|
+
for (const n of batch) {
|
|
44
49
|
for (const cb of [...n.subs]) {
|
|
45
50
|
try {
|
|
46
51
|
cb();
|
|
@@ -49,7 +54,20 @@ function reactive(root, opts = {}) {
|
|
|
49
54
|
err ??= e;
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
|
-
|
|
57
|
+
if (n.pathSubs.size) {
|
|
58
|
+
const paths = pathsForNode(n, dirtyPaths);
|
|
59
|
+
if (paths.length)
|
|
60
|
+
for (const cb of [...n.pathSubs]) {
|
|
61
|
+
try {
|
|
62
|
+
cb({ paths });
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
err ??= e;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!eng.scheduled && eng.dirty.size == 0 && eng.dirtyPaths.length == 0) {
|
|
53
71
|
const waiters = [...eng.waiters];
|
|
54
72
|
eng.waiters.clear();
|
|
55
73
|
for (const w of waiters)
|
|
@@ -60,13 +78,16 @@ function reactive(root, opts = {}) {
|
|
|
60
78
|
});
|
|
61
79
|
},
|
|
62
80
|
};
|
|
63
|
-
const rootNode = makeNode(root, null, 0, eng);
|
|
81
|
+
const rootNode = makeNode(root, null, [], 0, eng);
|
|
64
82
|
if (eager)
|
|
65
83
|
prewalk(rootNode);
|
|
66
84
|
return rootNode.proxy;
|
|
67
85
|
}
|
|
68
|
-
function makeNode(target, parent, level, eng) {
|
|
69
|
-
const node = {
|
|
86
|
+
function makeNode(target, parent, path, level, eng) {
|
|
87
|
+
const node = {
|
|
88
|
+
target, parent, path, active: true, level,
|
|
89
|
+
subs: new Set(), pathSubs: new Set(), kids: new Map(), proxy: null, eng,
|
|
90
|
+
};
|
|
70
91
|
const proxyTarget = (Array.isArray(target) ? [] : {});
|
|
71
92
|
node.proxy = new Proxy(proxyTarget, {
|
|
72
93
|
get(_, k) {
|
|
@@ -78,7 +99,7 @@ function makeNode(target, parent, level, eng) {
|
|
|
78
99
|
if (isReactiveObj(v) && level < eng.depth) {
|
|
79
100
|
let kid = node.kids.get(k);
|
|
80
101
|
if (!kid) {
|
|
81
|
-
kid = makeNode(v, node, level + 1, eng);
|
|
102
|
+
kid = makeNode(v, node, [...node.path, k], level + 1, eng);
|
|
82
103
|
node.kids.set(k, kid);
|
|
83
104
|
}
|
|
84
105
|
else if (kid.target !== v)
|
|
@@ -88,8 +109,10 @@ function makeNode(target, parent, level, eng) {
|
|
|
88
109
|
return v;
|
|
89
110
|
},
|
|
90
111
|
set(_, k, v) {
|
|
112
|
+
v = toRaw(v);
|
|
91
113
|
if (Object.is(node.target[k], v))
|
|
92
114
|
return true;
|
|
115
|
+
const dirtyPath = dirtyPathFor(node, k);
|
|
93
116
|
node.target[k] = v;
|
|
94
117
|
if (Array.isArray(proxyTarget) && k == "length")
|
|
95
118
|
proxyTarget.length = v;
|
|
@@ -97,21 +120,23 @@ function makeNode(target, parent, level, eng) {
|
|
|
97
120
|
if (kid)
|
|
98
121
|
rebind(kid, v);
|
|
99
122
|
if (eng.live > 0)
|
|
100
|
-
bubble(node);
|
|
123
|
+
bubble(node, dirtyPath);
|
|
101
124
|
return true;
|
|
102
125
|
},
|
|
103
126
|
defineProperty(_, k, d) {
|
|
104
127
|
const old = node.target[k];
|
|
105
|
-
const
|
|
128
|
+
const desc = 'value' in d ? { ...d, value: toRaw(d.value) } : d;
|
|
129
|
+
const ok = Reflect.defineProperty(node.target, k, desc);
|
|
106
130
|
if (!ok)
|
|
107
131
|
return false;
|
|
108
|
-
if (
|
|
109
|
-
const mirror = Reflect.defineProperty(proxyTarget, k,
|
|
132
|
+
if (desc.configurable === false) {
|
|
133
|
+
const mirror = Reflect.defineProperty(proxyTarget, k, desc);
|
|
110
134
|
if (!mirror)
|
|
111
135
|
return false;
|
|
112
136
|
}
|
|
113
137
|
const v = node.target[k];
|
|
114
138
|
if (!Object.is(old, v)) {
|
|
139
|
+
const dirtyPath = dirtyPathFor(node, k);
|
|
115
140
|
const kid = node.kids.get(k);
|
|
116
141
|
if (kid) {
|
|
117
142
|
if (isReactiveObj(v))
|
|
@@ -123,13 +148,14 @@ function makeNode(target, parent, level, eng) {
|
|
|
123
148
|
}
|
|
124
149
|
}
|
|
125
150
|
if (eng.live > 0)
|
|
126
|
-
bubble(node);
|
|
151
|
+
bubble(node, dirtyPath);
|
|
127
152
|
}
|
|
128
153
|
return true;
|
|
129
154
|
},
|
|
130
155
|
deleteProperty(_, k) {
|
|
131
156
|
if (!(k in node.target))
|
|
132
157
|
return true;
|
|
158
|
+
const dirtyPath = dirtyPathFor(node, k);
|
|
133
159
|
delete node.target[k];
|
|
134
160
|
const kid = node.kids.get(k);
|
|
135
161
|
if (kid) {
|
|
@@ -138,7 +164,7 @@ function makeNode(target, parent, level, eng) {
|
|
|
138
164
|
detachTree(kid);
|
|
139
165
|
}
|
|
140
166
|
if (eng.live > 0)
|
|
141
|
-
bubble(node);
|
|
167
|
+
bubble(node, dirtyPath);
|
|
142
168
|
return true;
|
|
143
169
|
},
|
|
144
170
|
has(_, k) { return k in node.target; },
|
|
@@ -165,16 +191,18 @@ function makeNode(target, parent, level, eng) {
|
|
|
165
191
|
});
|
|
166
192
|
return node;
|
|
167
193
|
}
|
|
168
|
-
function bubble(from) {
|
|
194
|
+
function bubble(from, dirtyPath) {
|
|
169
195
|
const eng = from.eng;
|
|
196
|
+
if (eng.pathLive > 0 && dirtyPath)
|
|
197
|
+
addDirtyPath(eng, dirtyPath);
|
|
170
198
|
for (let n = from; n && n.active; n = n.parent)
|
|
171
|
-
if (n.subs.size)
|
|
199
|
+
if (n.subs.size || n.pathSubs.size)
|
|
172
200
|
eng.dirty.add(n);
|
|
173
201
|
eng.schedule();
|
|
174
202
|
}
|
|
175
203
|
function rebind(node, next) {
|
|
176
204
|
node.target = next;
|
|
177
|
-
if (node.subs.size)
|
|
205
|
+
if (node.subs.size || node.pathSubs.size)
|
|
178
206
|
node.eng.dirty.add(node);
|
|
179
207
|
for (const [k, kid] of [...node.kids]) {
|
|
180
208
|
const cv = isReactiveObj(next) ? next[k] : undefined;
|
|
@@ -188,11 +216,37 @@ function rebind(node, next) {
|
|
|
188
216
|
}
|
|
189
217
|
}
|
|
190
218
|
function markChanged(node) {
|
|
191
|
-
if (node.subs.size)
|
|
219
|
+
if (node.subs.size || node.pathSubs.size)
|
|
192
220
|
node.eng.dirty.add(node);
|
|
193
221
|
for (const kid of node.kids.values())
|
|
194
222
|
markChanged(kid);
|
|
195
223
|
}
|
|
224
|
+
function dirtyPathFor(node, key) {
|
|
225
|
+
return Array.isArray(node.target) ? [...node.path] : [...node.path, key];
|
|
226
|
+
}
|
|
227
|
+
function addDirtyPath(eng, path) {
|
|
228
|
+
if (!eng.dirtyPaths.some(p => samePath(p, path)))
|
|
229
|
+
eng.dirtyPaths.push([...path]);
|
|
230
|
+
}
|
|
231
|
+
function samePath(a, b) {
|
|
232
|
+
return a.length == b.length && a.every((k, i) => Object.is(k, b[i]));
|
|
233
|
+
}
|
|
234
|
+
function startsWithPath(path, prefix) {
|
|
235
|
+
return prefix.length <= path.length && prefix.every((k, i) => Object.is(k, path[i]));
|
|
236
|
+
}
|
|
237
|
+
function pathsForNode(node, dirtyPaths) {
|
|
238
|
+
const out = [];
|
|
239
|
+
for (const path of dirtyPaths) {
|
|
240
|
+
let next = null;
|
|
241
|
+
if (startsWithPath(path, node.path))
|
|
242
|
+
next = path.slice(node.path.length);
|
|
243
|
+
else if (startsWithPath(node.path, path))
|
|
244
|
+
next = [];
|
|
245
|
+
if (next && !out.some(p => samePath(p, next)))
|
|
246
|
+
out.push(next);
|
|
247
|
+
}
|
|
248
|
+
return out;
|
|
249
|
+
}
|
|
196
250
|
function detachTree(node) {
|
|
197
251
|
if (!node.active)
|
|
198
252
|
return;
|
|
@@ -218,6 +272,10 @@ function isReactive(p) {
|
|
|
218
272
|
const node = p && p[NODE];
|
|
219
273
|
return !!node && node.active;
|
|
220
274
|
}
|
|
275
|
+
function toRaw(p) {
|
|
276
|
+
const node = p && p[NODE];
|
|
277
|
+
return node ? node.target : p;
|
|
278
|
+
}
|
|
221
279
|
function onUpdate(p, cb) {
|
|
222
280
|
const node = p && p[NODE];
|
|
223
281
|
if (!node)
|
|
@@ -232,12 +290,33 @@ function onUpdate(p, cb) {
|
|
|
232
290
|
return; done = true; if (node.subs.delete(sub))
|
|
233
291
|
node.eng.live--; };
|
|
234
292
|
}
|
|
293
|
+
function onUpdatePaths(p, cb) {
|
|
294
|
+
const node = p && p[NODE];
|
|
295
|
+
if (!node)
|
|
296
|
+
throw new Error('onUpdatePaths: not a reactive object');
|
|
297
|
+
if (!node.active)
|
|
298
|
+
throw new Error('onUpdatePaths: reactive object is detached');
|
|
299
|
+
const sub = (change) => cb(change);
|
|
300
|
+
node.pathSubs.add(sub);
|
|
301
|
+
node.eng.live++;
|
|
302
|
+
node.eng.pathLive++;
|
|
303
|
+
let done = false;
|
|
304
|
+
return () => {
|
|
305
|
+
if (done)
|
|
306
|
+
return;
|
|
307
|
+
done = true;
|
|
308
|
+
if (node.pathSubs.delete(sub)) {
|
|
309
|
+
node.eng.live--;
|
|
310
|
+
node.eng.pathLive--;
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
235
314
|
function flushReactive(p) {
|
|
236
315
|
const node = p && p[NODE];
|
|
237
316
|
if (!node)
|
|
238
317
|
throw new Error('flushReactive: not a reactive object');
|
|
239
318
|
const eng = node.eng;
|
|
240
|
-
if (!eng.scheduled && eng.dirty.size == 0)
|
|
319
|
+
if (!eng.scheduled && eng.dirty.size == 0 && eng.dirtyPaths.length == 0)
|
|
241
320
|
return Promise.resolve();
|
|
242
321
|
return new Promise(resolve => { eng.waiters.add(resolve); });
|
|
243
322
|
}
|
|
@@ -252,3 +331,14 @@ function listenUpdate(p) {
|
|
|
252
331
|
});
|
|
253
332
|
return listen;
|
|
254
333
|
}
|
|
334
|
+
function listenUpdatePaths(p) {
|
|
335
|
+
const listen = (0, Listen_1.funcListenCallbackBase)((emit) => onUpdatePaths(p, change => emit(change)), {
|
|
336
|
+
event: (type, count, api) => {
|
|
337
|
+
if (type == "add" && count == 1 && !api.isRun())
|
|
338
|
+
api.run();
|
|
339
|
+
if (type == "remove" && count == 0 && api.isRun())
|
|
340
|
+
api.close();
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
return listen;
|
|
344
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { listenUpdate, reactive } from "./reactive2";
|
|
1
|
+
import { listenUpdate, listenUpdatePaths, reactive, ReactiveChange } from "./reactive2";
|
|
2
2
|
export type StorePath = readonly PropertyKey[];
|
|
3
3
|
export type StoreDrain = "micro" | "immediate" | number | ((flush: () => void) => void);
|
|
4
4
|
export type StoreSubOpts = {
|
|
@@ -6,6 +6,11 @@ export type StoreSubOpts = {
|
|
|
6
6
|
drain?: StoreDrain;
|
|
7
7
|
key?: string;
|
|
8
8
|
};
|
|
9
|
+
export type StoreChange = ReactiveChange;
|
|
10
|
+
export type StoreSyncOpts = StoreSubOpts & {
|
|
11
|
+
partial?: boolean;
|
|
12
|
+
onError?: (error: any) => void;
|
|
13
|
+
};
|
|
9
14
|
export type StoreCtx<T = any> = {
|
|
10
15
|
store: Store<any>;
|
|
11
16
|
node: StoreNode<T>;
|
|
@@ -60,11 +65,13 @@ export type Store<T extends object> = {
|
|
|
60
65
|
once(cb: (value: T, ctx: StoreCtx<T>) => void, opts?: StoreSubOpts): () => void;
|
|
61
66
|
update<M extends StoreMask<T>>(mask: M, opts?: StoreSubOpts): StoreSelection<T, M>;
|
|
62
67
|
listen(): ReturnType<typeof listenUpdate>;
|
|
68
|
+
listenPaths(): ReturnType<typeof listenUpdatePaths>;
|
|
63
69
|
count(): number;
|
|
64
70
|
};
|
|
65
71
|
type RemoteStore<T extends object> = {
|
|
66
72
|
get(mask?: any): T | Promise<T>;
|
|
67
73
|
changed: any;
|
|
74
|
+
changedPaths?: any;
|
|
68
75
|
};
|
|
69
76
|
export declare function createStore<T extends object>(initial: T, opts?: Parameters<typeof reactive<T>>[1]): Store<T>;
|
|
70
77
|
export declare function exposeStore<T extends object>(store: Store<T>): {
|
|
@@ -72,20 +79,42 @@ export declare function exposeStore<T extends object>(store: Store<T>): {
|
|
|
72
79
|
set: (path: StorePath, value: any) => void;
|
|
73
80
|
replace: (path: StorePath, value: any) => void;
|
|
74
81
|
changed: {
|
|
75
|
-
func: import("
|
|
82
|
+
func: import("../..").Listener<[]>;
|
|
83
|
+
isRun: () => boolean;
|
|
84
|
+
run: () => void;
|
|
85
|
+
close: () => void;
|
|
86
|
+
eventClose: (cb: () => void) => () => void;
|
|
87
|
+
onClose: (cb: () => void) => () => void;
|
|
88
|
+
removeEventClose: (cb: () => void) => void;
|
|
89
|
+
on: import("../..").ListenOn<[]>;
|
|
90
|
+
off: (k: (string | symbol) | import("../..").Listener<[]> | null) => void;
|
|
91
|
+
addListen: (cb: import("../..").Listener<[]>, opts?: {
|
|
92
|
+
cbClose?: () => void;
|
|
93
|
+
key?: string | symbol;
|
|
94
|
+
}) => () => void;
|
|
95
|
+
removeListen: (k: (string | symbol) | import("../..").Listener<[]> | null) => void;
|
|
96
|
+
once: (cb: import("../..").Listener<[]>, opts?: {
|
|
97
|
+
key?: string | symbol;
|
|
98
|
+
}) => () => void;
|
|
99
|
+
count: () => number;
|
|
100
|
+
readonly getAllKeys: (string | symbol)[];
|
|
101
|
+
};
|
|
102
|
+
changedPaths: {
|
|
103
|
+
func: import("../..").Listener<[ReactiveChange]>;
|
|
76
104
|
isRun: () => boolean;
|
|
77
105
|
run: () => void;
|
|
78
106
|
close: () => void;
|
|
79
107
|
eventClose: (cb: () => void) => () => void;
|
|
80
108
|
onClose: (cb: () => void) => () => void;
|
|
81
109
|
removeEventClose: (cb: () => void) => void;
|
|
82
|
-
on: import("
|
|
83
|
-
|
|
110
|
+
on: import("../..").ListenOn<[ReactiveChange]>;
|
|
111
|
+
off: (k: (string | symbol) | import("../..").Listener<[ReactiveChange]> | null) => void;
|
|
112
|
+
addListen: (cb: import("../..").Listener<[ReactiveChange]>, opts?: {
|
|
84
113
|
cbClose?: () => void;
|
|
85
114
|
key?: string | symbol;
|
|
86
115
|
}) => () => void;
|
|
87
|
-
removeListen: (k: (string | symbol) | import("
|
|
88
|
-
once: (cb: import("
|
|
116
|
+
removeListen: (k: (string | symbol) | import("../..").Listener<[ReactiveChange]> | null) => void;
|
|
117
|
+
once: (cb: import("../..").Listener<[ReactiveChange]>, opts?: {
|
|
89
118
|
key?: string | symbol;
|
|
90
119
|
}) => () => void;
|
|
91
120
|
count: () => number;
|
|
@@ -93,6 +122,6 @@ export declare function exposeStore<T extends object>(store: Store<T>): {
|
|
|
93
122
|
};
|
|
94
123
|
};
|
|
95
124
|
export declare function createStoreMirror<T extends object>(remote: RemoteStore<T>, initial?: T, opts?: Parameters<typeof createStore<T>>[1]): Store<T> & {
|
|
96
|
-
sync: <M extends StoreMask<T>>(mask: M, subOpts?:
|
|
125
|
+
sync: <M extends StoreMask<T>>(mask: M, subOpts?: StoreSyncOpts) => Promise<() => void>;
|
|
97
126
|
};
|
|
98
127
|
export {};
|
|
@@ -5,9 +5,22 @@ exports.exposeStore = exposeStore;
|
|
|
5
5
|
exports.createStoreMirror = createStoreMirror;
|
|
6
6
|
const reactive2_1 = require("./reactive2");
|
|
7
7
|
const hasSetImmediate = typeof setImmediate == "function";
|
|
8
|
-
function
|
|
8
|
+
function pathText(path) {
|
|
9
9
|
return path.map(String).join(".");
|
|
10
10
|
}
|
|
11
|
+
const symbolIds = new Map();
|
|
12
|
+
let nextSymbolId = 1;
|
|
13
|
+
function symbolKey(k) {
|
|
14
|
+
let id = symbolIds.get(k);
|
|
15
|
+
if (id == null) {
|
|
16
|
+
id = nextSymbolId++;
|
|
17
|
+
symbolIds.set(k, id);
|
|
18
|
+
}
|
|
19
|
+
return id;
|
|
20
|
+
}
|
|
21
|
+
function pathKey(path) {
|
|
22
|
+
return JSON.stringify(path.map(k => typeof k == "symbol" ? ["symbol", symbolKey(k)] : ["key", String(k)]));
|
|
23
|
+
}
|
|
11
24
|
function schedule(drain, flush) {
|
|
12
25
|
if (drain == null) {
|
|
13
26
|
flush();
|
|
@@ -102,6 +115,7 @@ function setAt(root, path, value) {
|
|
|
102
115
|
p[path[path.length - 1]] = value;
|
|
103
116
|
}
|
|
104
117
|
function snapshotValue(value, seen = new WeakMap()) {
|
|
118
|
+
value = (0, reactive2_1.toRaw)(value);
|
|
105
119
|
if (!isObj(value))
|
|
106
120
|
return value;
|
|
107
121
|
if (value instanceof Date)
|
|
@@ -135,26 +149,92 @@ function maskPaths(mask, base = []) {
|
|
|
135
149
|
if (!isObj(mask))
|
|
136
150
|
return [base];
|
|
137
151
|
const out = [];
|
|
138
|
-
for (const k of
|
|
152
|
+
for (const k of Reflect.ownKeys(mask))
|
|
139
153
|
out.push(...maskPaths(mask[k], [...base, k]));
|
|
140
154
|
return out;
|
|
141
155
|
}
|
|
142
156
|
function pickSnapshot(root, mask, base = []) {
|
|
157
|
+
root = (0, reactive2_1.toRaw)(root);
|
|
143
158
|
if (mask === true || mask == null)
|
|
144
159
|
return snapshotValue(getAt(root, base));
|
|
145
160
|
const out = {};
|
|
146
|
-
for (const k of
|
|
161
|
+
for (const k of Reflect.ownKeys(mask))
|
|
147
162
|
out[k] = pickSnapshot(root, mask[k], [...base, k]);
|
|
148
163
|
return out;
|
|
149
164
|
}
|
|
165
|
+
function deleteAt(root, path) {
|
|
166
|
+
if (path.length == 0) {
|
|
167
|
+
replaceRoot(root, {});
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const parent = getAt(root, path.slice(0, -1));
|
|
171
|
+
if (isObj(parent))
|
|
172
|
+
delete parent[path[path.length - 1]];
|
|
173
|
+
}
|
|
150
174
|
function applyMask(root, mask, data, base = []) {
|
|
151
175
|
if (mask === true || mask == null) {
|
|
152
|
-
|
|
176
|
+
if (data === undefined && base.length)
|
|
177
|
+
deleteAt(root, base);
|
|
178
|
+
else
|
|
179
|
+
setAt(root, base, snapshotValue(data));
|
|
153
180
|
return;
|
|
154
181
|
}
|
|
155
|
-
for (const k of
|
|
182
|
+
for (const k of Reflect.ownKeys(mask))
|
|
156
183
|
applyMask(root, mask[k], data?.[k], [...base, k]);
|
|
157
184
|
}
|
|
185
|
+
function pathToMask(path) {
|
|
186
|
+
let out = true;
|
|
187
|
+
for (let i = path.length - 1; i >= 0; i--)
|
|
188
|
+
out = { [path[i]]: out };
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
function hasMaskKey(mask, key) {
|
|
192
|
+
return isObj(mask) && Reflect.ownKeys(mask).some(k => Object.is(k, key));
|
|
193
|
+
}
|
|
194
|
+
function mergeMasks(a, b) {
|
|
195
|
+
if (a === undefined)
|
|
196
|
+
return b;
|
|
197
|
+
if (b === undefined)
|
|
198
|
+
return a;
|
|
199
|
+
if (a === true || a == null || b === true || b == null)
|
|
200
|
+
return true;
|
|
201
|
+
if (!isObj(a) || !isObj(b))
|
|
202
|
+
return true;
|
|
203
|
+
const out = {};
|
|
204
|
+
for (const k of Reflect.ownKeys(a))
|
|
205
|
+
out[k] = a[k];
|
|
206
|
+
for (const k of Reflect.ownKeys(b)) {
|
|
207
|
+
out[k] = hasMaskKey(a, k) ? mergeMasks(a[k], b[k]) : b[k];
|
|
208
|
+
}
|
|
209
|
+
return out;
|
|
210
|
+
}
|
|
211
|
+
function startsWithPath(path, prefix) {
|
|
212
|
+
return prefix.length <= path.length && prefix.every((k, i) => Object.is(k, path[i]));
|
|
213
|
+
}
|
|
214
|
+
function intersectMaskWithPaths(mask, dirtyPaths) {
|
|
215
|
+
const baseMask = mask ?? true;
|
|
216
|
+
if (!Array.isArray(dirtyPaths))
|
|
217
|
+
return baseMask;
|
|
218
|
+
if (dirtyPaths.length == 0)
|
|
219
|
+
return undefined;
|
|
220
|
+
const selected = maskPaths(baseMask);
|
|
221
|
+
let out = undefined;
|
|
222
|
+
for (const dirty of dirtyPaths) {
|
|
223
|
+
if (!Array.isArray(dirty))
|
|
224
|
+
continue;
|
|
225
|
+
if (dirty.length == 0) {
|
|
226
|
+
out = mergeMasks(out, baseMask);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
for (const selectedPath of selected) {
|
|
230
|
+
if (startsWithPath(dirty, selectedPath))
|
|
231
|
+
out = mergeMasks(out, pathToMask(dirty));
|
|
232
|
+
else if (startsWithPath(selectedPath, dirty))
|
|
233
|
+
out = mergeMasks(out, pathToMask(selectedPath));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
158
238
|
function watchTarget(root, path) {
|
|
159
239
|
let cur = root;
|
|
160
240
|
let lastReactive = root;
|
|
@@ -183,7 +263,7 @@ function makeCtx(store, path) {
|
|
|
183
263
|
store,
|
|
184
264
|
node: getNode(store, path),
|
|
185
265
|
path: [...path],
|
|
186
|
-
pathString:
|
|
266
|
+
pathString: pathText(path),
|
|
187
267
|
exists: hasAt(store._state, path),
|
|
188
268
|
};
|
|
189
269
|
}
|
|
@@ -259,7 +339,7 @@ function getNode(store, path) {
|
|
|
259
339
|
return cached;
|
|
260
340
|
const api = {
|
|
261
341
|
get path() { return [...path]; },
|
|
262
|
-
get pathString() { return
|
|
342
|
+
get pathString() { return pathText(path); },
|
|
263
343
|
get: () => getAt(store._state, path),
|
|
264
344
|
has: () => hasAt(store._state, path),
|
|
265
345
|
snapshot: () => snapshotValue(getAt(store._state, path)),
|
|
@@ -309,8 +389,12 @@ function createSelection(store, base, mask, defaults = {}) {
|
|
|
309
389
|
off(); };
|
|
310
390
|
},
|
|
311
391
|
once(cb, opts = {}) {
|
|
392
|
+
let done = false;
|
|
312
393
|
let off = () => { };
|
|
313
|
-
off = this.on((v, c)
|
|
394
|
+
off = this.on(function fireOnce(v, c) { if (done)
|
|
395
|
+
return; done = true; off(); cb(v, c); }, { ...opts, current: opts.current ?? defaults.current });
|
|
396
|
+
if (done)
|
|
397
|
+
off();
|
|
314
398
|
return off;
|
|
315
399
|
},
|
|
316
400
|
onEach(cb, opts = {}) {
|
|
@@ -337,6 +421,7 @@ function createStore(initial, opts = {}) {
|
|
|
337
421
|
once: (cb, opts) => getNode(store, []).once(cb, opts),
|
|
338
422
|
update: (mask, opts) => createSelection(store, [], mask, opts),
|
|
339
423
|
listen: () => (0, reactive2_1.listenUpdate)(state),
|
|
424
|
+
listenPaths: () => (0, reactive2_1.listenUpdatePaths)(state),
|
|
340
425
|
count: () => Array.from(store._counts.values()).reduce((a, b) => a + b, 0),
|
|
341
426
|
};
|
|
342
427
|
return store;
|
|
@@ -357,25 +442,65 @@ function exposeStore(store) {
|
|
|
357
442
|
node.replace(value);
|
|
358
443
|
},
|
|
359
444
|
changed: store.listen(),
|
|
445
|
+
changedPaths: store.listenPaths(),
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
function subscribeRemote(listen, cb) {
|
|
449
|
+
let handle;
|
|
450
|
+
if (typeof listen?.on == "function")
|
|
451
|
+
handle = listen.on(cb);
|
|
452
|
+
else if (typeof listen?.addListen == "function")
|
|
453
|
+
handle = listen.addListen(cb);
|
|
454
|
+
else
|
|
455
|
+
return () => { };
|
|
456
|
+
return () => {
|
|
457
|
+
if (typeof handle == "function")
|
|
458
|
+
handle();
|
|
459
|
+
else if (typeof handle?.off == "function")
|
|
460
|
+
handle.off();
|
|
461
|
+
else if (typeof listen?.off == "function")
|
|
462
|
+
listen.off(cb);
|
|
463
|
+
else if (typeof listen?.removeListen == "function")
|
|
464
|
+
listen.removeListen(cb);
|
|
360
465
|
};
|
|
361
466
|
}
|
|
362
467
|
function createStoreMirror(remote, initial = {}, opts = {}) {
|
|
363
468
|
const store = createStore(initial, opts);
|
|
364
469
|
async function sync(mask, subOpts = { current: true }) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
470
|
+
const baseMask = mask ?? true;
|
|
471
|
+
const report = (error) => {
|
|
472
|
+
if (subOpts.onError)
|
|
473
|
+
subOpts.onError(error);
|
|
474
|
+
else
|
|
475
|
+
setTimeout(() => { throw error; }, 0);
|
|
476
|
+
};
|
|
477
|
+
async function pull(nextMask = baseMask) {
|
|
478
|
+
const snap = await remote.get(nextMask);
|
|
479
|
+
applyMask(store.state, nextMask, snap);
|
|
368
480
|
}
|
|
369
481
|
if (subOpts.current !== false)
|
|
370
|
-
await pull();
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
?
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
482
|
+
await pull(baseMask);
|
|
483
|
+
let pendingMask = undefined;
|
|
484
|
+
let chain = Promise.resolve();
|
|
485
|
+
const drained = createDrained(() => {
|
|
486
|
+
const nextMask = pendingMask === undefined ? baseMask : pendingMask;
|
|
487
|
+
pendingMask = undefined;
|
|
488
|
+
chain = chain.then(() => pull(nextMask)).catch(report);
|
|
489
|
+
}, subOpts.drain);
|
|
490
|
+
const queue = (nextMask) => {
|
|
491
|
+
pendingMask = pendingMask === undefined ? nextMask : mergeMasks(pendingMask, nextMask);
|
|
492
|
+
drained.push();
|
|
493
|
+
};
|
|
494
|
+
const changedPaths = remote.changedPaths;
|
|
495
|
+
const usePaths = subOpts.partial !== false && (typeof changedPaths?.on == "function" || typeof changedPaths?.addListen == "function");
|
|
496
|
+
const off = usePaths
|
|
497
|
+
? subscribeRemote(changedPaths, (change) => {
|
|
498
|
+
const nextMask = intersectMaskWithPaths(baseMask, change?.paths);
|
|
499
|
+
if (nextMask !== undefined)
|
|
500
|
+
queue(nextMask);
|
|
501
|
+
})
|
|
502
|
+
: subscribeRemote(remote.changed, () => queue(baseMask));
|
|
503
|
+
return () => { drained.close(); off(); };
|
|
379
504
|
}
|
|
380
505
|
return Object.assign(store, { sync });
|
|
381
506
|
}
|
|
@@ -37,6 +37,7 @@ export declare function funcListenCore<T>(options?: ListenCoreOptions<T>): {
|
|
|
37
37
|
func: Listener<NormalizeTuple<T>>;
|
|
38
38
|
has: (k: key) => boolean;
|
|
39
39
|
on: ListenOn<NormalizeTuple<T>>;
|
|
40
|
+
off: (k: Listener<NormalizeTuple<T>> | null | key) => void;
|
|
40
41
|
addListen: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
41
42
|
key?: key;
|
|
42
43
|
}) => () => void;
|
|
@@ -58,11 +59,12 @@ export declare function funcListenCallbackBase<T>(b: (e: Listener<NormalizeTuple
|
|
|
58
59
|
onClose: (cb: cbClose) => () => void;
|
|
59
60
|
removeEventClose: (cb: cbClose) => void;
|
|
60
61
|
on: ListenOn<NormalizeTuple<T>>;
|
|
62
|
+
off: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
61
63
|
addListen: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
62
64
|
cbClose?: cbClose;
|
|
63
65
|
key?: key;
|
|
64
66
|
}) => () => void;
|
|
65
|
-
removeListen: (k:
|
|
67
|
+
removeListen: (k: Listener<NormalizeTuple<T>> | null | key) => void;
|
|
66
68
|
once: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
67
69
|
key?: key;
|
|
68
70
|
}) => () => void;
|
|
@@ -79,6 +81,7 @@ export declare function funcListenCallbackFast<T>(a: (e: (Listener<NormalizeTupl
|
|
|
79
81
|
onClose: (cb: cbClose) => () => void;
|
|
80
82
|
removeEventClose: (cb: cbClose) => void;
|
|
81
83
|
on: ListenOn<NormalizeTuple<T>>;
|
|
84
|
+
off: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
82
85
|
addListen: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
83
86
|
cbClose?: cbClose;
|
|
84
87
|
key?: key;
|
|
@@ -100,6 +103,7 @@ export declare function UseListen<T>(data?: ListenOptions<T>): readonly [(...a:
|
|
|
100
103
|
onClose: (cb: cbClose) => () => void;
|
|
101
104
|
removeEventClose: (cb: cbClose) => void;
|
|
102
105
|
on: ListenOn<NormalizeTuple<T>>;
|
|
106
|
+
off: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
103
107
|
addListen: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
104
108
|
cbClose?: cbClose;
|
|
105
109
|
key?: key;
|
|
@@ -118,6 +122,7 @@ export declare function withStoreListen<T>(base: ListenApi<T>, currentProvider:
|
|
|
118
122
|
key?: key;
|
|
119
123
|
current?: ListenCurrent<NormalizeTuple<T>>;
|
|
120
124
|
}) => () => void;
|
|
125
|
+
removeListen: (k: Listener<NormalizeTuple<T>> | null | key) => void;
|
|
121
126
|
once: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
122
127
|
key?: key;
|
|
123
128
|
current?: ListenCurrent<NormalizeTuple<T>>;
|
|
@@ -130,7 +135,7 @@ export declare function withStoreListen<T>(base: ListenApi<T>, currentProvider:
|
|
|
130
135
|
eventClose: (cb: cbClose) => () => void;
|
|
131
136
|
onClose: (cb: cbClose) => () => void;
|
|
132
137
|
removeEventClose: (cb: cbClose) => void;
|
|
133
|
-
|
|
138
|
+
off: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
134
139
|
count: () => number;
|
|
135
140
|
};
|
|
136
141
|
export type ListenStoreApi<T> = ReturnType<typeof withStoreListen<T>>;
|
|
@@ -141,6 +146,7 @@ export declare function funcListenCallbackStore<T>(b: (e: Listener<NormalizeTupl
|
|
|
141
146
|
key?: key;
|
|
142
147
|
current?: ListenCurrent<NormalizeTuple<T>> | undefined;
|
|
143
148
|
}) => () => void;
|
|
149
|
+
removeListen: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
144
150
|
once: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
145
151
|
key?: key;
|
|
146
152
|
current?: ListenCurrent<NormalizeTuple<T>> | undefined;
|
|
@@ -153,7 +159,7 @@ export declare function funcListenCallbackStore<T>(b: (e: Listener<NormalizeTupl
|
|
|
153
159
|
eventClose: (cb: cbClose) => () => void;
|
|
154
160
|
onClose: (cb: cbClose) => () => void;
|
|
155
161
|
removeEventClose: (cb: cbClose) => void;
|
|
156
|
-
|
|
162
|
+
off: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
157
163
|
count: () => number;
|
|
158
164
|
};
|
|
159
165
|
export declare function UseListenStore<T>(data: ListenStoreOptions<T>): readonly [(...a: NormalizeTuple<T>) => void, {
|
|
@@ -163,6 +169,7 @@ export declare function UseListenStore<T>(data: ListenStoreOptions<T>): readonly
|
|
|
163
169
|
key?: key;
|
|
164
170
|
current?: ListenCurrent<NormalizeTuple<T>> | undefined;
|
|
165
171
|
}) => () => void;
|
|
172
|
+
removeListen: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
166
173
|
once: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
167
174
|
key?: key;
|
|
168
175
|
current?: ListenCurrent<NormalizeTuple<T>> | undefined;
|
|
@@ -175,13 +182,14 @@ export declare function UseListenStore<T>(data: ListenStoreOptions<T>): readonly
|
|
|
175
182
|
eventClose: (cb: cbClose) => () => void;
|
|
176
183
|
onClose: (cb: cbClose) => () => void;
|
|
177
184
|
removeEventClose: (cb: cbClose) => void;
|
|
178
|
-
|
|
185
|
+
off: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
179
186
|
count: () => number;
|
|
180
187
|
}];
|
|
181
188
|
export declare function toListen2<T>(full: ListenApi<T>): {
|
|
182
189
|
on: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
183
190
|
key?: key;
|
|
184
191
|
}) => () => void;
|
|
192
|
+
off: (k: Listener<NormalizeTuple<T>> | null | key) => void;
|
|
185
193
|
close: () => void;
|
|
186
194
|
count: () => number;
|
|
187
195
|
};
|
|
@@ -190,6 +198,7 @@ export declare function UseListen2<T>(data?: ListenOptions<T>): readonly [(...a:
|
|
|
190
198
|
on: (cb: Listener<NormalizeTuple<T>>, opts?: {
|
|
191
199
|
key?: key;
|
|
192
200
|
} | undefined) => () => void;
|
|
201
|
+
off: (k: key | Listener<NormalizeTuple<T>> | null) => void;
|
|
193
202
|
close: () => void;
|
|
194
203
|
count: () => number;
|
|
195
204
|
}];
|
|
@@ -68,8 +68,7 @@ function funcListenCore(options = {}) {
|
|
|
68
68
|
event?.('add', subs.size, api);
|
|
69
69
|
return function off() { removeOne(k); };
|
|
70
70
|
}),
|
|
71
|
-
|
|
72
|
-
removeListen: (k) => {
|
|
71
|
+
off: (k) => {
|
|
73
72
|
if (typeof k == 'function') {
|
|
74
73
|
for (const [kk, cb] of [...subs])
|
|
75
74
|
if (cb === k)
|
|
@@ -79,6 +78,8 @@ function funcListenCore(options = {}) {
|
|
|
79
78
|
if (k != null)
|
|
80
79
|
removeOne(k);
|
|
81
80
|
},
|
|
81
|
+
addListen: (cb, opts = {}) => api.on(cb, opts),
|
|
82
|
+
removeListen: (k) => api.off(k),
|
|
82
83
|
once: (cb, opts = {}) => {
|
|
83
84
|
let off = () => { };
|
|
84
85
|
off = api.on(((...e) => { off(); cb(...e); }), opts);
|
|
@@ -151,8 +152,9 @@ function funcListenCallbackBase(b, options = {}) {
|
|
|
151
152
|
event?.('add', core.count(), api);
|
|
152
153
|
return off;
|
|
153
154
|
}),
|
|
155
|
+
off: core.off,
|
|
154
156
|
addListen: (cb, opts = {}) => api.on(cb, opts),
|
|
155
|
-
removeListen:
|
|
157
|
+
removeListen: (k) => api.off(k),
|
|
156
158
|
once: (cb, opts = {}) => {
|
|
157
159
|
let off = () => { };
|
|
158
160
|
off = api.on(((...e) => { off(); cb(...e); }), opts);
|
|
@@ -193,6 +195,7 @@ function withStoreListen(base, currentProvider) {
|
|
|
193
195
|
return off;
|
|
194
196
|
}),
|
|
195
197
|
addListen: (cb, opts = {}) => api.on(cb, opts),
|
|
198
|
+
removeListen: (k) => api.off(k),
|
|
196
199
|
once: (cb, opts = {}) => {
|
|
197
200
|
if (opts.current) {
|
|
198
201
|
const m = currentValue(opts.current);
|
|
@@ -226,6 +229,7 @@ function UseListenStore(data) {
|
|
|
226
229
|
function toListen2(full) {
|
|
227
230
|
return {
|
|
228
231
|
on: (cb, opts) => full.on(cb, opts),
|
|
232
|
+
off: (k) => full.off(k),
|
|
229
233
|
close: () => full.close(),
|
|
230
234
|
count: () => full.count(),
|
|
231
235
|
};
|
|
@@ -33,6 +33,7 @@ export declare function funcListenCallbackSnapshot<T extends realSocket2<any | a
|
|
|
33
33
|
onClose: (cb: () => void) => () => void;
|
|
34
34
|
removeEventClose: (cb: () => void) => void;
|
|
35
35
|
on: import("./Listen3").ListenOn<[data: getTypeCallback<T>, memo: T3]>;
|
|
36
|
+
off: (k: (string | symbol) | import("./Listen3").Listener<[data: getTypeCallback<T>, memo: T3]> | null) => void;
|
|
36
37
|
addListen: (cb: import("./Listen3").Listener<[data: getTypeCallback<T>, memo: T3]>, opts?: {
|
|
37
38
|
cbClose?: () => void;
|
|
38
39
|
key?: string | symbol;
|
|
@@ -13,6 +13,7 @@ export declare function SocketServerHook(opt?: {
|
|
|
13
13
|
onClose: (cb: () => void) => () => void;
|
|
14
14
|
removeEventClose: (cb: () => void) => void;
|
|
15
15
|
on: import("./Listen3").ListenOn<[unknown]>;
|
|
16
|
+
off: (k: (string | symbol) | import("./Listen3").Listener<[unknown]> | null) => void;
|
|
16
17
|
addListen: (cb: import("./Listen3").Listener<[unknown]>, opts?: {
|
|
17
18
|
cbClose?: () => void;
|
|
18
19
|
key?: string | symbol;
|
|
@@ -34,6 +35,7 @@ export declare function SocketServerHook(opt?: {
|
|
|
34
35
|
onClose: (cb: () => void) => () => void;
|
|
35
36
|
removeEventClose: (cb: () => void) => void;
|
|
36
37
|
on: import("./Listen3").ListenOn<[unknown]>;
|
|
38
|
+
off: (k: (string | symbol) | import("./Listen3").Listener<[unknown]> | null) => void;
|
|
37
39
|
addListen: (cb: import("./Listen3").Listener<[unknown]>, opts?: {
|
|
38
40
|
cbClose?: () => void;
|
|
39
41
|
key?: string | symbol;
|
|
@@ -55,6 +57,7 @@ export declare function WebSocketServerHook(s: ReturnType<typeof SocketServerHoo
|
|
|
55
57
|
on: (z: (...args: any[]) => void) => import("../rcp/listen-socket").tSubHandle;
|
|
56
58
|
once: (z: (...args: any[]) => void) => import("../rcp/listen-socket").tSubHandle;
|
|
57
59
|
close: () => void;
|
|
60
|
+
off: () => boolean;
|
|
58
61
|
removeCallback: () => boolean;
|
|
59
62
|
};
|
|
60
63
|
};
|
|
@@ -10,6 +10,7 @@ export declare function UseListenTransform<TSource extends any[], TTarget extend
|
|
|
10
10
|
onClose: (cb: () => void) => () => void;
|
|
11
11
|
removeEventClose: (cb: () => void) => void;
|
|
12
12
|
on: import("./Listen3").ListenOn<NormalizeTuple<TTarget>>;
|
|
13
|
+
off: (k: (string | symbol) | Listener<NormalizeTuple<TTarget>> | null) => void;
|
|
13
14
|
addListen: (cb: Listener<NormalizeTuple<TTarget>>, opts?: {
|
|
14
15
|
cbClose?: () => void;
|
|
15
16
|
key?: string | symbol;
|
|
@@ -13,7 +13,7 @@ function createRpcServerAuto2({ socket, object: target, socketKey: key, debug =
|
|
|
13
13
|
const listenSockets = new Set();
|
|
14
14
|
function unsubscribeAllActive() {
|
|
15
15
|
for (const w of [...listenSockets])
|
|
16
|
-
w.
|
|
16
|
+
w.off();
|
|
17
17
|
}
|
|
18
18
|
function getListenSocket(parent) {
|
|
19
19
|
let result = cache.get(parent);
|
|
@@ -24,10 +24,10 @@ function createRpcServerAuto2({ socket, object: target, socketKey: key, debug =
|
|
|
24
24
|
function subscribe(z) {
|
|
25
25
|
if (typeof z !== "function")
|
|
26
26
|
return Promise.reject(new TypeError("Listen callback expects a function"));
|
|
27
|
-
subs.get(z)?.
|
|
27
|
+
subs.get(z)?.off();
|
|
28
28
|
const w = (0, listen_socket_1.listenSocket)(parent, { addListenClose: disconnectListen });
|
|
29
29
|
subs.set(z, w);
|
|
30
|
-
const done = w.
|
|
30
|
+
const done = w.on(z);
|
|
31
31
|
done.then(() => { if (subs.get(z) == w)
|
|
32
32
|
subs.delete(z); });
|
|
33
33
|
return done;
|
|
@@ -35,7 +35,7 @@ function createRpcServerAuto2({ socket, object: target, socketKey: key, debug =
|
|
|
35
35
|
function subscribeOnce(z) {
|
|
36
36
|
if (typeof z !== "function")
|
|
37
37
|
return Promise.reject(new TypeError("Listen once expects a function"));
|
|
38
|
-
subs.get(z)?.
|
|
38
|
+
subs.get(z)?.off();
|
|
39
39
|
const w = (0, listen_socket_1.listenSocket)(parent, { addListenClose: disconnectListen });
|
|
40
40
|
subs.set(z, w);
|
|
41
41
|
const done = w.once(z);
|
|
@@ -44,11 +44,11 @@ function createRpcServerAuto2({ socket, object: target, socketKey: key, debug =
|
|
|
44
44
|
return done;
|
|
45
45
|
}
|
|
46
46
|
function unsubscribeAll() {
|
|
47
|
-
subs.forEach(w => w.
|
|
47
|
+
subs.forEach(w => w.off());
|
|
48
48
|
subs.clear();
|
|
49
49
|
return true;
|
|
50
50
|
}
|
|
51
|
-
result = {
|
|
51
|
+
result = { on: subscribe, off: unsubscribeAll, callback: subscribe, removeCallback: unsubscribeAll, once: subscribeOnce, close: () => parent.close?.() };
|
|
52
52
|
listenSockets.add(result);
|
|
53
53
|
cache.set(parent, result);
|
|
54
54
|
}
|
|
@@ -2,6 +2,7 @@ import { funcListenCallbackBase, type Listener } from "../events/Listen";
|
|
|
2
2
|
import { type Off } from "./rpc-off";
|
|
3
3
|
type ListenCallbackResult<T extends any[] = any[]> = ReturnType<typeof funcListenCallbackBase<T>>;
|
|
4
4
|
export type tSubHandle = Off<void, {
|
|
5
|
+
off: () => void;
|
|
5
6
|
unsubscribe: () => void;
|
|
6
7
|
removeCallback: () => void;
|
|
7
8
|
}>;
|
|
@@ -12,9 +13,10 @@ export declare function listenSocket<Z extends any[] = any[]>(e: ListenCallbackR
|
|
|
12
13
|
readonly paramsModify?: (...e: Z) => any[];
|
|
13
14
|
readonly throttle?: number;
|
|
14
15
|
}): {
|
|
16
|
+
on: (z: Listener<Z>) => Promise<void>;
|
|
17
|
+
off: () => boolean;
|
|
15
18
|
callback: (z: Listener<Z>) => Promise<void>;
|
|
16
19
|
removeCallback: () => boolean;
|
|
17
|
-
on: (z: Listener<Z>) => Promise<void>;
|
|
18
20
|
once: (z: Listener<Z>) => Promise<void>;
|
|
19
21
|
close: () => void;
|
|
20
22
|
};
|
|
@@ -23,6 +25,7 @@ export declare function listenSocketFirst<Z extends any[] = any[]>(e: ListenCall
|
|
|
23
25
|
on: (z: (a: Z[0]) => void) => tSubHandle;
|
|
24
26
|
once: (z: (a: Z[0]) => void) => tSubHandle;
|
|
25
27
|
close: () => void;
|
|
28
|
+
off: () => boolean;
|
|
26
29
|
removeCallback: () => boolean;
|
|
27
30
|
};
|
|
28
31
|
export declare function listenSocketAll<Z extends any[] = any[]>(e: ListenCallbackResult<Z>, options?: Omit<Parameters<typeof listenSocket>[1], "paramsModify">): {
|
|
@@ -30,6 +33,7 @@ export declare function listenSocketAll<Z extends any[] = any[]>(e: ListenCallba
|
|
|
30
33
|
on: (z: (...args: Z) => void) => tSubHandle;
|
|
31
34
|
once: (z: (...args: Z) => void) => tSubHandle;
|
|
32
35
|
close: () => void;
|
|
36
|
+
off: () => boolean;
|
|
33
37
|
removeCallback: () => boolean;
|
|
34
38
|
};
|
|
35
39
|
type SmartCallback<Z extends any[]> = Z extends [infer Single] ? (a: Single) => void : (...args: Z) => void;
|
|
@@ -38,6 +42,7 @@ export declare function listenSocketSmart<Z extends any[] = any[]>(e: ListenCall
|
|
|
38
42
|
on: (z: SmartCallback<Z>) => tSubHandle;
|
|
39
43
|
once: (z: SmartCallback<Z>) => tSubHandle;
|
|
40
44
|
close: () => void;
|
|
45
|
+
off: () => boolean;
|
|
41
46
|
removeCallback: () => boolean;
|
|
42
47
|
};
|
|
43
48
|
export {};
|
|
@@ -58,7 +58,7 @@ function listenSocket(e, d) {
|
|
|
58
58
|
resolveWait = null;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
function
|
|
61
|
+
function off() {
|
|
62
62
|
if (throttleCh) {
|
|
63
63
|
throttleCh.cancel();
|
|
64
64
|
throttleCh = null;
|
|
@@ -79,9 +79,10 @@ function listenSocket(e, d) {
|
|
|
79
79
|
finish();
|
|
80
80
|
return true;
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
const removeCallback = off;
|
|
83
|
+
function on(z) {
|
|
83
84
|
if (typeof z !== "function") {
|
|
84
|
-
throw new TypeError("listenSocket.
|
|
85
|
+
throw new TypeError("listenSocket.on expects a function");
|
|
85
86
|
}
|
|
86
87
|
if (last)
|
|
87
88
|
stop?.(last);
|
|
@@ -110,7 +111,7 @@ function listenSocket(e, d) {
|
|
|
110
111
|
if (status())
|
|
111
112
|
wrapped(...a);
|
|
112
113
|
else
|
|
113
|
-
|
|
114
|
+
off();
|
|
114
115
|
};
|
|
115
116
|
}
|
|
116
117
|
let inner = handler;
|
|
@@ -146,12 +147,12 @@ function listenSocket(e, d) {
|
|
|
146
147
|
}
|
|
147
148
|
inner(...a);
|
|
148
149
|
};
|
|
149
|
-
activeOff = subscribe(active, { cbClose:
|
|
150
|
-
closeSignalOff = subscribeClose?.(
|
|
150
|
+
activeOff = subscribe(active, { cbClose: off });
|
|
151
|
+
closeSignalOff = subscribeClose?.(off) ?? null;
|
|
151
152
|
const wait = new Promise((resolve) => {
|
|
152
153
|
resolveWait = () => { resolve(); };
|
|
153
154
|
});
|
|
154
|
-
return (0, rpc_off_1.makeOff)(wait,
|
|
155
|
+
return (0, rpc_off_1.makeOff)(wait, off, { off, unsubscribe: off, removeCallback });
|
|
155
156
|
}
|
|
156
157
|
function once(z) {
|
|
157
158
|
if (typeof z !== "function") {
|
|
@@ -160,7 +161,7 @@ function listenSocket(e, d) {
|
|
|
160
161
|
let fired = false;
|
|
161
162
|
const oneShot = ((...a) => {
|
|
162
163
|
if (a[0] === rpc_protocol_1.RPC_STOP) {
|
|
163
|
-
|
|
164
|
+
off();
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
166
167
|
if (fired)
|
|
@@ -171,13 +172,18 @@ function listenSocket(e, d) {
|
|
|
171
172
|
}
|
|
172
173
|
finally {
|
|
173
174
|
(0, rpc_off_1.endCallback)(z);
|
|
174
|
-
|
|
175
|
+
off();
|
|
175
176
|
}
|
|
176
177
|
});
|
|
177
|
-
return
|
|
178
|
+
return on(oneShot);
|
|
178
179
|
}
|
|
179
180
|
function closeStream() { e.close?.(); }
|
|
180
|
-
|
|
181
|
+
function callback(z) {
|
|
182
|
+
if (typeof z !== "function")
|
|
183
|
+
throw new TypeError("listenSocket.callback expects a function");
|
|
184
|
+
return on(z);
|
|
185
|
+
}
|
|
186
|
+
return { on, off, callback, removeCallback, once, close: closeStream };
|
|
181
187
|
}
|
|
182
188
|
function listenSocketFirst(e, options) {
|
|
183
189
|
const r = listenSocket(e, {
|
|
@@ -186,9 +192,10 @@ function listenSocketFirst(e, options) {
|
|
|
186
192
|
});
|
|
187
193
|
return {
|
|
188
194
|
callback: r.callback,
|
|
189
|
-
on: r.
|
|
195
|
+
on: r.on,
|
|
190
196
|
once: r.once,
|
|
191
197
|
close: r.close,
|
|
198
|
+
off: r.off,
|
|
192
199
|
removeCallback: r.removeCallback,
|
|
193
200
|
};
|
|
194
201
|
}
|
|
@@ -196,9 +203,10 @@ function listenSocketAll(e, options) {
|
|
|
196
203
|
const r = listenSocket(e, { ...options });
|
|
197
204
|
return {
|
|
198
205
|
callback: r.callback,
|
|
199
|
-
on: r.
|
|
206
|
+
on: r.on,
|
|
200
207
|
once: r.once,
|
|
201
208
|
close: r.close,
|
|
209
|
+
off: r.off,
|
|
202
210
|
removeCallback: r.removeCallback,
|
|
203
211
|
};
|
|
204
212
|
}
|
|
@@ -206,9 +214,10 @@ function listenSocketSmart(e, options) {
|
|
|
206
214
|
const r = listenSocket(e, { ...options });
|
|
207
215
|
return {
|
|
208
216
|
callback: r.callback,
|
|
209
|
-
on: r.
|
|
217
|
+
on: r.on,
|
|
210
218
|
once: r.once,
|
|
211
219
|
close: r.close,
|
|
220
|
+
off: r.off,
|
|
212
221
|
removeCallback: r.removeCallback,
|
|
213
222
|
};
|
|
214
223
|
}
|
|
@@ -348,7 +348,7 @@ function createClient(socket, key, opts) {
|
|
|
348
348
|
if (sub.consumers.size == 0)
|
|
349
349
|
sub.stop();
|
|
350
350
|
};
|
|
351
|
-
return (0, rpc_off_1.makeOff)(p, unsub, { unsubscribe: unsub, removeCallback: unsub });
|
|
351
|
+
return (0, rpc_off_1.makeOff)(p, unsub, { off: unsub, unsubscribe: unsub, removeCallback: unsub });
|
|
352
352
|
}
|
|
353
353
|
const sendCall = (path, args, wait) => {
|
|
354
354
|
const last = path[path.length - 1];
|
|
@@ -10,7 +10,7 @@ function createRpcServerAuto({ socket, object: target, socketKey: key, debug, ho
|
|
|
10
10
|
const registry = new Map();
|
|
11
11
|
function unsubscribeAllActive() {
|
|
12
12
|
for (const { subs } of registry.values()) {
|
|
13
|
-
subs.forEach(w => w.
|
|
13
|
+
subs.forEach(w => w.off());
|
|
14
14
|
subs.clear();
|
|
15
15
|
}
|
|
16
16
|
registry.clear();
|
|
@@ -26,10 +26,10 @@ function createRpcServerAuto({ socket, object: target, socketKey: key, debug, ho
|
|
|
26
26
|
return Promise.resolve();
|
|
27
27
|
if (!registry.has(parent))
|
|
28
28
|
registry.set(parent, { subs });
|
|
29
|
-
subs.get(z)?.
|
|
29
|
+
subs.get(z)?.off();
|
|
30
30
|
const w = (0, listen_socket_1.listenSocket)(parent, { addListenClose: disconnectListen, throttle });
|
|
31
31
|
subs.set(z, w);
|
|
32
|
-
const done = w.
|
|
32
|
+
const done = w.on(z);
|
|
33
33
|
done.then(() => {
|
|
34
34
|
if (subs.get(z) == w)
|
|
35
35
|
subs.delete(z);
|
|
@@ -45,7 +45,7 @@ function createRpcServerAuto({ socket, object: target, socketKey: key, debug, ho
|
|
|
45
45
|
return Promise.resolve();
|
|
46
46
|
if (!registry.has(parent))
|
|
47
47
|
registry.set(parent, { subs });
|
|
48
|
-
subs.get(z)?.
|
|
48
|
+
subs.get(z)?.off();
|
|
49
49
|
const w = (0, listen_socket_1.listenSocket)(parent, { addListenClose: disconnectListen, throttle });
|
|
50
50
|
let fired = false;
|
|
51
51
|
const oneShot = (...a) => {
|
|
@@ -57,23 +57,23 @@ function createRpcServerAuto({ socket, object: target, socketKey: key, debug, ho
|
|
|
57
57
|
z(rpc_protocol_1.RPC_STOP);
|
|
58
58
|
}
|
|
59
59
|
finally {
|
|
60
|
-
w.
|
|
60
|
+
w.off();
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
63
|
subs.set(z, w);
|
|
64
|
-
const done = w.
|
|
64
|
+
const done = w.on(oneShot);
|
|
65
65
|
done.then(() => { if (subs.get(z) == w)
|
|
66
66
|
subs.delete(z); if (subs.size == 0)
|
|
67
67
|
registry.delete(parent); });
|
|
68
68
|
return done;
|
|
69
69
|
}
|
|
70
70
|
function unsubscribeAll() {
|
|
71
|
-
subs.forEach(w => w.
|
|
71
|
+
subs.forEach(w => w.off());
|
|
72
72
|
subs.clear();
|
|
73
73
|
registry.delete(parent);
|
|
74
74
|
return true;
|
|
75
75
|
}
|
|
76
|
-
result = {
|
|
76
|
+
result = { on: subscribe, off: unsubscribeAll, callback: subscribe, removeCallback: unsubscribeAll, once: subscribeOnce, close: () => parent.close?.() };
|
|
77
77
|
result[rpc_protocol_1.IS_RPC_LISTEN] = true;
|
|
78
78
|
cache.set(parent, result);
|
|
79
79
|
}
|
|
@@ -12,6 +12,7 @@ const SERVERS = new WeakMap();
|
|
|
12
12
|
function createServer(socket, key, target, hooks, limits, auth, opt) {
|
|
13
13
|
const lim = (0, rpc_limits_1.resolveLimits)(limits);
|
|
14
14
|
const IS_RPC_PIPE = Symbol.for("isRpcPipe");
|
|
15
|
+
const hasRpcListen = (obj) => !!obj && typeof obj == "object" && Object.prototype.hasOwnProperty.call(obj, rpc_protocol_1.IS_RPC_LISTEN);
|
|
15
16
|
function transformTree(obj) {
|
|
16
17
|
let current = obj;
|
|
17
18
|
if (hooks?.resolveTransform && !(0, rpc_dynamic_1.isNoStrict)(current)) {
|
|
@@ -20,7 +21,7 @@ function createServer(socket, key, target, hooks, limits, auth, opt) {
|
|
|
20
21
|
if (current == null || typeof current != "object" || (0, rpc_dynamic_1.isNoStrict)(current))
|
|
21
22
|
return current;
|
|
22
23
|
const out = {};
|
|
23
|
-
if (current
|
|
24
|
+
if (hasRpcListen(current))
|
|
24
25
|
out[rpc_protocol_1.IS_RPC_LISTEN] = true;
|
|
25
26
|
for (const k of Object.keys(current)) {
|
|
26
27
|
if (!(0, rpc_limits_1.isSafeKey)(k))
|
|
@@ -82,7 +83,7 @@ function createServer(socket, key, target, hooks, limits, auth, opt) {
|
|
|
82
83
|
cx.push(obj);
|
|
83
84
|
}
|
|
84
85
|
else if (v && typeof v == "object" && !(0, rpc_dynamic_1.isNoStrict)(v)) {
|
|
85
|
-
if (v
|
|
86
|
+
if (hasRpcListen(v))
|
|
86
87
|
lp.push(path);
|
|
87
88
|
index(v, path);
|
|
88
89
|
}
|