cry-synced-db-client 0.1.29 → 0.1.30
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/dist/db/DexieDb.d.ts +1 -2
- package/dist/db/SyncedDb.d.ts +2 -0
- package/dist/index.js +30 -49
- package/dist/types/I_DexieDb.d.ts +2 -2
- package/package.json +1 -1
package/dist/db/DexieDb.d.ts
CHANGED
|
@@ -39,9 +39,8 @@ export declare class DexieDb extends Dexie implements I_DexieDb {
|
|
|
39
39
|
deleteSyncMeta(collection: string): Promise<void>;
|
|
40
40
|
getTenant(): string;
|
|
41
41
|
getInstanceId(): string;
|
|
42
|
-
getNewerThan<T extends LocalDbEntity>(collection: string,
|
|
42
|
+
getNewerThan<T extends LocalDbEntity>(collection: string, rev: number): Promise<T[]>;
|
|
43
43
|
onMetaUpdated(callback: (payload: MetaUpdateBroadcast) => void): () => void;
|
|
44
|
-
private normalizeTimestamp;
|
|
45
44
|
/** Close the broadcast channel when done */
|
|
46
45
|
closeBroadcastChannel(): void;
|
|
47
46
|
}
|
package/dist/db/SyncedDb.d.ts
CHANGED
|
@@ -60,6 +60,8 @@ export declare class SyncedDb implements I_SyncedDb {
|
|
|
60
60
|
private readonly syncedDbInstanceId;
|
|
61
61
|
/** In-memory cache of sync metadata per collection */
|
|
62
62
|
private syncMetaCache;
|
|
63
|
+
/** In-memory cache of max _rev seen per collection (for cross-tab sync) */
|
|
64
|
+
private lastSeenRevCache;
|
|
63
65
|
/** Unsubscribe function for cross-tab meta updates */
|
|
64
66
|
private unsubscribeMetaUpdates?;
|
|
65
67
|
/** Whether this instance is the leader tab */
|
package/dist/index.js
CHANGED
|
@@ -306,6 +306,7 @@ class SyncedDb {
|
|
|
306
306
|
updaterId;
|
|
307
307
|
syncedDbInstanceId;
|
|
308
308
|
syncMetaCache = new Map;
|
|
309
|
+
lastSeenRevCache = new Map;
|
|
309
310
|
unsubscribeMetaUpdates;
|
|
310
311
|
isLeader = false;
|
|
311
312
|
leaderLockAbortController;
|
|
@@ -1528,51 +1529,45 @@ class SyncedDb {
|
|
|
1528
1529
|
}
|
|
1529
1530
|
}
|
|
1530
1531
|
async handleCrossTabMetaUpdate(payload) {
|
|
1531
|
-
if (payload.instanceId === this.
|
|
1532
|
+
if (payload.instanceId === this.dexieDb.getInstanceId()) {
|
|
1532
1533
|
return;
|
|
1533
1534
|
}
|
|
1534
1535
|
const collection = payload.collection;
|
|
1535
1536
|
if (!this.collections.has(collection)) {
|
|
1536
1537
|
return;
|
|
1537
1538
|
}
|
|
1538
|
-
const
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
if (item._deleted) {
|
|
1551
|
-
this.inMemDb.deleteOne(collection, item._id);
|
|
1552
|
-
} else {
|
|
1553
|
-
this.inMemDb.save(collection, item._id, item);
|
|
1554
|
-
}
|
|
1555
|
-
newItemsCount++;
|
|
1539
|
+
const lastSeenRev = this.lastSeenRevCache.get(collection) ?? 0;
|
|
1540
|
+
try {
|
|
1541
|
+
const newMeta = await this.dexieDb.getSyncMeta(collection);
|
|
1542
|
+
if (newMeta) {
|
|
1543
|
+
this.syncMetaCache.set(collection, newMeta);
|
|
1544
|
+
}
|
|
1545
|
+
const newerItems = await this.dexieDb.getNewerThan(collection, lastSeenRev);
|
|
1546
|
+
let newItemsCount = 0;
|
|
1547
|
+
let maxRev = lastSeenRev;
|
|
1548
|
+
for (const item of newerItems) {
|
|
1549
|
+
if (item._rev !== undefined && item._rev > maxRev) {
|
|
1550
|
+
maxRev = item._rev;
|
|
1556
1551
|
}
|
|
1557
|
-
if (
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
console.error("onExternalSync callback failed:", err);
|
|
1562
|
-
}
|
|
1552
|
+
if (item._deleted) {
|
|
1553
|
+
this.inMemDb.deleteOne(collection, item._id);
|
|
1554
|
+
} else {
|
|
1555
|
+
this.inMemDb.save(collection, item._id, this.stripLocalFields(item));
|
|
1563
1556
|
}
|
|
1564
|
-
|
|
1565
|
-
|
|
1557
|
+
newItemsCount++;
|
|
1558
|
+
}
|
|
1559
|
+
if (maxRev > lastSeenRev) {
|
|
1560
|
+
this.lastSeenRevCache.set(collection, maxRev);
|
|
1566
1561
|
}
|
|
1567
|
-
|
|
1568
|
-
console.warn(`Cross-tab sync: Received stale metadata for ${collection}. ` + `In-memory: ${cachedTs}, Received: ${receivedTs}`);
|
|
1569
|
-
if (this.onStaleMetaConflict) {
|
|
1562
|
+
if (this.onExternalSync) {
|
|
1570
1563
|
try {
|
|
1571
|
-
this.
|
|
1564
|
+
this.onExternalSync(collection, newItemsCount);
|
|
1572
1565
|
} catch (err) {
|
|
1573
|
-
console.error("
|
|
1566
|
+
console.error("onExternalSync callback failed:", err);
|
|
1574
1567
|
}
|
|
1575
1568
|
}
|
|
1569
|
+
} catch (err) {
|
|
1570
|
+
console.error(`Error handling cross-tab meta update for ${collection}:`, err);
|
|
1576
1571
|
}
|
|
1577
1572
|
}
|
|
1578
1573
|
async handleServerUpdate(payload) {
|
|
@@ -1731,7 +1726,7 @@ class DexieDb extends Dexie {
|
|
|
1731
1726
|
schema[SYNC_META_TABLE] = "[tenant+collection]";
|
|
1732
1727
|
for (const config of collectionConfigs) {
|
|
1733
1728
|
const additionalIndexes = config.indexes || [];
|
|
1734
|
-
const indexes = ["_id", "_dirty", "
|
|
1729
|
+
const indexes = ["_id", "_dirty", "_rev", ...additionalIndexes.map(String)];
|
|
1735
1730
|
schema[config.name] = indexes.join(", ");
|
|
1736
1731
|
}
|
|
1737
1732
|
this.version(1).stores(schema);
|
|
@@ -1893,10 +1888,9 @@ class DexieDb extends Dexie {
|
|
|
1893
1888
|
getInstanceId() {
|
|
1894
1889
|
return this.instanceId;
|
|
1895
1890
|
}
|
|
1896
|
-
async getNewerThan(collection,
|
|
1891
|
+
async getNewerThan(collection, rev) {
|
|
1897
1892
|
const table = this.getTable(collection);
|
|
1898
|
-
|
|
1899
|
-
return await table.where("_ts").above(normalizedTs).toArray();
|
|
1893
|
+
return await table.where("_rev").above(rev).toArray();
|
|
1900
1894
|
}
|
|
1901
1895
|
onMetaUpdated(callback) {
|
|
1902
1896
|
this.metaUpdateCallbacks.add(callback);
|
|
@@ -1904,19 +1898,6 @@ class DexieDb extends Dexie {
|
|
|
1904
1898
|
this.metaUpdateCallbacks.delete(callback);
|
|
1905
1899
|
};
|
|
1906
1900
|
}
|
|
1907
|
-
normalizeTimestamp(ts) {
|
|
1908
|
-
if (ts === null || ts === undefined)
|
|
1909
|
-
return 0;
|
|
1910
|
-
if (typeof ts === "number")
|
|
1911
|
-
return ts;
|
|
1912
|
-
if (ts instanceof Date)
|
|
1913
|
-
return ts.getTime();
|
|
1914
|
-
if (typeof ts.toNumber === "function")
|
|
1915
|
-
return ts.toNumber();
|
|
1916
|
-
if (typeof ts.valueOf === "function")
|
|
1917
|
-
return ts.valueOf();
|
|
1918
|
-
return 0;
|
|
1919
|
-
}
|
|
1920
1901
|
closeBroadcastChannel() {
|
|
1921
1902
|
if (this.debounceTimer) {
|
|
1922
1903
|
clearTimeout(this.debounceTimer);
|
|
@@ -61,8 +61,8 @@ export interface I_DexieDb {
|
|
|
61
61
|
deleteSyncMeta(collection: string): Promise<void>;
|
|
62
62
|
/** Vrne tenant */
|
|
63
63
|
getTenant(): string;
|
|
64
|
-
/** Get records newer than
|
|
65
|
-
getNewerThan<T extends LocalDbEntity>(collection: string,
|
|
64
|
+
/** Get records newer than revision (uses _rev index) */
|
|
65
|
+
getNewerThan<T extends LocalDbEntity>(collection: string, rev: number): Promise<T[]>;
|
|
66
66
|
/** Subscribe to metadata updates from other tabs. Returns unsubscribe function. */
|
|
67
67
|
onMetaUpdated(callback: (payload: MetaUpdateBroadcast) => void): () => void;
|
|
68
68
|
/** Get the instance ID */
|