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 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 result = await this.processIncomingServerData(collectionName, config, serverData);
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
- await this.syncEngine.processCollectionServerData(collection, serverData);
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"): void;
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[]): Promise<{
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") => void;
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"): void;
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") => void;
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[]): Promise<{
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") => void;
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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cry-synced-db-client",
3
- "version": "0.1.148",
3
+ "version": "0.1.150",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",