wenay-common2 1.0.53 → 1.0.55
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/index.d.ts +1 -0
- package/lib/Common/ObserveAll2/index.js +1 -0
- package/lib/Common/ObserveAll2/store-replay.d.ts +102 -0
- package/lib/Common/ObserveAll2/store-replay.js +53 -0
- package/lib/Common/ObserveAll2/store.d.ts +30 -47
- package/lib/Common/ObserveAll2/store.js +166 -15
- package/lib/Common/events/Listen3.d.ts +4 -0
- package/lib/Common/events/Listen3.js +2 -0
- package/lib/Common/events/replay-conflate.d.ts +45 -0
- package/lib/Common/events/replay-conflate.js +99 -0
- package/lib/Common/events/replay-history.d.ts +55 -0
- package/lib/Common/events/replay-history.js +123 -0
- package/lib/Common/events/replay-index.d.ts +4 -0
- package/lib/Common/events/replay-index.js +20 -0
- package/lib/Common/events/replay-listen.d.ts +114 -0
- package/lib/Common/events/replay-listen.js +134 -0
- package/lib/Common/events/replay-wire.d.ts +43 -0
- package/lib/Common/events/replay-wire.js +84 -0
- package/lib/Common/rcp/rpc-limits.d.ts +1 -0
- package/lib/Common/rcp/rpc-limits.js +1 -0
- package/lib/Common/rcp/rpc-walk.js +13 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -1
- package/package.json +2 -1
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./reactive2"), exports);
|
|
18
18
|
__exportStar(require("./store"), exports);
|
|
19
|
+
__exportStar(require("./store-replay"), exports);
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Store, StorePatch } from './store';
|
|
2
|
+
import { ReplayListenOptions } from '../events/replay-listen';
|
|
3
|
+
import { ReplayRemote, ReplaySubscribeOpts } from '../events/replay-wire';
|
|
4
|
+
import { ReplayStorage } from '../events/replay-history';
|
|
5
|
+
export type StoreReplayOpts = Pick<ReplayListenOptions<[StorePatch]>, 'history' | 'getSince' | 'onJournal' | 'now'>;
|
|
6
|
+
export declare function storePatchKey(patch: StorePatch): string | null;
|
|
7
|
+
export declare function exposeStoreReplay<T extends object>(store: Store<T>, opts?: StoreReplayOpts): {
|
|
8
|
+
api: {
|
|
9
|
+
replay: {
|
|
10
|
+
line: {
|
|
11
|
+
func: import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]>;
|
|
12
|
+
isRun: () => boolean;
|
|
13
|
+
run: () => void;
|
|
14
|
+
close: () => void;
|
|
15
|
+
eventClose: (cb: () => void) => () => void;
|
|
16
|
+
onClose: (cb: () => void) => () => void;
|
|
17
|
+
removeEventClose: (cb: () => void) => void;
|
|
18
|
+
on: import("../..").ListenOn<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]>;
|
|
19
|
+
off: (k: (string | symbol) | import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]> | null) => void;
|
|
20
|
+
addListen: (cb: import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]>, opts?: {
|
|
21
|
+
cbClose?: () => void;
|
|
22
|
+
key?: string | symbol;
|
|
23
|
+
}) => () => void;
|
|
24
|
+
removeListen: (k: (string | symbol) | import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]> | null) => void;
|
|
25
|
+
once: (cb: import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]>, opts?: {
|
|
26
|
+
key?: string | symbol;
|
|
27
|
+
}) => () => void;
|
|
28
|
+
count: () => number;
|
|
29
|
+
readonly getAllKeys: (string | symbol)[];
|
|
30
|
+
};
|
|
31
|
+
since: (seq: number) => import("../events/replay-listen").ReplayEvent<[StorePatch]>[] | null;
|
|
32
|
+
keyframe: () => import("../events/replay-listen").ReplayEvent<[StorePatch]> | null;
|
|
33
|
+
};
|
|
34
|
+
get(): T;
|
|
35
|
+
get<M extends import("./store").StoreMask<T>>(mask: M): import("./store").StorePick<T, M>;
|
|
36
|
+
set(path: import("./store").StorePath, value: any): void;
|
|
37
|
+
replace(path: import("./store").StorePath, value: any): void;
|
|
38
|
+
changed: any;
|
|
39
|
+
changedPaths: any;
|
|
40
|
+
patches?: any;
|
|
41
|
+
changedData?: any;
|
|
42
|
+
};
|
|
43
|
+
replay: {
|
|
44
|
+
func: import("../..").Listener<[StorePatch]>;
|
|
45
|
+
head: () => number;
|
|
46
|
+
getSince: (seq: number) => import("../events/replay-listen").ReplayEvent<[StorePatch]>[] | undefined;
|
|
47
|
+
line: {
|
|
48
|
+
func: import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]>;
|
|
49
|
+
isRun: () => boolean;
|
|
50
|
+
run: () => void;
|
|
51
|
+
close: () => void;
|
|
52
|
+
eventClose: (cb: () => void) => () => void;
|
|
53
|
+
onClose: (cb: () => void) => () => void;
|
|
54
|
+
removeEventClose: (cb: () => void) => void;
|
|
55
|
+
on: import("../..").ListenOn<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]>;
|
|
56
|
+
off: (k: (string | symbol) | import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]> | null) => void;
|
|
57
|
+
addListen: (cb: import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]>, opts?: {
|
|
58
|
+
cbClose?: () => void;
|
|
59
|
+
key?: string | symbol;
|
|
60
|
+
}) => () => void;
|
|
61
|
+
removeListen: (k: (string | symbol) | import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]> | null) => void;
|
|
62
|
+
once: (cb: import("../..").Listener<[import("../events/replay-listen").ReplayEvent<[StorePatch]>]>, opts?: {
|
|
63
|
+
key?: string | symbol;
|
|
64
|
+
}) => () => void;
|
|
65
|
+
count: () => number;
|
|
66
|
+
readonly getAllKeys: (string | symbol)[];
|
|
67
|
+
};
|
|
68
|
+
hasKeyframe: boolean;
|
|
69
|
+
keyframe: () => import("../events/replay-listen").ReplayEvent<[StorePatch]> | undefined;
|
|
70
|
+
on: import("../events/replay-listen").ListenOnReplay<[StorePatch]>;
|
|
71
|
+
addListen: (cb: import("../..").Listener<[StorePatch]>, opts?: {
|
|
72
|
+
cbClose?: () => void;
|
|
73
|
+
key?: string | symbol;
|
|
74
|
+
current?: import("../..").ListenCurrent<[StorePatch]> | undefined;
|
|
75
|
+
since?: number;
|
|
76
|
+
onSeq?: (seq: number) => void;
|
|
77
|
+
}) => () => void;
|
|
78
|
+
removeListen: (k: import("../..").Listener<[StorePatch]> | (string | symbol) | null) => void;
|
|
79
|
+
once: (cb: import("../..").Listener<[StorePatch]>, opts?: {
|
|
80
|
+
key?: string | symbol;
|
|
81
|
+
current?: import("../..").ListenCurrent<[StorePatch]> | undefined;
|
|
82
|
+
}) => () => void;
|
|
83
|
+
getAllKeys: (string | symbol)[];
|
|
84
|
+
isRun: () => boolean;
|
|
85
|
+
run: () => void;
|
|
86
|
+
close: () => void;
|
|
87
|
+
eventClose: (cb: () => void) => () => void;
|
|
88
|
+
onClose: (cb: () => void) => () => void;
|
|
89
|
+
removeEventClose: (cb: () => void) => void;
|
|
90
|
+
off: (k: (string | symbol) | import("../..").Listener<[StorePatch]> | null) => void;
|
|
91
|
+
count: () => number;
|
|
92
|
+
};
|
|
93
|
+
close: () => void;
|
|
94
|
+
};
|
|
95
|
+
export declare function syncStoreReplay<T extends object>(store: Store<T>, remote: ReplayRemote<[StorePatch]>, opts?: ReplaySubscribeOpts): (() => void) & {
|
|
96
|
+
ready: Promise<void>;
|
|
97
|
+
seq: () => number;
|
|
98
|
+
};
|
|
99
|
+
export declare function storeReplayAt<T extends object>(storage: ReplayStorage<[StorePatch]>, at?: {
|
|
100
|
+
seq?: number;
|
|
101
|
+
ts?: number;
|
|
102
|
+
}): T | undefined;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.storePatchKey = storePatchKey;
|
|
4
|
+
exports.exposeStoreReplay = exposeStoreReplay;
|
|
5
|
+
exports.syncStoreReplay = syncStoreReplay;
|
|
6
|
+
exports.storeReplayAt = storeReplayAt;
|
|
7
|
+
const store_1 = require("./store");
|
|
8
|
+
const replay_listen_1 = require("../events/replay-listen");
|
|
9
|
+
const replay_wire_1 = require("../events/replay-wire");
|
|
10
|
+
const replay_history_1 = require("../events/replay-history");
|
|
11
|
+
function makeStorePatch(store, path) {
|
|
12
|
+
let node = store.node;
|
|
13
|
+
for (const k of path)
|
|
14
|
+
node = node.at(k);
|
|
15
|
+
const exists = node.has();
|
|
16
|
+
return { path: [...path], exists, value: exists ? node.snapshot() : undefined };
|
|
17
|
+
}
|
|
18
|
+
function storePatchKey(patch) {
|
|
19
|
+
for (const k of patch.path)
|
|
20
|
+
if (typeof k == 'symbol')
|
|
21
|
+
return null;
|
|
22
|
+
return JSON.stringify(patch.path);
|
|
23
|
+
}
|
|
24
|
+
function exposeStoreReplay(store, opts = {}) {
|
|
25
|
+
const [emitPatch, lineApi] = (0, replay_listen_1.UseReplayListen)({
|
|
26
|
+
current: () => [{ path: [], exists: true, value: store.snapshot() }],
|
|
27
|
+
history: opts.getSince ? undefined : (opts.history ?? 1024),
|
|
28
|
+
getSince: opts.getSince,
|
|
29
|
+
onJournal: opts.onJournal,
|
|
30
|
+
now: opts.now,
|
|
31
|
+
});
|
|
32
|
+
const offStore = store.listenPaths().on(function journalStoreChange(change) {
|
|
33
|
+
for (const path of change.paths)
|
|
34
|
+
emitPatch(makeStorePatch(store, path));
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
api: { ...(0, store_1.exposeStore)(store), replay: (0, replay_wire_1.exposeReplay)(lineApi) },
|
|
38
|
+
replay: lineApi,
|
|
39
|
+
close: () => { offStore(); },
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function syncStoreReplay(store, remote, opts = {}) {
|
|
43
|
+
return (0, replay_wire_1.replaySubscribe)(remote, function applyLine(patch) { (0, store_1.applyStorePatch)(store, patch); }, opts);
|
|
44
|
+
}
|
|
45
|
+
function storeReplayAt(storage, at = {}) {
|
|
46
|
+
const envelopes = (0, replay_history_1.openHistory)(storage).at(at);
|
|
47
|
+
if (!envelopes)
|
|
48
|
+
return undefined;
|
|
49
|
+
const scratch = (0, store_1.createStore)({});
|
|
50
|
+
for (const ev of envelopes)
|
|
51
|
+
(0, store_1.applyStorePatch)(scratch, ev.event[0]);
|
|
52
|
+
return scratch.snapshot();
|
|
53
|
+
}
|
|
@@ -7,10 +7,22 @@ export type StoreSubOpts = {
|
|
|
7
7
|
key?: string;
|
|
8
8
|
};
|
|
9
9
|
export type StoreChange = ReactiveChange;
|
|
10
|
+
export type StorePatch = {
|
|
11
|
+
path: PropertyKey[];
|
|
12
|
+
value: any;
|
|
13
|
+
exists: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type StoreChangedData<M = any> = {
|
|
16
|
+
mask: M;
|
|
17
|
+
data: any;
|
|
18
|
+
};
|
|
10
19
|
export type StoreSyncOpts = StoreSubOpts & {
|
|
11
20
|
partial?: boolean;
|
|
12
21
|
onError?: (error: any) => void;
|
|
13
22
|
};
|
|
23
|
+
export type StoreExposeOpts = {
|
|
24
|
+
push?: boolean;
|
|
25
|
+
};
|
|
14
26
|
export type StoreCtx<T = any> = {
|
|
15
27
|
store: Store<any>;
|
|
16
28
|
node: StoreNode<T>;
|
|
@@ -72,56 +84,27 @@ type RemoteStore<T extends object> = {
|
|
|
72
84
|
get(mask?: any): T | Promise<T>;
|
|
73
85
|
changed: any;
|
|
74
86
|
changedPaths?: any;
|
|
87
|
+
patches?: any;
|
|
88
|
+
changedData?: any;
|
|
75
89
|
};
|
|
76
|
-
export
|
|
77
|
-
|
|
78
|
-
get
|
|
79
|
-
set
|
|
80
|
-
replace
|
|
81
|
-
changed:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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]>;
|
|
104
|
-
isRun: () => boolean;
|
|
105
|
-
run: () => void;
|
|
106
|
-
close: () => void;
|
|
107
|
-
eventClose: (cb: () => void) => () => void;
|
|
108
|
-
onClose: (cb: () => void) => () => void;
|
|
109
|
-
removeEventClose: (cb: () => void) => void;
|
|
110
|
-
on: import("../..").ListenOn<[ReactiveChange]>;
|
|
111
|
-
off: (k: (string | symbol) | import("../..").Listener<[ReactiveChange]> | null) => void;
|
|
112
|
-
addListen: (cb: import("../..").Listener<[ReactiveChange]>, opts?: {
|
|
113
|
-
cbClose?: () => void;
|
|
114
|
-
key?: string | symbol;
|
|
115
|
-
}) => () => void;
|
|
116
|
-
removeListen: (k: (string | symbol) | import("../..").Listener<[ReactiveChange]> | null) => void;
|
|
117
|
-
once: (cb: import("../..").Listener<[ReactiveChange]>, opts?: {
|
|
118
|
-
key?: string | symbol;
|
|
119
|
-
}) => () => void;
|
|
120
|
-
count: () => number;
|
|
121
|
-
readonly getAllKeys: (string | symbol)[];
|
|
122
|
-
};
|
|
90
|
+
export type StoreRemoteApi<T extends object> = {
|
|
91
|
+
get(): T;
|
|
92
|
+
get<M extends StoreMask<T>>(mask: M): StorePick<T, M>;
|
|
93
|
+
set(path: StorePath, value: any): void;
|
|
94
|
+
replace(path: StorePath, value: any): void;
|
|
95
|
+
changed: any;
|
|
96
|
+
changedPaths: any;
|
|
97
|
+
patches?: any;
|
|
98
|
+
changedData?: any;
|
|
123
99
|
};
|
|
100
|
+
export declare function applyStoreMask<T extends object>(store: Store<T>, mask: StoreMask<T> | any, data: any): void;
|
|
101
|
+
export declare function applyStorePatch<T extends object>(store: Store<T>, patch: StorePatch): void;
|
|
102
|
+
export declare function applyStorePatches<T extends object>(store: Store<T>, patches: readonly StorePatch[]): void;
|
|
103
|
+
export declare function createStore<T extends object>(initial: T, opts?: Parameters<typeof reactive<T>>[1]): Store<T>;
|
|
104
|
+
export declare function exposeStore<T extends object>(store: Store<T>, opts?: StoreExposeOpts): StoreRemoteApi<T>;
|
|
124
105
|
export declare function createStoreMirror<T extends object>(remote: RemoteStore<T>, initial?: T, opts?: Parameters<typeof createStore<T>>[1]): Store<T> & {
|
|
125
106
|
sync: <M extends StoreMask<T>>(mask: M, subOpts?: StoreSyncOpts) => Promise<() => void>;
|
|
107
|
+
syncPatches: <M extends StoreMask<T>>(mask: M, subOpts?: StoreSyncOpts) => Promise<() => void>;
|
|
108
|
+
syncChangedData: <M extends StoreMask<T>>(mask: M, subOpts?: StoreSyncOpts) => Promise<() => void>;
|
|
126
109
|
};
|
|
127
110
|
export {};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.applyStoreMask = applyStoreMask;
|
|
4
|
+
exports.applyStorePatch = applyStorePatch;
|
|
5
|
+
exports.applyStorePatches = applyStorePatches;
|
|
3
6
|
exports.createStore = createStore;
|
|
4
7
|
exports.exposeStore = exposeStore;
|
|
5
8
|
exports.createStoreMirror = createStoreMirror;
|
|
9
|
+
const Listen_1 = require("../events/Listen");
|
|
6
10
|
const reactive2_1 = require("./reactive2");
|
|
7
11
|
const hasSetImmediate = typeof setImmediate == "function";
|
|
8
12
|
function pathText(path) {
|
|
@@ -182,6 +186,19 @@ function applyMask(root, mask, data, base = []) {
|
|
|
182
186
|
for (const k of Reflect.ownKeys(mask))
|
|
183
187
|
applyMask(root, mask[k], data?.[k], [...base, k]);
|
|
184
188
|
}
|
|
189
|
+
function applyStoreMask(store, mask, data) {
|
|
190
|
+
applyMask(store.state, mask ?? true, data);
|
|
191
|
+
}
|
|
192
|
+
function applyStorePatch(store, patch) {
|
|
193
|
+
if (patch.exists === false)
|
|
194
|
+
deleteAt(store.state, patch.path);
|
|
195
|
+
else
|
|
196
|
+
setAt(store.state, patch.path, snapshotValue(patch.value));
|
|
197
|
+
}
|
|
198
|
+
function applyStorePatches(store, patches) {
|
|
199
|
+
for (const patch of patches)
|
|
200
|
+
applyStorePatch(store, patch);
|
|
201
|
+
}
|
|
185
202
|
function pathToMask(path) {
|
|
186
203
|
let out = true;
|
|
187
204
|
for (let i = path.length - 1; i >= 0; i--)
|
|
@@ -235,6 +252,77 @@ function intersectMaskWithPaths(mask, dirtyPaths) {
|
|
|
235
252
|
}
|
|
236
253
|
return out;
|
|
237
254
|
}
|
|
255
|
+
function maskFromPaths(paths) {
|
|
256
|
+
let out = undefined;
|
|
257
|
+
for (const path of paths)
|
|
258
|
+
out = mergeMasks(out, pathToMask(path));
|
|
259
|
+
return out ?? true;
|
|
260
|
+
}
|
|
261
|
+
function makePatch(root, path) {
|
|
262
|
+
root = (0, reactive2_1.toRaw)(root);
|
|
263
|
+
const exists = hasAt(root, path);
|
|
264
|
+
return {
|
|
265
|
+
path: [...path],
|
|
266
|
+
exists,
|
|
267
|
+
value: exists ? snapshotValue(getAt(root, path)) : undefined,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function patchesForMask(patch, mask) {
|
|
271
|
+
const selected = maskPaths(mask ?? true);
|
|
272
|
+
const out = [];
|
|
273
|
+
let emittedWholePatch = false;
|
|
274
|
+
for (const selectedPath of selected) {
|
|
275
|
+
if (startsWithPath(patch.path, selectedPath)) {
|
|
276
|
+
if (!emittedWholePatch) {
|
|
277
|
+
out.push(patch);
|
|
278
|
+
emittedWholePatch = true;
|
|
279
|
+
}
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (!startsWithPath(selectedPath, patch.path))
|
|
283
|
+
continue;
|
|
284
|
+
const rel = selectedPath.slice(patch.path.length);
|
|
285
|
+
const exists = patch.exists && hasAt(patch.value, rel);
|
|
286
|
+
out.push({
|
|
287
|
+
path: [...selectedPath],
|
|
288
|
+
exists,
|
|
289
|
+
value: exists ? snapshotValue(getAt(patch.value, rel)) : undefined,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return out;
|
|
293
|
+
}
|
|
294
|
+
function createPatchesListen(store) {
|
|
295
|
+
return (0, Listen_1.funcListenCallbackBase)((emit) => {
|
|
296
|
+
const off = store.listenPaths().on((change) => {
|
|
297
|
+
for (const path of change.paths)
|
|
298
|
+
emit(makePatch(store.state, path));
|
|
299
|
+
});
|
|
300
|
+
return off;
|
|
301
|
+
}, {
|
|
302
|
+
event: (type, count, api) => {
|
|
303
|
+
if (type == "add" && count == 1 && !api.isRun())
|
|
304
|
+
api.run();
|
|
305
|
+
if (type == "remove" && count == 0 && api.isRun())
|
|
306
|
+
api.close();
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
function createChangedDataListen(store) {
|
|
311
|
+
return (0, Listen_1.funcListenCallbackBase)((emit) => {
|
|
312
|
+
const off = store.listenPaths().on((change) => {
|
|
313
|
+
const mask = maskFromPaths(change.paths);
|
|
314
|
+
emit({ mask, data: pickSnapshot(store.state, mask) });
|
|
315
|
+
});
|
|
316
|
+
return off;
|
|
317
|
+
}, {
|
|
318
|
+
event: (type, count, api) => {
|
|
319
|
+
if (type == "add" && count == 1 && !api.isRun())
|
|
320
|
+
api.run();
|
|
321
|
+
if (type == "remove" && count == 0 && api.isRun())
|
|
322
|
+
api.close();
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
}
|
|
238
326
|
function watchTarget(root, path) {
|
|
239
327
|
let cur = root;
|
|
240
328
|
let lastReactive = root;
|
|
@@ -426,9 +514,10 @@ function createStore(initial, opts = {}) {
|
|
|
426
514
|
};
|
|
427
515
|
return store;
|
|
428
516
|
}
|
|
429
|
-
function exposeStore(store) {
|
|
430
|
-
|
|
431
|
-
|
|
517
|
+
function exposeStore(store, opts = {}) {
|
|
518
|
+
const get = ((mask) => mask ? store.update(mask).get() : store.snapshot());
|
|
519
|
+
const api = {
|
|
520
|
+
get,
|
|
432
521
|
set: (path, value) => {
|
|
433
522
|
let node = store.node;
|
|
434
523
|
for (const k of path)
|
|
@@ -444,6 +533,14 @@ function exposeStore(store) {
|
|
|
444
533
|
changed: store.listen(),
|
|
445
534
|
changedPaths: store.listenPaths(),
|
|
446
535
|
};
|
|
536
|
+
if (opts.push) {
|
|
537
|
+
api.patches = createPatchesListen(store);
|
|
538
|
+
api.changedData = createChangedDataListen(store);
|
|
539
|
+
}
|
|
540
|
+
return api;
|
|
541
|
+
}
|
|
542
|
+
function isRemoteListen(listen) {
|
|
543
|
+
return typeof listen?.on == "function" || typeof listen?.addListen == "function";
|
|
447
544
|
}
|
|
448
545
|
function subscribeRemote(listen, cb) {
|
|
449
546
|
let handle;
|
|
@@ -466,18 +563,19 @@ function subscribeRemote(listen, cb) {
|
|
|
466
563
|
}
|
|
467
564
|
function createStoreMirror(remote, initial = {}, opts = {}) {
|
|
468
565
|
const store = createStore(initial, opts);
|
|
566
|
+
const makeReport = (subOpts) => (error) => {
|
|
567
|
+
if (subOpts.onError)
|
|
568
|
+
subOpts.onError(error);
|
|
569
|
+
else
|
|
570
|
+
setTimeout(() => { throw error; }, 0);
|
|
571
|
+
};
|
|
572
|
+
async function pull(mask) {
|
|
573
|
+
const snap = await remote.get(mask);
|
|
574
|
+
applyMask(store.state, mask, snap);
|
|
575
|
+
}
|
|
469
576
|
async function sync(mask, subOpts = { current: true }) {
|
|
470
577
|
const baseMask = mask ?? true;
|
|
471
|
-
const report = (
|
|
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);
|
|
480
|
-
}
|
|
578
|
+
const report = makeReport(subOpts);
|
|
481
579
|
if (subOpts.current !== false)
|
|
482
580
|
await pull(baseMask);
|
|
483
581
|
let pendingMask = undefined;
|
|
@@ -492,7 +590,7 @@ function createStoreMirror(remote, initial = {}, opts = {}) {
|
|
|
492
590
|
drained.push();
|
|
493
591
|
};
|
|
494
592
|
const changedPaths = remote.changedPaths;
|
|
495
|
-
const usePaths = subOpts.partial !== false && (
|
|
593
|
+
const usePaths = subOpts.partial !== false && isRemoteListen(changedPaths);
|
|
496
594
|
const off = usePaths
|
|
497
595
|
? subscribeRemote(changedPaths, (change) => {
|
|
498
596
|
const nextMask = intersectMaskWithPaths(baseMask, change?.paths);
|
|
@@ -502,5 +600,58 @@ function createStoreMirror(remote, initial = {}, opts = {}) {
|
|
|
502
600
|
: subscribeRemote(remote.changed, () => queue(baseMask));
|
|
503
601
|
return () => { drained.close(); off(); };
|
|
504
602
|
}
|
|
505
|
-
|
|
603
|
+
async function syncPatches(mask, subOpts = { current: true }) {
|
|
604
|
+
if (!isRemoteListen(remote.patches))
|
|
605
|
+
throw new Error("createStoreMirror.syncPatches: remote.patches is not exposed");
|
|
606
|
+
const baseMask = mask ?? true;
|
|
607
|
+
const report = makeReport(subOpts);
|
|
608
|
+
if (subOpts.current !== false)
|
|
609
|
+
await pull(baseMask);
|
|
610
|
+
const pending = [];
|
|
611
|
+
const drained = createDrained(() => {
|
|
612
|
+
const batch = pending.splice(0);
|
|
613
|
+
try {
|
|
614
|
+
applyStorePatches(store, batch);
|
|
615
|
+
}
|
|
616
|
+
catch (e) {
|
|
617
|
+
report(e);
|
|
618
|
+
}
|
|
619
|
+
}, subOpts.drain);
|
|
620
|
+
const off = subscribeRemote(remote.patches, (patch) => {
|
|
621
|
+
const next = patchesForMask(patch, baseMask);
|
|
622
|
+
if (next.length == 0)
|
|
623
|
+
return;
|
|
624
|
+
pending.push(...next);
|
|
625
|
+
drained.push();
|
|
626
|
+
});
|
|
627
|
+
return () => { drained.close(); off(); };
|
|
628
|
+
}
|
|
629
|
+
async function syncChangedData(mask, subOpts = { current: true }) {
|
|
630
|
+
if (!isRemoteListen(remote.changedData))
|
|
631
|
+
throw new Error("createStoreMirror.syncChangedData: remote.changedData is not exposed");
|
|
632
|
+
const baseMask = mask ?? true;
|
|
633
|
+
const report = makeReport(subOpts);
|
|
634
|
+
if (subOpts.current !== false)
|
|
635
|
+
await pull(baseMask);
|
|
636
|
+
const pending = [];
|
|
637
|
+
const drained = createDrained(() => {
|
|
638
|
+
const batch = pending.splice(0);
|
|
639
|
+
try {
|
|
640
|
+
for (const change of batch) {
|
|
641
|
+
const nextMask = intersectMaskWithPaths(baseMask, maskPaths(change?.mask ?? true));
|
|
642
|
+
if (nextMask !== undefined)
|
|
643
|
+
applyMask(store.state, nextMask, change.data);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
catch (e) {
|
|
647
|
+
report(e);
|
|
648
|
+
}
|
|
649
|
+
}, subOpts.drain);
|
|
650
|
+
const off = subscribeRemote(remote.changedData, (change) => {
|
|
651
|
+
pending.push(change);
|
|
652
|
+
drained.push();
|
|
653
|
+
});
|
|
654
|
+
return () => { drained.close(); off(); };
|
|
655
|
+
}
|
|
656
|
+
return Object.assign(store, { sync, syncPatches, syncChangedData });
|
|
506
657
|
}
|
|
@@ -33,6 +33,10 @@ export type ListenStoreOptions<T> = ListenOptions<T> & {
|
|
|
33
33
|
};
|
|
34
34
|
export declare function getListenByOn(fn: any): any;
|
|
35
35
|
export declare function isListenOn(fn: any): boolean;
|
|
36
|
+
export declare function registerListenOn(on: Function, api: any): void;
|
|
37
|
+
export type ListenOnBrand<Z extends any[] = any[]> = {
|
|
38
|
+
readonly [LISTEN_ON_BRAND]: Z;
|
|
39
|
+
};
|
|
36
40
|
export declare function funcListenCore<T>(options?: ListenCoreOptions<T>): {
|
|
37
41
|
func: Listener<NormalizeTuple<T>>;
|
|
38
42
|
has: (k: key) => boolean;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.funcListenCallback = void 0;
|
|
4
4
|
exports.getListenByOn = getListenByOn;
|
|
5
5
|
exports.isListenOn = isListenOn;
|
|
6
|
+
exports.registerListenOn = registerListenOn;
|
|
6
7
|
exports.funcListenCore = funcListenCore;
|
|
7
8
|
exports.funcListenCallbackBase = funcListenCallbackBase;
|
|
8
9
|
exports.funcListenCallbackFast = funcListenCallbackFast;
|
|
@@ -16,6 +17,7 @@ exports.isListenCallback = isListenCallback;
|
|
|
16
17
|
const listenByOn = new WeakMap();
|
|
17
18
|
function getListenByOn(fn) { return typeof fn == 'function' ? listenByOn.get(fn) : undefined; }
|
|
18
19
|
function isListenOn(fn) { return typeof fn == 'function' && listenByOn.has(fn); }
|
|
20
|
+
function registerListenOn(on, api) { listenByOn.set(on, api); }
|
|
19
21
|
function funcListenCore(options = {}) {
|
|
20
22
|
const { fast = true, onRemove, event } = options;
|
|
21
23
|
const subs = new Map();
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { NormalizeTuple } from './Listen3';
|
|
2
|
+
import { ListenReplayApi, ReplayEvent } from './replay-listen';
|
|
3
|
+
export type ConflateOpts<Z extends any[] = any[]> = {
|
|
4
|
+
pending: () => number;
|
|
5
|
+
highWater: number;
|
|
6
|
+
lowWater?: number;
|
|
7
|
+
pollMs?: number;
|
|
8
|
+
keyOf?: (...event: Z) => PropertyKey | null | undefined;
|
|
9
|
+
maxKeys?: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function conflateReplay<T>(replay: ListenReplayApi<T>, opts: ConflateOpts<NormalizeTuple<T>>): {
|
|
12
|
+
api: {
|
|
13
|
+
line: {
|
|
14
|
+
func: import("./Listen3").Listener<[ReplayEvent<NormalizeTuple<T>>]>;
|
|
15
|
+
isRun: () => boolean;
|
|
16
|
+
run: () => void;
|
|
17
|
+
close: () => void;
|
|
18
|
+
eventClose: (cb: () => void) => () => void;
|
|
19
|
+
onClose: (cb: () => void) => () => void;
|
|
20
|
+
removeEventClose: (cb: () => void) => void;
|
|
21
|
+
on: import("./Listen3").ListenOn<[ReplayEvent<NormalizeTuple<T>>]>;
|
|
22
|
+
off: (k: (string | symbol) | import("./Listen3").Listener<[ReplayEvent<NormalizeTuple<T>>]> | null) => void;
|
|
23
|
+
addListen: (cb: import("./Listen3").Listener<[ReplayEvent<NormalizeTuple<T>>]>, opts?: {
|
|
24
|
+
cbClose?: () => void;
|
|
25
|
+
key?: string | symbol;
|
|
26
|
+
}) => () => void;
|
|
27
|
+
removeListen: (k: (string | symbol) | import("./Listen3").Listener<[ReplayEvent<NormalizeTuple<T>>]> | null) => void;
|
|
28
|
+
once: (cb: import("./Listen3").Listener<[ReplayEvent<NormalizeTuple<T>>]>, opts?: {
|
|
29
|
+
key?: string | symbol;
|
|
30
|
+
}) => () => void;
|
|
31
|
+
count: () => number;
|
|
32
|
+
readonly getAllKeys: (string | symbol)[];
|
|
33
|
+
};
|
|
34
|
+
since: (seq: number) => ReplayEvent<NormalizeTuple<T>>[] | null;
|
|
35
|
+
keyframe: () => ReplayEvent<NormalizeTuple<T>> | null;
|
|
36
|
+
};
|
|
37
|
+
close: () => void;
|
|
38
|
+
stats: () => {
|
|
39
|
+
conflating: boolean;
|
|
40
|
+
dropped: number;
|
|
41
|
+
keyframes: number;
|
|
42
|
+
coalesced: number;
|
|
43
|
+
flushes: number;
|
|
44
|
+
};
|
|
45
|
+
};
|