@tanstack/db 0.1.1 → 0.1.4

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.
Files changed (110) hide show
  1. package/dist/cjs/collection.cjs +112 -6
  2. package/dist/cjs/collection.cjs.map +1 -1
  3. package/dist/cjs/collection.d.cts +12 -3
  4. package/dist/cjs/errors.cjs +6 -0
  5. package/dist/cjs/errors.cjs.map +1 -1
  6. package/dist/cjs/errors.d.cts +3 -0
  7. package/dist/cjs/index.cjs +1 -0
  8. package/dist/cjs/index.cjs.map +1 -1
  9. package/dist/cjs/indexes/auto-index.cjs +30 -19
  10. package/dist/cjs/indexes/auto-index.cjs.map +1 -1
  11. package/dist/cjs/indexes/auto-index.d.cts +1 -0
  12. package/dist/cjs/indexes/base-index.cjs.map +1 -1
  13. package/dist/cjs/indexes/base-index.d.cts +2 -1
  14. package/dist/cjs/indexes/btree-index.cjs +29 -3
  15. package/dist/cjs/indexes/btree-index.cjs.map +1 -1
  16. package/dist/cjs/indexes/btree-index.d.cts +7 -0
  17. package/dist/cjs/indexes/index-options.d.cts +1 -1
  18. package/dist/cjs/query/builder/index.cjs +9 -2
  19. package/dist/cjs/query/builder/index.cjs.map +1 -1
  20. package/dist/cjs/query/builder/index.d.cts +2 -2
  21. package/dist/cjs/query/builder/types.d.cts +27 -6
  22. package/dist/cjs/query/compiler/evaluators.cjs +2 -2
  23. package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
  24. package/dist/cjs/query/compiler/evaluators.d.cts +1 -1
  25. package/dist/cjs/query/compiler/group-by.cjs +3 -1
  26. package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
  27. package/dist/cjs/query/compiler/index.cjs +72 -6
  28. package/dist/cjs/query/compiler/index.cjs.map +1 -1
  29. package/dist/cjs/query/compiler/index.d.cts +16 -2
  30. package/dist/cjs/query/compiler/joins.cjs +111 -12
  31. package/dist/cjs/query/compiler/joins.cjs.map +1 -1
  32. package/dist/cjs/query/compiler/joins.d.cts +9 -2
  33. package/dist/cjs/query/compiler/order-by.cjs +80 -23
  34. package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
  35. package/dist/cjs/query/compiler/order-by.d.cts +12 -2
  36. package/dist/cjs/query/ir.cjs.map +1 -1
  37. package/dist/cjs/query/ir.d.cts +2 -1
  38. package/dist/cjs/query/live-query-collection.cjs +196 -23
  39. package/dist/cjs/query/live-query-collection.cjs.map +1 -1
  40. package/dist/cjs/types.d.cts +1 -0
  41. package/dist/cjs/utils/btree.cjs +15 -0
  42. package/dist/cjs/utils/btree.cjs.map +1 -1
  43. package/dist/cjs/utils/btree.d.cts +8 -0
  44. package/dist/cjs/utils/comparison.cjs +29 -7
  45. package/dist/cjs/utils/comparison.cjs.map +1 -1
  46. package/dist/cjs/utils/comparison.d.cts +6 -2
  47. package/dist/esm/collection.d.ts +12 -3
  48. package/dist/esm/collection.js +113 -7
  49. package/dist/esm/collection.js.map +1 -1
  50. package/dist/esm/errors.d.ts +3 -0
  51. package/dist/esm/errors.js +6 -0
  52. package/dist/esm/errors.js.map +1 -1
  53. package/dist/esm/index.js +2 -1
  54. package/dist/esm/indexes/auto-index.d.ts +1 -0
  55. package/dist/esm/indexes/auto-index.js +31 -20
  56. package/dist/esm/indexes/auto-index.js.map +1 -1
  57. package/dist/esm/indexes/base-index.d.ts +2 -1
  58. package/dist/esm/indexes/base-index.js.map +1 -1
  59. package/dist/esm/indexes/btree-index.d.ts +7 -0
  60. package/dist/esm/indexes/btree-index.js +29 -3
  61. package/dist/esm/indexes/btree-index.js.map +1 -1
  62. package/dist/esm/indexes/index-options.d.ts +1 -1
  63. package/dist/esm/query/builder/index.d.ts +2 -2
  64. package/dist/esm/query/builder/index.js +9 -2
  65. package/dist/esm/query/builder/index.js.map +1 -1
  66. package/dist/esm/query/builder/types.d.ts +27 -6
  67. package/dist/esm/query/compiler/evaluators.d.ts +1 -1
  68. package/dist/esm/query/compiler/evaluators.js +2 -2
  69. package/dist/esm/query/compiler/evaluators.js.map +1 -1
  70. package/dist/esm/query/compiler/group-by.js +3 -1
  71. package/dist/esm/query/compiler/group-by.js.map +1 -1
  72. package/dist/esm/query/compiler/index.d.ts +16 -2
  73. package/dist/esm/query/compiler/index.js +73 -7
  74. package/dist/esm/query/compiler/index.js.map +1 -1
  75. package/dist/esm/query/compiler/joins.d.ts +9 -2
  76. package/dist/esm/query/compiler/joins.js +114 -15
  77. package/dist/esm/query/compiler/joins.js.map +1 -1
  78. package/dist/esm/query/compiler/order-by.d.ts +12 -2
  79. package/dist/esm/query/compiler/order-by.js +81 -24
  80. package/dist/esm/query/compiler/order-by.js.map +1 -1
  81. package/dist/esm/query/ir.d.ts +2 -1
  82. package/dist/esm/query/ir.js.map +1 -1
  83. package/dist/esm/query/live-query-collection.js +196 -23
  84. package/dist/esm/query/live-query-collection.js.map +1 -1
  85. package/dist/esm/types.d.ts +1 -0
  86. package/dist/esm/utils/btree.d.ts +8 -0
  87. package/dist/esm/utils/btree.js +15 -0
  88. package/dist/esm/utils/btree.js.map +1 -1
  89. package/dist/esm/utils/comparison.d.ts +6 -2
  90. package/dist/esm/utils/comparison.js +30 -8
  91. package/dist/esm/utils/comparison.js.map +1 -1
  92. package/package.json +2 -2
  93. package/src/collection.ts +237 -11
  94. package/src/errors.ts +6 -0
  95. package/src/indexes/auto-index.ts +53 -31
  96. package/src/indexes/base-index.ts +6 -1
  97. package/src/indexes/btree-index.ts +32 -3
  98. package/src/indexes/index-options.ts +2 -2
  99. package/src/query/builder/index.ts +19 -2
  100. package/src/query/builder/types.ts +48 -15
  101. package/src/query/compiler/evaluators.ts +6 -3
  102. package/src/query/compiler/group-by.ts +3 -1
  103. package/src/query/compiler/index.ts +112 -5
  104. package/src/query/compiler/joins.ts +216 -20
  105. package/src/query/compiler/order-by.ts +117 -26
  106. package/src/query/ir.ts +2 -1
  107. package/src/query/live-query-collection.ts +352 -24
  108. package/src/types.ts +1 -0
  109. package/src/utils/btree.ts +17 -0
  110. package/src/utils/comparison.ts +40 -7
