@tanstack/db 0.0.30 → 0.0.32

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.
@@ -7,7 +7,6 @@ import { SingleRowRefProxy } from './query/builder/ref-proxy.js';
7
7
  import { ChangeListener, ChangeMessage, CollectionConfig, CollectionStatus, CurrentStateAsChangesOptions, Fn, InsertConfig, OperationConfig, OptimisticChangeMessage, ResolveInsertInput, ResolveType, SubscribeChangesOptions, Transaction as TransactionType, UtilsRecord } from './types.js';
8
8
  import { IndexOptions } from './indexes/index-options.js';
9
9
  import { BaseIndex, IndexResolver } from './indexes/base-index.js';
10
- export declare const collectionsStore: Map<string, CollectionImpl<any, any, any, StandardSchemaV1<unknown, unknown>, any>>;
11
10
  interface PendingSyncedTransaction<T extends object = Record<string, unknown>> {
12
11
  committed: boolean;
13
12
  operations: Array<OptimisticChangeMessage<T>>;
@@ -240,6 +239,11 @@ export declare class CollectionImpl<T extends object = Record<string, unknown>,
240
239
  * Get the previous value for a key given previous optimistic state
241
240
  */
242
241
  private getPreviousValue;
242
+ /**
243
+ * Emit an empty ready event to notify subscribers that the collection is ready
244
+ * This bypasses the normal empty array check in emitEvents
245
+ */
246
+ private emitEmptyReadyEvent;
243
247
  /**
244
248
  * Emit events either immediately or batch them for later emission
245
249
  */
@@ -7,7 +7,6 @@ import { ensureIndexForExpression } from "./indexes/auto-index.js";
7
7
  import { getActiveTransaction, createTransaction } from "./transactions.js";
8
8
  import { MissingInsertHandlerError, DuplicateKeyError, MissingDeleteHandlerError, NoKeysPassedToDeleteError, DeleteKeyNotFoundError, CollectionRequiresConfigError, CollectionRequiresSyncConfigError, CollectionInErrorStateError, InvalidCollectionStatusTransitionError, NoPendingSyncTransactionCommitError, SyncTransactionAlreadyCommittedError, NoPendingSyncTransactionWriteError, SyncTransactionAlreadyCommittedWriteError, DuplicateKeySyncError, CollectionIsInErrorStateError, SyncCleanupError, NegativeActiveSubscribersError, InvalidSchemaError, UndefinedKeyError, SchemaMustBeSynchronousError, SchemaValidationError, MissingUpdateArgumentError, MissingUpdateHandlerError, NoKeysPassedToUpdateError, UpdateKeyNotFoundError, KeyUpdateNotAllowedError } from "./errors.js";
9
9
  import { currentStateAsChanges, createFilteredCallback } from "./change-events.js";
10
- const collectionsStore = /* @__PURE__ */ new Map();
11
10
  function createCollection(options) {
12
11
  const collection = new CollectionImpl(options);
13
12
  if (options.utils) {
@@ -253,7 +252,7 @@ class CollectionImpl {
253
252
  if (ambientTransaction) {
254
253
  ambientTransaction.applyMutations(mutations);
255
254
  this.transactions.set(ambientTransaction.id, ambientTransaction);
256
- this.recomputeOptimisticState();
255
+ this.recomputeOptimisticState(true);
257
256
  return ambientTransaction;
258
257
  } else {
259
258
  const directOpTransaction = createTransaction({
@@ -267,7 +266,7 @@ class CollectionImpl {
267
266
  directOpTransaction.applyMutations(mutations);
268
267
  directOpTransaction.commit();
269
268
  this.transactions.set(directOpTransaction.id, directOpTransaction);
270
- this.recomputeOptimisticState();
269
+ this.recomputeOptimisticState(true);
271
270
  return directOpTransaction;
272
271
  }
273
272
  };
@@ -307,7 +306,7 @@ class CollectionImpl {
307
306
  if (ambientTransaction) {
308
307
  ambientTransaction.applyMutations(mutations);
309
308
  this.transactions.set(ambientTransaction.id, ambientTransaction);
310
- this.recomputeOptimisticState();
309
+ this.recomputeOptimisticState(true);
311
310
  return ambientTransaction;
312
311
  }
313
312
  const directOpTransaction = createTransaction({
@@ -322,7 +321,7 @@ class CollectionImpl {
322
321
  directOpTransaction.applyMutations(mutations);
323
322
  directOpTransaction.commit();
324
323
  this.transactions.set(directOpTransaction.id, directOpTransaction);
325
- this.recomputeOptimisticState();
324
+ this.recomputeOptimisticState(true);
326
325
  return directOpTransaction;
327
326
  };
328
327
  if (!config) {
@@ -343,7 +342,6 @@ class CollectionImpl {
343
342
  ...config,
344
343
  autoIndex: config.autoIndex ?? `eager`
345
344
  };
346
- collectionsStore.set(this.id, this);
347
345
  if (this.config.compare) {
348
346
  this.syncedData = new SortedMap(this.config.compare);
349
347
  } else {
@@ -402,6 +400,9 @@ class CollectionImpl {
402
400
  const callbacks = [...this.onFirstReadyCallbacks];
403
401
  this.onFirstReadyCallbacks = [];
404
402
  callbacks.forEach((callback) => callback());
403
+ if (this.size === 0 && this.changeListeners.size > 0) {
404
+ this.emitEmptyReadyEvent();
405
+ }
405
406
  }
406
407
  }
407
408
  }
@@ -651,7 +652,7 @@ class CollectionImpl {
651
652
  /**
652
653
  * Recompute optimistic state from active transactions
653
654
  */
654
- recomputeOptimisticState() {
655
+ recomputeOptimisticState(triggeredByUserAction = false) {
655
656
  if (this.isCommittingSyncTransactions) {
656
657
  return;
657
658
  }
@@ -688,10 +689,16 @@ class CollectionImpl {
688
689
  this._size = this.calculateSize();
689
690
  const events = [];
690
691
  this.collectOptimisticChanges(previousState, previousDeletes, events);
691
- const filteredEventsBySyncStatus = events.filter(
692
- (event) => !this.recentlySyncedKeys.has(event.key)
693
- );
694
- if (this.pendingSyncedTransactions.length > 0) {
692
+ const filteredEventsBySyncStatus = events.filter((event) => {
693
+ if (!this.recentlySyncedKeys.has(event.key)) {
694
+ return true;
695
+ }
696
+ if (triggeredByUserAction) {
697
+ return true;
698
+ }
699
+ return false;
700
+ });
701
+ if (this.pendingSyncedTransactions.length > 0 && !triggeredByUserAction) {
695
702
  const pendingSyncKeys = /* @__PURE__ */ new Set();
696
703
  const completedTransactionMutations = /* @__PURE__ */ new Set();
697
704
  for (const transaction of this.pendingSyncedTransactions) {
@@ -722,12 +729,12 @@ class CollectionImpl {
722
729
  if (filteredEvents.length > 0) {
723
730
  this.updateIndexes(filteredEvents);
724
731
  }
725
- this.emitEvents(filteredEvents);
732
+ this.emitEvents(filteredEvents, triggeredByUserAction);
726
733
  } else {
727
734
  if (filteredEventsBySyncStatus.length > 0) {
728
735
  this.updateIndexes(filteredEventsBySyncStatus);
729
736
  }
730
- this.emitEvents(filteredEventsBySyncStatus);
737
+ this.emitEvents(filteredEventsBySyncStatus, triggeredByUserAction);
731
738
  }
732
739
  }
733
740
  /**
@@ -786,19 +793,26 @@ class CollectionImpl {
786
793
  }
787
794
  return this.syncedData.get(key);
788
795
  }
796
+ /**
797
+ * Emit an empty ready event to notify subscribers that the collection is ready
798
+ * This bypasses the normal empty array check in emitEvents
799
+ */
800
+ emitEmptyReadyEvent() {
801
+ for (const listener of this.changeListeners) {
802
+ listener([]);
803
+ }
804
+ }
789
805
  /**
790
806
  * Emit events either immediately or batch them for later emission
791
807
  */
792
- emitEvents(changes, endBatching = false) {
793
- if (this.shouldBatchEvents && !endBatching) {
808
+ emitEvents(changes, forceEmit = false) {
809
+ if (this.shouldBatchEvents && !forceEmit) {
794
810
  this.batchedEvents.push(...changes);
795
811
  return;
796
812
  }
797
813
  let eventsToEmit = changes;
798
- if (endBatching) {
799
- if (this.batchedEvents.length > 0) {
800
- eventsToEmit = [...this.batchedEvents, ...changes];
801
- }
814
+ if (this.batchedEvents.length > 0 && forceEmit) {
815
+ eventsToEmit = [...this.batchedEvents, ...changes];
802
816
  this.batchedEvents = [];
803
817
  this.shouldBatchEvents = false;
804
818
  }
@@ -1204,7 +1218,7 @@ class CollectionImpl {
1204
1218
  if (ambientTransaction) {
1205
1219
  ambientTransaction.applyMutations(mutations);
1206
1220
  this.transactions.set(ambientTransaction.id, ambientTransaction);
1207
- this.recomputeOptimisticState();
1221
+ this.recomputeOptimisticState(true);
1208
1222
  return ambientTransaction;
1209
1223
  }
1210
1224
  const directOpTransaction = createTransaction({
@@ -1218,7 +1232,7 @@ class CollectionImpl {
1218
1232
  directOpTransaction.applyMutations(mutations);
1219
1233
  directOpTransaction.commit();
1220
1234
  this.transactions.set(directOpTransaction.id, directOpTransaction);
1221
- this.recomputeOptimisticState();
1235
+ this.recomputeOptimisticState(true);
1222
1236
  return directOpTransaction;
1223
1237
  }
1224
1238
  /**
@@ -1422,12 +1436,11 @@ class CollectionImpl {
1422
1436
  onTransactionStateChange() {
1423
1437
  this.shouldBatchEvents = this.pendingSyncedTransactions.length > 0;
1424
1438
  this.capturePreSyncVisibleState();
1425
- this.recomputeOptimisticState();
1439
+ this.recomputeOptimisticState(false);
1426
1440
  }
1427
1441
  }
1428
1442
  export {
1429
1443
  CollectionImpl,
1430
- collectionsStore,
1431
1444
  createCollection
1432
1445
  };
1433
1446
  //# sourceMappingURL=collection.js.map