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.
@@ -1,2 +1,3 @@
1
1
  export * from "./reactive2";
2
2
  export * from "./store";
3
+ export * from "./store-replay";
@@ -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 declare function createStore<T extends object>(initial: T, opts?: Parameters<typeof reactive<T>>[1]): Store<T>;
77
- export declare function exposeStore<T extends object>(store: Store<T>): {
78
- get: (mask?: StoreMask<T>) => T extends object ? T | { [K in (string | number | symbol) & keyof T]: T[K] | (NonNullable<T[K]> extends object ? T[K] | { [K_2 in (string | number | symbol) & keyof NonNullable<T[K]>]: NonNullable<T[K]>[K_2] | (NonNullable<NonNullable<T[K]>[K_2]> extends object ? NonNullable<T[K]>[K_2] | { [K_3 in (string | number | symbol) & keyof NonNullable<NonNullable<T[K]>[K_2]>]: NonNullable<NonNullable<T[K]>[K_2]>[K_3] | (NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]> extends object ? NonNullable<NonNullable<T[K]>[K_2]>[K_3] | { [K_4 in (string | number | symbol) & keyof NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>]: NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4] | (NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]> extends object ? NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4] | { [K_5 in (string | number | symbol) & keyof NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>]: NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5] | (NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]> extends object ? NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5] | { [K_6 in (string | number | symbol) & keyof NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>]: NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6] | (NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]> extends object ? NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6] | { [K_7 in (string | number | symbol) & keyof NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>]: NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7] | (NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]> extends object ? NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7] | { [K_8 in (string | number | symbol) & keyof NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>]: NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8] | (NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]> extends object ? NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8] | { [K_9 in (string | number | symbol) & keyof NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>]: NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9] | (NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]> extends object ? NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9] | { [K_10 in (string | number | symbol) & keyof NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]>]: NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]>[K_10] | (NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]>[K_10]> extends object ? NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]>[K_10] | { [K_11 in (string | number | symbol) & keyof NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]>[K_10]>]: NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]>[K_10]>[K_11] | any; } : NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]>[K_10]); } : NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]>[K_9]); } : NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]>[K_8]); } : NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]>[K_7]); } : NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]>[K_6]); } : NonNullable<NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]>[K_5]); } : NonNullable<NonNullable<NonNullable<T[K]>[K_2]>[K_3]>[K_4]); } : NonNullable<NonNullable<T[K]>[K_2]>[K_3]); } : NonNullable<T[K]>[K_2]); } : T[K]); } : T;
79
- set: (path: StorePath, value: any) => void;
80
- replace: (path: StorePath, value: any) => void;
81
- changed: {
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]>;
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
- return {
431
- get: (mask) => mask ? store.update(mask).get() : store.snapshot(),
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 = (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);
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 && (typeof changedPaths?.on == "function" || typeof changedPaths?.addListen == "function");
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
- return Object.assign(store, { sync });
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
+ };