@@ -61,7 +61,10 @@ class CollectionImpl {
61
61
  break;
62
62
  }
63
63
  }
64
- if (!hasPersistingTransaction) {
64
+ const hasTruncateSync = this.pendingSyncedTransactions.some(
65
+ (t) => t.truncate === true
66
+ );
67
+ if (!hasPersistingTransaction || hasTruncateSync) {
65
68
  this.isCommittingSyncTransactions = true;
66
69
  const changedKeys = /* @__PURE__ */ new Set();
67
70
  for (const transaction of this.pendingSyncedTransactions) {
@@ -82,6 +85,18 @@ class CollectionImpl {
82
85
  const events = [];
83
86
  const rowUpdateMode = this.config.sync.rowUpdateMode || `partial`;
84
87
  for (const transaction of this.pendingSyncedTransactions) {
88
+ if (transaction.truncate) {
89
+ for (const key of this.syncedData.keys()) {
90
+ if (this.optimisticDeletes.has(key)) continue;
91
+ const previousValue = this.optimisticUpserts.get(key) || this.syncedData.get(key);
92
+ if (previousValue !== void 0) {
93
+ events.push({ type: `delete`, key, value: previousValue });
94
+ }
95
+ }
96
+ this.syncedData.clear();
97
+ this.syncedMetadata.clear();
98
+ this.syncedKeys.clear();
99
+ }
85
100
  for (const operation of transaction.operations) {
86
101
  const key = operation.key;
87
102
  this.syncedKeys.add(key);
@@ -126,6 +141,78 @@ class CollectionImpl {
126
141
  }
127
142
  }
128
143
  }
144
+ const hadTruncate = this.pendingSyncedTransactions.some(
145
+ (t) => t.truncate === true
146
+ );
147
+ if (hadTruncate) {
148
+ const syncedInsertedOrUpdatedKeys = /* @__PURE__ */ new Set();
149
+ for (const t of this.pendingSyncedTransactions) {
150
+ for (const op of t.operations) {
151
+ if (op.type === `insert` || op.type === `update`) {
152
+ syncedInsertedOrUpdatedKeys.add(op.key);
153
+ }
154
+ }
155
+ }
156
+ const reapplyUpserts = /* @__PURE__ */ new Map();
157
+ const reapplyDeletes = /* @__PURE__ */ new Set();
158
+ for (const tx of this.transactions.values()) {
159
+ if ([`completed`, `failed`].includes(tx.state)) continue;
160
+ for (const mutation of tx.mutations) {
161
+ if (mutation.collection !== this || !mutation.optimistic) continue;
162
+ const key = mutation.key;
163
+ switch (mutation.type) {
164
+ case `insert`:
165
+ reapplyUpserts.set(key, mutation.modified);
166
+ reapplyDeletes.delete(key);
167
+ break;
168
+ case `update`: {
169
+ const base = this.syncedData.get(key);
170
+ const next = base ? Object.assign({}, base, mutation.changes) : mutation.modified;
171
+ reapplyUpserts.set(key, next);
172
+ reapplyDeletes.delete(key);
173
+ break;
174
+ }
175
+ case `delete`:
176
+ reapplyUpserts.delete(key);
177
+ reapplyDeletes.add(key);
178
+ break;
179
+ }
180
+ }
181
+ }
182
+ for (const [key, value] of reapplyUpserts) {
183
+ if (reapplyDeletes.has(key)) continue;
184
+ if (syncedInsertedOrUpdatedKeys.has(key)) {
185
+ let foundInsert = false;
186
+ for (let i = events.length - 1; i >= 0; i--) {
187
+ const evt = events[i];
188
+ if (evt.key === key && evt.type === `insert`) {
189
+ evt.value = value;
190
+ foundInsert = true;
191
+ break;
192
+ }
193
+ }
194
+ if (!foundInsert) {
195
+ events.push({ type: `insert`, key, value });
196
+ }
197
+ } else {
198
+ events.push({ type: `insert`, key, value });
199
+ }
200
+ }
201
+ if (events.length > 0 && reapplyDeletes.size > 0) {
202
+ const filtered = [];
203
+ for (const evt of events) {
204
+ if (evt.type === `insert` && reapplyDeletes.has(evt.key)) {
205
+ continue;
206
+ }
207
+ filtered.push(evt);
208
+ }
209
+ events.length = 0;
210
+ events.push(...filtered);
211
+ }
212
+ if (!this.isReady()) {
213
+ this.setStatus(`ready`);
214
+ }
215
+ }
129
216
  this.optimisticUpserts.clear();
130
217
  this.optimisticDeletes.clear();
131
218
  this.isCommittingSyncTransactions = false;
@@ -406,7 +493,7 @@ class CollectionImpl {
406
493
  const callbacks = [...this.onFirstReadyCallbacks];
407
494
  this.onFirstReadyCallbacks = [];
408
495
  callbacks.forEach((callback) => callback());
409
- if (this.size === 0 && this.changeListeners.size > 0) {
496
+ if (this.changeListeners.size > 0) {
410
497
  this.emitEmptyReadyEvent();
411
498
  }
412
499
  }
@@ -499,9 +586,12 @@ class CollectionImpl {
499
586
  }
500
587
  const key = this.getKeyFromItem(messageWithoutKey.value);
501
588
  if (messageWithoutKey.type === `insert`) {
502
- if (this.syncedData.has(key) && !pendingTransaction.operations.some(
589
+ const insertingIntoExistingSynced = this.syncedData.has(key);
590
+ const hasPendingDeleteForKey = pendingTransaction.operations.some(
503
591
  (op) => op.key === key && op.type === `delete`
504
- )) {
592
+ );
593
+ const isTruncateTransaction = pendingTransaction.truncate === true;
594
+ if (insertingIntoExistingSynced && !hasPendingDeleteForKey && !isTruncateTransaction) {
505
595
  throw new errors.DuplicateKeySyncError(key, this.id);
506
596
  }
507
597
  }
@@ -527,6 +617,17 @@ class CollectionImpl {
527
617
  },
528
618
  markReady: () => {
529
619
  this.markReady();
620
+ },
621
+ truncate: () => {
622
+ const pendingTransaction = this.pendingSyncedTransactions[this.pendingSyncedTransactions.length - 1];
623
+ if (!pendingTransaction) {
624
+ throw new errors.NoPendingSyncTransactionWriteError();
625
+ }
626
+ if (pendingTransaction.committed) {
627
+ throw new errors.SyncTransactionAlreadyCommittedWriteError();
628
+ }
629
+ pendingTransaction.operations = [];
630
+ pendingTransaction.truncate = true;
530
631
  }
531
632
  });
532
633
  this.syncCleanupFn = typeof cleanupFn === `function` ? cleanupFn : null;
@@ -796,6 +897,11 @@ class CollectionImpl {
796
897
  for (const listener of this.changeListeners) {
797
898
  listener([]);
798
899
  }
900
+ for (const [_key, keyListeners] of this.changeKeyListeners) {
901
+ for (const listener of keyListeners) {
902
+ listener([]);
903
+ }
904
+ }
799
905
  }
800
906
  /**
801
907
  * Emit events either immediately or batch them for later emission
@@ -959,8 +1065,8 @@ class CollectionImpl {
959
1065
  }
960
1066
  /**
961
1067
  * Creates an index on a collection for faster queries.
962
- * Indexes significantly improve query performance by allowing binary search
963
- * and range queries instead of full scans.
1068
+ * Indexes significantly improve query performance by allowing constant time lookups
1069
+ * and logarithmic time range queries instead of full scans.
964
1070
  *
965
1071
  * @template TResolver - The type of the index resolver (constructor or async loader)
966
1072
  * @param indexCallback - Function that extracts the indexed value from each item