wenay-common2 1.0.58 → 1.0.61
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/store-replay.d.ts +11 -1
- package/lib/Common/ObserveAll2/store-replay.js +15 -0
- package/lib/Common/ObserveAll2/store.d.ts +8 -0
- package/lib/Common/ObserveAll2/store.js +48 -0
- package/lib/Common/rcp/listen-deep.d.ts +2 -2
- package/lib/Common/rcp/rpc-client.d.ts +3 -2
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Store, StorePatch } from './store';
|
|
1
|
+
import { Store, StorePatch, StoreDrain, StoreEachCtx } from './store';
|
|
2
2
|
import { ReplayListenOptions, ReplayEvent } from '../events/replay-listen';
|
|
3
3
|
import { ReplayRemote, ReplaySubscribeOpts } from '../events/replay-wire';
|
|
4
4
|
import { ReplayStorage } from '../events/replay-history';
|
|
@@ -77,6 +77,16 @@ export declare function syncStoreReplay<T extends object>(store: Store<T>, remot
|
|
|
77
77
|
isStale: () => boolean;
|
|
78
78
|
lastTs: () => number;
|
|
79
79
|
};
|
|
80
|
+
export declare function syncStoreReplayEach<T extends object>(remote: ReplayRemote<[StorePatch]>, cb: (key: string, value: T[keyof T] | undefined, ctx: StoreEachCtx) => void, opts?: ReplaySubscribeOpts & {
|
|
81
|
+
drain?: StoreDrain;
|
|
82
|
+
initial?: T;
|
|
83
|
+
}): (() => void) & {
|
|
84
|
+
store: Store<T>;
|
|
85
|
+
ready: Promise<void>;
|
|
86
|
+
seq: () => number;
|
|
87
|
+
isStale: () => boolean;
|
|
88
|
+
lastTs: () => number;
|
|
89
|
+
};
|
|
80
90
|
export declare function storeReplayAt<T extends object>(storage: ReplayStorage<[StorePatch]>, at?: {
|
|
81
91
|
seq?: number;
|
|
82
92
|
ts?: number;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.storePatchKey = storePatchKey;
|
|
4
4
|
exports.exposeStoreReplay = exposeStoreReplay;
|
|
5
5
|
exports.syncStoreReplay = syncStoreReplay;
|
|
6
|
+
exports.syncStoreReplayEach = syncStoreReplayEach;
|
|
6
7
|
exports.storeReplayAt = storeReplayAt;
|
|
7
8
|
const store_1 = require("./store");
|
|
8
9
|
const replay_listen_1 = require("../events/replay-listen");
|
|
@@ -54,6 +55,20 @@ function exposeStoreReplay(store, opts = {}) {
|
|
|
54
55
|
function syncStoreReplay(store, remote, opts = {}) {
|
|
55
56
|
return (0, replay_wire_1.replaySubscribe)(remote, function applyLine(patch) { (0, store_1.applyStorePatch)(store, patch); }, opts);
|
|
56
57
|
}
|
|
58
|
+
function syncStoreReplayEach(remote, cb, opts = {}) {
|
|
59
|
+
const { drain, initial, ...wireOpts } = opts;
|
|
60
|
+
const store = (0, store_1.createStore)((initial ?? {}), drain !== undefined ? { drain } : {});
|
|
61
|
+
const offEach = store.each().on(cb);
|
|
62
|
+
const sub = syncStoreReplay(store, remote, wireOpts);
|
|
63
|
+
function off() { offEach(); sub(); }
|
|
64
|
+
return Object.assign(off, {
|
|
65
|
+
store,
|
|
66
|
+
ready: sub.ready,
|
|
67
|
+
seq: sub.seq,
|
|
68
|
+
isStale: sub.isStale,
|
|
69
|
+
lastTs: sub.lastTs,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
57
72
|
function storeReplayAt(storage, at = {}) {
|
|
58
73
|
const envelopes = (0, replay_history_1.openHistory)(storage).at(at);
|
|
59
74
|
if (!envelopes)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { funcListenCallbackBase } from "../events/Listen";
|
|
1
2
|
import { listenUpdate, listenUpdatePaths, reactive, ReactiveChange } from "./reactive2";
|
|
2
3
|
export type StorePath = readonly PropertyKey[];
|
|
3
4
|
export type StoreDrain = "micro" | "immediate" | number | ((flush: () => void) => void);
|
|
@@ -67,6 +68,12 @@ export type StoreSelectionCtx<T, M> = {
|
|
|
67
68
|
mask: M;
|
|
68
69
|
paths: PropertyKey[][];
|
|
69
70
|
};
|
|
71
|
+
export type StoreEachOpts = {
|
|
72
|
+
depth?: number;
|
|
73
|
+
};
|
|
74
|
+
export type StoreEachCtx = {
|
|
75
|
+
path: PropertyKey[];
|
|
76
|
+
};
|
|
70
77
|
export type Store<T extends object> = {
|
|
71
78
|
readonly state: T;
|
|
72
79
|
readonly node: StoreNode<T>;
|
|
@@ -76,6 +83,7 @@ export type Store<T extends object> = {
|
|
|
76
83
|
on(cb: (value: T, ctx: StoreCtx<T>) => void, opts?: StoreSubOpts): () => void;
|
|
77
84
|
once(cb: (value: T, ctx: StoreCtx<T>) => void, opts?: StoreSubOpts): () => void;
|
|
78
85
|
update<M extends StoreMask<T>>(mask: M, opts?: StoreSubOpts): StoreSelection<T, M>;
|
|
86
|
+
each(opts?: StoreEachOpts): ReturnType<typeof funcListenCallbackBase<[key: string, value: T[keyof T] | undefined, ctx: StoreEachCtx]>>;
|
|
79
87
|
listen(): ReturnType<typeof listenUpdate>;
|
|
80
88
|
listenPaths(): ReturnType<typeof listenUpdatePaths>;
|
|
81
89
|
count(): number;
|
|
@@ -307,6 +307,48 @@ function createPatchesListen(store) {
|
|
|
307
307
|
},
|
|
308
308
|
});
|
|
309
309
|
}
|
|
310
|
+
function createEachListen(store, opts = {}) {
|
|
311
|
+
if (opts.depth != null && opts.depth != 1)
|
|
312
|
+
throw new Error("store.each: only depth 1 is supported (reserved option)");
|
|
313
|
+
return (0, Listen_1.funcListenCallbackBase)((emit) => {
|
|
314
|
+
const known = new Set(Reflect.ownKeys((0, reactive2_1.toRaw)(store.state)));
|
|
315
|
+
function emitKey(key) {
|
|
316
|
+
const raw = (0, reactive2_1.toRaw)(store.state);
|
|
317
|
+
const exists = isObj(raw) && key in raw;
|
|
318
|
+
if (exists)
|
|
319
|
+
known.add(key);
|
|
320
|
+
else
|
|
321
|
+
known.delete(key);
|
|
322
|
+
emit(key, exists ? store.state[key] : undefined, { path: [key] });
|
|
323
|
+
}
|
|
324
|
+
const off = store.listenPaths().on(function eachStoreChange(change) {
|
|
325
|
+
const keys = new Set();
|
|
326
|
+
let root = false;
|
|
327
|
+
for (const path of change.paths) {
|
|
328
|
+
if (path.length == 0)
|
|
329
|
+
root = true;
|
|
330
|
+
else
|
|
331
|
+
keys.add(path[0]);
|
|
332
|
+
}
|
|
333
|
+
if (root) {
|
|
334
|
+
for (const key of Reflect.ownKeys((0, reactive2_1.toRaw)(store.state)))
|
|
335
|
+
keys.add(key);
|
|
336
|
+
for (const key of known)
|
|
337
|
+
keys.add(key);
|
|
338
|
+
}
|
|
339
|
+
for (const key of keys)
|
|
340
|
+
emitKey(key);
|
|
341
|
+
});
|
|
342
|
+
return off;
|
|
343
|
+
}, {
|
|
344
|
+
event: (type, count, api) => {
|
|
345
|
+
if (type == "add" && count == 1 && !api.isRun())
|
|
346
|
+
api.run();
|
|
347
|
+
if (type == "remove" && count == 0 && api.isRun())
|
|
348
|
+
api.close();
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
}
|
|
310
352
|
function createChangedDataListen(store) {
|
|
311
353
|
return (0, Listen_1.funcListenCallbackBase)((emit) => {
|
|
312
354
|
const off = store.listenPaths().on((change) => {
|
|
@@ -458,6 +500,7 @@ function getNode(store, path) {
|
|
|
458
500
|
store._nodeCache.set(k, proxy);
|
|
459
501
|
return proxy;
|
|
460
502
|
}
|
|
503
|
+
let warnedRootOnEach = false;
|
|
461
504
|
function createSelection(store, base, mask, defaults = {}) {
|
|
462
505
|
const fullPaths = maskPaths(mask, base);
|
|
463
506
|
const rootNode = getNode(store, base);
|
|
@@ -486,6 +529,10 @@ function createSelection(store, base, mask, defaults = {}) {
|
|
|
486
529
|
return off;
|
|
487
530
|
},
|
|
488
531
|
onEach(cb, opts = {}) {
|
|
532
|
+
if (fullPaths.some(p => p.length == base.length) && !warnedRootOnEach) {
|
|
533
|
+
warnedRootOnEach = true;
|
|
534
|
+
console.warn("store: update(true).onEach fires ONCE per drain window with the WHOLE value (per selected path, not per key). For per-changed-key delivery use store.each(); for a subset — an explicit key mask.");
|
|
535
|
+
}
|
|
489
536
|
const o = { ...defaults, ...opts };
|
|
490
537
|
const offs = fullPaths.map(p => subscribePath(store, p, cb, o, false));
|
|
491
538
|
return () => { for (const off of offs)
|
|
@@ -508,6 +555,7 @@ function createStore(initial, opts = {}) {
|
|
|
508
555
|
on: (cb, opts) => getNode(store, []).on(cb, opts),
|
|
509
556
|
once: (cb, opts) => getNode(store, []).once(cb, opts),
|
|
510
557
|
update: (mask, opts) => createSelection(store, [], mask, opts),
|
|
558
|
+
each: (opts) => createEachListen(store, opts),
|
|
511
559
|
listen: () => (0, reactive2_1.listenUpdate)(state),
|
|
512
560
|
listenPaths: () => (0, reactive2_1.listenUpdatePaths)(state),
|
|
513
561
|
count: () => Array.from(store._counts.values()).reduce((a, b) => a + b, 0),
|
|
@@ -9,7 +9,7 @@ type WithSubHandle<R> = R extends {
|
|
|
9
9
|
once: (...a: A) => tSubHandle & Promise<void>;
|
|
10
10
|
} : R;
|
|
11
11
|
type Obj = Record<string, any>;
|
|
12
|
-
type InferArgs<T> = T extends {
|
|
12
|
+
export type InferArgs<T> = T extends {
|
|
13
13
|
addListen: (cb: (...args: infer R) => void, ...rest: any[]) => any;
|
|
14
14
|
} ? R : never;
|
|
15
15
|
export type ReplaySocketListen<Z extends any[]> = WithSubHandle<ReturnType<typeof listenSocket<Z>>> & {
|
|
@@ -19,7 +19,7 @@ export type ReplaySocketListen<Z extends any[]> = WithSubHandle<ReturnType<typeo
|
|
|
19
19
|
keyframe: () => Promise<ReplayEvent<Z> | null>;
|
|
20
20
|
frame: (seq: number, hint?: unknown) => Promise<ReplayEvent<Z>[]>;
|
|
21
21
|
};
|
|
22
|
-
type IsReplayMember<V> = V extends {
|
|
22
|
+
export type IsReplayMember<V> = V extends {
|
|
23
23
|
addListen: Function;
|
|
24
24
|
getSince: Function;
|
|
25
25
|
keyframe: Function;
|
|
@@ -2,6 +2,7 @@ import { type SocketTmpl } from "./rpc-protocol";
|
|
|
2
2
|
import { type RpcLimits } from "./rpc-limits";
|
|
3
3
|
import { makeOff } from "./rpc-off";
|
|
4
4
|
import { type RpcOpt } from "./rpc-caps";
|
|
5
|
+
import type { IsReplayMember, InferArgs, ReplaySocketListen } from "./listen-deep";
|
|
5
6
|
type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;
|
|
6
7
|
export type DeepDataOnly<T> = T extends Function ? never : T extends readonly any[] ? {
|
|
7
8
|
[I in keyof T]: DeepDataOnly<T[I]>;
|
|
@@ -9,11 +10,11 @@ export type DeepDataOnly<T> = T extends Function ? never : T extends readonly an
|
|
|
9
10
|
[K in keyof T as T[K] extends Function ? never : K]: DeepDataOnly<T[K]>;
|
|
10
11
|
} : T;
|
|
11
12
|
export type ClientAPIAll<T> = {
|
|
12
|
-
[K in keyof T as T[K] extends Function ? K : T[K] extends object ? K : never]: T[K] extends (...args: infer A) => infer R ? (...args: A) => Promise<DeepDataOnly<UnwrapPromise<R>>> : T[K] extends object ? ClientAPIAll<T[K]> : never;
|
|
13
|
+
[K in keyof T as T[K] extends Function ? K : T[K] extends object ? K : never]: IsReplayMember<T[K]> extends true ? ReplaySocketListen<InferArgs<T[K]>> : T[K] extends (...args: infer A) => infer R ? (...args: A) => Promise<DeepDataOnly<UnwrapPromise<R>>> : T[K] extends object ? ClientAPIAll<T[K]> : never;
|
|
13
14
|
};
|
|
14
15
|
type NonFalsy<T> = Exclude<T, false | null | 0 | "" | undefined>;
|
|
15
16
|
export type ClientAPIStrict<T> = {
|
|
16
|
-
[K in keyof T as NonFalsy<T[K]> extends Function ? K : NonFalsy<T[K]> extends object ? K : never]: NonFalsy<T[K]> extends (...args: infer A) => infer R ? (...args: A) => Promise<DeepDataOnly<UnwrapPromise<R>>> : NonFalsy<T[K]> extends object ? ClientAPIStrict<NonFalsy<T[K]>> : never;
|
|
17
|
+
[K in keyof T as NonFalsy<T[K]> extends Function ? K : NonFalsy<T[K]> extends object ? K : never]: IsReplayMember<NonFalsy<T[K]>> extends true ? ReplaySocketListen<InferArgs<NonFalsy<T[K]>>> : NonFalsy<T[K]> extends (...args: infer A) => infer R ? (...args: A) => Promise<DeepDataOnly<UnwrapPromise<R>>> : NonFalsy<T[K]> extends object ? ClientAPIStrict<NonFalsy<T[K]>> : never;
|
|
17
18
|
};
|
|
18
19
|
export interface PipeArrayAPI<T> extends Promise<DeepDataOnly<T[]>> {
|
|
19
20
|
[index: number]: PipeAPI<T>;
|