@tanstack/db 0.1.3 → 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.
- package/dist/cjs/collection.cjs +112 -6
- package/dist/cjs/collection.cjs.map +1 -1
- package/dist/cjs/collection.d.cts +3 -2
- package/dist/cjs/errors.cjs +6 -0
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/errors.d.cts +3 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/indexes/auto-index.cjs +30 -19
- package/dist/cjs/indexes/auto-index.cjs.map +1 -1
- package/dist/cjs/indexes/auto-index.d.cts +1 -0
- package/dist/cjs/indexes/base-index.cjs.map +1 -1
- package/dist/cjs/indexes/base-index.d.cts +2 -1
- package/dist/cjs/indexes/btree-index.cjs +26 -0
- package/dist/cjs/indexes/btree-index.cjs.map +1 -1
- package/dist/cjs/indexes/btree-index.d.cts +7 -0
- package/dist/cjs/indexes/index-options.d.cts +1 -1
- package/dist/cjs/query/compiler/evaluators.cjs +2 -2
- package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
- package/dist/cjs/query/compiler/evaluators.d.cts +1 -1
- package/dist/cjs/query/compiler/group-by.cjs +3 -1
- package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/index.cjs +72 -6
- package/dist/cjs/query/compiler/index.cjs.map +1 -1
- package/dist/cjs/query/compiler/index.d.cts +16 -2
- package/dist/cjs/query/compiler/joins.cjs +111 -12
- package/dist/cjs/query/compiler/joins.cjs.map +1 -1
- package/dist/cjs/query/compiler/joins.d.cts +9 -2
- package/dist/cjs/query/compiler/order-by.cjs +62 -3
- package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.d.cts +12 -2
- package/dist/cjs/query/live-query-collection.cjs +196 -23
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/types.d.cts +1 -0
- package/dist/cjs/utils/btree.cjs +15 -0
- package/dist/cjs/utils/btree.cjs.map +1 -1
- package/dist/cjs/utils/btree.d.cts +8 -0
- package/dist/esm/collection.d.ts +3 -2
- package/dist/esm/collection.js +113 -7
- package/dist/esm/collection.js.map +1 -1
- package/dist/esm/errors.d.ts +3 -0
- package/dist/esm/errors.js +6 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/indexes/auto-index.d.ts +1 -0
- package/dist/esm/indexes/auto-index.js +31 -20
- package/dist/esm/indexes/auto-index.js.map +1 -1
- package/dist/esm/indexes/base-index.d.ts +2 -1
- package/dist/esm/indexes/base-index.js.map +1 -1
- package/dist/esm/indexes/btree-index.d.ts +7 -0
- package/dist/esm/indexes/btree-index.js +26 -0
- package/dist/esm/indexes/btree-index.js.map +1 -1
- package/dist/esm/indexes/index-options.d.ts +1 -1
- package/dist/esm/query/compiler/evaluators.d.ts +1 -1
- package/dist/esm/query/compiler/evaluators.js +2 -2
- package/dist/esm/query/compiler/evaluators.js.map +1 -1
- package/dist/esm/query/compiler/group-by.js +3 -1
- package/dist/esm/query/compiler/group-by.js.map +1 -1
- package/dist/esm/query/compiler/index.d.ts +16 -2
- package/dist/esm/query/compiler/index.js +73 -7
- package/dist/esm/query/compiler/index.js.map +1 -1
- package/dist/esm/query/compiler/joins.d.ts +9 -2
- package/dist/esm/query/compiler/joins.js +114 -15
- package/dist/esm/query/compiler/joins.js.map +1 -1
- package/dist/esm/query/compiler/order-by.d.ts +12 -2
- package/dist/esm/query/compiler/order-by.js +62 -3
- package/dist/esm/query/compiler/order-by.js.map +1 -1
- package/dist/esm/query/live-query-collection.js +196 -23
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/types.d.ts +1 -0
- package/dist/esm/utils/btree.d.ts +8 -0
- package/dist/esm/utils/btree.js +15 -0
- package/dist/esm/utils/btree.js.map +1 -1
- package/package.json +2 -2
- package/src/collection.ts +163 -10
- package/src/errors.ts +6 -0
- package/src/indexes/auto-index.ts +53 -31
- package/src/indexes/base-index.ts +6 -1
- package/src/indexes/btree-index.ts +29 -0
- package/src/indexes/index-options.ts +2 -2
- package/src/query/compiler/evaluators.ts +6 -3
- package/src/query/compiler/group-by.ts +3 -1
- package/src/query/compiler/index.ts +112 -5
- package/src/query/compiler/joins.ts +216 -20
- package/src/query/compiler/order-by.ts +98 -3
- package/src/query/live-query-collection.ts +352 -24
- package/src/types.ts +1 -0
- package/src/utils/btree.ts +17 -0
package/dist/cjs/collection.cjs
CHANGED
|
@@ -61,7 +61,10 @@ class CollectionImpl {
|
|
|
61
61
|
break;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|