cry-synced-db-client 0.1.170 → 0.1.172
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/CHANGELOG.md +96 -0
- package/dist/index.js +242 -115
- package/dist/src/db/SyncedDb.d.ts +30 -1
- package/dist/src/db/managers/LeaderElectionManager.d.ts +13 -0
- package/dist/src/db/types/managers.d.ts +4 -0
- package/dist/src/types/I_SyncedDb.d.ts +67 -0
- package/dist/src/utils/computeDiff.d.ts +9 -3
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AggregateOptions } from "mongodb";
|
|
2
|
-
import type { I_SyncedDb, SyncedDbConfig, WsNotificationInfo, EvictionInfo, EvictionCollectionInfo } from "../types/I_SyncedDb";
|
|
2
|
+
import type { I_SyncedDb, SyncedDbConfig, CollectionConfig, WsNotificationInfo, EvictionInfo, EvictionCollectionInfo } from "../types/I_SyncedDb";
|
|
3
3
|
import type { DirtyMeta, MetaUpdateBroadcast } from "../types/I_DexieDb";
|
|
4
4
|
import type { QuerySpec, QueryOpts, UpdateSpec, InsertSpec, BatchSpec } from "../types/I_RestInterface";
|
|
5
5
|
import type { Id, DbEntity } from "../types/DbEntity";
|
|
@@ -36,6 +36,7 @@ export declare class SyncedDb implements I_SyncedDb {
|
|
|
36
36
|
private unsubscribeServerUpdates?;
|
|
37
37
|
private cleanupNotifierCallbacks?;
|
|
38
38
|
private beforeUnloadHandler?;
|
|
39
|
+
private visibilityFlushHandler?;
|
|
39
40
|
private readonly defaultReturnDeleted;
|
|
40
41
|
private readonly defaultReturnArchived;
|
|
41
42
|
private readonly onDatabaseCreated?;
|
|
@@ -62,6 +63,22 @@ export declare class SyncedDb implements I_SyncedDb {
|
|
|
62
63
|
getInstanceId(): string;
|
|
63
64
|
getCrossTabSyncDebounceMs(): number;
|
|
64
65
|
isLeaderTab(): boolean;
|
|
66
|
+
leaderSince(): Date | undefined;
|
|
67
|
+
followerSince(): Date | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Register a collection for sync at runtime. See `I_SyncedDb.addCollectionToSync`.
|
|
70
|
+
*/
|
|
71
|
+
addCollectionToSync(spec: CollectionConfig): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Replace the collection config and re-sync. See `I_SyncedDb.replaceSyncCollection`.
|
|
74
|
+
*/
|
|
75
|
+
replaceSyncCollection(spec: CollectionConfig): Promise<boolean>;
|
|
76
|
+
/**
|
|
77
|
+
* Shared install path for addCollectionToSync / replaceSyncCollection:
|
|
78
|
+
* write config, extend active sync filter, load Dexie cursor + in-mem,
|
|
79
|
+
* fire a targeted one-shot download for just this collection.
|
|
80
|
+
*/
|
|
81
|
+
private _installCollectionConfig;
|
|
65
82
|
/**
|
|
66
83
|
* Restrict sync to only these collections. When non-empty, only the listed
|
|
67
84
|
* collections load from Dexie→in-mem and download from server. Pass an empty
|
|
@@ -87,6 +104,18 @@ export declare class SyncedDb implements I_SyncedDb {
|
|
|
87
104
|
* Does NOT upload to server — call sync() for that.
|
|
88
105
|
*/
|
|
89
106
|
flush(): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Push dirty data to the server immediately, bypassing the upload debounce.
|
|
109
|
+
*
|
|
110
|
+
* Flushes pending Dexie writes, awaits any in-flight REST upload, then fires
|
|
111
|
+
* a fresh `uploadDirtyItems()`. Called automatically when the tab becomes
|
|
112
|
+
* hidden so data is not stranded by browser tab-throttling / suspension.
|
|
113
|
+
*
|
|
114
|
+
* No-op when offline, forced offline, or not yet initialized.
|
|
115
|
+
*
|
|
116
|
+
* @param calledFrom Diagnostic tag threaded through to upload callbacks
|
|
117
|
+
*/
|
|
118
|
+
flushToServer(calledFrom?: string): Promise<void>;
|
|
90
119
|
private _lastFullSyncDate?;
|
|
91
120
|
private _lastInitialSyncDate?;
|
|
92
121
|
/**
|
|
@@ -12,6 +12,8 @@ export declare class LeaderElectionManager implements I_LeaderElectionManager {
|
|
|
12
12
|
private isLeaderFlag;
|
|
13
13
|
private closing;
|
|
14
14
|
private releasingDueToVisibility;
|
|
15
|
+
private _leaderSince?;
|
|
16
|
+
private _followerSince?;
|
|
15
17
|
private releaseLeaderLockResolve?;
|
|
16
18
|
private becameLeaderPromise?;
|
|
17
19
|
private becameLeaderResolve?;
|
|
@@ -36,6 +38,17 @@ export declare class LeaderElectionManager implements I_LeaderElectionManager {
|
|
|
36
38
|
* Check if this instance is currently the leader.
|
|
37
39
|
*/
|
|
38
40
|
isLeader(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the timestamp when this tab became leader, or undefined if currently a follower.
|
|
43
|
+
* Cleared on transition to follower.
|
|
44
|
+
*/
|
|
45
|
+
leaderSince(): Date | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Returns the timestamp when this tab became follower, or undefined if currently a leader.
|
|
48
|
+
* Initialized at construction (every tab starts as a follower until it claims the lock).
|
|
49
|
+
* Cleared on transition to leader.
|
|
50
|
+
*/
|
|
51
|
+
followerSince(): Date | undefined;
|
|
39
52
|
/**
|
|
40
53
|
* Cleanup resources.
|
|
41
54
|
*/
|
|
@@ -26,6 +26,10 @@ export interface I_LeaderElectionManager {
|
|
|
26
26
|
releaseLeaderLock(): void;
|
|
27
27
|
/** Check if this instance is currently the leader. */
|
|
28
28
|
isLeader(): boolean;
|
|
29
|
+
/** Timestamp when this tab became leader, or undefined if currently a follower. */
|
|
30
|
+
leaderSince(): Date | undefined;
|
|
31
|
+
/** Timestamp when this tab became follower, or undefined if currently a leader. */
|
|
32
|
+
followerSince(): Date | undefined;
|
|
29
33
|
/** Initialize (setup visibility listeners, BroadcastChannel). */
|
|
30
34
|
init(): void;
|
|
31
35
|
/** Cleanup resources. */
|
|
@@ -402,6 +402,13 @@ export interface CollectionConfig<T extends DbEntity = any, M = any> {
|
|
|
402
402
|
* Read operations throw. Server sync and WS notifications are skipped.
|
|
403
403
|
*/
|
|
404
404
|
writeOnly?: boolean;
|
|
405
|
+
/**
|
|
406
|
+
* Marks this config as provisional — a later `addCollectionToSync()` with
|
|
407
|
+
* a permanent (non-temporary) config will replace it. Permanent configs
|
|
408
|
+
* (the default) are immutable: subsequent `addCollectionToSync()` calls
|
|
409
|
+
* for the same collection are no-ops once a permanent config is in place.
|
|
410
|
+
*/
|
|
411
|
+
temporaryConfig?: boolean;
|
|
405
412
|
/** Whether this collection uses in-memory metadata */
|
|
406
413
|
hasMetadata?: boolean;
|
|
407
414
|
/** Callback called when a single object is written to in-mem. Returns metadata to store. */
|
|
@@ -737,6 +744,53 @@ export interface I_SyncedDb {
|
|
|
737
744
|
* Does NOT upload to server — call sync() for that.
|
|
738
745
|
*/
|
|
739
746
|
flush(): Promise<void>;
|
|
747
|
+
/**
|
|
748
|
+
* Push dirty data to the server immediately, bypassing the upload debounce.
|
|
749
|
+
* Flushes pending Dexie writes, awaits any in-flight REST upload, then fires
|
|
750
|
+
* a fresh upload. Called automatically on `visibilitychange` to `hidden` so
|
|
751
|
+
* data is not stranded by browser tab-throttling / suspension.
|
|
752
|
+
* No-op when offline, forced offline, or not yet initialized.
|
|
753
|
+
* @param calledFrom Diagnostic tag threaded through to upload callbacks
|
|
754
|
+
*/
|
|
755
|
+
flushToServer(calledFrom?: string): Promise<void>;
|
|
756
|
+
/**
|
|
757
|
+
* Register a collection for sync at runtime.
|
|
758
|
+
*
|
|
759
|
+
* Behavior depends on whether a config already exists for `spec.name`:
|
|
760
|
+
* - permanent (existing config has `temporaryConfig !== true`): no-op
|
|
761
|
+
* - temporary (existing config has `temporaryConfig === true`): replaced by `spec`
|
|
762
|
+
* - none: `spec` is added
|
|
763
|
+
*
|
|
764
|
+
* On add or replace: loads the Dexie cursor for this collection into the
|
|
765
|
+
* sync-meta cache, hydrates in-mem from Dexie, and (when online + not
|
|
766
|
+
* `writeOnly`) fires a one-shot download sync for just this collection.
|
|
767
|
+
* If a `syncOnlyTheseCollections` filter is active, the new collection is
|
|
768
|
+
* added to it so future syncs include it.
|
|
769
|
+
*
|
|
770
|
+
* @param spec Collection config to register
|
|
771
|
+
*/
|
|
772
|
+
addCollectionToSync(spec: CollectionConfig): Promise<void>;
|
|
773
|
+
/**
|
|
774
|
+
* Replace the collection config and re-sync.
|
|
775
|
+
*
|
|
776
|
+
* Like `addCollectionToSync` but more aggressive — overrides even a
|
|
777
|
+
* permanent existing config. The only blocked transition is
|
|
778
|
+
* **permanent → temporary** (cannot downgrade an already-established
|
|
779
|
+
* config to provisional):
|
|
780
|
+
*
|
|
781
|
+
* - no existing config: install `spec`, return `true`
|
|
782
|
+
* - existing temporary: replace with `spec` (any type), return `true`
|
|
783
|
+
* - existing permanent, `spec.temporaryConfig === true`: return `false`, no-op
|
|
784
|
+
* - existing permanent, `spec` permanent: replace with `spec`, return `true`
|
|
785
|
+
*
|
|
786
|
+
* On replace: extends active `syncOnlyTheseCollections` filter, reloads
|
|
787
|
+
* the Dexie cursor, re-hydrates in-mem, and (when online + not `writeOnly`)
|
|
788
|
+
* fires a one-shot targeted download.
|
|
789
|
+
*
|
|
790
|
+
* @param spec Collection config to install
|
|
791
|
+
* @returns `true` if installed, `false` if blocked (permanent → temporary)
|
|
792
|
+
*/
|
|
793
|
+
replaceSyncCollection(spec: CollectionConfig): Promise<boolean>;
|
|
740
794
|
/**
|
|
741
795
|
* Returns when all collections were last successfully synced
|
|
742
796
|
* from the server, or undefined if never synced.
|
|
@@ -954,6 +1008,19 @@ export interface I_SyncedDb {
|
|
|
954
1008
|
* @returns true if this instance holds the leader lock
|
|
955
1009
|
*/
|
|
956
1010
|
isLeaderTab(): boolean;
|
|
1011
|
+
/**
|
|
1012
|
+
* Timestamp when this tab became the leader.
|
|
1013
|
+
* Set on transition from follower to leader; cleared when leadership is lost.
|
|
1014
|
+
* @returns Date of leader transition, or undefined if currently a follower
|
|
1015
|
+
*/
|
|
1016
|
+
leaderSince(): Date | undefined;
|
|
1017
|
+
/**
|
|
1018
|
+
* Timestamp when this tab became a follower.
|
|
1019
|
+
* Initialized at construction (every tab starts as a follower until it claims
|
|
1020
|
+
* the lock); cleared when leadership is gained, set again on transition to follower.
|
|
1021
|
+
* @returns Date of follower transition, or undefined if currently the leader
|
|
1022
|
+
*/
|
|
1023
|
+
followerSince(): Date | undefined;
|
|
957
1024
|
/**
|
|
958
1025
|
* Get metadata for a single object.
|
|
959
1026
|
* @param collection Collection name
|
|
@@ -84,9 +84,15 @@ export declare function deleteByPath(target: any, path: string): boolean;
|
|
|
84
84
|
* wrapped element[0], not into the array itself. The pending insert
|
|
85
85
|
* absorbs the sub-field edit.
|
|
86
86
|
*
|
|
87
|
-
* 2. New path is an ANCESTOR of existing keys
|
|
88
|
-
*
|
|
89
|
-
*
|
|
87
|
+
* 2. New path is an ANCESTOR of existing keys.
|
|
88
|
+
* - Plain ancestor (e.g. existing "koraki.0.diag", new "koraki" with full
|
|
89
|
+
* array): drop the descendants; the new full value supersedes any
|
|
90
|
+
* field-level deltas.
|
|
91
|
+
* - TERMINAL-bracket ancestor whose `newValue` is element-shaped
|
|
92
|
+
* (`arr[a].sub[b]` with `[<el>]` or plain object): LAYER pending
|
|
93
|
+
* descendant sub-field edits INTO `newValue` before dropping them,
|
|
94
|
+
* so the element-level write absorbs the prior sub-field-level
|
|
95
|
+
* writes instead of silently overwriting them.
|
|
90
96
|
*
|
|
91
97
|
* 3. New path is ORTHOGONAL to existing keys: simple set (Object.assign-equivalent).
|
|
92
98
|
*
|