cry-synced-db-client 0.1.76 → 0.1.77

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
@@ -705,7 +705,6 @@ var CrossTabSyncManager = class {
705
705
  // Private Methods
706
706
  // ============================================================
707
707
  async handleCrossTabMetaUpdate(payload) {
708
- var _a;
709
708
  if (!this.deps.isInitialized()) {
710
709
  return;
711
710
  }
@@ -717,7 +716,7 @@ var CrossTabSyncManager = class {
717
716
  if (!collections.has(collection)) {
718
717
  continue;
719
718
  }
720
- if ((_a = collections.get(collection)) == null ? void 0 : _a.writeOnly) {
719
+ if (!this.deps.isSyncAllowed(collection)) {
721
720
  continue;
722
721
  }
723
722
  if (ids.length === 0) {
@@ -2344,7 +2343,7 @@ var _SyncEngine = class _SyncEngine {
2344
2343
  const syncSpecs = [];
2345
2344
  const configMap = /* @__PURE__ */ new Map();
2346
2345
  for (const [collectionName, config] of this.collections) {
2347
- if (config.writeOnly) continue;
2346
+ if (!this.deps.isSyncAllowed(collectionName)) continue;
2348
2347
  const syncEnabled = (_a = config.syncConfig) == null ? void 0 : _a.enabled;
2349
2348
  const shouldSync = typeof syncEnabled === "function" ? syncEnabled() : syncEnabled;
2350
2349
  if (shouldSync === false) {
@@ -2873,13 +2872,12 @@ var ServerUpdateHandler = class {
2873
2872
  * Handle incoming server update (WebSocket notification).
2874
2873
  */
2875
2874
  async handleServerUpdate(payload) {
2876
- var _a;
2877
2875
  this.callOnWsNotification(payload);
2878
2876
  if (!this.deps.isLeader()) return;
2879
2877
  if (!this.deps.canReceiveServerUpdates()) return;
2880
2878
  const collectionName = payload.collection;
2881
2879
  if (!this.collections.has(collectionName)) return;
2882
- if ((_a = this.collections.get(collectionName)) == null ? void 0 : _a.writeOnly) return;
2880
+ if (!this.deps.isSyncAllowed(collectionName)) return;
2883
2881
  const updatedIds = [];
2884
2882
  switch (payload.operation) {
2885
2883
  case "insert": {
@@ -3293,6 +3291,8 @@ var SyncedDb = class {
3293
3291
  this.syncing = false;
3294
3292
  this.syncLock = false;
3295
3293
  this.wsUpdateQueue = [];
3294
+ /** When non-null, only these collections participate in sync/in-mem loading. */
3295
+ this.syncOnlyCollections = null;
3296
3296
  // Sync metadata cache
3297
3297
  this.syncMetaCache = /* @__PURE__ */ new Map();
3298
3298
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
@@ -3358,7 +3358,8 @@ var SyncedDb = class {
3358
3358
  dexieDb: this.dexieDb,
3359
3359
  writeToInMemBatch: (collection, items, operation) => {
3360
3360
  this.inMemManager.writeBatch(collection, items, operation);
3361
- }
3361
+ },
3362
+ isSyncAllowed: (collection) => this.isSyncAllowed(collection)
3362
3363
  }
3363
3364
  });
3364
3365
  this.connectionManager = new ConnectionManager({
@@ -3438,7 +3439,8 @@ var SyncedDb = class {
3438
3439
  flushAllPendingChanges: () => this.pendingChanges.flushAll(),
3439
3440
  cancelRestUploadTimer: () => this.pendingChanges.cancelRestUploadTimer(),
3440
3441
  awaitRestUpload: () => this.pendingChanges.awaitRestUpload(),
3441
- broadcastUpdates: (updates) => this.crossTabSync.broadcastMetaUpdate(updates)
3442
+ broadcastUpdates: (updates) => this.crossTabSync.broadcastMetaUpdate(updates),
3443
+ isSyncAllowed: (collection) => this.isSyncAllowed(collection)
3442
3444
  }
3443
3445
  });
3444
3446
  this.serverUpdateHandler = new ServerUpdateHandler({
@@ -3457,7 +3459,8 @@ var SyncedDb = class {
3457
3459
  this.inMemManager.writeBatch(collection, items, operation);
3458
3460
  },
3459
3461
  broadcastUpdates: (updates) => this.crossTabSync.broadcastMetaUpdate(updates),
3460
- getPendingChange: (collection, id) => this.pendingChanges.getPendingChange(collection, id)
3462
+ getPendingChange: (collection, id) => this.pendingChanges.getPendingChange(collection, id),
3463
+ isSyncAllowed: (collection) => this.isSyncAllowed(collection)
3461
3464
  }
3462
3465
  });
3463
3466
  if (config.wakeSyncEnabled) {
@@ -3500,6 +3503,41 @@ var SyncedDb = class {
3500
3503
  isLeaderTab() {
3501
3504
  return this.leaderElection.isLeader();
3502
3505
  }
3506
+ /**
3507
+ * Restrict sync to only these collections. When non-empty, only the listed
3508
+ * collections load from Dexie→in-mem and download from server. Pass an empty
3509
+ * array to sync all collections again.
3510
+ *
3511
+ * Newly-allowed collections are loaded from Dexie immediately and a sync is
3512
+ * triggered if online.
3513
+ */
3514
+ async setSyncOnlyTheseCollections(collections) {
3515
+ const prevAllowed = /* @__PURE__ */ new Set();
3516
+ for (const [name] of this.collections) {
3517
+ if (this.isSyncAllowed(name)) prevAllowed.add(name);
3518
+ }
3519
+ this.syncOnlyCollections = collections.length > 0 ? new Set(collections) : null;
3520
+ const newlyAllowed = [];
3521
+ for (const [name] of this.collections) {
3522
+ if (this.isSyncAllowed(name) && !prevAllowed.has(name)) {
3523
+ newlyAllowed.push(name);
3524
+ }
3525
+ }
3526
+ for (const name of newlyAllowed) {
3527
+ await this.loadCollectionToInMem(name);
3528
+ }
3529
+ if (newlyAllowed.length > 0 && this.connectionManager.canSync()) {
3530
+ this.sync("setSyncOnlyTheseCollections").catch(() => {
3531
+ });
3532
+ }
3533
+ }
3534
+ /**
3535
+ * Get the current syncOnlyTheseCollections filter.
3536
+ * Returns null when all collections are synced.
3537
+ */
3538
+ getSyncOnlyTheseCollections() {
3539
+ return this.syncOnlyCollections;
3540
+ }
3503
3541
  /**
3504
3542
  * Test helper: simulate receiving a cross-tab broadcast from another instance.
3505
3543
  */
@@ -3523,26 +3561,9 @@ var SyncedDb = class {
3523
3561
  );
3524
3562
  }
3525
3563
  await this.pendingChanges.recoverPendingWrites();
3526
- for (const [name, config] of this.collections) {
3527
- if (config.writeOnly) continue;
3528
- this.inMemManager.clearCollection(name);
3529
- await this.dexieDb.forEachBatch(name, 2e3, async (chunk) => {
3530
- let writeIdx = 0;
3531
- for (let i = 0; i < chunk.length; i++) {
3532
- const item = chunk[i];
3533
- if (!item._deleted && !item._archived) {
3534
- chunk[writeIdx++] = item;
3535
- }
3536
- }
3537
- chunk.length = writeIdx;
3538
- if (chunk.length > 0) {
3539
- this.inMemManager.writeBatch(name, chunk, "upsert");
3540
- }
3541
- });
3542
- const meta = await this.dexieDb.getSyncMeta(name);
3543
- if (meta) {
3544
- this.syncMetaCache.set(name, meta);
3545
- }
3564
+ for (const [name] of this.collections) {
3565
+ if (!this.isSyncAllowed(name)) continue;
3566
+ await this.loadCollectionToInMem(name);
3546
3567
  }
3547
3568
  this.leaderElection.init();
3548
3569
  this.crossTabSync.init();
@@ -4263,6 +4284,42 @@ var SyncedDb = class {
4263
4284
  returnArchived: (_b = opts == null ? void 0 : opts.returnArchived) != null ? _b : this.defaultReturnArchived
4264
4285
  });
4265
4286
  }
4287
+ /**
4288
+ * Whether a collection participates in sync (server download,
4289
+ * WS notifications, cross-tab sync, Dexie→in-mem loading).
4290
+ * False for writeOnly collections and collections excluded by syncOnlyCollections.
4291
+ */
4292
+ isSyncAllowed(collection) {
4293
+ const config = this.collections.get(collection);
4294
+ if (!config) return false;
4295
+ if (config.writeOnly) return false;
4296
+ if (this.syncOnlyCollections && !this.syncOnlyCollections.has(collection)) return false;
4297
+ return true;
4298
+ }
4299
+ /**
4300
+ * Load a single collection from Dexie into in-memory cache.
4301
+ * Filters out deleted and archived items.
4302
+ */
4303
+ async loadCollectionToInMem(name) {
4304
+ this.inMemManager.clearCollection(name);
4305
+ await this.dexieDb.forEachBatch(name, 2e3, async (chunk) => {
4306
+ let writeIdx = 0;
4307
+ for (let i = 0; i < chunk.length; i++) {
4308
+ const item = chunk[i];
4309
+ if (!item._deleted && !item._archived) {
4310
+ chunk[writeIdx++] = item;
4311
+ }
4312
+ }
4313
+ chunk.length = writeIdx;
4314
+ if (chunk.length > 0) {
4315
+ this.inMemManager.writeBatch(name, chunk, "upsert");
4316
+ }
4317
+ });
4318
+ const meta = await this.dexieDb.getSyncMeta(name);
4319
+ if (meta) {
4320
+ this.syncMetaCache.set(name, meta);
4321
+ }
4322
+ }
4266
4323
  assertCollection(name) {
4267
4324
  if (!this.collections.has(name)) {
4268
4325
  throw new Error(`Collection "${name}" not configured`);
@@ -27,6 +27,8 @@ export declare class SyncedDb implements I_SyncedDb {
27
27
  private syncing;
28
28
  private syncLock;
29
29
  private wsUpdateQueue;
30
+ /** When non-null, only these collections participate in sync/in-mem loading. */
31
+ private syncOnlyCollections;
30
32
  private readonly updaterId;
31
33
  private readonly syncedDbInstanceId;
32
34
  private syncMetaCache;
@@ -44,6 +46,20 @@ export declare class SyncedDb implements I_SyncedDb {
44
46
  getInstanceId(): string;
45
47
  getCrossTabSyncDebounceMs(): number;
46
48
  isLeaderTab(): boolean;
49
+ /**
50
+ * Restrict sync to only these collections. When non-empty, only the listed
51
+ * collections load from Dexie→in-mem and download from server. Pass an empty
52
+ * array to sync all collections again.
53
+ *
54
+ * Newly-allowed collections are loaded from Dexie immediately and a sync is
55
+ * triggered if online.
56
+ */
57
+ setSyncOnlyTheseCollections(collections: string[]): Promise<void>;
58
+ /**
59
+ * Get the current syncOnlyTheseCollections filter.
60
+ * Returns null when all collections are synced.
61
+ */
62
+ getSyncOnlyTheseCollections(): ReadonlySet<string> | null;
47
63
  /**
48
64
  * Test helper: simulate receiving a cross-tab broadcast from another instance.
49
65
  */
@@ -114,6 +130,17 @@ export declare class SyncedDb implements I_SyncedDb {
114
130
  * Per-call values take precedence over global defaults.
115
131
  */
116
132
  private resolveOpts;
133
+ /**
134
+ * Whether a collection participates in sync (server download,
135
+ * WS notifications, cross-tab sync, Dexie→in-mem loading).
136
+ * False for writeOnly collections and collections excluded by syncOnlyCollections.
137
+ */
138
+ private isSyncAllowed;
139
+ /**
140
+ * Load a single collection from Dexie into in-memory cache.
141
+ * Filters out deleted and archived items.
142
+ */
143
+ private loadCollectionToInMem;
117
144
  private assertCollection;
118
145
  /**
119
146
  * Asserts write-only collection has online connectivity for reads.
@@ -50,6 +50,8 @@ export interface CrossTabSyncDeps {
50
50
  dexieDb: I_DexieDb;
51
51
  /** Write to in-mem batch. */
52
52
  writeToInMemBatch: <T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete") => void;
53
+ /** Whether a collection participates in sync (not writeOnly, not filtered out). */
54
+ isSyncAllowed: (collection: string) => boolean;
53
55
  }
54
56
  export interface CrossTabSyncConfig {
55
57
  tenant: string;
@@ -225,6 +227,8 @@ export interface SyncEngineDeps {
225
227
  awaitRestUpload: () => Promise<void>;
226
228
  /** Broadcast updated IDs to other tabs */
227
229
  broadcastUpdates: (updates: Record<string, string[]>) => void;
230
+ /** Whether a collection participates in sync (not writeOnly, not filtered out). */
231
+ isSyncAllowed: (collection: string) => boolean;
228
232
  }
229
233
  export interface SyncEngineConfig {
230
234
  tenant: string;
@@ -256,6 +260,8 @@ export interface ServerUpdateHandlerDeps {
256
260
  getPendingChange: (collection: string, id: Id) => PendingChange | undefined;
257
261
  broadcastUpdates: (updates: Record<string, string[]>) => void;
258
262
  writeToInMemBatch: <T extends DbEntity>(collection: string, items: T[], operation: "upsert" | "delete") => void;
263
+ /** Whether a collection participates in sync (not writeOnly, not filtered out). */
264
+ isSyncAllowed: (collection: string) => boolean;
259
265
  }
260
266
  export interface ServerUpdateHandlerConfig {
261
267
  tenant: string;
@@ -518,6 +518,18 @@ export interface I_SyncedDb {
518
518
  sync(calledFrom?: string): Promise<void>;
519
519
  /** Ali je sinhronizacija v teku */
520
520
  isSyncing(): boolean;
521
+ /**
522
+ * Restrict sync to only these collections. When non-empty, only listed
523
+ * collections load Dexie→in-mem and download from server. Pass empty
524
+ * array to sync all collections. Newly-allowed collections are loaded
525
+ * immediately and a sync is triggered if online.
526
+ */
527
+ setSyncOnlyTheseCollections(collections: string[]): Promise<void>;
528
+ /**
529
+ * Get the current syncOnlyTheseCollections filter.
530
+ * Returns null when all collections are synced.
531
+ */
532
+ getSyncOnlyTheseCollections(): ReadonlySet<string> | null;
521
533
  /**
522
534
  * Izvede batch upsert na serverju
523
535
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cry-synced-db-client",
3
- "version": "0.1.76",
3
+ "version": "0.1.77",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",