cry-synced-db-client 0.1.101 → 0.1.104

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
@@ -2348,6 +2348,7 @@ var _SyncEngine = class _SyncEngine {
2348
2348
  let sentCount = 0;
2349
2349
  let conflictsResolved = 0;
2350
2350
  const collectionStats = {};
2351
+ this.callOnSyncStart({ calledFrom });
2351
2352
  try {
2352
2353
  this.deps.cancelRestUploadTimer();
2353
2354
  await this.deps.awaitRestUpload();
@@ -2373,6 +2374,7 @@ var _SyncEngine = class _SyncEngine {
2373
2374
  configMap.set(collectionName, config);
2374
2375
  }
2375
2376
  this.callOnFindNewerManyCall(syncSpecs, calledFrom);
2377
+ this.callbackSafe(this.callbacks.onServerSyncStart, { calledFrom, collectionCount: syncSpecs.length });
2376
2378
  const findNewerManyStartTime = Date.now();
2377
2379
  const collectionState = /* @__PURE__ */ new Map();
2378
2380
  for (const [name] of configMap) {
@@ -2414,8 +2416,22 @@ var _SyncEngine = class _SyncEngine {
2414
2416
  };
2415
2417
  }
2416
2418
  this.callOnFindNewerManyResult(syncSpecs, {}, findNewerManyStartTime, true, calledFrom);
2419
+ this.callbackSafe(this.callbacks.onServerSyncEnd, {
2420
+ calledFrom,
2421
+ collectionCount: syncSpecs.length,
2422
+ receivedCount,
2423
+ durationMs: Date.now() - findNewerManyStartTime,
2424
+ success: true
2425
+ });
2417
2426
  } catch (err) {
2418
2427
  this.callOnFindNewerManyResult(syncSpecs, {}, findNewerManyStartTime, false, calledFrom, err);
2428
+ this.callbackSafe(this.callbacks.onServerSyncEnd, {
2429
+ calledFrom,
2430
+ collectionCount: syncSpecs.length,
2431
+ receivedCount,
2432
+ durationMs: Date.now() - findNewerManyStartTime,
2433
+ success: false
2434
+ });
2419
2435
  throw err;
2420
2436
  }
2421
2437
  const uploadStats = await this.uploadDirtyItems(calledFrom);
@@ -2430,7 +2446,7 @@ var _SyncEngine = class _SyncEngine {
2430
2446
  };
2431
2447
  }
2432
2448
  }
