cry-synced-db-client 0.1.113 → 0.1.115

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
@@ -3427,7 +3427,7 @@ var SyncedDb = class _SyncedDb {
3427
3427
  this.syncOnlyCollections = null;
3428
3428
  // Sync metadata cache
3429
3429
  this.syncMetaCache = /* @__PURE__ */ new Map();
3430
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
3430
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
3431
3431
  this.tenant = config.tenant;
3432
3432
  this.dexieDb = config.dexieDb;
3433
3433
  this.inMemDb = config.inMemDb;
@@ -3435,9 +3435,11 @@ var SyncedDb = class _SyncedDb {
3435
3435
  this.serverUpdateNotifier = config.serverUpdateNotifier;
3436
3436
  this.updaterId = Math.random().toString(36).substring(2, 15);
3437
3437
  this.syncedDbInstanceId = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
3438
- const windowId = (_a = config._testWindowId) != null ? _a : this.getOrCreateWindowId();
3439
- this.defaultReturnDeleted = (_b = config.returnDeleted) != null ? _b : false;
3440
- this.defaultReturnArchived = (_c = config.returnArchived) != null ? _c : false;
3438
+ this.dexieLoadConcurrency = (_a = config.dexieLoadConcurrency) != null ? _a : 1;
3439
+ const windowId = (_b = config._testWindowId) != null ? _b : this.getOrCreateWindowId();
3440
+ this.defaultReturnDeleted = (_c = config.returnDeleted) != null ? _c : false;
3441
+ this.defaultReturnArchived = (_d = config.returnArchived) != null ? _d : false;
3442
+ this.onDatabaseCreated = config.onDatabaseCreated;
3441
3443
  this.onSyncStart = config.onSyncStart;
3442
3444
  this.onSyncEnd = config.onSyncEnd;
3443
3445
  this.onDexieSyncStart = config.onDexieSyncStart;
@@ -3455,7 +3457,7 @@ var SyncedDb = class _SyncedDb {
3455
3457
  this.inMemManager = new InMemManager({
3456
3458
  inMemDb: this.inMemDb,
3457
3459
  collections: this.collections,
3458
- useObjectMetadata: (_d = config.useObjectMetadata) != null ? _d : false
3460
+ useObjectMetadata: (_e = config.useObjectMetadata) != null ? _e : false
3459
3461
  });
3460
3462
  this.leaderElection = new LeaderElectionManager({
3461
3463
  tenant: this.tenant,
@@ -3477,7 +3479,7 @@ var SyncedDb = class _SyncedDb {
3477
3479
  tenant: this.tenant,
3478
3480
  instanceId: this.syncedDbInstanceId,
3479
3481
  windowId,
3480
- debounceMs: (_e = config.crossTabSyncDebounceMs) != null ? _e : 100,
3482
+ debounceMs: (_f = config.crossTabSyncDebounceMs) != null ? _f : 100,
3481
3483
  callbacks: {
3482
3484
  onCrossTabSync: config.onCrossTabSync,
3483
3485
  onInfrastructureError: config.onInfrastructureError ? (type, message, error) => {
@@ -3503,8 +3505,8 @@ var SyncedDb = class _SyncedDb {
3503
3505
  });
3504
3506
  this.connectionManager = new ConnectionManager({
3505
3507
  restInterface: this.restInterface,
3506
- restTimeoutMs: (_f = config.restTimeoutMs) != null ? _f : 9e4,
3507
- syncTimeoutMs: (_g = config.syncTimeoutMs) != null ? _g : 12e4,
3508
+ restTimeoutMs: (_g = config.restTimeoutMs) != null ? _g : 9e4,
3509
+ syncTimeoutMs: (_h = config.syncTimeoutMs) != null ? _h : 12e4,
3508
3510
  autoSyncIntervalMs: config.autoSyncIntervalMs,
3509
3511
  callbacks: {
3510
3512
  onOnlineStatusChange: config.onOnlineStatusChange,
@@ -3530,8 +3532,8 @@ var SyncedDb = class _SyncedDb {
3530
3532
  });
3531
3533
  this.pendingChanges = new PendingChangesManager({
3532
3534
  tenant: this.tenant,
3533
- debounceDexieWritesMs: (_h = config.debounceDexieWritesMs) != null ? _h : 500,
3534
- debounceRestWritesMs: (_i = config.debounceRestWritesMs) != null ? _i : 100,
3535
+ debounceDexieWritesMs: (_i = config.debounceDexieWritesMs) != null ? _i : 500,
3536
+ debounceRestWritesMs: (_j = config.debounceRestWritesMs) != null ? _j : 100,
3535
3537
  callbacks: {
3536
3538
  onDexieWriteRequest: config.onDexieWriteRequest,
3537
3539
  onDexieWriteResult: config.onDexieWriteResult,
@@ -3608,8 +3610,8 @@ var SyncedDb = class _SyncedDb {
3608
3610
  });
3609
3611
  if (config.wakeSyncEnabled) {
3610
3612
  this.wakeSync = new WakeSyncManager({
3611
- gapThresholdMs: (_j = config.wakeSyncGapThresholdMs) != null ? _j : 1e4,
3612
- debounceMs: (_k = config.wakeSyncDebounceMs) != null ? _k : 2e3,
3613
+ gapThresholdMs: (_k = config.wakeSyncGapThresholdMs) != null ? _k : 1e4,
3614
+ debounceMs: (_l = config.wakeSyncDebounceMs) != null ? _l : 2e3,
3613
3615
  callbacks: {
3614
3616
  onWakeSync: config.onWakeSync
3615
3617
  },
@@ -3624,7 +3626,7 @@ var SyncedDb = class _SyncedDb {
3624
3626
  }
3625
3627
  if (config.networkStatusEnabled) {
3626
3628
  this.networkStatus = new NetworkStatusManager({
3627
- debounceMs: (_l = config.networkStatusDebounceMs) != null ? _l : 100,
3629
+ debounceMs: (_m = config.networkStatusDebounceMs) != null ? _m : 100,
3628
3630
  callbacks: {
3629
3631
  onBrowserNetworkChange: config.onBrowserNetworkChange,
3630
3632
  onBrowserOnline: config.onBrowserOnline,
@@ -3667,16 +3669,7 @@ var SyncedDb = class _SyncedDb {
3667
3669
  }
3668
3670
  }
3669
3671
  if (newlyAllowed.length > 0) {
3670
- const dexieStart = Date.now();
3671
- let totalItems = 0;
3672
- this.safeCallback(this.onDexieSyncStart, { calledFrom: "setSyncOnlyTheseCollections", collectionCount: newlyAllowed.length });
3673
- for (let i = 0; i < newlyAllowed.length; i++) {
3674
- const name = newlyAllowed[i];
3675
- const items = await this.loadCollectionToInMem(name);
3676
- totalItems += items;
3677
- this.safeCallback(this.onSyncProgress, { collection: name, loaded: i + 1, total: newlyAllowed.length, items });
3678
- }
3679
- this.safeCallback(this.onDexieSyncEnd, { calledFrom: "setSyncOnlyTheseCollections", collectionCount: newlyAllowed.length, totalItems, durationMs: Date.now() - dexieStart });
3672
+ await this.loadCollectionsToInMem(newlyAllowed, "setSyncOnlyTheseCollections");
3680
3673
  }
3681
3674
  if (newlyAllowed.length > 0 && this.connectionManager.canSync()) {
3682
3675
  this.sync("setSyncOnlyTheseCollections").catch(() => {
@@ -3714,18 +3707,16 @@ var SyncedDb = class _SyncedDb {
3714
3707
  }
3715
3708
  await this._loadLastFullSync();
3716
3709
  await this._loadLastInitialSync();
3710
+ if (this.dexieDb.isNewDatabase() && this.onDatabaseCreated) {
3711
+ try {
3712
+ this.onDatabaseCreated();
3713
+ } catch (err) {
3714
+ console.error("onDatabaseCreated callback failed:", err);
3715
+ }
3716
+ }
3717
3717
  await this.pendingChanges.recoverPendingWrites();
3718
3718
  const allowedColls = [...this.collections.keys()].filter((n) => this.isSyncAllowed(n));
3719
- const dexieStart = Date.now();
3720
- let totalItems = 0;
3721
- this.safeCallback(this.onDexieSyncStart, { calledFrom: "init", collectionCount: allowedColls.length });
3722
- for (let i = 0; i < allowedColls.length; i++) {
3723
- const name = allowedColls[i];
3724
- const items = await this.loadCollectionToInMem(name);
3725
- totalItems += items;
3726
- this.safeCallback(this.onSyncProgress, { collection: name, loaded: i + 1, total: allowedColls.length, items });
3727
- }
3728
- this.safeCallback(this.onDexieSyncEnd, { calledFrom: "init", collectionCount: allowedColls.length, totalItems, durationMs: Date.now() - dexieStart });
3719
+ await this.loadCollectionsToInMem(allowedColls, "init");
3729
3720
  this.leaderElection.init();
3730
3721
  this.crossTabSync.init();
3731
3722
  (_a = this.wakeSync) == null ? void 0 : _a.init();
@@ -4558,6 +4549,47 @@ var SyncedDb = class _SyncedDb {
4558
4549
  }
4559
4550
  }
4560
4551
  }
4552
+ /**
4553
+ * Load multiple collections from Dexie into in-mem with concurrency control.
4554
+ * @returns total items loaded
4555
+ */
4556
+ async loadCollectionsToInMem(names, calledFrom) {
4557
+ if (names.length === 0) return 0;
4558
+ const dexieStart = Date.now();
4559
+ let totalItems = 0;
4560
+ let loaded = 0;
4561
+ this.safeCallback(this.onDexieSyncStart, {
4562
+ calledFrom,
4563
+ collectionCount: names.length
4564
+ });
4565
+ const concurrency = this.dexieLoadConcurrency;
4566
+ const queue = [...names];
4567
+ const workers = Array.from(
4568
+ { length: Math.min(concurrency, queue.length) },
4569
+ async () => {
4570
+ while (queue.length > 0) {
4571
+ const name = queue.shift();
4572
+ const items = await this.loadCollectionToInMem(name);
4573
+ totalItems += items;
4574
+ loaded++;
4575
+ this.safeCallback(this.onSyncProgress, {
4576
+ collection: name,
4577
+ loaded,
4578
+ total: names.length,
4579
+ items
4580
+ });
4581
+ }
4582
+ }
4583
+ );
4584
+ await Promise.all(workers);
4585
+ this.safeCallback(this.onDexieSyncEnd, {
4586
+ calledFrom,
4587
+ collectionCount: names.length,
4588
+ totalItems,
4589
+ durationMs: Date.now() - dexieStart
4590
+ });
4591
+ return totalItems;
4592
+ }
4561
4593
  async loadCollectionToInMem(name) {
4562
4594
  const allItems = [];
4563
4595
  await this.dexieDb.forEachBatch(name, 2e3, async (chunk) => {
@@ -4577,7 +4609,7 @@ var SyncedDb = class _SyncedDb {
4577
4609
  }
4578
4610
  assertCollection(name) {
4579
4611
  if (!this.collections.has(name)) {
4580
- throw new Error(`Collection "${name}" not configured`);
4612
+ throw new Error(`SyncedDb: Collection "${(name == null ? void 0 : name.toString()) || "?"}" not configured`);
4581
4613
  }
4582
4614
  }
4583
4615
  /** Stringify an Id parameter (ObjectId → hex string). */
@@ -4658,6 +4690,7 @@ var DexieDb = class extends Dexie {
4658
4690
  constructor(tenant, collectionConfigs) {
4659
4691
  super(`synced-db-${tenant}`);
4660
4692
  this.collections = /* @__PURE__ */ new Map();
4693
+ this._isNewDatabase = false;
4661
4694
  this.tenant = tenant;
4662
4695
  const schema = {};
4663
4696
  schema[SYNC_META_TABLE] = "[tenant+collection]";
@@ -4666,6 +4699,9 @@ var DexieDb = class extends Dexie {
4666
4699
  schema[config.name] = "_id";
4667
4700
  }
4668
4701
  this.version(1).stores(schema);
4702
+ this.on("populate", () => {
4703
+ this._isNewDatabase = true;
4704
+ });
4669
4705
  this.syncMeta = this.table(SYNC_META_TABLE);
4670
4706
  this.dirtyChanges = this.table(DIRTY_CHANGES_TABLE);
4671
4707
  for (const config of collectionConfigs) {
@@ -4675,7 +4711,7 @@ var DexieDb = class extends Dexie {
4675
4711
  getTable(collection) {
4676
4712
  const table = this.collections.get(collection);
4677
4713
  if (!table) {
4678
- throw new Error(`Collection "${collection}" not configured`);
4714
+ throw new Error(`DexieDb: Collection "${(collection == null ? void 0 : collection.toString()) || "?"}" not configured`);
4679
4715
  }
4680
4716
  return table;
4681
4717
  }
@@ -4874,6 +4910,9 @@ var DexieDb = class extends Dexie {
4874
4910
  getTenant() {
4875
4911
  return this.tenant;
4876
4912
  }
4913
+ isNewDatabase() {
4914
+ return this._isNewDatabase;
4915
+ }
4877
4916
  };
4878
4917
 
4879
4918
  // node_modules/msgpackr/unpack.js
@@ -12,6 +12,7 @@ export declare class DexieDb extends Dexie implements I_DexieDb {
12
12
  private collections;
13
13
  private syncMeta;
14
14
  private dirtyChanges;
15
+ private _isNewDatabase;
15
16
  constructor(tenant: string, collectionConfigs: CollectionConfig<any>[]);
16
17
  private getTable;
17
18
  private idToString;
@@ -51,4 +52,5 @@ export declare class DexieDb extends Dexie implements I_DexieDb {
51
52
  setSyncMeta(collection: string, lastSyncTs: any): Promise<void>;
52
53
  deleteSyncMeta(collection: string): Promise<void>;
53
54
  getTenant(): string;
55
+ isNewDatabase(): boolean;
54
56
  }
@@ -31,12 +31,14 @@ export declare class SyncedDb implements I_SyncedDb {
31
31
  private syncOnlyCollections;
32
32
  private readonly updaterId;
33
33
  private readonly syncedDbInstanceId;
34
+ private readonly dexieLoadConcurrency;
34
35
  private syncMetaCache;
35
36
  private unsubscribeServerUpdates?;
36
37
  private cleanupNotifierCallbacks?;
37
38
  private beforeUnloadHandler?;
38
39
  private readonly defaultReturnDeleted;
39
40
  private readonly defaultReturnArchived;
41
+ private readonly onDatabaseCreated?;
40
42
  private readonly onSyncStart?;
41
43
  private readonly onSyncEnd?;
42
44
  private readonly onDexieSyncStart?;
@@ -181,6 +183,11 @@ export declare class SyncedDb implements I_SyncedDb {
181
183
  */
182
184
  /** Safe callback invocation — swallows errors */
183
185
  private safeCallback;
186
+ /**
187
+ * Load multiple collections from Dexie into in-mem with concurrency control.
188
+ * @returns total items loaded
189
+ */
190
+ private loadCollectionsToInMem;
184
191
  private loadCollectionToInMem;
185
192
  private assertCollection;
186
193
  /** Stringify an Id parameter (ObjectId → hex string). */
@@ -116,5 +116,7 @@ export interface I_DexieDb {
116
116
  deleteSyncMeta(collection: string): Promise<void>;
117
117
  /** Vrne tenant */
118
118
  getTenant(): string;
119
+ /** Returns true if the IndexedDB database was created fresh during this session (first ever open). */
120
+ isNewDatabase(): boolean;
119
121
  }
120
122
  export {};
@@ -293,6 +293,8 @@ 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 fired once during init() when the IndexedDB database was created fresh (first ever open). */
297
+ onDatabaseCreated?: () => void;
296
298
  /** Callback at the start of each sync cycle. initialSync=true if no full sync has completed yet. */
297
299
  onSyncStart?: (info: {
298
300
  calledFrom?: string;
@@ -406,6 +408,12 @@ export interface SyncedDbConfig {
406
408
  * Default: false
407
409
  */
408
410
  returnArchived?: boolean;
411
+ /**
412
+ * Number of collections to load from Dexie concurrently during init
413
+ * and setSyncOnlyTheseCollections. Higher values speed up initial load
414
+ * by issuing parallel IndexedDB reads. Default: 1 (sequential).
415
+ */
416
+ dexieLoadConcurrency?: number;
409
417
  /**
410
418
  * Enable sync on wake from sleep for leader tab.
411
419
  * When enabled, detects wake via pageshow/focus/visibilitychange events
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cry-synced-db-client",
3
- "version": "0.1.113",
3
+ "version": "0.1.115",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",