cry-synced-db-client 2.0.11 → 2.0.14
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/index.js
CHANGED
|
@@ -3325,20 +3325,35 @@ var SyncEngine = class {
|
|
|
3325
3325
|
async (collection, items, specId) => {
|
|
3326
3326
|
if (specId !== void 0) {
|
|
3327
3327
|
if (specId.endsWith(":exit")) {
|
|
3328
|
-
const exitItems = items.filter((
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3328
|
+
const exitItems = items.filter((item) => item._evictIds);
|
|
3329
|
+
const state2 = collectionState.get(collection);
|
|
3330
|
+
for (const exitItem of exitItems) {
|
|
3331
|
+
if (exitItem._ts && (!(state2 == null ? void 0 : state2.maxTs) || this.compareTimestamps(exitItem._ts, state2.maxTs) > 0)) {
|
|
3332
|
+
state2.maxTs = exitItem._ts;
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3335
|
+
const exitIds = exitItems.map((item) => String(item._id));
|
|
3336
|
+
const dirtyChanges = await this.dexieDb.getDirtyChangesBatch(
|
|
3337
|
+
collection,
|
|
3338
|
+
exitIds
|
|
3339
|
+
);
|
|
3340
|
+
const evictIds = exitIds.filter((id) => !dirtyChanges.has(id));
|
|
3341
|
+
const dirtySkipped = exitIds.length - evictIds.length;
|
|
3342
|
+
if (evictIds.length > 0) {
|
|
3343
|
+
await this.dexieDb.deleteMany(collection, evictIds);
|
|
3332
3344
|
this.deps.writeToInMemBatch(
|
|
3333
3345
|
collection,
|
|
3334
|
-
|
|
3346
|
+
evictIds.map((id) => ({ _id: id })),
|
|
3335
3347
|
"delete",
|
|
3336
3348
|
{ source: "incremental" }
|
|
3337
3349
|
);
|
|
3350
|
+
}
|
|
3351
|
+
if (exitIds.length > 0) {
|
|
3338
3352
|
this.callbackSafe(this.callbacks.onEviction, {
|
|
3339
3353
|
collection,
|
|
3340
|
-
totalEvicted:
|
|
3341
|
-
totalServerEvicted:
|
|
3354
|
+
totalEvicted: evictIds.length,
|
|
3355
|
+
totalServerEvicted: evictIds.length,
|
|
3356
|
+
dirtySkipped
|
|
3342
3357
|
});
|
|
3343
3358
|
}
|
|
3344
3359
|
} else if (extras) {
|
|
@@ -3403,6 +3418,15 @@ var SyncEngine = class {
|
|
|
3403
3418
|
),
|
|
3404
3419
|
"findNewerManyStream"
|
|
3405
3420
|
);
|
|
3421
|
+
for (const [collection, state] of collectionState) {
|
|
3422
|
+
if (!state.maxTs) continue;
|
|
3423
|
+
await this.dexieDb.setSyncMeta(collection, state.maxTs);
|
|
3424
|
+
this.deps.setSyncMetaCache(collection, {
|
|
3425
|
+
tenant: this.tenant,
|
|
3426
|
+
collection,
|
|
3427
|
+
lastSyncTs: state.maxTs
|
|
3428
|
+
});
|
|
3429
|
+
}
|
|
3406
3430
|
for (const [name, state] of collectionState) {
|
|
3407
3431
|
receivedCount += state.receivedCount;
|
|
3408
3432
|
conflictsResolved += state.conflicts;
|
|
@@ -4111,28 +4135,6 @@ var SyncEngine = class {
|
|
|
4111
4135
|
if (collectionSentCount > 0) {
|
|
4112
4136
|
collectionSentCounts[collection] = collectionSentCount;
|
|
4113
4137
|
}
|
|
4114
|
-
let maxTs;
|
|
4115
|
-
for (const arr of [inserted, updated, deleted]) {
|
|
4116
|
-
for (const item of arr) {
|
|
4117
|
-
if (item._ts) {
|
|
4118
|
-
if (!maxTs || this.compareTimestamps(item._ts, maxTs) > 0) {
|
|
4119
|
-
maxTs = item._ts;
|
|
4120
|
-
}
|
|
4121
|
-
}
|
|
4122
|
-
}
|
|
4123
|
-
}
|
|
4124
|
-
if (maxTs) {
|
|
4125
|
-
const currentMeta = this.deps.getSyncMetaCache().get(collection);
|
|
4126
|
-
const currentTs = currentMeta == null ? void 0 : currentMeta.lastSyncTs;
|
|
4127
|
-
if (!currentTs || this.compareTimestamps(maxTs, currentTs) > 0) {
|
|
4128
|
-
await this.dexieDb.setSyncMeta(collection, maxTs);
|
|
4129
|
-
this.deps.setSyncMetaCache(collection, {
|
|
4130
|
-
tenant: this.tenant,
|
|
4131
|
-
collection,
|
|
4132
|
-
lastSyncTs: maxTs
|
|
4133
|
-
});
|
|
4134
|
-
}
|
|
4135
|
-
}
|
|
4136
4138
|
if (errors2 && errors2.length > 0) {
|
|
4137
4139
|
for (const e of errors2) {
|
|
4138
4140
|
console.error(
|
|
@@ -4338,7 +4340,7 @@ var SyncEngine = class {
|
|
|
4338
4340
|
async processCollectionServerData(collectionName, serverData, opts) {
|
|
4339
4341
|
var _a;
|
|
4340
4342
|
const config = this.collections.get(collectionName);
|
|
4341
|
-
if (!config) return { updatedIds: [] };
|
|
4343
|
+
if (!config) return { updatedIds: [], maxTs: void 0 };
|
|
4342
4344
|
const source = (_a = opts == null ? void 0 : opts.source) != null ? _a : "incremental";
|
|
4343
4345
|
const result = await this.processIncomingServerData(
|
|
4344
4346
|
collectionName,
|
|
@@ -4349,7 +4351,7 @@ var SyncEngine = class {
|
|
|
4349
4351
|
if (result.updatedIds.length > 0) {
|
|
4350
4352
|
this.deps.broadcastUpdates({ [collectionName]: result.updatedIds });
|
|
4351
4353
|
}
|
|
4352
|
-
return { updatedIds: result.updatedIds };
|
|
4354
|
+
return { updatedIds: result.updatedIds, maxTs: result.maxTs };
|
|
4353
4355
|
}
|
|
4354
4356
|
async processIncomingServerData(collectionName, config, serverData, source = "incremental") {
|
|
4355
4357
|
if (serverData.length === 0) {
|
|
@@ -4443,14 +4445,6 @@ var SyncEngine = class {
|
|
|
4443
4445
|
);
|
|
4444
4446
|
}
|
|
4445
4447
|
}
|
|
4446
|
-
if (maxTs) {
|
|
4447
|
-
await this.dexieDb.setSyncMeta(collectionName, maxTs);
|
|
4448
|
-
this.deps.setSyncMetaCache(collectionName, {
|
|
4449
|
-
tenant: this.tenant,
|
|
4450
|
-
collection: collectionName,
|
|
4451
|
-
lastSyncTs: maxTs
|
|
4452
|
-
});
|
|
4453
|
-
}
|
|
4454
4448
|
return { conflictsResolved, maxTs, updatedIds: allUpdatedIds, dexieMs: totalDexieMs, inMemMs: totalInMemMs };
|
|
4455
4449
|
}
|
|
4456
4450
|
// ============================================================
|
|
@@ -5911,11 +5905,14 @@ var _SyncedDb = class _SyncedDb {
|
|
|
5911
5905
|
if (!data || data.length === 0) continue;
|
|
5912
5906
|
const source = plan.wasFirstTime ? "initial" : "incremental";
|
|
5913
5907
|
try {
|
|
5914
|
-
await this.syncEngine.processCollectionServerData(
|
|
5908
|
+
const result = await this.syncEngine.processCollectionServerData(
|
|
5915
5909
|
plan.spec.name,
|
|
5916
5910
|
data,
|
|
5917
5911
|
{ source }
|
|
5918
5912
|
);
|
|
5913
|
+
if (plan.wasFirstTime) {
|
|
5914
|
+
await this._persistInitialCollectionCursor(plan.spec.name, result.maxTs);
|
|
5915
|
+
}
|
|
5919
5916
|
} catch (err) {
|
|
5920
5917
|
console.error(
|
|
5921
5918
|
`[SyncedDb] addCollectionsToSync: processCollectionServerData failed for "${plan.spec.name}":`,
|
|
@@ -5954,9 +5951,12 @@ var _SyncedDb = class _SyncedDb {
|
|
|
5954
5951
|
if (!spec.writeOnly && this.connectionManager.canSync()) {
|
|
5955
5952
|
const rawQuery = (_a = spec.syncConfig) == null ? void 0 : _a.query;
|
|
5956
5953
|
const query = typeof rawQuery === "function" ? rawQuery() : rawQuery;
|
|
5957
|
-
await this.syncCollectionForFind(
|
|
5958
|
-
|
|
5959
|
-
|
|
5954
|
+
await this.syncCollectionForFind(
|
|
5955
|
+
spec.name,
|
|
5956
|
+
query,
|
|
5957
|
+
{ returnDeleted: true },
|
|
5958
|
+
true
|
|
5959
|
+
);
|
|
5960
5960
|
}
|
|
5961
5961
|
}
|
|
5962
5962
|
/**
|
|
@@ -6586,7 +6586,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
6586
6586
|
* Sync a collection from server before querying locally.
|
|
6587
6587
|
* Used when returnDeleted/returnArchived is specified on find/findOne.
|
|
6588
6588
|
*/
|
|
6589
|
-
async syncCollectionForFind(collection, query, opts) {
|
|
6589
|
+
async syncCollectionForFind(collection, query, opts, checkpointInitialCollection = false) {
|
|
6590
6590
|
const meta = this.syncMetaCache.get(collection);
|
|
6591
6591
|
const timestamp = (meta == null ? void 0 : meta.lastSyncTs) || 0;
|
|
6592
6592
|
try {
|
|
@@ -6604,15 +6604,28 @@ var _SyncedDb = class _SyncedDb {
|
|
|
6604
6604
|
);
|
|
6605
6605
|
if (serverData.length > 0) {
|
|
6606
6606
|
const source = timestamp === 0 ? "initial" : "incremental";
|
|
6607
|
-
await this.syncEngine.processCollectionServerData(
|
|
6607
|
+
const result = await this.syncEngine.processCollectionServerData(
|
|
6608
6608
|
collection,
|
|
6609
6609
|
serverData,
|
|
6610
6610
|
{ source }
|
|
6611
6611
|
);
|
|
6612
|
+
if (checkpointInitialCollection && timestamp === 0) {
|
|
6613
|
+
await this._persistInitialCollectionCursor(collection, result.maxTs);
|
|
6614
|
+
}
|
|
6612
6615
|
}
|
|
6613
6616
|
} catch (e) {
|
|
6614
6617
|
}
|
|
6615
6618
|
}
|
|
6619
|
+
async _persistInitialCollectionCursor(collection, maxTs) {
|
|
6620
|
+
var _a;
|
|
6621
|
+
if (!maxTs || ((_a = this.syncMetaCache.get(collection)) == null ? void 0 : _a.lastSyncTs)) return;
|
|
6622
|
+
await this.dexieDb.setSyncMeta(collection, maxTs);
|
|
6623
|
+
this.syncMetaCache.set(collection, {
|
|
6624
|
+
tenant: this.tenant,
|
|
6625
|
+
collection,
|
|
6626
|
+
lastSyncTs: maxTs
|
|
6627
|
+
});
|
|
6628
|
+
}
|
|
6616
6629
|
/**
|
|
6617
6630
|
* Fire-and-forget background query to server.
|
|
6618
6631
|
* Uses timestamp 0 to fetch all matching items (not just newer than
|
|
@@ -8641,30 +8654,15 @@ var DexieDb = class extends Dexie {
|
|
|
8641
8654
|
async saveMany(collection, items) {
|
|
8642
8655
|
if (items.length === 0) return;
|
|
8643
8656
|
const table = this.getTable(collection);
|
|
8644
|
-
const valid = [];
|
|
8645
8657
|
for (const item of items) {
|
|
8646
8658
|
this.ensureStringId(item);
|
|
8647
8659
|
if (typeof item._id !== "string" || item._id.length === 0) {
|
|
8648
|
-
|
|
8649
|
-
`[DexieDb] DexieDb.saveMany:
|
|
8650
|
-
{ _id: item._id, _idType: typeof item._id, item }
|
|
8660
|
+
throw new Error(
|
|
8661
|
+
`[DexieDb] DexieDb.saveMany: invalid _id in "${collection}": ${String(item._id)}`
|
|
8651
8662
|
);
|
|
8652
|
-
continue;
|
|
8653
8663
|
}
|
|
8654
|
-
valid.push(item);
|
|
8655
|
-
}
|
|
8656
|
-
if (valid.length === 0) return;
|
|
8657
|
-
try {
|
|
8658
|
-
await table.bulkPut(valid);
|
|
8659
|
-
} catch (err) {
|
|
8660
|
-
const ids = valid.map((it) => String(it._id));
|
|
8661
|
-
console.error(
|
|
8662
|
-
`[DexieDb] DexieDb.saveMany: bulkPut failed for "${collection}" (${valid.length} items):`,
|
|
8663
|
-
err,
|
|
8664
|
-
"_ids:",
|
|
8665
|
-
ids
|
|
8666
|
-
);
|
|
8667
8664
|
}
|
|
8665
|
+
await table.bulkPut(items);
|
|
8668
8666
|
}
|
|
8669
8667
|
async deleteOne(collection, id) {
|
|
8670
8668
|
const table = this.getTable(collection);
|
|
@@ -9435,36 +9433,45 @@ function readStringJS(length) {
|
|
|
9435
9433
|
if ((byte1 & 128) === 0) {
|
|
9436
9434
|
units.push(byte1);
|
|
9437
9435
|
} else if ((byte1 & 224) === 192) {
|
|
9438
|
-
|
|
9439
|
-
const codePoint = (byte1 & 31) << 6 | byte2;
|
|
9440
|
-
if (codePoint < 128) {
|
|
9436
|
+
if (byte1 < 194 || position >= end || (src[position] & 192) !== 128) {
|
|
9441
9437
|
units.push(65533);
|
|
9442
9438
|
} else {
|
|
9443
|
-
|
|
9439
|
+
const byte2 = src[position++] & 63;
|
|
9440
|
+
units.push((byte1 & 31) << 6 | byte2);
|
|
9444
9441
|
}
|
|
9445
9442
|
} else if ((byte1 & 240) === 224) {
|
|
9446
|
-
const byte2 = src[position
|
|
9447
|
-
|
|
9448
|
-
const codePoint = (byte1 & 31) << 12 | byte2 << 6 | byte3;
|
|
9449
|
-
if (codePoint < 2048 || codePoint >= 55296 && codePoint <= 57343) {
|
|
9443
|
+
const byte2 = position < end ? src[position] : 0;
|
|
9444
|
+
if (position >= end || (byte2 & 192) !== 128 || byte1 === 224 && byte2 < 160 || byte1 === 237 && byte2 >= 160) {
|
|
9450
9445
|
units.push(65533);
|
|
9451
9446
|
} else {
|
|
9452
|
-
|
|
9447
|
+
position++;
|
|
9448
|
+
if (position >= end || (src[position] & 192) !== 128) {
|
|
9449
|
+
units.push(65533);
|
|
9450
|
+
} else {
|
|
9451
|
+
const byte3 = src[position++] & 63;
|
|
9452
|
+
units.push((byte1 & 31) << 12 | (byte2 & 63) << 6 | byte3);
|
|
9453
|
+
}
|
|
9453
9454
|
}
|
|
9454
9455
|
} else if ((byte1 & 248) === 240) {
|
|
9455
|
-
const byte2 = src[position
|
|
9456
|
-
|
|
9457
|
-
const byte4 = src[position++] & 63;
|
|
9458
|
-
let unit = (byte1 & 7) << 18 | byte2 << 12 | byte3 << 6 | byte4;
|
|
9459
|
-
if (unit < 65536 || unit > 1114111) {
|
|
9456
|
+
const byte2 = position < end ? src[position] : 0;
|
|
9457
|
+
if (byte1 > 244 || position >= end || (byte2 & 192) !== 128 || byte1 === 240 && byte2 < 144 || byte1 === 244 && byte2 >= 144) {
|
|
9460
9458
|
units.push(65533);
|
|
9461
|
-
} else if (unit > 65535) {
|
|
9462
|
-
unit -= 65536;
|
|
9463
|
-
units.push(unit >>> 10 & 1023 | 55296);
|
|
9464
|
-
unit = 56320 | unit & 1023;
|
|
9465
|
-
units.push(unit);
|
|
9466
9459
|
} else {
|
|
9467
|
-
|
|
9460
|
+
position++;
|
|
9461
|
+
if (position >= end || (src[position] & 192) !== 128) {
|
|
9462
|
+
units.push(65533);
|
|
9463
|
+
} else {
|
|
9464
|
+
const byte3 = src[position++] & 63;
|
|
9465
|
+
if (position >= end || (src[position] & 192) !== 128) {
|
|
9466
|
+
units.push(65533);
|
|
9467
|
+
} else {
|
|
9468
|
+
const byte4 = src[position++] & 63;
|
|
9469
|
+
let unit = (byte1 & 7) << 18 | (byte2 & 63) << 12 | byte3 << 6 | byte4;
|
|
9470
|
+
unit -= 65536;
|
|
9471
|
+
units.push(unit >>> 10 & 1023 | 55296);
|
|
9472
|
+
units.push(56320 | unit & 1023);
|
|
9473
|
+
}
|
|
9474
|
+
}
|
|
9468
9475
|
}
|
|
9469
9476
|
} else {
|
|
9470
9477
|
units.push(65533);
|
|
@@ -234,6 +234,7 @@ export declare class SyncedDb implements I_SyncedDb {
|
|
|
234
234
|
* Used when returnDeleted/returnArchived is specified on find/findOne.
|
|
235
235
|
*/
|
|
236
236
|
private syncCollectionForFind;
|
|
237
|
+
private _persistInitialCollectionCursor;
|
|
237
238
|
/**
|
|
238
239
|
* Fire-and-forget background query to server.
|
|
239
240
|
* Uses timestamp 0 to fetch all matching items (not just newer than
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* - Processing incoming data with conflict resolution
|
|
7
7
|
* - Uploading dirty items to server
|
|
8
8
|
*/
|
|
9
|
+
import type { Timestamp } from "mongodb";
|
|
9
10
|
import type { LocalDbEntity } from "../../types/DbEntity";
|
|
10
11
|
import type { SyncSource } from "../../types/I_InMemDb";
|
|
11
12
|
import type { I_SyncEngine, SyncEngineConfig, SyncExtras } from "../types/managers";
|
|
@@ -118,6 +119,7 @@ export declare class SyncEngine implements I_SyncEngine {
|
|
|
118
119
|
source?: SyncSource;
|
|
119
120
|
}): Promise<{
|
|
120
121
|
updatedIds: string[];
|
|
122
|
+
maxTs: Timestamp | undefined;
|
|
121
123
|
}>;
|
|
122
124
|
private readonly syncBatchSize;
|
|
123
125
|
private processIncomingServerData;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cry-synced-db-client",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"vitest": "^4.1.10"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"cry-db": "^2.6.
|
|
42
|
-
"cry-helpers": "^2.1.
|
|
43
|
-
"msgpackr": "^2.0.
|
|
41
|
+
"cry-db": "^2.6.4",
|
|
42
|
+
"cry-helpers": "^2.1.208",
|
|
43
|
+
"msgpackr": "^2.0.5",
|
|
44
44
|
"superjson": "^2.2.6"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|