cry-synced-db-client 0.1.104 → 0.1.105

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,7 +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
+ this.callOnSyncStart({ calledFrom, initialSync: false });
2352
2352
  try {
2353
2353
  this.deps.cancelRestUploadTimer();
2354
2354
  await this.deps.awaitRestUpload();
@@ -3475,7 +3475,7 @@ var SyncedDb = class _SyncedDb {
3475
3475
  dexieDb: this.dexieDb,
3476
3476
  restInterface: this.restInterface,
3477
3477
  callbacks: {
3478
- onSyncStart: config.onSyncStart,
3478
+ onSyncStart: config.onSyncStart ? (info) => config.onSyncStart(__spreadProps(__spreadValues({}, info), { initialSync: !this._lastFullSyncDate })) : void 0,
3479
3479
  onSyncEnd: config.onSyncEnd,
3480
3480
  onServerSyncStart: config.onServerSyncStart,
3481
3481
  onServerSyncEnd: config.onServerSyncEnd,
@@ -3583,11 +3583,12 @@ var SyncedDb = class _SyncedDb {
3583
3583
  }
3584
3584
  if (newlyAllowed.length > 0) {
3585
3585
  const dexieStart = Date.now();
3586
+ let totalItems = 0;
3586
3587
  this.safeCallback(this.onDexieSyncStart, { calledFrom: "setSyncOnlyTheseCollections", collectionCount: newlyAllowed.length });
3587
3588
  for (const name of newlyAllowed) {
3588
- await this.loadCollectionToInMem(name);
3589
+ totalItems += await this.loadCollectionToInMem(name);
3589
3590
  }
3590
- this.safeCallback(this.onDexieSyncEnd, { calledFrom: "setSyncOnlyTheseCollections", collectionCount: newlyAllowed.length, durationMs: Date.now() - dexieStart });
3591
+ this.safeCallback(this.onDexieSyncEnd, { calledFrom: "setSyncOnlyTheseCollections", collectionCount: newlyAllowed.length, totalItems, durationMs: Date.now() - dexieStart });
3591
3592
  }
3592
3593
  if (newlyAllowed.length > 0 && this.connectionManager.canSync()) {
3593
3594
  this.sync("setSyncOnlyTheseCollections").catch(() => {
@@ -3623,14 +3624,16 @@ var SyncedDb = class _SyncedDb {
3623
3624
  "BroadcastChannel API is not available. Cross-tab synchronization disabled."
3624
3625
  );
3625
3626
  }
3627
+ await this._loadLastFullSync();
3626
3628
  await this.pendingChanges.recoverPendingWrites();
3627
3629
  const allowedColls = [...this.collections.keys()].filter((n) => this.isSyncAllowed(n));
3628
3630
  const dexieStart = Date.now();
3631
+ let totalItems = 0;
3629
3632
  this.safeCallback(this.onDexieSyncStart, { calledFrom: "init", collectionCount: allowedColls.length });
3630
3633
  for (const name of allowedColls) {
3631
- await this.loadCollectionToInMem(name);
3634
+ totalItems += await this.loadCollectionToInMem(name);
3632
3635
  }
3633
- this.safeCallback(this.onDexieSyncEnd, { calledFrom: "init", collectionCount: allowedColls.length, durationMs: Date.now() - dexieStart });
3636
+ this.safeCallback(this.onDexieSyncEnd, { calledFrom: "init", collectionCount: allowedColls.length, totalItems, durationMs: Date.now() - dexieStart });
3634
3637
  this.leaderElection.init();
3635
3638
  this.crossTabSync.init();
3636
3639
  (_a = this.wakeSync) == null ? void 0 : _a.init();
@@ -3675,6 +3678,40 @@ var SyncedDb = class _SyncedDb {
3675
3678
  }
3676
3679
  this.initialized = true;
3677
3680
  }
3681
+ /**
3682
+ * Flush all debounced pending writes to Dexie.
3683
+ * Resolves when all data is persisted to IndexedDB.
3684
+ * Does NOT upload to server — call sync() for that.
3685
+ */
3686
+ async flush() {
3687
+ await this.pendingChanges.flushAll();
3688
+ }
3689
+ /**
3690
+ * Returns when all collections were last successfully synced
3691
+ * from the server, or undefined if never.
3692
+ * Value is persisted in Dexie and survives page reload.
3693
+ * Only set when syncOnlyCollections is null (all collections active).
3694
+ * Cleared on dropDatabase.
3695
+ */
3696
+ lastSuccessfulServerSync() {
3697
+ return this._lastFullSyncDate;
3698
+ }
3699
+ /** @internal Update after successful full sync */
3700
+ async _setLastFullSync(date) {
3701
+ this._lastFullSyncDate = date;
3702
+ await this.dexieDb.setSyncMeta("__lastFullSync", date.toISOString());
3703
+ }
3704
+ /** @internal Load cached value from Dexie */
3705
+ async _loadLastFullSync() {
3706
+ const meta = await this.dexieDb.getSyncMeta("__lastFullSync");
3707
+ if (meta == null ? void 0 : meta.lastSyncTs) {
3708
+ this._lastFullSyncDate = new Date(meta.lastSyncTs);
3709
+ }
3710
+ }
3711
+ /** @internal Clear on dropDatabase */
3712
+ _clearLastFullSync() {
3713
+ this._lastFullSyncDate = void 0;
3714
+ }
3678
3715
  async close() {
3679
3716
  var _a, _b;
3680
3717
  this.leaderElection.setClosing(true);
@@ -4176,6 +4213,10 @@ var SyncedDb = class _SyncedDb {
4176
4213
  this.syncing = true;
4177
4214
  try {
4178
4215
  await this.syncEngine.sync(calledFrom);
4216
+ if (!this.syncOnlyCollections) {
4217
+ this._setLastFullSync(/* @__PURE__ */ new Date()).catch(() => {
4218
+ });
4219
+ }
4179
4220
  } finally {
4180
4221
  this.syncing = false;
4181
4222
  this.syncLock = false;
@@ -4317,6 +4358,7 @@ var SyncedDb = class _SyncedDb {
4317
4358
  await this.dexieDb.clearDirtyChanges(collectionName);
4318
4359
  }
4319
4360
  this.syncMetaCache.clear();
4361
+ this._clearLastFullSync();
4320
4362
  }
4321
4363
  // ==================== Object Metadata ====================
4322
4364
  getObjectMetadata(collection, _id) {
@@ -4406,6 +4448,7 @@ var SyncedDb = class _SyncedDb {
4406
4448
  if (meta) {
4407
4449
  this.syncMetaCache.set(name, meta);
4408
4450
  }
4451
+ return allItems.length;
4409
4452
  }
4410
4453
  assertCollection(name) {
4411
4454
  if (!this.collections.has(name)) {
@@ -70,6 +70,27 @@ export declare class SyncedDb implements I_SyncedDb {
70
70
  */
71
71
  simulateExternalBroadcast(payload: MetaUpdateBroadcast): void;
72
72
  init(): Promise<void>;
73
+ /**
74
+ * Flush all debounced pending writes to Dexie.
75
+ * Resolves when all data is persisted to IndexedDB.
76
+ * Does NOT upload to server — call sync() for that.
77
+ */
78
+ flush(): Promise<void>;
79
+ private _lastFullSyncDate?;
80
+ /**
81
+ * Returns when all collections were last successfully synced
82
+ * from the server, or undefined if never.
83
+ * Value is persisted in Dexie and survives page reload.
84
+ * Only set when syncOnlyCollections is null (all collections active).
85
+ * Cleared on dropDatabase.
86
+ */
87
+ lastSuccessfulServerSync(): Date | undefined;
88
+ /** @internal Update after successful full sync */
89
+ _setLastFullSync(date: Date): Promise<void>;
90
+ /** @internal Load cached value from Dexie */
91
+ private _loadLastFullSync;
92
+ /** @internal Clear on dropDatabase */
93
+ private _clearLastFullSync;
73
94
  close(): Promise<void>;
74
95
  isOnline(): boolean;
75
96
  forceOffline(forced: boolean): void;
@@ -210,6 +210,7 @@ export interface I_InMemManager {
210
210
  export interface SyncEngineCallbacks {
211
211
  onSyncStart?: (info: {
212
212
  calledFrom?: string;
213
+ initialSync: boolean;
213
214
  }) => void;
214
215
  onSyncEnd?: (info: SyncInfo) => void;
215
216
  onServerSyncStart?: (info: {
@@ -293,9 +293,10 @@ 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 at the start of each sync cycle */
296
+ /** Callback at the start of each sync cycle. initialSync=true if no full sync has completed yet. */
297
297
  onSyncStart?: (info: {
298
298
  calledFrom?: string;
299
+ initialSync: boolean;
299
300
  }) => void;
300
301
  /** Callback at the end of each sync cycle */
301
302
  onSyncEnd?: (info: SyncInfo) => void;
@@ -308,6 +309,7 @@ export interface SyncedDbConfig {
308
309
  onDexieSyncEnd?: (info: {
309
310
  calledFrom?: string;
310
311
  collectionCount: number;
312
+ totalItems: number;
311
313
  durationMs: number;
312
314
  }) => void;
313
315
  /** Callback when server download starts (findNewerManyStream) */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cry-synced-db-client",
3
- "version": "0.1.104",
3
+ "version": "0.1.105",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",