cry-synced-db-client 0.1.148 → 0.1.150
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 +36 -0
- package/dist/index.js +62 -40
- package/dist/src/db/managers/InMemManager.d.ts +9 -1
- package/dist/src/db/sync/SyncEngine.d.ts +8 -1
- package/dist/src/db/types/managers.d.ts +16 -6
- package/dist/src/types/I_InMemDb.d.ts +23 -2
- package/dist/src/types/index.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
### `SyncSource` flag in `I_InMemDb.saveMany` / `deleteManyByIds`
|
|
6
|
+
|
|
7
|
+
The in-mem write API now accepts an opcijski `opts: { source?: SyncSource }`
|
|
8
|
+
parameter that labels the **origin** of each batch:
|
|
9
|
+
|
|
10
|
+
- `'initial'` — first full sync of a collection (no prior `lastSyncTs`)
|
|
11
|
+
- `'refresh'` — `referToServerSync` background reload (timestamp = 0
|
|
12
|
+
for already-synced collection, e.g. when the app needs records outside
|
|
13
|
+
the current sync window)
|
|
14
|
+
- `'incremental'` — everything else: delta sync, server WS push,
|
|
15
|
+
optimistic local writes (`save` / `insert` / `deleteOne` / `deleteMany`
|
|
16
|
+
/ `hardDelete`), `findById` / `findByIds` `returnDeleted` server fetch,
|
|
17
|
+
`ensureItemsAreLoaded`, `refreshByIdsInBackground`, eviction deletes
|
|
18
|
+
|
|
19
|
+
**Default**: when no `opts` is passed, `InMemManager.writeBatch`
|
|
20
|
+
normalizes to `'incremental'`. Backward compatible — existing
|
|
21
|
+
`I_InMemDb` implementations that ignore `opts` keep working unchanged.
|
|
22
|
+
|
|
23
|
+
The signal is **advisory**: it does not change sync semantics or
|
|
24
|
+
conflict resolution. Consumers can use it to apply per-source policies
|
|
25
|
+
(e.g. selective Vue reactivity in the in-mem store: items first seen
|
|
26
|
+
via `'incremental'` upgrade to reactive proxies; `'initial'` /
|
|
27
|
+
`'refresh'` floods stay as plain JS objects).
|
|
28
|
+
|
|
29
|
+
Threading: `SyncEngine` resolves `'initial'` per collection from
|
|
30
|
+
`syncMetaCache` lookup at the start of each `sync()` cycle (no prior
|
|
31
|
+
`lastSyncTs` ⇒ `'initial'`), and propagates the source via the
|
|
32
|
+
`writeToInMemBatch` deps callback through `InMemManager` to
|
|
33
|
+
`I_InMemDb.saveMany` / `deleteManyByIds`. `SyncedDb.referToServerSync`
|
|
34
|
+
hardcodes `'refresh'`; `syncCollectionForFind` derives source from the
|
|
35
|
+
local `timestamp === 0` check.
|
|
36
|
+
|
|
37
|
+
Tests: `test/syncSource.test.ts` (9 cases) covers initial / incremental
|
|
38
|
+
/ refresh propagation across all public write paths. `MockInMemDb`
|
|
39
|
+
exposes `recordedCalls: RecordedInMemCall[]` for assertion.
|
|
40
|
+
|
|
5
41
|
### `uploadDirtyItems` follow-up pass — drain in-sync writes immediately
|
|
6
42
|
|
|
7
43
|
Writes that land **during** a sync iteration had their
|
package/dist/index.js
CHANGED
|
@@ -272,12 +272,19 @@ var InMemManager = class {
|
|
|
272
272
|
/**
|
|
273
273
|
* Write batch of items to in-mem.
|
|
274
274
|
* Handles metadata callbacks automatically when useObjectMetadata is enabled.
|
|
275
|
+
*
|
|
276
|
+
* @param opts.source — origin of the write ('initial' | 'refresh' | 'incremental').
|
|
277
|
+
* Implementacija I_InMemDb lahko ta signal uporabi za optimizacije
|
|
278
|
+
* (npr. selektivna reactivity); ne vpliva na sync semantiko.
|
|
279
|
+
* Default: 'incremental'.
|
|
275
280
|
*/
|
|
276
|
-
writeBatch(collection, items, operation) {
|
|
281
|
+
writeBatch(collection, items, operation, opts) {
|
|
282
|
+
var _a;
|
|
277
283
|
if (items.length === 0) return;
|
|
278
284
|
const config = this.collections.get(collection);
|
|
285
|
+
const source = (_a = opts == null ? void 0 : opts.source) != null ? _a : "incremental";
|
|
279
286
|
if (operation === "upsert") {
|
|
280
|
-
this.inMemDb.saveMany(collection, items);
|
|
287
|
+
this.inMemDb.saveMany(collection, items, { source });
|
|
281
288
|
if (this.useObjectMetadata && (config == null ? void 0 : config.hasMetadata)) {
|
|
282
289
|
const ids = [];
|
|
283
290
|
for (const item of items) ids.push(item._id);
|
|
@@ -304,7 +311,7 @@ var InMemManager = class {
|
|
|
304
311
|
} else if (operation === "delete") {
|
|
305
312
|
const ids = [];
|
|
306
313
|
for (const item of items) ids.push(item._id);
|
|
307
|
-
this.inMemDb.deleteManyByIds(collection, ids);
|
|
314
|
+
this.inMemDb.deleteManyByIds(collection, ids, { source });
|
|
308
315
|
if (this.useObjectMetadata && (config == null ? void 0 : config.hasMetadata)) {
|
|
309
316
|
this.deleteObjectsMetadataInternal(collection, ids);
|
|
310
317
|
}
|
|
@@ -2478,10 +2485,13 @@ var _SyncEngine = class _SyncEngine {
|
|
|
2478
2485
|
const findNewerManyStartTime = Date.now();
|
|
2479
2486
|
const collectionState = /* @__PURE__ */ new Map();
|
|
2480
2487
|
for (const [name] of configMap) {
|
|
2488
|
+
const prior = this.deps.getSyncMetaCache().get(name);
|
|
2489
|
+
const isInitial = !(prior == null ? void 0 : prior.lastSyncTs);
|
|
2481
2490
|
collectionState.set(name, {
|
|
2482
2491
|
maxTs: void 0,
|
|
2483
2492
|
conflicts: 0,
|
|
2484
|
-
receivedCount: 0
|
|
2493
|
+
receivedCount: 0,
|
|
2494
|
+
source: isInitial ? "initial" : "incremental"
|
|
2485
2495
|
});
|
|
2486
2496
|
}
|
|
2487
2497
|
try {
|
|
@@ -2499,7 +2509,7 @@ var _SyncEngine = class _SyncEngine {
|
|
|
2499
2509
|
if (!config) return;
|
|
2500
2510
|
const state = collectionState.get(collection);
|
|
2501
2511
|
state.receivedCount += items.length;
|
|
2502
|
-
const stats = await this.processIncomingServerData(collection, config, items);
|
|
2512
|
+
const stats = await this.processIncomingServerData(collection, config, items, state.source);
|
|
2503
2513
|
state.conflicts += stats.conflictsResolved;
|
|
2504
2514
|
if (stats.maxTs) {
|
|
2505
2515
|
if (!state.maxTs || this.compareTimestamps(stats.maxTs, state.maxTs) > 0) {
|
|
@@ -2723,13 +2733,14 @@ var _SyncEngine = class _SyncEngine {
|
|
|
2723
2733
|
await this.dexieDb.deleteMany(collection, dexieDeleteIds);
|
|
2724
2734
|
}
|
|
2725
2735
|
if (inMemUpdateBatch.length > 0) {
|
|
2726
|
-
this.deps.writeToInMemBatch(collection, inMemUpdateBatch, "upsert");
|
|
2736
|
+
this.deps.writeToInMemBatch(collection, inMemUpdateBatch, "upsert", { source: "incremental" });
|
|
2727
2737
|
}
|
|
2728
2738
|
if (inMemDeleteIds.length > 0) {
|
|
2729
2739
|
this.deps.writeToInMemBatch(
|
|
2730
2740
|
collection,
|
|
2731
2741
|
inMemDeleteIds.map((id) => ({ _id: id })),
|
|
2732
|
-
"delete"
|
|
2742
|
+
"delete",
|
|
2743
|
+
{ source: "incremental" }
|
|
2733
2744
|
);
|
|
2734
2745
|
}
|
|
2735
2746
|
}
|
|
@@ -2745,7 +2756,7 @@ var _SyncEngine = class _SyncEngine {
|
|
|
2745
2756
|
}
|
|
2746
2757
|
await this.dexieDb.deleteMany(collection, deleteIds);
|
|
2747
2758
|
if (!isWriteOnly) {
|
|
2748
|
-
this.deps.writeToInMemBatch(collection, deleteDbEntities, "delete");
|
|
2759
|
+
this.deps.writeToInMemBatch(collection, deleteDbEntities, "delete", { source: "incremental" });
|
|
2749
2760
|
}
|
|
2750
2761
|
sentCount += deleted.length;
|
|
2751
2762
|
collectionSentCount += deleted.length;
|
|
@@ -2855,17 +2866,23 @@ var _SyncEngine = class _SyncEngine {
|
|
|
2855
2866
|
/**
|
|
2856
2867
|
* Process incoming server data for a single collection.
|
|
2857
2868
|
* Used by referToServer to process findNewer results.
|
|
2869
|
+
*
|
|
2870
|
+
* @param opts.source — origin label posredovan v writeBatch → inMemDb.
|
|
2871
|
+
* Default `'incremental'`. Caller naj uporabi `'refresh'` za množični
|
|
2872
|
+
* reload (referToServerSync) in `'initial'` za first-time fill.
|
|
2858
2873
|
*/
|
|
2859
|
-
async processCollectionServerData(collectionName, serverData) {
|
|
2874
|
+
async processCollectionServerData(collectionName, serverData, opts) {
|
|
2875
|
+
var _a;
|
|
2860
2876
|
const config = this.collections.get(collectionName);
|
|
2861
2877
|
if (!config) return { updatedIds: [] };
|
|
2862
|
-
const
|
|
2878
|
+
const source = (_a = opts == null ? void 0 : opts.source) != null ? _a : "incremental";
|
|
2879
|
+
const result = await this.processIncomingServerData(collectionName, config, serverData, source);
|
|
2863
2880
|
if (result.updatedIds.length > 0) {
|
|
2864
2881
|
this.deps.broadcastUpdates({ [collectionName]: result.updatedIds });
|
|
2865
2882
|
}
|
|
2866
2883
|
return { updatedIds: result.updatedIds };
|
|
2867
2884
|
}
|
|
2868
|
-
async processIncomingServerData(collectionName, config, serverData) {
|
|
2885
|
+
async processIncomingServerData(collectionName, config, serverData, source = "incremental") {
|
|
2869
2886
|
if (serverData.length === 0) {
|
|
2870
2887
|
return { conflictsResolved: 0, maxTs: void 0, updatedIds: [] };
|
|
2871
2888
|
}
|
|
@@ -2927,13 +2944,14 @@ var _SyncEngine = class _SyncEngine {
|
|
|
2927
2944
|
await this.dexieDb.saveMany(collectionName, dexieBatch);
|
|
2928
2945
|
}
|
|
2929
2946
|
if (inMemSaveBatch.length > 0) {
|
|
2930
|
-
this.deps.writeToInMemBatch(collectionName, inMemSaveBatch, "upsert");
|
|
2947
|
+
this.deps.writeToInMemBatch(collectionName, inMemSaveBatch, "upsert", { source });
|
|
2931
2948
|
}
|
|
2932
2949
|
if (inMemDeleteIds.length > 0) {
|
|
2933
2950
|
this.deps.writeToInMemBatch(
|
|
2934
2951
|
collectionName,
|
|
2935
2952
|
inMemDeleteIds.map((id) => ({ _id: id })),
|
|
2936
|
-
"delete"
|
|
2953
|
+
"delete",
|
|
2954
|
+
{ source }
|
|
2937
2955
|
);
|
|
2938
2956
|
}
|
|
2939
2957
|
}
|
|
@@ -3207,12 +3225,12 @@ var ServerUpdateHandler = class {
|
|
|
3207
3225
|
await this.dexieDb.clearDirtyChange(collection, serverItem._id);
|
|
3208
3226
|
}
|
|
3209
3227
|
if (!serverItem._deleted && !serverItem._archived) {
|
|
3210
|
-
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(serverItem)], "upsert");
|
|
3228
|
+
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(serverItem)], "upsert", { source: "incremental" });
|
|
3211
3229
|
}
|
|
3212
3230
|
} else {
|
|
3213
3231
|
await this.dexieDb.insert(collection, serverItem);
|
|
3214
3232
|
if (!serverItem._deleted && !serverItem._archived) {
|
|
3215
|
-
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(serverItem)], "upsert");
|
|
3233
|
+
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(serverItem)], "upsert", { source: "incremental" });
|
|
3216
3234
|
}
|
|
3217
3235
|
}
|
|
3218
3236
|
}
|
|
@@ -3241,7 +3259,7 @@ var ServerUpdateHandler = class {
|
|
|
3241
3259
|
const currentInMemState = Object.assign({}, localItem, pendingChange.data);
|
|
3242
3260
|
const merged = this.mergeLocalWithDelta(currentInMemState, serverDelta);
|
|
3243
3261
|
if (!merged._deleted && !merged._archived) {
|
|
3244
|
-
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(merged)], "upsert");
|
|
3262
|
+
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(merged)], "upsert", { source: "incremental" });
|
|
3245
3263
|
}
|
|
3246
3264
|
return;
|
|
3247
3265
|
}
|
|
@@ -3253,16 +3271,16 @@ var ServerUpdateHandler = class {
|
|
|
3253
3271
|
await this.dexieDb.save(collection, serverDelta._id, merged);
|
|
3254
3272
|
}
|
|
3255
3273
|
if (!merged._deleted && !merged._archived) {
|
|
3256
|
-
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(merged)], "upsert");
|
|
3274
|
+
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(merged)], "upsert", { source: "incremental" });
|
|
3257
3275
|
}
|
|
3258
3276
|
} else {
|
|
3259
3277
|
if (!metaChanged) return;
|
|
3260
3278
|
const merged = this.mergeLocalWithDelta(localItem, serverDelta);
|
|
3261
3279
|
await this.dexieDb.save(collection, serverDelta._id, merged);
|
|
3262
3280
|
if (!merged._deleted && !merged._archived) {
|
|
3263
|
-
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(merged)], "upsert");
|
|
3281
|
+
this.deps.writeToInMemBatch(collection, [this.stripLocalFields(merged)], "upsert", { source: "incremental" });
|
|
3264
3282
|
} else {
|
|
3265
|
-
this.deps.writeToInMemBatch(collection, [{ _id: serverDelta._id }], "delete");
|
|
3283
|
+
this.deps.writeToInMemBatch(collection, [{ _id: serverDelta._id }], "delete", { source: "incremental" });
|
|
3266
3284
|
}
|
|
3267
3285
|
}
|
|
3268
3286
|
}
|
|
@@ -3278,7 +3296,7 @@ var ServerUpdateHandler = class {
|
|
|
3278
3296
|
} else {
|
|
3279
3297
|
await this.dexieDb.deleteOne(collection, id);
|
|
3280
3298
|
}
|
|
3281
|
-
this.deps.writeToInMemBatch(collection, [{ _id: id }], "delete");
|
|
3299
|
+
this.deps.writeToInMemBatch(collection, [{ _id: id }], "delete", { source: "incremental" });
|
|
3282
3300
|
}
|
|
3283
3301
|
// ============================================================
|
|
3284
3302
|
// Private Helpers
|
|
@@ -3603,8 +3621,8 @@ var _SyncedDb = class _SyncedDb {
|
|
|
3603
3621
|
isLeader: () => this.leaderElection.isLeader(),
|
|
3604
3622
|
getCollections: () => this.collections,
|
|
3605
3623
|
dexieDb: this.dexieDb,
|
|
3606
|
-
writeToInMemBatch: (collection, items, operation) => {
|
|
3607
|
-
this.inMemManager.writeBatch(collection, items, operation);
|
|
3624
|
+
writeToInMemBatch: (collection, items, operation, opts) => {
|
|
3625
|
+
this.inMemManager.writeBatch(collection, items, operation, opts);
|
|
3608
3626
|
},
|
|
3609
3627
|
isSyncAllowed: (collection) => this.isSyncAllowed(collection),
|
|
3610
3628
|
reloadCollectionFromDexie: (collection) => this.loadCollectionToInMem(collection).then(() => void 0)
|
|
@@ -3683,8 +3701,8 @@ var _SyncedDb = class _SyncedDb {
|
|
|
3683
3701
|
deps: {
|
|
3684
3702
|
getSyncMetaCache: () => this.syncMetaCache,
|
|
3685
3703
|
setSyncMetaCache: (collection, meta) => this.syncMetaCache.set(collection, meta),
|
|
3686
|
-
writeToInMemBatch: (collection, items, operation) => {
|
|
3687
|
-
this.inMemManager.writeBatch(collection, items, operation);
|
|
3704
|
+
writeToInMemBatch: (collection, items, operation, opts) => {
|
|
3705
|
+
this.inMemManager.writeBatch(collection, items, operation, opts);
|
|
3688
3706
|
},
|
|
3689
3707
|
getInMemById: (collection, id) => this.inMemDb.getById(collection, id),
|
|
3690
3708
|
withSyncTimeout: (promise, operation) => this.connectionManager.withSyncTimeout(promise, operation),
|
|
@@ -3708,8 +3726,8 @@ var _SyncedDb = class _SyncedDb {
|
|
|
3708
3726
|
deps: {
|
|
3709
3727
|
isLeader: () => this.leaderElection.isLeader(),
|
|
3710
3728
|
canReceiveServerUpdates: () => this.connectionManager.canReceiveServerUpdates(),
|
|
3711
|
-
writeToInMemBatch: (collection, items, operation) => {
|
|
3712
|
-
this.inMemManager.writeBatch(collection, items, operation);
|
|
3729
|
+
writeToInMemBatch: (collection, items, operation, opts) => {
|
|
3730
|
+
this.inMemManager.writeBatch(collection, items, operation, opts);
|
|
3713
3731
|
},
|
|
3714
3732
|
broadcastUpdates: (updates) => this.crossTabSync.broadcastMetaUpdate(updates),
|
|
3715
3733
|
getPendingChange: (collection, id) => this.pendingChanges.getPendingChange(collection, id),
|
|
@@ -4018,7 +4036,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4018
4036
|
if (serverItem) {
|
|
4019
4037
|
await this.dexieDb.saveMany(collection, [serverItem]);
|
|
4020
4038
|
if (!serverItem._deleted && !serverItem._archived) {
|
|
4021
|
-
this.inMemManager.writeBatch(collection, [serverItem], "upsert");
|
|
4039
|
+
this.inMemManager.writeBatch(collection, [serverItem], "upsert", { source: "incremental" });
|
|
4022
4040
|
}
|
|
4023
4041
|
}
|
|
4024
4042
|
} catch (e) {
|
|
@@ -4077,7 +4095,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4077
4095
|
await this.dexieDb.saveMany(collection, serverItems);
|
|
4078
4096
|
const toInMem = serverItems.filter((s) => !s._deleted && !s._archived);
|
|
4079
4097
|
if (toInMem.length > 0) {
|
|
4080
|
-
this.inMemManager.writeBatch(collection, toInMem, "upsert");
|
|
4098
|
+
this.inMemManager.writeBatch(collection, toInMem, "upsert", { source: "incremental" });
|
|
4081
4099
|
}
|
|
4082
4100
|
}
|
|
4083
4101
|
} catch (e) {
|
|
@@ -4196,7 +4214,8 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4196
4214
|
"syncCollectionForFind"
|
|
4197
4215
|
);
|
|
4198
4216
|
if (serverData.length > 0) {
|
|
4199
|
-
|
|
4217
|
+
const source = timestamp === 0 ? "initial" : "incremental";
|
|
4218
|
+
await this.syncEngine.processCollectionServerData(collection, serverData, { source });
|
|
4200
4219
|
}
|
|
4201
4220
|
} catch (e) {
|
|
4202
4221
|
}
|
|
@@ -4214,7 +4233,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4214
4233
|
"referToServer"
|
|
4215
4234
|
).then(async (serverData) => {
|
|
4216
4235
|
if (serverData.length > 0) {
|
|
4217
|
-
await this.syncEngine.processCollectionServerData(collection, serverData);
|
|
4236
|
+
await this.syncEngine.processCollectionServerData(collection, serverData, { source: "refresh" });
|
|
4218
4237
|
}
|
|
4219
4238
|
}).catch((err) => {
|
|
4220
4239
|
console.error(`referToServer failed for ${collection}:`, err);
|
|
@@ -4236,7 +4255,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4236
4255
|
"refreshInBackground"
|
|
4237
4256
|
).then(async (serverItems) => {
|
|
4238
4257
|
if (!serverItems || serverItems.length === 0) return;
|
|
4239
|
-
await this.syncEngine.processCollectionServerData(collection, serverItems);
|
|
4258
|
+
await this.syncEngine.processCollectionServerData(collection, serverItems, { source: "incremental" });
|
|
4240
4259
|
}).catch((err) => {
|
|
4241
4260
|
console.error(`refreshInBackground failed for ${collection}:`, err);
|
|
4242
4261
|
});
|
|
@@ -4274,7 +4293,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4274
4293
|
await this.dexieDb.saveMany(collection, toSaveDexie);
|
|
4275
4294
|
}
|
|
4276
4295
|
if (toSaveInMem.length > 0) {
|
|
4277
|
-
this.inMemManager.writeBatch(collection, toSaveInMem, "upsert");
|
|
4296
|
+
this.inMemManager.writeBatch(collection, toSaveInMem, "upsert", { source: "incremental" });
|
|
4278
4297
|
}
|
|
4279
4298
|
}
|
|
4280
4299
|
// ==================== Write Operations ====================
|
|
@@ -4309,7 +4328,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4309
4328
|
const currentMem = isWriteOnly ? null : this.inMemDb.getById(collection, id);
|
|
4310
4329
|
const merged = __spreadValues(__spreadValues({}, currentMem || existing || { _id: id }), update);
|
|
4311
4330
|
if (!isWriteOnly && !(existing == null ? void 0 : existing._deleted) && !(existing == null ? void 0 : existing._archived)) {
|
|
4312
|
-
this.inMemManager.writeBatch(collection, [merged], "upsert");
|
|
4331
|
+
this.inMemManager.writeBatch(collection, [merged], "upsert", { source: "incremental" });
|
|
4313
4332
|
}
|
|
4314
4333
|
return merged;
|
|
4315
4334
|
}
|
|
@@ -4349,7 +4368,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4349
4368
|
});
|
|
4350
4369
|
this.pendingChanges.schedule(collection, id, newData, 0, "insert");
|
|
4351
4370
|
if (!((_a = this.collections.get(collection)) == null ? void 0 : _a.writeOnly)) {
|
|
4352
|
-
this.inMemManager.writeBatch(collection, [newData], "upsert");
|
|
4371
|
+
this.inMemManager.writeBatch(collection, [newData], "upsert", { source: "incremental" });
|
|
4353
4372
|
}
|
|
4354
4373
|
return newData;
|
|
4355
4374
|
}
|
|
@@ -4373,7 +4392,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4373
4392
|
};
|
|
4374
4393
|
this.pendingChanges.schedule(collection, id, deleteUpdate, 0, "deleteOne");
|
|
4375
4394
|
if (!((_a = this.collections.get(collection)) == null ? void 0 : _a.writeOnly)) {
|
|
4376
|
-
this.inMemManager.writeBatch(collection, [{ _id: id }], "delete");
|
|
4395
|
+
this.inMemManager.writeBatch(collection, [{ _id: id }], "delete", { source: "incremental" });
|
|
4377
4396
|
}
|
|
4378
4397
|
return existing;
|
|
4379
4398
|
}
|
|
@@ -4410,7 +4429,8 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4410
4429
|
this.inMemManager.writeBatch(
|
|
4411
4430
|
collection,
|
|
4412
4431
|
idsToDelete.map((id) => ({ _id: id })),
|
|
4413
|
-
"delete"
|
|
4432
|
+
"delete",
|
|
4433
|
+
{ source: "incremental" }
|
|
4414
4434
|
);
|
|
4415
4435
|
}
|
|
4416
4436
|
return idsToDelete.length;
|
|
@@ -4431,7 +4451,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4431
4451
|
"hardDeleteOne"
|
|
4432
4452
|
);
|
|
4433
4453
|
await this.dexieDb.deleteOne(collection, id);
|
|
4434
|
-
this.inMemManager.writeBatch(collection, [{ _id: id }], "delete");
|
|
4454
|
+
this.inMemManager.writeBatch(collection, [{ _id: id }], "delete", { source: "incremental" });
|
|
4435
4455
|
return existing;
|
|
4436
4456
|
}
|
|
4437
4457
|
async hardDelete(collection, query) {
|
|
@@ -4468,7 +4488,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4468
4488
|
"hardDelete"
|
|
4469
4489
|
);
|
|
4470
4490
|
await this.dexieDb.deleteOne(collection, item.id);
|
|
4471
|
-
this.inMemManager.writeBatch(collection, [{ _id: item.id }], "delete");
|
|
4491
|
+
this.inMemManager.writeBatch(collection, [{ _id: item.id }], "delete", { source: "incremental" });
|
|
4472
4492
|
results.push(true);
|
|
4473
4493
|
} catch (err) {
|
|
4474
4494
|
console.error(`Failed to hard delete ${String(item.id)}:`, err);
|
|
@@ -4848,7 +4868,8 @@ var _SyncedDb = class _SyncedDb {
|
|
|
4848
4868
|
this.inMemManager.writeBatch(
|
|
4849
4869
|
collection,
|
|
4850
4870
|
evictIds.map((id) => ({ _id: id })),
|
|
4851
|
-
"delete"
|
|
4871
|
+
"delete",
|
|
4872
|
+
{ source: "incremental" }
|
|
4852
4873
|
);
|
|
4853
4874
|
}
|
|
4854
4875
|
this.crossTabSync.broadcastReload([collection]);
|
|
@@ -5101,7 +5122,8 @@ var _SyncedDb = class _SyncedDb {
|
|
|
5101
5122
|
this.inMemManager.writeBatch(
|
|
5102
5123
|
p.collection,
|
|
5103
5124
|
uniqueEvictIds.map((id) => ({ _id: id })),
|
|
5104
|
-
"delete"
|
|
5125
|
+
"delete",
|
|
5126
|
+
{ source: "incremental" }
|
|
5105
5127
|
);
|
|
5106
5128
|
}
|
|
5107
5129
|
this.crossTabSync.broadcastReload([p.collection]);
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - Encapsulation: Hides metadata storage implementation
|
|
8
8
|
*/
|
|
9
9
|
import type { Id, DbEntity } from "../../types/DbEntity";
|
|
10
|
+
import type { SyncSource } from "../../types/I_InMemDb";
|
|
10
11
|
import type { I_InMemManager, InMemManagerConfig } from "../types/managers";
|
|
11
12
|
export declare class InMemManager implements I_InMemManager {
|
|
12
13
|
private readonly inMemDb;
|
|
@@ -18,8 +19,15 @@ export declare class InMemManager implements I_InMemManager {
|
|
|
18
19
|
/**
|
|
19
20
|
* Write batch of items to in-mem.
|
|
20
21
|
* Handles metadata callbacks automatically when useObjectMetadata is enabled.
|
|
22
|
+
*
|
|
23
|
+
* @param opts.source — origin of the write ('initial' | 'refresh' | 'incremental').
|
|
24
|
+
* Implementacija I_InMemDb lahko ta signal uporabi za optimizacije
|
|
25
|
+
* (npr. selektivna reactivity); ne vpliva na sync semantiko.
|
|
26
|
+
* Default: 'incremental'.
|
|
21
27
|
*/
|
|
22
|
-
writeBatch<T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete"
|
|
28
|
+
writeBatch<T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete", opts?: {
|
|
29
|
+
source?: SyncSource;
|
|
30
|
+
}): void;
|
|
23
31
|
/**
|
|
24
32
|
* Initialize collection from Dexie data.
|
|
25
33
|
* Called during SyncedDb.init().
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - Uploading dirty items to server
|
|
8
8
|
*/
|
|
9
9
|
import type { LocalDbEntity } from "../../types/DbEntity";
|
|
10
|
+
import type { SyncSource } from "../../types/I_InMemDb";
|
|
10
11
|
import type { I_SyncEngine, SyncEngineConfig, SyncExtras } from "../types/managers";
|
|
11
12
|
import type { UploadResult } from "../types/internal";
|
|
12
13
|
export declare class SyncEngine implements I_SyncEngine {
|
|
@@ -39,8 +40,14 @@ export declare class SyncEngine implements I_SyncEngine {
|
|
|
39
40
|
/**
|
|
40
41
|
* Process incoming server data for a single collection.
|
|
41
42
|
* Used by referToServer to process findNewer results.
|
|
43
|
+
*
|
|
44
|
+
* @param opts.source — origin label posredovan v writeBatch → inMemDb.
|
|
45
|
+
* Default `'incremental'`. Caller naj uporabi `'refresh'` za množični
|
|
46
|
+
* reload (referToServerSync) in `'initial'` za first-time fill.
|
|
42
47
|
*/
|
|
43
|
-
processCollectionServerData(collectionName: string, serverData: LocalDbEntity[]
|
|
48
|
+
processCollectionServerData(collectionName: string, serverData: LocalDbEntity[], opts?: {
|
|
49
|
+
source?: SyncSource;
|
|
50
|
+
}): Promise<{
|
|
44
51
|
updatedIds: string[];
|
|
45
52
|
}>;
|
|
46
53
|
/** Max items to process per batch in processIncomingServerData */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { Id, DbEntity, LocalDbEntity } from "../../types/DbEntity";
|
|
6
6
|
import type { I_DexieDb, SyncMeta, MetaUpdateBroadcast } from "../../types/I_DexieDb";
|
|
7
|
-
import type { I_InMemDb } from "../../types/I_InMemDb";
|
|
7
|
+
import type { I_InMemDb, SyncSource } from "../../types/I_InMemDb";
|
|
8
8
|
import type { I_RestInterface } from "../../types/I_RestInterface";
|
|
9
9
|
import type { PublishDataPayload } from "../../types/PublishRevsPayload";
|
|
10
10
|
import type { CollectionConfig, SyncInfo, ConflictResolutionReport, ServerWriteRequestInfo, ServerWriteResultInfo, FindNewerManyCallInfo, FindNewerManyResultInfo, DexieWriteRequestInfo, DexieWriteResultInfo, LocalstorageWriteResultInfo, WsNotificationInfo, CrossTabSyncInfo } from "../../types/I_SyncedDb";
|
|
@@ -49,7 +49,9 @@ export interface CrossTabSyncDeps {
|
|
|
49
49
|
/** DexieDb instance. */
|
|
50
50
|
dexieDb: I_DexieDb;
|
|
51
51
|
/** Write to in-mem batch. */
|
|
52
|
-
writeToInMemBatch: <T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete"
|
|
52
|
+
writeToInMemBatch: <T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete", opts?: {
|
|
53
|
+
source?: SyncSource;
|
|
54
|
+
}) => void;
|
|
53
55
|
/** Whether a collection participates in sync (not writeOnly, not filtered out). */
|
|
54
56
|
isSyncAllowed: (collection: string) => boolean;
|
|
55
57
|
/** Reload a collection fully from Dexie into in-mem (called on reload broadcast). */
|
|
@@ -212,7 +214,9 @@ export interface InMemManagerConfig {
|
|
|
212
214
|
}
|
|
213
215
|
export interface I_InMemManager {
|
|
214
216
|
/** Write batch of items to in-mem. */
|
|
215
|
-
writeBatch<T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete"
|
|
217
|
+
writeBatch<T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete", opts?: {
|
|
218
|
+
source?: import("../../types/I_InMemDb").SyncSource;
|
|
219
|
+
}): void;
|
|
216
220
|
/** Initialize collection from Dexie data. */
|
|
217
221
|
initCollection<T extends DbEntity>(collection: string, items: T[]): void;
|
|
218
222
|
/** Clear collection data and metadata. */
|
|
@@ -261,7 +265,9 @@ export interface SyncEngineCallbacks {
|
|
|
261
265
|
export interface SyncEngineDeps {
|
|
262
266
|
getSyncMetaCache: () => Map<string, SyncMeta>;
|
|
263
267
|
setSyncMetaCache: (collection: string, meta: SyncMeta) => void;
|
|
264
|
-
writeToInMemBatch: <T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete"
|
|
268
|
+
writeToInMemBatch: <T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete", opts?: {
|
|
269
|
+
source?: SyncSource;
|
|
270
|
+
}) => void;
|
|
265
271
|
getInMemById: <T extends DbEntity>(collection: string, id: Id) => T | undefined;
|
|
266
272
|
withSyncTimeout: <T>(promise: Promise<T>, operation: string) => Promise<T>;
|
|
267
273
|
/** Notify consumers that a sync cycle failed. Does not mutate online state. */
|
|
@@ -311,7 +317,9 @@ export interface I_SyncEngine {
|
|
|
311
317
|
/** Upload dirty items for a specific collection. */
|
|
312
318
|
uploadDirtyItemsForCollection(collection: string): Promise<UploadResult>;
|
|
313
319
|
/** Process incoming server data for a single collection (used by referToServer). */
|
|
314
|
-
processCollectionServerData(collectionName: string, serverData: import("../../types/DbEntity").LocalDbEntity[]
|
|
320
|
+
processCollectionServerData(collectionName: string, serverData: import("../../types/DbEntity").LocalDbEntity[], opts?: {
|
|
321
|
+
source?: SyncSource;
|
|
322
|
+
}): Promise<{
|
|
315
323
|
updatedIds: string[];
|
|
316
324
|
}>;
|
|
317
325
|
}
|
|
@@ -323,7 +331,9 @@ export interface ServerUpdateHandlerDeps {
|
|
|
323
331
|
canReceiveServerUpdates: () => boolean;
|
|
324
332
|
getPendingChange: (collection: string, id: Id) => PendingChange | undefined;
|
|
325
333
|
broadcastUpdates: (updates: Record<string, string[]>) => void;
|
|
326
|
-
writeToInMemBatch: <T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete"
|
|
334
|
+
writeToInMemBatch: <T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete", opts?: {
|
|
335
|
+
source?: SyncSource;
|
|
336
|
+
}) => void;
|
|
327
337
|
/** Whether a collection participates in sync (not writeOnly, not filtered out). */
|
|
328
338
|
isSyncAllowed: (collection: string) => boolean;
|
|
329
339
|
}
|
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
import type { Id, DbEntity } from "./DbEntity";
|
|
2
|
+
/**
|
|
3
|
+
* Izvor sync zapisa. Implementacija I_InMemDb lahko ta signal
|
|
4
|
+
* uporabi za optimizacije (npr. selektivna reactivity v klijentu),
|
|
5
|
+
* ne vpliva pa na sync semantiko.
|
|
6
|
+
*
|
|
7
|
+
* - 'initial' — full snapshot pri prvem polnjenju kolekcije
|
|
8
|
+
* - 'refresh' — refreshLocal pull (množični reload obstoječe kolekcije)
|
|
9
|
+
* - 'incremental' — delta s servera (vključno z lokalnim optimistic write
|
|
10
|
+
* pred server confirmom)
|
|
11
|
+
*/
|
|
12
|
+
export type SyncSource = "initial" | "refresh" | "incremental";
|
|
13
|
+
/**
|
|
14
|
+
* Opcije za zapisovalne operacije.
|
|
15
|
+
* Field-i so opcijski — implementacije, ki jih ne uporabljajo, jih lahko ignorirajo.
|
|
16
|
+
*/
|
|
17
|
+
export interface SaveManyOpts {
|
|
18
|
+
source?: SyncSource;
|
|
19
|
+
}
|
|
20
|
+
export interface DeleteManyByIdsOpts {
|
|
21
|
+
source?: SyncSource;
|
|
22
|
+
}
|
|
2
23
|
/**
|
|
3
24
|
* Interface za in-memory bazo podatkov
|
|
4
25
|
* UI samo bere iz te baze, posodablja jo samo sync-db
|
|
5
26
|
*/
|
|
6
27
|
export interface I_InMemDb {
|
|
7
28
|
/** Shrani/posodobi več objektov naenkrat (bulk upsert) */
|
|
8
|
-
saveMany<T extends DbEntity>(collection: string, items: T[]): void;
|
|
29
|
+
saveMany<T extends DbEntity>(collection: string, items: T[], opts?: SaveManyOpts): void;
|
|
9
30
|
/** Izbriše več objektov iz kolekcije po ID-jih */
|
|
10
|
-
deleteManyByIds(collection: string, ids: Id[]): void;
|
|
31
|
+
deleteManyByIds(collection: string, ids: Id[], opts?: DeleteManyByIdsOpts): void;
|
|
11
32
|
/** Shrani celotno kolekcijo (nadomesti obstoječo) */
|
|
12
33
|
saveCollection<T extends DbEntity>(collection: string, data: T[]): void;
|
|
13
34
|
/** Izbriše celotno kolekcijo */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type { Id, Entity, IdOrEntity, DbEntity, LocalDbEntity } from "./DbEntity";
|
|
2
2
|
export type { PublishableOperation, PublishRevsPayloadInsert, PublishRevsPayloadUpdate, PublishRevsPayloadDelete, PublishRevsPayloadUpdateMany, PublishRevsPayloadDeleteMany, PublishRevsPayloadBatchItem, PublishRevsPayloadBatch, PublishRevsPayload, PublishRevsSpec, PublishDataPayloadBase, PublishDataPayloadInsert, PublishDataPayloadUpdate, PublishDataPayloadDelete, PublishDataPayloadBatch, PublishDataPayload, PublishDataSpec, PublishSpec, } from "./PublishRevsPayload";
|
|
3
3
|
export type { Obj, QuerySpec, Projection, QueryOpts, KeyOf, InsertKeyOf, InsertSpec, UpdateSpec, BatchSpec, UpsertOptions, GetNewerSpec, I_RestInterface as RestInterface, } from "./I_RestInterface";
|
|
4
|
-
export type { I_InMemDb as InMemDb } from "./I_InMemDb";
|
|
4
|
+
export type { I_InMemDb as InMemDb, SyncSource, SaveManyOpts, DeleteManyByIdsOpts } from "./I_InMemDb";
|
|
5
5
|
export type { I_DexieDb as DexieDb, SyncMeta, DirtyChange, DirtyMeta } from "./I_DexieDb";
|
|
6
6
|
export type { I_ServerUpdateNotifier as ServerUpdateNotifier, ServerUpdateCallback, ServerUpdateNotifierCallbacks } from "./I_ServerUpdateNotifier";
|
|
7
7
|
export type { I_SyncedDb as SyncedDb, SyncedDbConfig, CollectionConfig, CollectionSyncConfig, SyncInfo, ServerWriteRequestInfo, ServerWriteResultInfo, FindNewerManyCallInfo, FindNewerManyResultInfo, DexieWriteRequestInfo, DexieWriteResultInfo, LocalstorageWriteResultInfo, WsNotificationInfo, InfrastructureErrorType, InfrastructureErrorInfo, ConflictSource, ConflictResolutionReport, CrossTabSyncInfo, EvictionInfo, EvictionCollectionInfo, } from "./I_SyncedDb";
|