@tanstack/db 0.5.32 → 0.6.0
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/change-events.cjs.map +1 -1
- package/dist/cjs/collection/change-events.d.cts +3 -2
- package/dist/cjs/collection/changes.cjs +13 -4
- package/dist/cjs/collection/changes.cjs.map +1 -1
- package/dist/cjs/collection/changes.d.cts +10 -1
- package/dist/cjs/collection/cleanup-queue.cjs +89 -0
- package/dist/cjs/collection/cleanup-queue.cjs.map +1 -0
- package/dist/cjs/collection/cleanup-queue.d.cts +30 -0
- package/dist/cjs/collection/events.cjs +14 -0
- package/dist/cjs/collection/events.cjs.map +1 -1
- package/dist/cjs/collection/events.d.cts +39 -1
- package/dist/cjs/collection/index.cjs +66 -28
- package/dist/cjs/collection/index.cjs.map +1 -1
- package/dist/cjs/collection/index.d.cts +49 -36
- package/dist/cjs/collection/indexes.cjs +211 -62
- package/dist/cjs/collection/indexes.cjs.map +1 -1
- package/dist/cjs/collection/indexes.d.cts +27 -17
- package/dist/cjs/collection/lifecycle.cjs +5 -22
- package/dist/cjs/collection/lifecycle.cjs.map +1 -1
- package/dist/cjs/collection/lifecycle.d.cts +0 -1
- package/dist/cjs/collection/mutations.cjs +18 -0
- package/dist/cjs/collection/mutations.cjs.map +1 -1
- package/dist/cjs/collection/mutations.d.cts +1 -0
- package/dist/cjs/collection/state.cjs +381 -53
- package/dist/cjs/collection/state.cjs.map +1 -1
- package/dist/cjs/collection/state.d.cts +65 -1
- package/dist/cjs/collection/subscription.cjs +6 -0
- package/dist/cjs/collection/subscription.cjs.map +1 -1
- package/dist/cjs/collection/subscription.d.cts +4 -0
- package/dist/cjs/collection/sync.cjs +108 -1
- package/dist/cjs/collection/sync.cjs.map +1 -1
- package/dist/cjs/collection/sync.d.cts +2 -0
- package/dist/cjs/collection/transaction-metadata.cjs +5 -0
- package/dist/cjs/collection/transaction-metadata.cjs.map +1 -0
- package/dist/cjs/collection/transaction-metadata.d.cts +1 -0
- package/dist/cjs/errors.cjs +8 -0
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/errors.d.cts +3 -0
- package/dist/cjs/index.cjs +24 -4
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +12 -3
- package/dist/cjs/indexes/auto-index.cjs +13 -6
- package/dist/cjs/indexes/auto-index.cjs.map +1 -1
- package/dist/cjs/indexes/base-index.cjs +0 -3
- package/dist/cjs/indexes/base-index.cjs.map +1 -1
- package/dist/cjs/indexes/base-index.d.cts +2 -6
- package/dist/cjs/indexes/basic-index.cjs +361 -0
- package/dist/cjs/indexes/basic-index.cjs.map +1 -0
- package/dist/cjs/indexes/basic-index.d.cts +102 -0
- package/dist/cjs/indexes/btree-index.cjs.map +1 -1
- package/dist/cjs/indexes/btree-index.d.cts +1 -1
- package/dist/cjs/indexes/index-options.d.cts +8 -9
- package/dist/cjs/indexes/index-registry.cjs +89 -0
- package/dist/cjs/indexes/index-registry.cjs.map +1 -0
- package/dist/cjs/indexes/index-registry.d.cts +61 -0
- package/dist/cjs/local-only.cjs +5 -0
- package/dist/cjs/local-only.cjs.map +1 -1
- package/dist/cjs/query/builder/functions.cjs +27 -11
- package/dist/cjs/query/builder/functions.cjs.map +1 -1
- package/dist/cjs/query/builder/functions.d.cts +25 -3
- package/dist/cjs/query/builder/index.cjs +200 -39
- package/dist/cjs/query/builder/index.cjs.map +1 -1
- package/dist/cjs/query/builder/index.d.cts +4 -3
- package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -1
- package/dist/cjs/query/builder/ref-proxy.d.cts +14 -3
- package/dist/cjs/query/builder/types.d.cts +84 -19
- package/dist/cjs/query/compiler/evaluators.cjs +51 -0
- package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
- package/dist/cjs/query/compiler/group-by.cjs +100 -28
- package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/group-by.d.cts +4 -2
- package/dist/cjs/query/compiler/index.cjs +283 -11
- package/dist/cjs/query/compiler/index.cjs.map +1 -1
- package/dist/cjs/query/compiler/index.d.cts +30 -2
- package/dist/cjs/query/compiler/order-by.cjs +29 -10
- package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.d.cts +1 -1
- package/dist/cjs/query/compiler/select.cjs +8 -0
- package/dist/cjs/query/compiler/select.cjs.map +1 -1
- package/dist/cjs/query/effect.cjs +602 -0
- package/dist/cjs/query/effect.cjs.map +1 -0
- package/dist/cjs/query/effect.d.cts +94 -0
- package/dist/cjs/query/index.d.cts +2 -1
- package/dist/cjs/query/ir.cjs +18 -1
- package/dist/cjs/query/ir.cjs.map +1 -1
- package/dist/cjs/query/ir.d.cts +21 -1
- package/dist/cjs/query/live/collection-config-builder.cjs +493 -66
- package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
- package/dist/cjs/query/live/collection-config-builder.d.cts +7 -0
- package/dist/cjs/query/live/collection-subscriber.cjs +33 -100
- package/dist/cjs/query/live/collection-subscriber.cjs.map +1 -1
- package/dist/cjs/query/live/collection-subscriber.d.cts +0 -1
- package/dist/cjs/query/live/types.d.cts +3 -3
- package/dist/cjs/query/live/utils.cjs +219 -0
- package/dist/cjs/query/live/utils.cjs.map +1 -0
- package/dist/cjs/query/live/utils.d.cts +110 -0
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/query/live-query-collection.d.cts +9 -6
- package/dist/cjs/query/query-once.cjs.map +1 -1
- package/dist/cjs/query/query-once.d.cts +7 -5
- package/dist/cjs/query/subset-dedupe.cjs +9 -3
- package/dist/cjs/query/subset-dedupe.cjs.map +1 -1
- package/dist/cjs/types.d.cts +42 -8
- package/dist/cjs/utils/array-utils.cjs +27 -0
- package/dist/cjs/utils/array-utils.cjs.map +1 -0
- package/dist/cjs/utils/array-utils.d.cts +16 -0
- package/dist/cjs/utils/comparison.cjs +11 -0
- package/dist/cjs/utils/comparison.cjs.map +1 -1
- package/dist/cjs/utils/index-optimization.cjs +4 -0
- package/dist/cjs/utils/index-optimization.cjs.map +1 -1
- package/dist/cjs/utils.cjs +7 -9
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +6 -1
- package/dist/cjs/virtual-props.cjs +33 -0
- package/dist/cjs/virtual-props.cjs.map +1 -0
- package/dist/cjs/virtual-props.d.cts +196 -0
- package/dist/esm/collection/change-events.d.ts +3 -2
- package/dist/esm/collection/change-events.js.map +1 -1
- package/dist/esm/collection/changes.d.ts +10 -1
- package/dist/esm/collection/changes.js +13 -4
- package/dist/esm/collection/changes.js.map +1 -1
- package/dist/esm/collection/cleanup-queue.d.ts +30 -0
- package/dist/esm/collection/cleanup-queue.js +89 -0
- package/dist/esm/collection/cleanup-queue.js.map +1 -0
- package/dist/esm/collection/events.d.ts +39 -1
- package/dist/esm/collection/events.js +14 -0
- package/dist/esm/collection/events.js.map +1 -1
- package/dist/esm/collection/index.d.ts +49 -36
- package/dist/esm/collection/index.js +67 -29
- package/dist/esm/collection/index.js.map +1 -1
- package/dist/esm/collection/indexes.d.ts +27 -17
- package/dist/esm/collection/indexes.js +211 -62
- package/dist/esm/collection/indexes.js.map +1 -1
- package/dist/esm/collection/lifecycle.d.ts +0 -1
- package/dist/esm/collection/lifecycle.js +5 -22
- package/dist/esm/collection/lifecycle.js.map +1 -1
- package/dist/esm/collection/mutations.d.ts +1 -0
- package/dist/esm/collection/mutations.js +18 -0
- package/dist/esm/collection/mutations.js.map +1 -1
- package/dist/esm/collection/state.d.ts +65 -1
- package/dist/esm/collection/state.js +381 -53
- package/dist/esm/collection/state.js.map +1 -1
- package/dist/esm/collection/subscription.d.ts +4 -0
- package/dist/esm/collection/subscription.js +6 -0
- package/dist/esm/collection/subscription.js.map +1 -1
- package/dist/esm/collection/sync.d.ts +2 -0
- package/dist/esm/collection/sync.js +108 -1
- package/dist/esm/collection/sync.js.map +1 -1
- package/dist/esm/collection/transaction-metadata.d.ts +1 -0
- package/dist/esm/collection/transaction-metadata.js +5 -0
- package/dist/esm/collection/transaction-metadata.js.map +1 -0
- package/dist/esm/errors.d.ts +3 -0
- package/dist/esm/errors.js +8 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +12 -3
- package/dist/esm/index.js +27 -7
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/indexes/auto-index.js +13 -6
- package/dist/esm/indexes/auto-index.js.map +1 -1
- package/dist/esm/indexes/base-index.d.ts +2 -6
- package/dist/esm/indexes/base-index.js +1 -4
- package/dist/esm/indexes/base-index.js.map +1 -1
- package/dist/esm/indexes/basic-index.d.ts +102 -0
- package/dist/esm/indexes/basic-index.js +361 -0
- package/dist/esm/indexes/basic-index.js.map +1 -0
- package/dist/esm/indexes/btree-index.d.ts +1 -1
- package/dist/esm/indexes/btree-index.js.map +1 -1
- package/dist/esm/indexes/index-options.d.ts +8 -9
- package/dist/esm/indexes/index-registry.d.ts +61 -0
- package/dist/esm/indexes/index-registry.js +89 -0
- package/dist/esm/indexes/index-registry.js.map +1 -0
- package/dist/esm/local-only.js +5 -0
- package/dist/esm/local-only.js.map +1 -1
- package/dist/esm/query/builder/functions.d.ts +25 -3
- package/dist/esm/query/builder/functions.js +27 -11
- package/dist/esm/query/builder/functions.js.map +1 -1
- package/dist/esm/query/builder/index.d.ts +4 -3
- package/dist/esm/query/builder/index.js +201 -40
- package/dist/esm/query/builder/index.js.map +1 -1
- package/dist/esm/query/builder/ref-proxy.d.ts +14 -3
- package/dist/esm/query/builder/ref-proxy.js.map +1 -1
- package/dist/esm/query/builder/types.d.ts +84 -19
- package/dist/esm/query/compiler/evaluators.js +51 -0
- package/dist/esm/query/compiler/evaluators.js.map +1 -1
- package/dist/esm/query/compiler/group-by.d.ts +4 -2
- package/dist/esm/query/compiler/group-by.js +101 -29
- package/dist/esm/query/compiler/group-by.js.map +1 -1
- package/dist/esm/query/compiler/index.d.ts +30 -2
- package/dist/esm/query/compiler/index.js +285 -13
- package/dist/esm/query/compiler/index.js.map +1 -1
- package/dist/esm/query/compiler/order-by.d.ts +1 -1
- package/dist/esm/query/compiler/order-by.js +30 -11
- package/dist/esm/query/compiler/order-by.js.map +1 -1
- package/dist/esm/query/compiler/select.js +8 -0
- package/dist/esm/query/compiler/select.js.map +1 -1
- package/dist/esm/query/effect.d.ts +94 -0
- package/dist/esm/query/effect.js +602 -0
- package/dist/esm/query/effect.js.map +1 -0
- package/dist/esm/query/index.d.ts +2 -1
- package/dist/esm/query/ir.d.ts +21 -1
- package/dist/esm/query/ir.js +18 -1
- package/dist/esm/query/ir.js.map +1 -1
- package/dist/esm/query/live/collection-config-builder.d.ts +7 -0
- package/dist/esm/query/live/collection-config-builder.js +492 -65
- package/dist/esm/query/live/collection-config-builder.js.map +1 -1
- package/dist/esm/query/live/collection-subscriber.d.ts +0 -1
- package/dist/esm/query/live/collection-subscriber.js +31 -98
- package/dist/esm/query/live/collection-subscriber.js.map +1 -1
- package/dist/esm/query/live/types.d.ts +3 -3
- package/dist/esm/query/live/utils.d.ts +110 -0
- package/dist/esm/query/live/utils.js +219 -0
- package/dist/esm/query/live/utils.js.map +1 -0
- package/dist/esm/query/live-query-collection.d.ts +9 -6
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/query/query-once.d.ts +7 -5
- package/dist/esm/query/query-once.js.map +1 -1
- package/dist/esm/query/subset-dedupe.js +9 -3
- package/dist/esm/query/subset-dedupe.js.map +1 -1
- package/dist/esm/types.d.ts +42 -8
- package/dist/esm/utils/array-utils.d.ts +16 -0
- package/dist/esm/utils/array-utils.js +27 -0
- package/dist/esm/utils/array-utils.js.map +1 -0
- package/dist/esm/utils/comparison.js +11 -0
- package/dist/esm/utils/comparison.js.map +1 -1
- package/dist/esm/utils/index-optimization.js +4 -0
- package/dist/esm/utils/index-optimization.js.map +1 -1
- package/dist/esm/utils.d.ts +6 -1
- package/dist/esm/utils.js +7 -9
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/virtual-props.d.ts +196 -0
- package/dist/esm/virtual-props.js +33 -0
- package/dist/esm/virtual-props.js.map +1 -0
- package/package.json +2 -2
- package/skills/db-core/collection-setup/references/electric-adapter.md +1 -1
- package/src/collection/change-events.ts +13 -9
- package/src/collection/changes.ts +30 -7
- package/src/collection/cleanup-queue.ts +105 -0
- package/src/collection/events.ts +65 -0
- package/src/collection/index.ts +110 -45
- package/src/collection/indexes.ts +283 -76
- package/src/collection/lifecycle.ts +5 -26
- package/src/collection/mutations.ts +21 -0
- package/src/collection/state.ts +545 -71
- package/src/collection/subscription.ts +7 -0
- package/src/collection/sync.ts +137 -0
- package/src/collection/transaction-metadata.ts +1 -0
- package/src/errors.ts +9 -0
- package/src/index.ts +57 -3
- package/src/indexes/auto-index.ts +18 -8
- package/src/indexes/base-index.ts +2 -10
- package/src/indexes/basic-index.ts +507 -0
- package/src/indexes/btree-index.ts +1 -1
- package/src/indexes/index-options.ts +17 -37
- package/src/indexes/index-registry.ts +174 -0
- package/src/local-only.ts +7 -0
- package/src/query/builder/functions.ts +84 -7
- package/src/query/builder/index.ts +329 -9
- package/src/query/builder/ref-proxy.ts +22 -4
- package/src/query/builder/types.ts +257 -62
- package/src/query/compiler/evaluators.ts +57 -0
- package/src/query/compiler/group-by.ts +156 -35
- package/src/query/compiler/index.ts +445 -15
- package/src/query/compiler/order-by.ts +51 -12
- package/src/query/compiler/select.ts +9 -0
- package/src/query/effect.ts +1119 -0
- package/src/query/index.ts +7 -0
- package/src/query/ir.ts +23 -2
- package/src/query/live/collection-config-builder.ts +778 -104
- package/src/query/live/collection-subscriber.ts +40 -156
- package/src/query/live/types.ts +10 -4
- package/src/query/live/utils.ts +417 -0
- package/src/query/live-query-collection.ts +43 -18
- package/src/query/query-once.ts +31 -12
- package/src/query/subset-dedupe.ts +11 -7
- package/src/types.ts +49 -9
- package/src/utils/array-utils.ts +49 -0
- package/src/utils/comparison.ts +14 -0
- package/src/utils/index-optimization.ts +4 -0
- package/src/utils.ts +12 -9
- package/src/virtual-props.ts +282 -0
- package/dist/cjs/indexes/lazy-index.cjs +0 -190
- package/dist/cjs/indexes/lazy-index.cjs.map +0 -1
- package/dist/cjs/indexes/lazy-index.d.cts +0 -96
- package/dist/esm/indexes/lazy-index.d.ts +0 -96
- package/dist/esm/indexes/lazy-index.js +0 -190
- package/dist/esm/indexes/lazy-index.js.map +0 -1
- package/src/indexes/lazy-index.ts +0 -251
|
@@ -256,6 +256,13 @@ export class CollectionSubscription
|
|
|
256
256
|
this.orderByIndex = index
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
+
/**
|
|
260
|
+
* Check if an orderBy index has been set for this subscription
|
|
261
|
+
*/
|
|
262
|
+
hasOrderByIndex(): boolean {
|
|
263
|
+
return this.orderByIndex !== undefined
|
|
264
|
+
}
|
|
265
|
+
|
|
259
266
|
/**
|
|
260
267
|
* Set subscription status and emit events if changed
|
|
261
268
|
*/
|
package/src/collection/sync.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
LoadSubsetOptions,
|
|
19
19
|
OptimisticChangeMessage,
|
|
20
20
|
SyncConfigRes,
|
|
21
|
+
SyncMetadataApi,
|
|
21
22
|
} from '../types'
|
|
22
23
|
import type { CollectionImpl } from './index.js'
|
|
23
24
|
import type { CollectionStateManager } from './state'
|
|
@@ -93,6 +94,8 @@ export class CollectionSyncManager<
|
|
|
93
94
|
committed: false,
|
|
94
95
|
operations: [],
|
|
95
96
|
deletedKeys: new Set(),
|
|
97
|
+
rowMetadataWrites: new Map(),
|
|
98
|
+
collectionMetadataWrites: new Map(),
|
|
96
99
|
immediate: options?.immediate,
|
|
97
100
|
})
|
|
98
101
|
},
|
|
@@ -120,6 +123,10 @@ export class CollectionSyncManager<
|
|
|
120
123
|
key = this.config.getKey(messageWithOptionalKey.value)
|
|
121
124
|
}
|
|
122
125
|
|
|
126
|
+
if (this.state.pendingLocalChanges.has(key)) {
|
|
127
|
+
this.state.pendingLocalOrigins.add(key)
|
|
128
|
+
}
|
|
129
|
+
|
|
123
130
|
let messageType = messageWithOptionalKey.type
|
|
124
131
|
|
|
125
132
|
// Check if an item with this key already exists when inserting
|
|
@@ -165,6 +172,23 @@ export class CollectionSyncManager<
|
|
|
165
172
|
|
|
166
173
|
if (messageType === `delete`) {
|
|
167
174
|
pendingTransaction.deletedKeys.add(key)
|
|
175
|
+
pendingTransaction.rowMetadataWrites.set(key, { type: `delete` })
|
|
176
|
+
} else if (messageType === `insert`) {
|
|
177
|
+
if (message.metadata !== undefined) {
|
|
178
|
+
pendingTransaction.rowMetadataWrites.set(key, {
|
|
179
|
+
type: `set`,
|
|
180
|
+
value: message.metadata,
|
|
181
|
+
})
|
|
182
|
+
} else {
|
|
183
|
+
pendingTransaction.rowMetadataWrites.set(key, {
|
|
184
|
+
type: `delete`,
|
|
185
|
+
})
|
|
186
|
+
}
|
|
187
|
+
} else if (message.metadata !== undefined) {
|
|
188
|
+
pendingTransaction.rowMetadataWrites.set(key, {
|
|
189
|
+
type: `set`,
|
|
190
|
+
value: message.metadata,
|
|
191
|
+
})
|
|
168
192
|
}
|
|
169
193
|
},
|
|
170
194
|
commit: () => {
|
|
@@ -201,6 +225,11 @@ export class CollectionSyncManager<
|
|
|
201
225
|
// Clear all operations from the current transaction
|
|
202
226
|
pendingTransaction.operations = []
|
|
203
227
|
pendingTransaction.deletedKeys.clear()
|
|
228
|
+
pendingTransaction.rowMetadataWrites.clear()
|
|
229
|
+
// Intentionally preserve collectionMetadataWrites across truncate.
|
|
230
|
+
// Collection-scoped metadata (for example persisted resume/reset
|
|
231
|
+
// state) can be staged before truncate and should commit atomically
|
|
232
|
+
// with the truncate transaction.
|
|
204
233
|
|
|
205
234
|
// Mark the transaction as a truncate operation. During commit, this triggers:
|
|
206
235
|
// - Delete events for all previously synced keys (excluding optimistic-deleted keys)
|
|
@@ -216,6 +245,7 @@ export class CollectionSyncManager<
|
|
|
216
245
|
deletes: new Set(this.state.optimisticDeletes),
|
|
217
246
|
}
|
|
218
247
|
},
|
|
248
|
+
metadata: this.createSyncMetadataApi(),
|
|
219
249
|
}),
|
|
220
250
|
)
|
|
221
251
|
|
|
@@ -241,6 +271,113 @@ export class CollectionSyncManager<
|
|
|
241
271
|
}
|
|
242
272
|
}
|
|
243
273
|
|
|
274
|
+
private getActivePendingSyncTransaction() {
|
|
275
|
+
const pendingTransaction =
|
|
276
|
+
this.state.pendingSyncedTransactions[
|
|
277
|
+
this.state.pendingSyncedTransactions.length - 1
|
|
278
|
+
]
|
|
279
|
+
|
|
280
|
+
if (!pendingTransaction) {
|
|
281
|
+
throw new NoPendingSyncTransactionWriteError()
|
|
282
|
+
}
|
|
283
|
+
if (pendingTransaction.committed) {
|
|
284
|
+
throw new SyncTransactionAlreadyCommittedWriteError()
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return pendingTransaction
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
private createSyncMetadataApi(): SyncMetadataApi<TKey> {
|
|
291
|
+
return {
|
|
292
|
+
row: {
|
|
293
|
+
get: (key) => {
|
|
294
|
+
const pendingTransaction =
|
|
295
|
+
this.state.pendingSyncedTransactions[
|
|
296
|
+
this.state.pendingSyncedTransactions.length - 1
|
|
297
|
+
]
|
|
298
|
+
const pendingWrite = pendingTransaction?.rowMetadataWrites.get(key)
|
|
299
|
+
if (pendingWrite) {
|
|
300
|
+
return pendingWrite.type === `delete`
|
|
301
|
+
? undefined
|
|
302
|
+
: pendingWrite.value
|
|
303
|
+
}
|
|
304
|
+
if (pendingTransaction?.truncate) {
|
|
305
|
+
return undefined
|
|
306
|
+
}
|
|
307
|
+
return this.state.syncedMetadata.get(key)
|
|
308
|
+
},
|
|
309
|
+
set: (key, metadata) => {
|
|
310
|
+
const pendingTransaction = this.getActivePendingSyncTransaction()
|
|
311
|
+
pendingTransaction.rowMetadataWrites.set(key, {
|
|
312
|
+
type: `set`,
|
|
313
|
+
value: metadata,
|
|
314
|
+
})
|
|
315
|
+
},
|
|
316
|
+
delete: (key) => {
|
|
317
|
+
const pendingTransaction = this.getActivePendingSyncTransaction()
|
|
318
|
+
pendingTransaction.rowMetadataWrites.set(key, {
|
|
319
|
+
type: `delete`,
|
|
320
|
+
})
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
collection: {
|
|
324
|
+
get: (key) => {
|
|
325
|
+
const pendingTransaction =
|
|
326
|
+
this.state.pendingSyncedTransactions[
|
|
327
|
+
this.state.pendingSyncedTransactions.length - 1
|
|
328
|
+
]
|
|
329
|
+
const pendingWrite =
|
|
330
|
+
pendingTransaction?.collectionMetadataWrites.get(key)
|
|
331
|
+
if (pendingWrite) {
|
|
332
|
+
return pendingWrite.type === `delete`
|
|
333
|
+
? undefined
|
|
334
|
+
: pendingWrite.value
|
|
335
|
+
}
|
|
336
|
+
return this.state.syncedCollectionMetadata.get(key)
|
|
337
|
+
},
|
|
338
|
+
set: (key, value) => {
|
|
339
|
+
const pendingTransaction = this.getActivePendingSyncTransaction()
|
|
340
|
+
pendingTransaction.collectionMetadataWrites.set(key, {
|
|
341
|
+
type: `set`,
|
|
342
|
+
value,
|
|
343
|
+
})
|
|
344
|
+
},
|
|
345
|
+
delete: (key) => {
|
|
346
|
+
const pendingTransaction = this.getActivePendingSyncTransaction()
|
|
347
|
+
pendingTransaction.collectionMetadataWrites.set(key, {
|
|
348
|
+
type: `delete`,
|
|
349
|
+
})
|
|
350
|
+
},
|
|
351
|
+
list: (prefix) => {
|
|
352
|
+
const merged = new Map(this.state.syncedCollectionMetadata)
|
|
353
|
+
const pendingTransaction =
|
|
354
|
+
this.state.pendingSyncedTransactions[
|
|
355
|
+
this.state.pendingSyncedTransactions.length - 1
|
|
356
|
+
]
|
|
357
|
+
if (pendingTransaction) {
|
|
358
|
+
for (const [
|
|
359
|
+
key,
|
|
360
|
+
pendingWrite,
|
|
361
|
+
] of pendingTransaction.collectionMetadataWrites) {
|
|
362
|
+
if (pendingWrite.type === `delete`) {
|
|
363
|
+
merged.delete(key)
|
|
364
|
+
} else {
|
|
365
|
+
merged.set(key, pendingWrite.value)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return Array.from(merged.entries())
|
|
371
|
+
.filter(([key]) => (prefix ? key.startsWith(prefix) : true))
|
|
372
|
+
.map(([key, value]) => ({
|
|
373
|
+
key,
|
|
374
|
+
value,
|
|
375
|
+
}))
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
244
381
|
/**
|
|
245
382
|
* Preload the collection data by starting sync if not already started
|
|
246
383
|
* Multiple concurrent calls will share the same promise
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DIRECT_TRANSACTION_METADATA_KEY = `__tanstack_db_direct`
|
package/src/errors.ts
CHANGED
|
@@ -444,6 +444,15 @@ export class FnSelectWithGroupByError extends QueryCompilationError {
|
|
|
444
444
|
}
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
+
export class UnsupportedRootScalarSelectError extends QueryCompilationError {
|
|
448
|
+
constructor() {
|
|
449
|
+
super(
|
|
450
|
+
`Top-level scalar select() is not supported by createLiveQueryCollection() or queryOnce(). ` +
|
|
451
|
+
`Return an object from .select(), or use the scalar query inside toArray(...) or concat(toArray(...)).`,
|
|
452
|
+
)
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
447
456
|
export class HavingRequiresGroupByError extends QueryCompilationError {
|
|
448
457
|
constructor() {
|
|
449
458
|
super(`HAVING clause requires GROUP BY clause`)
|
package/src/index.ts
CHANGED
|
@@ -17,15 +17,69 @@ export { deepEquals } from './utils'
|
|
|
17
17
|
export * from './paced-mutations'
|
|
18
18
|
export * from './strategies/index.js'
|
|
19
19
|
|
|
20
|
+
// Virtual properties exports
|
|
21
|
+
export {
|
|
22
|
+
type VirtualRowProps,
|
|
23
|
+
type VirtualOrigin,
|
|
24
|
+
type WithVirtualProps,
|
|
25
|
+
type WithoutVirtualProps,
|
|
26
|
+
hasVirtualProps,
|
|
27
|
+
} from './virtual-props.js'
|
|
28
|
+
|
|
20
29
|
// Index system exports
|
|
21
|
-
export
|
|
22
|
-
export
|
|
23
|
-
|
|
30
|
+
export { BaseIndex } from './indexes/base-index.js'
|
|
31
|
+
export type {
|
|
32
|
+
IndexInterface,
|
|
33
|
+
IndexConstructor,
|
|
34
|
+
IndexStats,
|
|
35
|
+
IndexOperation,
|
|
36
|
+
} from './indexes/base-index.js'
|
|
24
37
|
export { type IndexOptions } from './indexes/index-options.js'
|
|
25
38
|
|
|
39
|
+
// Index implementations
|
|
40
|
+
export { BasicIndex } from './indexes/basic-index.js'
|
|
41
|
+
export type {
|
|
42
|
+
BasicIndexOptions,
|
|
43
|
+
RangeQueryOptions,
|
|
44
|
+
} from './indexes/basic-index.js'
|
|
45
|
+
export { BTreeIndex } from './indexes/btree-index.js'
|
|
46
|
+
export type { RangeQueryOptions as BTreeRangeQueryOptions } from './indexes/btree-index.js'
|
|
47
|
+
export { ReverseIndex } from './indexes/reverse-index.js'
|
|
48
|
+
|
|
49
|
+
// Index optimization utilities
|
|
50
|
+
export {
|
|
51
|
+
optimizeExpressionWithIndexes,
|
|
52
|
+
findIndexForField,
|
|
53
|
+
} from './utils/index-optimization.js'
|
|
54
|
+
|
|
55
|
+
// Dev mode utilities
|
|
56
|
+
export {
|
|
57
|
+
configureIndexDevMode,
|
|
58
|
+
isDevModeEnabled,
|
|
59
|
+
getIndexDevModeConfig,
|
|
60
|
+
trackQuery,
|
|
61
|
+
clearQueryPatterns,
|
|
62
|
+
getQueryPatterns,
|
|
63
|
+
} from './indexes/index-registry.js'
|
|
64
|
+
export type {
|
|
65
|
+
IndexDevModeConfig,
|
|
66
|
+
IndexSuggestion,
|
|
67
|
+
} from './indexes/index-registry.js'
|
|
68
|
+
|
|
26
69
|
// Expression helpers
|
|
27
70
|
export * from './query/expression-helpers.js'
|
|
28
71
|
|
|
72
|
+
// Reactive effects
|
|
73
|
+
export {
|
|
74
|
+
createEffect,
|
|
75
|
+
type DeltaEvent,
|
|
76
|
+
type DeltaType,
|
|
77
|
+
type EffectConfig,
|
|
78
|
+
type EffectContext,
|
|
79
|
+
type Effect,
|
|
80
|
+
type EffectQueryInput,
|
|
81
|
+
} from './query/effect.js'
|
|
82
|
+
|
|
29
83
|
// Re-export some stuff explicitly to ensure the type & value is exported
|
|
30
84
|
export type { Collection } from './collection/index.js'
|
|
31
85
|
export { IR }
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_COMPARE_OPTIONS } from '../utils'
|
|
2
|
-
import {
|
|
2
|
+
import { hasVirtualPropPath } from '../virtual-props'
|
|
3
|
+
import { checkCollectionSizeForIndex, isDevModeEnabled } from './index-registry'
|
|
3
4
|
import type { CompareOptions } from '../query/builder/types'
|
|
4
5
|
import type { BasicExpression } from '../query/ir'
|
|
5
6
|
import type { CollectionImpl } from '../collection/index.js'
|
|
@@ -10,11 +11,9 @@ export interface AutoIndexConfig {
|
|
|
10
11
|
|
|
11
12
|
function shouldAutoIndex(collection: CollectionImpl<any, any, any, any, any>) {
|
|
12
13
|
// Only proceed if auto-indexing is enabled
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return true
|
|
14
|
+
// Note: autoIndex: 'eager' without defaultIndexType is caught at construction time
|
|
15
|
+
// in CollectionImpl, so we don't need to check for it here.
|
|
16
|
+
return collection.config.autoIndex === `eager`
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
export function ensureIndexForField<
|
|
@@ -27,6 +26,9 @@ export function ensureIndexForField<
|
|
|
27
26
|
compareOptions?: CompareOptions,
|
|
28
27
|
compareFn?: (a: any, b: any) => number,
|
|
29
28
|
) {
|
|
29
|
+
if (hasVirtualPropPath(fieldPath)) {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
30
32
|
if (!shouldAutoIndex(collection)) {
|
|
31
33
|
return
|
|
32
34
|
}
|
|
@@ -46,9 +48,18 @@ export function ensureIndexForField<
|
|
|
46
48
|
return // Index already exists
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
// Dev mode: check if collection size warrants an index suggestion
|
|
52
|
+
if (isDevModeEnabled()) {
|
|
53
|
+
checkCollectionSizeForIndex(
|
|
54
|
+
collection.id || `unknown`,
|
|
55
|
+
collection.size,
|
|
56
|
+
fieldPath,
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
49
60
|
// Create a new index for this field using the collection's createIndex method
|
|
61
|
+
// The collection will use its defaultIndexType
|
|
50
62
|
try {
|
|
51
|
-
// Use the proxy-based approach to create the proper accessor for nested paths
|
|
52
63
|
collection.createIndex(
|
|
53
64
|
(row) => {
|
|
54
65
|
// Navigate through the field path
|
|
@@ -60,7 +71,6 @@ export function ensureIndexForField<
|
|
|
60
71
|
},
|
|
61
72
|
{
|
|
62
73
|
name: `auto:${fieldPath.join(`.`)}`,
|
|
63
|
-
indexType: BTreeIndex,
|
|
64
74
|
options: compareFn ? { compareFn, compareOptions: compareOpts } : {},
|
|
65
75
|
},
|
|
66
76
|
)
|
|
@@ -26,7 +26,7 @@ export interface IndexStats {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export interface IndexInterface<
|
|
29
|
-
TKey extends string | number
|
|
29
|
+
TKey extends string | number = string | number,
|
|
30
30
|
> {
|
|
31
31
|
add: (key: TKey, item: any) => void
|
|
32
32
|
remove: (key: TKey, item: any) => void
|
|
@@ -79,7 +79,7 @@ export interface IndexInterface<
|
|
|
79
79
|
* Base abstract class that all index types extend
|
|
80
80
|
*/
|
|
81
81
|
export abstract class BaseIndex<
|
|
82
|
-
TKey extends string | number
|
|
82
|
+
TKey extends string | number = string | number,
|
|
83
83
|
> implements IndexInterface<TKey> {
|
|
84
84
|
public readonly id: number
|
|
85
85
|
public readonly name?: string
|
|
@@ -189,7 +189,6 @@ export abstract class BaseIndex<
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
// Protected methods for subclasses
|
|
193
192
|
protected abstract initialize(options?: any): void
|
|
194
193
|
|
|
195
194
|
protected evaluateIndexExpression(item: any): any {
|
|
@@ -218,10 +217,3 @@ export type IndexConstructor<TKey extends string | number = string | number> =
|
|
|
218
217
|
name?: string,
|
|
219
218
|
options?: any,
|
|
220
219
|
) => BaseIndex<TKey>
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Index resolver can be either a class constructor or async loader
|
|
224
|
-
*/
|
|
225
|
-
export type IndexResolver<TKey extends string | number = string | number> =
|
|
226
|
-
| IndexConstructor<TKey>
|
|
227
|
-
| (() => Promise<IndexConstructor<TKey>>)
|