cry-synced-db-client 0.1.167 → 0.1.170
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 +158 -32
- package/dist/src/db/RestProxy.d.ts +0 -1
- package/dist/src/types/I_SyncedDb.d.ts +2 -2
- package/package.json +3 -6
package/dist/index.js
CHANGED
|
@@ -329,6 +329,22 @@ function sameIdSequence(a, b) {
|
|
|
329
329
|
}
|
|
330
330
|
return true;
|
|
331
331
|
}
|
|
332
|
+
function containsIdArrayDescendant(value) {
|
|
333
|
+
if (value === null || typeof value !== "object") return false;
|
|
334
|
+
if (value instanceof Date || isObjectIdLike(value)) return false;
|
|
335
|
+
if (Array.isArray(value)) {
|
|
336
|
+
if (value.length > 0 && allElementsHaveId(value)) return true;
|
|
337
|
+
for (const v of value) {
|
|
338
|
+
if (containsIdArrayDescendant(v)) return true;
|
|
339
|
+
}
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
if (!isPlainObject(value)) return false;
|
|
343
|
+
for (const key of Object.keys(value)) {
|
|
344
|
+
if (containsIdArrayDescendant(value[key])) return true;
|
|
345
|
+
}
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
332
348
|
function computeArrayDiff(existingArr, updateArr, basePath, diff) {
|
|
333
349
|
if (existingArr.length === 0 && updateArr.length === 0) return;
|
|
334
350
|
if (!allElementsHaveId(updateArr) || existingArr.length > 0 && !allElementsHaveId(existingArr)) {
|
|
@@ -354,12 +370,14 @@ function computeArrayDiff(existingArr, updateArr, basePath, diff) {
|
|
|
354
370
|
if (sameIdSequence(existingArr, updateArr)) {
|
|
355
371
|
for (let i = 0; i < updateArr.length; i++) {
|
|
356
372
|
const elementId = String(updateArr[i]._id);
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
updateArr[i]
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
373
|
+
const elementPath = `${basePath}[${elementId}]`;
|
|
374
|
+
if (containsIdArrayDescendant(updateArr[i])) {
|
|
375
|
+
if (!deepEquals(existingArr[i], updateArr[i])) {
|
|
376
|
+
diff[elementPath] = updateArr[i];
|
|
377
|
+
}
|
|
378
|
+
} else {
|
|
379
|
+
computeDiffInto(existingArr[i], updateArr[i], elementPath, diff);
|
|
380
|
+
}
|
|
363
381
|
}
|
|
364
382
|
} else {
|
|
365
383
|
diff[basePath] = updateArr;
|
|
@@ -383,12 +401,19 @@ function computeArrayDiff(existingArr, updateArr, basePath, diff) {
|
|
|
383
401
|
for (const updateEl of updateArr) {
|
|
384
402
|
const id = String(updateEl._id);
|
|
385
403
|
if (existingIds.has(id)) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
updateEl
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
404
|
+
const elementPath = `${basePath}[${id}]`;
|
|
405
|
+
if (containsIdArrayDescendant(updateEl)) {
|
|
406
|
+
if (!deepEquals(existingById.get(id), updateEl)) {
|
|
407
|
+
diff[elementPath] = updateEl;
|
|
408
|
+
}
|
|
409
|
+
} else {
|
|
410
|
+
computeDiffInto(
|
|
411
|
+
existingById.get(id),
|
|
412
|
+
updateEl,
|
|
413
|
+
elementPath,
|
|
414
|
+
diff
|
|
415
|
+
);
|
|
416
|
+
}
|
|
392
417
|
}
|
|
393
418
|
}
|
|
394
419
|
}
|
|
@@ -3271,11 +3296,45 @@ var _SyncEngine = class _SyncEngine {
|
|
|
3271
3296
|
let sentCount = 0;
|
|
3272
3297
|
const collectionSentCounts = {};
|
|
3273
3298
|
for (const result of results) {
|
|
3274
|
-
const {
|
|
3299
|
+
const {
|
|
3300
|
+
collection,
|
|
3301
|
+
results: { inserted, updated, deleted, errors: errors2, warnings }
|
|
3302
|
+
} = result;
|
|
3303
|
+
const erroredIds = /* @__PURE__ */ new Set();
|
|
3304
|
+
if (errors2 && errors2.length > 0) {
|
|
3305
|
+
for (const e of errors2) erroredIds.add(String(e._id));
|
|
3306
|
+
}
|
|
3275
3307
|
const allSuccessIds = [];
|
|
3276
|
-
|
|
3277
|
-
for (const e of
|
|
3278
|
-
|
|
3308
|
+
const ambiguous = [];
|
|
3309
|
+
for (const e of inserted) {
|
|
3310
|
+
const sid = String(e._id);
|
|
3311
|
+
if (erroredIds.has(sid)) {
|
|
3312
|
+
ambiguous.push(sid);
|
|
3313
|
+
continue;
|
|
3314
|
+
}
|
|
3315
|
+
allSuccessIds.push(e._id);
|
|
3316
|
+
}
|
|
3317
|
+
for (const e of updated) {
|
|
3318
|
+
const sid = String(e._id);
|
|
3319
|
+
if (erroredIds.has(sid)) {
|
|
3320
|
+
ambiguous.push(sid);
|
|
3321
|
+
continue;
|
|
3322
|
+
}
|
|
3323
|
+
allSuccessIds.push(e._id);
|
|
3324
|
+
}
|
|
3325
|
+
for (const e of deleted) {
|
|
3326
|
+
const sid = String(e._id);
|
|
3327
|
+
if (erroredIds.has(sid)) {
|
|
3328
|
+
ambiguous.push(sid);
|
|
3329
|
+
continue;
|
|
3330
|
+
}
|
|
3331
|
+
allSuccessIds.push(e._id);
|
|
3332
|
+
}
|
|
3333
|
+
if (ambiguous.length > 0) {
|
|
3334
|
+
console.error(
|
|
3335
|
+
`Sync upload [${collection}]: ${ambiguous.length} id(s) appeared in BOTH inserted/updated/deleted AND errors[] \u2014 keeping dirty for safety. _ids: ${ambiguous.join(", ")}`
|
|
3336
|
+
);
|
|
3337
|
+
}
|
|
3279
3338
|
if (allSuccessIds.length > 0) {
|
|
3280
3339
|
await this.dexieDb.clearDirtyChangesBatch(collection, allSuccessIds);
|
|
3281
3340
|
}
|
|
@@ -3368,12 +3427,19 @@ var _SyncEngine = class _SyncEngine {
|
|
|
3368
3427
|
});
|
|
3369
3428
|
}
|
|
3370
3429
|
}
|
|
3371
|
-
if (errors2) {
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3430
|
+
if (errors2 && errors2.length > 0) {
|
|
3431
|
+
for (const e of errors2) {
|
|
3432
|
+
console.error(
|
|
3433
|
+
`Sync upload error [${collection}] _id=${e._id}: ${e.error} \u2014 dirty entry will persist until retry`
|
|
3434
|
+
);
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
if (warnings && warnings.length > 0) {
|
|
3438
|
+
for (const w of warnings) {
|
|
3439
|
+
console.warn(
|
|
3440
|
+
`Sync upload warning [${collection}] _id=${w._id}: ${w.error}`
|
|
3441
|
+
);
|
|
3442
|
+
}
|
|
3377
3443
|
}
|
|
3378
3444
|
const sentIds = /* @__PURE__ */ new Set([
|
|
3379
3445
|
...collectionBatches.flat().filter((b) => b.collection === collection).flatMap((b) => [
|
|
@@ -3433,15 +3499,60 @@ var _SyncEngine = class _SyncEngine {
|
|
|
3433
3499
|
);
|
|
3434
3500
|
let sentCount = 0;
|
|
3435
3501
|
for (const result of results) {
|
|
3436
|
-
const {
|
|
3502
|
+
const {
|
|
3503
|
+
results: { inserted, updated, deleted, errors: errors2, warnings }
|
|
3504
|
+
} = result;
|
|
3505
|
+
const erroredIds = /* @__PURE__ */ new Set();
|
|
3506
|
+
if (errors2 && errors2.length > 0) {
|
|
3507
|
+
for (const e of errors2) {
|
|
3508
|
+
erroredIds.add(String(e._id));
|
|
3509
|
+
console.error(
|
|
3510
|
+
`Sync upload error [${collection}] _id=${e._id}: ${e.error} \u2014 dirty entry will persist until retry`
|
|
3511
|
+
);
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
if (warnings && warnings.length > 0) {
|
|
3515
|
+
for (const w of warnings) {
|
|
3516
|
+
console.warn(
|
|
3517
|
+
`Sync upload warning [${collection}] _id=${w._id}: ${w.error}`
|
|
3518
|
+
);
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3437
3521
|
const allSuccessIds = [];
|
|
3438
|
-
|
|
3439
|
-
for (const e of
|
|
3440
|
-
|
|
3522
|
+
const ambiguous = [];
|
|
3523
|
+
for (const e of inserted) {
|
|
3524
|
+
const sid = String(e._id);
|
|
3525
|
+
if (erroredIds.has(sid)) {
|
|
3526
|
+
ambiguous.push(sid);
|
|
3527
|
+
continue;
|
|
3528
|
+
}
|
|
3529
|
+
allSuccessIds.push(e._id);
|
|
3530
|
+
}
|
|
3531
|
+
for (const e of updated) {
|
|
3532
|
+
const sid = String(e._id);
|
|
3533
|
+
if (erroredIds.has(sid)) {
|
|
3534
|
+
ambiguous.push(sid);
|
|
3535
|
+
continue;
|
|
3536
|
+
}
|
|
3537
|
+
allSuccessIds.push(e._id);
|
|
3538
|
+
}
|
|
3539
|
+
for (const e of deleted) {
|
|
3540
|
+
const sid = String(e._id);
|
|
3541
|
+
if (erroredIds.has(sid)) {
|
|
3542
|
+
ambiguous.push(sid);
|
|
3543
|
+
continue;
|
|
3544
|
+
}
|
|
3545
|
+
allSuccessIds.push(e._id);
|
|
3546
|
+
}
|
|
3547
|
+
if (ambiguous.length > 0) {
|
|
3548
|
+
console.error(
|
|
3549
|
+
`Sync upload [${collection}]: ${ambiguous.length} id(s) appeared in BOTH inserted/updated/deleted AND errors[] \u2014 keeping dirty for safety. _ids: ${ambiguous.join(", ")}`
|
|
3550
|
+
);
|
|
3551
|
+
}
|
|
3441
3552
|
if (allSuccessIds.length > 0) {
|
|
3442
3553
|
await this.dexieDb.clearDirtyChangesBatch(collection, allSuccessIds);
|
|
3443
3554
|
}
|
|
3444
|
-
sentCount +=
|
|
3555
|
+
sentCount += allSuccessIds.length;
|
|
3445
3556
|
}
|
|
3446
3557
|
return { sentCount };
|
|
3447
3558
|
}
|
|
@@ -4270,8 +4381,8 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4270
4381
|
});
|
|
4271
4382
|
this.pendingChanges = new PendingChangesManager({
|
|
4272
4383
|
tenant: this.tenant,
|
|
4273
|
-
debounceDexieWritesMs: (_l = config.debounceDexieWritesMs) != null ? _l :
|
|
4274
|
-
debounceRestWritesMs: (_m = config.debounceRestWritesMs) != null ? _m :
|
|
4384
|
+
debounceDexieWritesMs: (_l = config.debounceDexieWritesMs) != null ? _l : 200,
|
|
4385
|
+
debounceRestWritesMs: (_m = config.debounceRestWritesMs) != null ? _m : 1e3,
|
|
4275
4386
|
callbacks: {
|
|
4276
4387
|
onDexieWriteRequest: config.onDexieWriteRequest,
|
|
4277
4388
|
onDexieWriteResult: config.onDexieWriteResult,
|
|
@@ -6312,6 +6423,18 @@ var SyncedDb = _SyncedDb;
|
|
|
6312
6423
|
import Dexie from "dexie";
|
|
6313
6424
|
var SYNC_META_TABLE = "_sync_meta";
|
|
6314
6425
|
var DIRTY_CHANGES_TABLE = "_dirty_changes";
|
|
6426
|
+
var META_ONLY_DIRTY_KEYS = /* @__PURE__ */ new Set([
|
|
6427
|
+
"_id",
|
|
6428
|
+
"_ts",
|
|
6429
|
+
"_rev",
|
|
6430
|
+
"_lastUpdaterId"
|
|
6431
|
+
]);
|
|
6432
|
+
function isMetaOnlyChanges(changes) {
|
|
6433
|
+
for (const k of Object.keys(changes)) {
|
|
6434
|
+
if (!META_ONLY_DIRTY_KEYS.has(k)) return false;
|
|
6435
|
+
}
|
|
6436
|
+
return true;
|
|
6437
|
+
}
|
|
6315
6438
|
var DexieDb = class extends Dexie {
|
|
6316
6439
|
constructor(tenant, collectionConfigs) {
|
|
6317
6440
|
super(`synced-db-${tenant}`);
|
|
@@ -6476,6 +6599,7 @@ var DexieDb = class extends Dexie {
|
|
|
6476
6599
|
return result;
|
|
6477
6600
|
}
|
|
6478
6601
|
async addDirtyChange(collection, id, changes, baseMeta) {
|
|
6602
|
+
if (isMetaOnlyChanges(changes)) return;
|
|
6479
6603
|
const stringId = this.idToString(id);
|
|
6480
6604
|
const existing = await this.dirtyChanges.get([collection, stringId]);
|
|
6481
6605
|
const now = Date.now();
|
|
@@ -6498,13 +6622,15 @@ var DexieDb = class extends Dexie {
|
|
|
6498
6622
|
async addDirtyChangesBatch(collection, changesList) {
|
|
6499
6623
|
var _a, _b;
|
|
6500
6624
|
if (changesList.length === 0) return;
|
|
6625
|
+
const filtered = changesList.filter((c) => !isMetaOnlyChanges(c.changes));
|
|
6626
|
+
if (filtered.length === 0) return;
|
|
6501
6627
|
const now = Date.now();
|
|
6502
6628
|
const keys = [];
|
|
6503
|
-
for (const c of
|
|
6629
|
+
for (const c of filtered) keys.push([collection, this.idToString(c.id)]);
|
|
6504
6630
|
const existingEntries = await this.dirtyChanges.bulkGet(keys);
|
|
6505
6631
|
const toWrite = [];
|
|
6506
|
-
for (let i = 0; i <
|
|
6507
|
-
const changeItem =
|
|
6632
|
+
for (let i = 0; i < filtered.length; i++) {
|
|
6633
|
+
const changeItem = filtered[i];
|
|
6508
6634
|
const stringId = this.idToString(changeItem.id);
|
|
6509
6635
|
const existing = existingEntries[i];
|
|
6510
6636
|
if (existing) {
|
|
@@ -429,9 +429,9 @@ export interface SyncedDbConfig {
|
|
|
429
429
|
restTimeoutMs?: number;
|
|
430
430
|
/** Timeout za sync REST klice v ms (default: 120000) - daljši ker sync prenaša več podatkov */
|
|
431
431
|
syncTimeoutMs?: number;
|
|
432
|
-
/** Debounce čas za zapis v Dexie v ms (default:
|
|
432
|
+
/** Debounce čas za zapis v Dexie v ms (default: 200) */
|
|
433
433
|
debounceDexieWritesMs?: number;
|
|
434
|
-
/** Debounce čas za pošiljanje na REST v ms (default:
|
|
434
|
+
/** Debounce čas za pošiljanje na REST v ms (default: 1000) - po uspešnem zapisu v Dexie */
|
|
435
435
|
debounceRestWritesMs?: number;
|
|
436
436
|
/**
|
|
437
437
|
* Callback fired on each sync failure. Unlike the removed `onForcedOffline`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cry-synced-db-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.170",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"scripts": {
|
|
19
19
|
"clean": "rm -rf dist",
|
|
20
20
|
"build": "bun run clean && bun run build:js && bun run build:types",
|
|
21
|
-
"build:js": "esbuild ./src/index.ts --bundle --outdir=./dist --target=es2017 --format=esm --platform=browser --external:dexie --external:bson --external:cry-helpers
|
|
21
|
+
"build:js": "esbuild ./src/index.ts --bundle --outdir=./dist --target=es2017 --format=esm --platform=browser --external:dexie --external:bson --external:cry-helpers",
|
|
22
22
|
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
|
23
23
|
"test": "bun test test/*.test.ts test/restProxy/*.test.ts && vitest run",
|
|
24
24
|
"test:bun": "bun test test/*.test.ts test/restProxy/*.test.ts",
|
|
@@ -39,10 +39,7 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"cry-helpers": "^2.1.194",
|
|
41
41
|
"msgpackr": "^2.0.1",
|
|
42
|
-
"
|
|
43
|
-
"notepack.io": "^3.0.1",
|
|
44
|
-
"superjson": "^2.2.6",
|
|
45
|
-
"undici": "^8.2.0"
|
|
42
|
+
"superjson": "^2.2.6"
|
|
46
43
|
},
|
|
47
44
|
"peerDependencies": {
|
|
48
45
|
"bson": "^6.0.0 || ^7.0.0",
|