@tanstack/db 0.0.30 → 0.0.31

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/db",
3
3
  "description": "A reactive client store for building super fast apps on sync",
4
- "version": "0.0.30",
4
+ "version": "0.0.31",
5
5
  "dependencies": {
6
6
  "@electric-sql/d2mini": "^0.1.7",
7
7
  "@standard-schema/spec": "^1.0.0"
package/src/collection.ts CHANGED
@@ -687,7 +687,9 @@ export class CollectionImpl<
687
687
  /**
688
688
  * Recompute optimistic state from active transactions
689
689
  */
690
- private recomputeOptimisticState(): void {
690
+ private recomputeOptimisticState(
691
+ triggeredByUserAction: boolean = false
692
+ ): void {
691
693
  // Skip redundant recalculations when we're in the middle of committing sync transactions
692
694
  if (this.isCommittingSyncTransactions) {
693
695
  return
@@ -738,13 +740,26 @@ export class CollectionImpl<
738
740
  this.collectOptimisticChanges(previousState, previousDeletes, events)
739
741
 
740
742
  // Filter out events for recently synced keys to prevent duplicates
741
- const filteredEventsBySyncStatus = events.filter(
742
- (event) => !this.recentlySyncedKeys.has(event.key)
743
- )
743
+ // BUT: Only filter out events that are actually from sync operations
744
+ // New user transactions should NOT be filtered even if the key was recently synced
745
+ const filteredEventsBySyncStatus = events.filter((event) => {
746
+ if (!this.recentlySyncedKeys.has(event.key)) {
747
+ return true // Key not recently synced, allow event through
748
+ }
749
+
750
+ // Key was recently synced - allow if this is a user-triggered action
751
+ if (triggeredByUserAction) {
752
+ return true
753
+ }
754
+
755
+ // Otherwise filter out duplicate sync events
756
+ return false
757
+ })
744
758
 
745
759
  // Filter out redundant delete events if there are pending sync transactions
746
760
  // that will immediately restore the same data, but only for completed transactions
747
- if (this.pendingSyncedTransactions.length > 0) {
761
+ // IMPORTANT: Skip complex filtering for user-triggered actions to prevent UI blocking
762
+ if (this.pendingSyncedTransactions.length > 0 && !triggeredByUserAction) {
748
763
  const pendingSyncKeys = new Set<TKey>()
749
764
  const completedTransactionMutations = new Set<string>()
750
765
 
@@ -788,14 +803,14 @@ export class CollectionImpl<
788
803
  if (filteredEvents.length > 0) {
789
804
  this.updateIndexes(filteredEvents)
790
805
  }
791
- this.emitEvents(filteredEvents)
806
+ this.emitEvents(filteredEvents, triggeredByUserAction)
792
807
  } else {
793
808
  // Update indexes for all events
794
809
  if (filteredEventsBySyncStatus.length > 0) {
795
810
  this.updateIndexes(filteredEventsBySyncStatus)
796
811
  }
797
812
  // Emit all events if no pending sync transactions
798
- this.emitEvents(filteredEventsBySyncStatus)
813
+ this.emitEvents(filteredEventsBySyncStatus, triggeredByUserAction)
799
814
  }
800
815
  }
801
816
 
@@ -878,22 +893,21 @@ export class CollectionImpl<
878
893
  */
879
894
  private emitEvents(
880
895
  changes: Array<ChangeMessage<T, TKey>>,
881
- endBatching = false
896
+ forceEmit = false
882
897
  ): void {
883
- if (this.shouldBatchEvents && !endBatching) {
898
+ // Skip batching for user actions (forceEmit=true) to keep UI responsive
899
+ if (this.shouldBatchEvents && !forceEmit) {
884
900
  // Add events to the batch
885
901
  this.batchedEvents.push(...changes)
886
902
  return
887
903
  }
888
904
 
889
- // Either we're not batching, or we're ending the batching cycle
905
+ // Either we're not batching, or we're forcing emission (user action or ending batch cycle)
890
906
  let eventsToEmit = changes
891
907
 
892
- if (endBatching) {
893
- // End batching: combine any batched events with new events and clean up state
894
- if (this.batchedEvents.length > 0) {
895
- eventsToEmit = [...this.batchedEvents, ...changes]
896
- }
908
+ // If we have batched events and this is a forced emit, combine them
909
+ if (this.batchedEvents.length > 0 && forceEmit) {
910
+ eventsToEmit = [...this.batchedEvents, ...changes]
897
911
  this.batchedEvents = []
898
912
  this.shouldBatchEvents = false
899
913
  }
@@ -1625,7 +1639,7 @@ export class CollectionImpl<
1625
1639
  ambientTransaction.applyMutations(mutations)
1626
1640
 
1627
1641
  this.transactions.set(ambientTransaction.id, ambientTransaction)
1628
- this.recomputeOptimisticState()
1642
+ this.recomputeOptimisticState(true)
1629
1643
 
1630
1644
  return ambientTransaction
1631
1645
  } else {
@@ -1650,7 +1664,7 @@ export class CollectionImpl<
1650
1664
 
1651
1665
  // Add the transaction to the collection's transactions store
1652
1666
  this.transactions.set(directOpTransaction.id, directOpTransaction)
1653
- this.recomputeOptimisticState()
1667
+ this.recomputeOptimisticState(true)
1654
1668
 
1655
1669
  return directOpTransaction
1656
1670
  }
@@ -1847,7 +1861,7 @@ export class CollectionImpl<
1847
1861
  ambientTransaction.applyMutations(mutations)
1848
1862
 
1849
1863
  this.transactions.set(ambientTransaction.id, ambientTransaction)
1850
- this.recomputeOptimisticState()
1864
+ this.recomputeOptimisticState(true)
1851
1865
 
1852
1866
  return ambientTransaction
1853
1867
  }
@@ -1876,7 +1890,7 @@ export class CollectionImpl<
1876
1890
  // Add the transaction to the collection's transactions store
1877
1891
 
1878
1892
  this.transactions.set(directOpTransaction.id, directOpTransaction)
1879
- this.recomputeOptimisticState()
1893
+ this.recomputeOptimisticState(true)
1880
1894
 
1881
1895
  return directOpTransaction
1882
1896
  }
@@ -1963,7 +1977,7 @@ export class CollectionImpl<
1963
1977
  ambientTransaction.applyMutations(mutations)
1964
1978
 
1965
1979
  this.transactions.set(ambientTransaction.id, ambientTransaction)
1966
- this.recomputeOptimisticState()
1980
+ this.recomputeOptimisticState(true)
1967
1981
 
1968
1982
  return ambientTransaction
1969
1983
  }
@@ -1989,7 +2003,7 @@ export class CollectionImpl<
1989
2003
  directOpTransaction.commit()
1990
2004
 
1991
2005
  this.transactions.set(directOpTransaction.id, directOpTransaction)
1992
- this.recomputeOptimisticState()
2006
+ this.recomputeOptimisticState(true)
1993
2007
 
1994
2008
  return directOpTransaction
1995
2009
  }
@@ -2251,6 +2265,6 @@ export class CollectionImpl<
2251
2265
  // CRITICAL: Capture visible state BEFORE clearing optimistic state
2252
2266
  this.capturePreSyncVisibleState()
2253
2267
 
2254
- this.recomputeOptimisticState()
2268
+ this.recomputeOptimisticState(false)
2255
2269
  }
2256
2270
  }