2433
- this.callOnSync({
2449
+ this.callOnSyncEnd({
2434
2450
  durationMs: Date.now() - startTime,
2435
2451
  receivedCount,
2436
2452
  sentCount,
@@ -2443,7 +2459,7 @@ var _SyncEngine = class _SyncEngine {
2443
2459
  const reason = err instanceof Error ? err.message : String(err);
2444
2460
  console.error("Sync failed, going offline:", err);
2445
2461
  this.deps.goOffline(`Sync failed: ${reason}`);
2446
- this.callOnSync({
2462
+ this.callOnSyncEnd({
2447
2463
  durationMs: Date.now() - startTime,
2448
2464
  receivedCount,
2449
2465
  sentCount,
@@ -2798,12 +2814,31 @@ var _SyncEngine = class _SyncEngine {
2798
2814
  // ============================================================
2799
2815
  // Callback Wrappers
2800
2816
  // ============================================================
2801
- callOnSync(info) {
2802
- if (this.callbacks.onSync) {
2817
+ /** Safe callback invocation — swallows errors */
2818
+ callbackSafe(fn, info) {
2819
+ if (fn) {
2820
+ try {
2821
+ fn(info);
2822
+ } catch (err) {
2823
+ console.error("Callback failed:", err);
2824
+ }
2825
+ }
2826
+ }
2827
+ callOnSyncStart(info) {
2828
+ if (this.callbacks.onSyncStart) {
2829
+ try {
2830
+ this.callbacks.onSyncStart(info);
2831
+ } catch (err) {
2832
+ console.error("onSyncStart callback failed:", err);
2833
+ }
2834
+ }
2835
+ }
2836
+ callOnSyncEnd(info) {
2837
+ if (this.callbacks.onSyncEnd) {
2803
2838
  try {
2804
- this.callbacks.onSync(info);
2839
+ this.callbacks.onSyncEnd(info);
2805
2840
  } catch (err) {
2806
- console.error("onSync callback failed:", err);
2841
+ console.error("onSyncEnd callback failed:", err);
2807
2842
  }
2808
2843
  }
2809
2844
  }
@@ -3321,7 +3356,12 @@ var SyncedDb = class _SyncedDb {
3321
3356
  const windowId = (_a = config._testWindowId) != null ? _a : this.getOrCreateWindowId();
3322
3357
  this.defaultReturnDeleted = (_b = config.returnDeleted) != null ? _b : false;
3323
3358
  this.defaultReturnArchived = (_c = config.returnArchived) != null ? _c : false;
3324
- this.onSync = config.onSync;
3359
+ this.onSyncStart = config.onSyncStart;
3360
+ this.onSyncEnd = config.onSyncEnd;
3361
+ this.onDexieSyncStart = config.onDexieSyncStart;
3362
+ this.onDexieSyncEnd = config.onDexieSyncEnd;
3363
+ this.onServerSyncStart = config.onServerSyncStart;
3364
+ this.onServerSyncEnd = config.onServerSyncEnd;
3325
3365
  this.onConflictResolved = config.onConflictResolved;
3326
3366
  this.onWsNotification = config.onWsNotification;
3327
3367
  this.onCrossTabSync = config.onCrossTabSync;
@@ -3435,7 +3475,10 @@ var SyncedDb = class _SyncedDb {
3435
3475
  dexieDb: this.dexieDb,
3436
3476
  restInterface: this.restInterface,
3437
3477
  callbacks: {
3438
- onSync: config.onSync,
3478
+ onSyncStart: config.onSyncStart,
3479
+ onSyncEnd: config.onSyncEnd,
3480
+ onServerSyncStart: config.onServerSyncStart,
3481
+ onServerSyncEnd: config.onServerSyncEnd,
3439
3482
  onConflictResolved: config.onConflictResolved,
3440
3483
  onServerWriteRequest: config.onServerWriteRequest,
3441
3484
  onServerWriteResult: config.onServerWriteResult,
@@ -3538,8 +3581,13 @@ var SyncedDb = class _SyncedDb {
3538
3581
  newlyAllowed.push(name);
3539
3582
  }
3540
3583
  }
3541
- for (const name of newlyAllowed) {
3542
- await this.loadCollectionToInMem(name);
3584
+ if (newlyAllowed.length > 0) {
3585
+ const dexieStart = Date.now();
3586
+ this.safeCallback(this.onDexieSyncStart, { calledFrom: "setSyncOnlyTheseCollections", collectionCount: newlyAllowed.length });
3587
+ for (const name of newlyAllowed) {
3588
+ await this.loadCollectionToInMem(name);
3589
+ }
3590
+ this.safeCallback(this.onDexieSyncEnd, { calledFrom: "setSyncOnlyTheseCollections", collectionCount: newlyAllowed.length, durationMs: Date.now() - dexieStart });
3543
3591
  }
3544
3592
  if (newlyAllowed.length > 0 && this.connectionManager.canSync()) {
3545
3593
  this.sync("setSyncOnlyTheseCollections").catch(() => {
@@ -3576,10 +3624,13 @@ var SyncedDb = class _SyncedDb {
3576
3624
  );
3577
3625
  }
3578
3626
  await this.pendingChanges.recoverPendingWrites();
3579
- for (const [name] of this.collections) {
3580
- if (!this.isSyncAllowed(name)) continue;
3627
+ const allowedColls = [...this.collections.keys()].filter((n) => this.isSyncAllowed(n));
3628
+ const dexieStart = Date.now();
3629
+ this.safeCallback(this.onDexieSyncStart, { calledFrom: "init", collectionCount: allowedColls.length });
3630
+ for (const name of allowedColls) {
3581
3631
  await this.loadCollectionToInMem(name);
3582
3632
  }
3633
+ this.safeCallback(this.onDexieSyncEnd, { calledFrom: "init", collectionCount: allowedColls.length, durationMs: Date.now() - dexieStart });
3583
3634
  this.leaderElection.init();
3584
3635
  this.crossTabSync.init();
3585
3636
  (_a = this.wakeSync) == null ? void 0 : _a.init();
@@ -4057,7 +4108,7 @@ var SyncedDb = class _SyncedDb {
4057
4108
  return null;
4058
4109
  }
4059
4110
  await this.connectionManager.withRestTimeout(
4060
- this.restInterface.deleteOne(collection, { _id: id }),
4111
+ this.restInterface.call("hardDeleteOne", { collection, query: { _id: id } }),
4061
4112
  "hardDeleteOne"
4062
4113
  );
4063
4114
  await this.dexieDb.deleteOne(collection, id);
@@ -4093,7 +4144,7 @@ var SyncedDb = class _SyncedDb {
4093
4144
  if (!item) break;
4094
4145
  try {
4095
4146
  await this.connectionManager.withRestTimeout(
4096
- this.restInterface.deleteOne(collection, { _id: item.id }),
4147
+ this.restInterface.call("hardDeleteOne", { collection, query: { _id: item.id } }),
4097
4148
  "hardDelete"
4098
4149
  );
4099
4150
  await this.dexieDb.deleteOne(collection, item.id);
@@ -4330,6 +4381,16 @@ var SyncedDb = class _SyncedDb {
4330
4381
  * Accumulates all items first, then does a single initCollection
4331
4382
  * call to minimize reactive update overhead.
4332
4383
  */
4384
+ /** Safe callback invocation — swallows errors */
4385
+ safeCallback(fn, info) {
4386
+ if (fn) {
4387
+ try {
4388
+ fn(info);
4389
+ } catch (err) {
4390
+ console.error("Callback failed:", err);
4391
+ }
4392
+ }
4393
+ }
4333
4394
  async loadCollectionToInMem(name) {
4334
4395
  const allItems = [];
4335
4396
  await this.dexieDb.forEachBatch(name, 2e3, async (chunk) => {
@@ -37,7 +37,12 @@ export declare class SyncedDb implements I_SyncedDb {
37
37
  private beforeUnloadHandler?;
38
38
  private readonly defaultReturnDeleted;
39
39
  private readonly defaultReturnArchived;
40
- private readonly onSync?;
40
+ private readonly onSyncStart?;
41
+ private readonly onSyncEnd?;
42
+ private readonly onDexieSyncStart?;
43
+ private readonly onDexieSyncEnd?;
44
+ private readonly onServerSyncStart?;
45
+ private readonly onServerSyncEnd?;
41
46
  private readonly onConflictResolved?;
42
47
  private readonly onWsNotification?;
43
48
  private readonly onCrossTabSync?;
@@ -141,6 +146,8 @@ export declare class SyncedDb implements I_SyncedDb {
141
146
  * Accumulates all items first, then does a single initCollection
142
147
  * call to minimize reactive update overhead.
143
148
  */
149
+ /** Safe callback invocation — swallows errors */
150
+ private safeCallback;
144
151
  private loadCollectionToInMem;
145
152
  private assertCollection;
146
153
  /** Stringify an Id parameter (ObjectId → hex string). */
@@ -43,7 +43,10 @@ export declare class SyncEngine implements I_SyncEngine {
43
43
  private processIncomingServerData;
44
44
  private compareTimestamps;
45
45
  private resolveCollectionConflict;
46
- private callOnSync;
46
+ /** Safe callback invocation — swallows errors */
47
+ private callbackSafe;
48
+ private callOnSyncStart;
49
+ private callOnSyncEnd;
47
50
  private callOnFindNewerManyCall;
48
51
  private callOnFindNewerManyResult;
49
52
  private callOnServerWriteRequest;
@@ -208,7 +208,21 @@ export interface I_InMemManager {
208
208
  deleteObjectsMetadata(collection: string, ids: Id[]): void;
209
209
  }
210
210
  export interface SyncEngineCallbacks {
211
- onSync?: (info: SyncInfo) => void;
211
+ onSyncStart?: (info: {
212
+ calledFrom?: string;
213
+ }) => void;
214
+ onSyncEnd?: (info: SyncInfo) => void;
215
+ onServerSyncStart?: (info: {
216
+ calledFrom?: string;
217
+ collectionCount: number;
218
+ }) => void;
219
+ onServerSyncEnd?: (info: {
220
+ calledFrom?: string;
221
+ collectionCount: number;
222
+ receivedCount: number;
223
+ durationMs: number;
224
+ success: boolean;
225
+ }) => void;
212
226
  onConflictResolved?: (report: ConflictResolutionReport) => void;
213
227
  onServerWriteRequest?: (info: ServerWriteRequestInfo) => void;
214
228
  onServerWriteResult?: (info: ServerWriteResultInfo) => void;
@@ -1,6 +1,7 @@
1
1
  import type { Timestamp, Document, SchemaMember, CollationOptions, ReadPreference, FindOneAndUpdateOptions, AggregateOptions } from "mongodb";
2
2
  import type { Types } from "cry-db";
3
3
  import type { Id } from "./DbEntity";
4
+ import type { Rdb2CallMap, Rdb2Operation } from "./Rdb2CallMap";
4
5
  export type CollectionUpdateResult = Types.CollectionUpdateResult;
5
6
  export type Obj = {
6
7
  [key: string]: any;
@@ -79,4 +80,9 @@ export interface I_RestInterface {
79
80
  upsertBatch<T>(collection: string, batch: BatchSpec<T>): Promise<T[]>;
80
81
  /** Pošlje batch update/delete za več kolekcij naenkrat */
81
82
  updateCollections<T>(collectionsBatches: CollectionUpdateRequest<T>[]): Promise<CollectionUpdateResult[]>;
83
+ /** Generic rdb2 operation call for operations beyond the minimal sync interface */
84
+ call<K extends Rdb2Operation, T = unknown>(operation: K, payload?: Rdb2CallMap[K], options?: {
85
+ timeoutMs?: number;
86
+ signal?: AbortSignal;
87
+ }): Promise<T>;
82
88
  }
@@ -293,8 +293,36 @@ export interface SyncedDbConfig {
293
293
  debounceRestWritesMs?: number;
294
294
  /** Callback ki se pokliče, ko SyncedDb sam preide v offline stanje (npr. ob sync napaki) */
295
295
  onForcedOffline?: (reason: string) => void;
296
- /** Callback za debugging/logging - pokliče se po vsaki sinhronizaciji */
297
- onSync?: (info: SyncInfo) => void;
296
+ /** Callback at the start of each sync cycle */
297
+ onSyncStart?: (info: {
298
+ calledFrom?: string;
299
+ }) => void;
300
+ /** Callback at the end of each sync cycle */
301
+ onSyncEnd?: (info: SyncInfo) => void;
302
+ /** Callback when Dexie→inMem loading starts (loadCollectionToInMem) */
303
+ onDexieSyncStart?: (info: {
304
+ calledFrom?: string;
305
+ collectionCount: number;
306
+ }) => void;
307
+ /** Callback when Dexie→inMem loading ends */
308
+ onDexieSyncEnd?: (info: {
309
+ calledFrom?: string;
310
+ collectionCount: number;
311
+ durationMs: number;
312
+ }) => void;
313
+ /** Callback when server download starts (findNewerManyStream) */
314
+ onServerSyncStart?: (info: {
315
+ calledFrom?: string;
316
+ collectionCount: number;
317
+ }) => void;
318
+ /** Callback when server download ends */
319
+ onServerSyncEnd?: (info: {
320
+ calledFrom?: string;
321
+ collectionCount: number;
322
+ receivedCount: number;
323
+ durationMs: number;
324
+ success: boolean;
325
+ }) => void;
298
326
  /** Callback when a sync conflict is resolved (local vs server data) */
299
327
  onConflictResolved?: (report: ConflictResolutionReport) => void;
300
328
  /** Callback before sending data to server (updateCollections) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cry-synced-db-client",
3
- "version": "0.1.101",
3
+ "version": "0.1.104",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",