@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CollectionImpl } from '../../collection/index.js'
|
|
1
|
+
import type { Collection, CollectionImpl } from '../../collection/index.js'
|
|
2
2
|
import type { SingleResult, StringCollationConfig } from '../../types.js'
|
|
3
3
|
import type {
|
|
4
4
|
Aggregate,
|
|
@@ -8,7 +8,9 @@ import type {
|
|
|
8
8
|
PropRef,
|
|
9
9
|
Value,
|
|
10
10
|
} from '../ir.js'
|
|
11
|
-
import type { QueryBuilder } from './index.js'
|
|
11
|
+
import type { InitialQueryBuilder, QueryBuilder } from './index.js'
|
|
12
|
+
import type { VirtualRowProps, WithVirtualProps } from '../../virtual-props.js'
|
|
13
|
+
import type { ConcatToArrayWrapper, ToArrayWrapper } from './functions.js'
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Context - The central state container for query builder operations
|
|
@@ -48,6 +50,8 @@ export interface Context {
|
|
|
48
50
|
>
|
|
49
51
|
// The result type after select (if select has been called)
|
|
50
52
|
result?: any
|
|
53
|
+
// Whether select/fn.select has been called
|
|
54
|
+
hasResult?: true
|
|
51
55
|
// Single result only (if findOne has been called)
|
|
52
56
|
singleResult?: boolean
|
|
53
57
|
}
|
|
@@ -83,7 +87,9 @@ export type Source = {
|
|
|
83
87
|
* This can be an explicit type passed by the user or the schema output type.
|
|
84
88
|
*/
|
|
85
89
|
export type InferCollectionType<T> =
|
|
86
|
-
T extends CollectionImpl<infer TOutput,
|
|
90
|
+
T extends CollectionImpl<infer TOutput, infer TKey, any, any, any>
|
|
91
|
+
? WithVirtualProps<TOutput, TKey>
|
|
92
|
+
: never
|
|
87
93
|
|
|
88
94
|
/**
|
|
89
95
|
* SchemaFromSource - Converts a Source definition into a ContextSchema
|
|
@@ -174,9 +180,23 @@ type SelectValue =
|
|
|
174
180
|
| undefined // Optional values
|
|
175
181
|
| { [key: string]: SelectValue }
|
|
176
182
|
| Array<RefLeaf<any>>
|
|
183
|
+
| ToArrayWrapper // toArray() wrapped subquery
|
|
184
|
+
| ConcatToArrayWrapper // concat(toArray(...)) wrapped subquery
|
|
185
|
+
| QueryBuilder<any> // includes subquery (produces a child Collection)
|
|
177
186
|
|
|
178
187
|
// Recursive shape for select objects allowing nested projections
|
|
179
188
|
type SelectShape = { [key: string]: SelectValue | SelectShape }
|
|
189
|
+
export type ScalarSelectValue =
|
|
190
|
+
| BasicExpression
|
|
191
|
+
| Aggregate
|
|
192
|
+
| Ref
|
|
193
|
+
| RefLeaf<any>
|
|
194
|
+
| string
|
|
195
|
+
| number
|
|
196
|
+
| boolean
|
|
197
|
+
| null
|
|
198
|
+
| undefined
|
|
199
|
+
export type StringifiableScalar = string | number | boolean | null | undefined
|
|
180
200
|
|
|
181
201
|
/**
|
|
182
202
|
* SelectObject - Wrapper type for select clause objects
|
|
@@ -186,6 +206,69 @@ type SelectShape = { [key: string]: SelectValue | SelectShape }
|
|
|
186
206
|
* messages when invalid selections are attempted.
|
|
187
207
|
*/
|
|
188
208
|
export type SelectObject<T extends SelectShape = SelectShape> = T
|
|
209
|
+
type RefBrandKeys = typeof RefBrand | typeof NullableBrand
|
|
210
|
+
type HasNamedSelectKeys<T> =
|
|
211
|
+
Exclude<keyof T, RefBrandKeys> extends never ? false : true
|
|
212
|
+
type IsScalarSelectLike<T> = T extends BasicExpression | Aggregate
|
|
213
|
+
? true
|
|
214
|
+
: T extends string | number | boolean | null | undefined
|
|
215
|
+
? true
|
|
216
|
+
: typeof RefBrand extends keyof T
|
|
217
|
+
? HasNamedSelectKeys<T> extends true
|
|
218
|
+
? false
|
|
219
|
+
: true
|
|
220
|
+
: false
|
|
221
|
+
export type NonScalarSelectObject<T> = T extends SelectObject
|
|
222
|
+
? IsScalarSelectLike<T> extends true
|
|
223
|
+
? never
|
|
224
|
+
: T
|
|
225
|
+
: never
|
|
226
|
+
|
|
227
|
+
export type ResultTypeFromSelectValue<TSelectValue> =
|
|
228
|
+
IsAny<TSelectValue> extends true
|
|
229
|
+
? any
|
|
230
|
+
: WithoutRefBrand<
|
|
231
|
+
NeedsExtraction<TSelectValue> extends true
|
|
232
|
+
? ExtractExpressionType<TSelectValue>
|
|
233
|
+
: TSelectValue extends ToArrayWrapper<infer T>
|
|
234
|
+
? Array<T>
|
|
235
|
+
: TSelectValue extends ConcatToArrayWrapper<any>
|
|
236
|
+
? string
|
|
237
|
+
: TSelectValue extends QueryBuilder<infer TChildContext>
|
|
238
|
+
? Collection<GetResult<TChildContext>>
|
|
239
|
+
: TSelectValue extends Ref<infer _T>
|
|
240
|
+
? ExtractRef<TSelectValue>
|
|
241
|
+
: TSelectValue extends RefLeaf<infer T>
|
|
242
|
+
? IsNullableRef<TSelectValue> extends true
|
|
243
|
+
? T | undefined
|
|
244
|
+
: T
|
|
245
|
+
: TSelectValue extends RefLeaf<infer T> | undefined
|
|
246
|
+
? T | undefined
|
|
247
|
+
: TSelectValue extends RefLeaf<infer T> | null
|
|
248
|
+
? IsNullableRef<
|
|
249
|
+
Exclude<TSelectValue, null>
|
|
250
|
+
> extends true
|
|
251
|
+
? T | null | undefined
|
|
252
|
+
: T | null
|
|
253
|
+
: TSelectValue extends Ref<infer _T> | undefined
|
|
254
|
+
?
|
|
255
|
+
| ExtractRef<Exclude<TSelectValue, undefined>>
|
|
256
|
+
| undefined
|
|
257
|
+
: TSelectValue extends Ref<infer _T> | null
|
|
258
|
+
? ExtractRef<Exclude<TSelectValue, null>> | null
|
|
259
|
+
: TSelectValue extends Aggregate<infer T>
|
|
260
|
+
? T
|
|
261
|
+
: TSelectValue extends
|
|
262
|
+
| string
|
|
263
|
+
| number
|
|
264
|
+
| boolean
|
|
265
|
+
| null
|
|
266
|
+
| undefined
|
|
267
|
+
? TSelectValue
|
|
268
|
+
: TSelectValue extends Record<string, any>
|
|
269
|
+
? ResultTypeFromSelect<TSelectValue>
|
|
270
|
+
: never
|
|
271
|
+
>
|
|
189
272
|
|
|
190
273
|
/**
|
|
191
274
|
* ResultTypeFromSelect - Infers the result type from a select object
|
|
@@ -223,46 +306,71 @@ export type SelectObject<T extends SelectShape = SelectShape> = T
|
|
|
223
306
|
* { id: number, name: string, status: 'active', count: 42, profile: { bio: string } }
|
|
224
307
|
* ```
|
|
225
308
|
*/
|
|
226
|
-
export type ResultTypeFromSelect<TSelectObject> =
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
>
|
|
309
|
+
export type ResultTypeFromSelect<TSelectObject> =
|
|
310
|
+
IsAny<TSelectObject> extends true
|
|
311
|
+
? any
|
|
312
|
+
: WithoutRefBrand<
|
|
313
|
+
Prettify<{
|
|
314
|
+
[K in keyof TSelectObject]: NeedsExtraction<
|
|
315
|
+
TSelectObject[K]
|
|
316
|
+
> extends true
|
|
317
|
+
? ExtractExpressionType<TSelectObject[K]>
|
|
318
|
+
: TSelectObject[K] extends ToArrayWrapper<infer T>
|
|
319
|
+
? Array<T>
|
|
320
|
+
: TSelectObject[K] extends ConcatToArrayWrapper<any>
|
|
321
|
+
? string
|
|
322
|
+
: // includes subquery (bare QueryBuilder) — produces a child Collection
|
|
323
|
+
TSelectObject[K] extends QueryBuilder<infer TChildContext>
|
|
324
|
+
? Collection<GetResult<TChildContext>>
|
|
325
|
+
: // Ref (full object ref or spread with RefBrand) - recursively process properties
|
|
326
|
+
TSelectObject[K] extends Ref<infer _T>
|
|
327
|
+
? ExtractRef<TSelectObject[K]>
|
|
328
|
+
: // RefLeaf (simple property ref like user.name)
|
|
329
|
+
TSelectObject[K] extends RefLeaf<infer T>
|
|
330
|
+
? IsNullableRef<TSelectObject[K]> extends true
|
|
331
|
+
? T | undefined
|
|
332
|
+
: T
|
|
333
|
+
: // RefLeaf | undefined (schema-optional field)
|
|
334
|
+
TSelectObject[K] extends RefLeaf<infer T> | undefined
|
|
335
|
+
? T | undefined
|
|
336
|
+
: // RefLeaf | null (schema-nullable field)
|
|
337
|
+
TSelectObject[K] extends RefLeaf<infer T> | null
|
|
338
|
+
? IsNullableRef<
|
|
339
|
+
Exclude<TSelectObject[K], null>
|
|
340
|
+
> extends true
|
|
341
|
+
? T | null | undefined
|
|
342
|
+
: T | null
|
|
343
|
+
: // Ref | undefined (optional object-type schema field)
|
|
344
|
+
TSelectObject[K] extends Ref<infer _T> | undefined
|
|
345
|
+
?
|
|
346
|
+
| ExtractRef<
|
|
347
|
+
Exclude<TSelectObject[K], undefined>
|
|
348
|
+
>
|
|
349
|
+
| undefined
|
|
350
|
+
: // Ref | null (nullable object-type schema field)
|
|
351
|
+
TSelectObject[K] extends Ref<infer _T> | null
|
|
352
|
+
? ExtractRef<
|
|
353
|
+
Exclude<TSelectObject[K], null>
|
|
354
|
+
> | null
|
|
355
|
+
: TSelectObject[K] extends Aggregate<infer T>
|
|
356
|
+
? T
|
|
357
|
+
: TSelectObject[K] extends
|
|
358
|
+
| string
|
|
359
|
+
| number
|
|
360
|
+
| boolean
|
|
361
|
+
| null
|
|
362
|
+
| undefined
|
|
363
|
+
? TSelectObject[K]
|
|
364
|
+
: TSelectObject[K] extends Record<string, any>
|
|
365
|
+
? ResultTypeFromSelect<TSelectObject[K]>
|
|
366
|
+
: never
|
|
367
|
+
}>
|
|
368
|
+
>
|
|
369
|
+
|
|
370
|
+
export type SelectResult<TSelect> =
|
|
371
|
+
IsPlainObject<TSelect> extends true
|
|
372
|
+
? ResultTypeFromSelect<TSelect>
|
|
373
|
+
: ResultTypeFromSelectValue<TSelect>
|
|
266
374
|
|
|
267
375
|
// Extract Ref or subobject with a spread or a Ref
|
|
268
376
|
type ExtractRef<T> = Prettify<ResultTypeFromSelect<WithoutRefBrand<T>>>
|
|
@@ -373,7 +481,7 @@ export type JoinOnCallback<TContext extends Context> = (
|
|
|
373
481
|
* Example (no GROUP BY): `(row) => row.user.salary > 70000 && row.$selected.user_count > 2`
|
|
374
482
|
*/
|
|
375
483
|
export type FunctionalHavingRow<TContext extends Context> = TContext[`schema`] &
|
|
376
|
-
(TContext[`
|
|
484
|
+
(TContext[`hasResult`] extends true ? { $selected: TContext[`result`] } : {})
|
|
377
485
|
|
|
378
486
|
/**
|
|
379
487
|
* RefsForContext - Creates ref proxies for all tables/collections in a query context
|
|
@@ -409,7 +517,7 @@ export type RefsForContext<TContext extends Context> = {
|
|
|
409
517
|
: // T is exactly undefined, exactly null, or neither optional nor nullable
|
|
410
518
|
// Wrap in Ref as-is (includes exact undefined, exact null, and normal types)
|
|
411
519
|
Ref<TContext[`schema`][K]>
|
|
412
|
-
} & (TContext[`
|
|
520
|
+
} & (TContext[`hasResult`] extends true
|
|
413
521
|
? { $selected: Ref<TContext[`result`]> }
|
|
414
522
|
: {})
|
|
415
523
|
|
|
@@ -474,6 +582,29 @@ type NonUndefined<T> = T extends undefined ? never : T
|
|
|
474
582
|
// Helper type to extract non-null type
|
|
475
583
|
type NonNull<T> = T extends null ? never : T
|
|
476
584
|
|
|
585
|
+
/**
|
|
586
|
+
* Virtual properties available on all Ref types in query builders.
|
|
587
|
+
* These allow querying on sync status, origin, key, and collection ID.
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* ```typescript
|
|
591
|
+
* // Filter by sync status
|
|
592
|
+
* .where(({ user }) => eq(user.$synced, true))
|
|
593
|
+
*
|
|
594
|
+
* // Filter by origin
|
|
595
|
+
* .where(({ order }) => eq(order.$origin, 'local'))
|
|
596
|
+
*
|
|
597
|
+
* // Access key in select
|
|
598
|
+
* .select(({ user }) => ({
|
|
599
|
+
* key: user.$key,
|
|
600
|
+
* collectionId: user.$collectionId,
|
|
601
|
+
* }))
|
|
602
|
+
* ```
|
|
603
|
+
*/
|
|
604
|
+
type VirtualPropsRef<TKey extends string | number = string | number> = {
|
|
605
|
+
readonly [K in keyof VirtualRowProps<TKey>]: RefLeaf<VirtualRowProps<TKey>[K]>
|
|
606
|
+
}
|
|
607
|
+
|
|
477
608
|
/**
|
|
478
609
|
* Ref - The user-facing ref interface for the query builder
|
|
479
610
|
*
|
|
@@ -487,12 +618,18 @@ type NonNull<T> = T extends null ? never : T
|
|
|
487
618
|
* through all nested property accesses, ensuring the result type includes
|
|
488
619
|
* `| undefined` for all fields accessed through this ref.
|
|
489
620
|
*
|
|
621
|
+
* Includes virtual properties ($synced, $origin, $key, $collectionId) for
|
|
622
|
+
* querying on sync status and row metadata.
|
|
623
|
+
*
|
|
490
624
|
* Example usage:
|
|
491
625
|
* ```typescript
|
|
492
|
-
* //
|
|
493
|
-
*
|
|
626
|
+
* // Clean interface - no internal properties visible
|
|
627
|
+
* const users: Ref<{ id: number; profile?: { bio: string } }> = { ... }
|
|
628
|
+
* users.id // Ref<number> - clean display
|
|
629
|
+
* users.profile?.bio // Ref<string> - nested optional access works
|
|
630
|
+
* users.$synced // RefLeaf<boolean> - virtual property access
|
|
494
631
|
*
|
|
495
|
-
* // Nullable ref (left join
|
|
632
|
+
* // Nullable ref (left/right/full join side):
|
|
496
633
|
* select(({ dept }) => ({ name: dept.name })) // result: string | undefined
|
|
497
634
|
*
|
|
498
635
|
* // Spread operations work cleanly:
|
|
@@ -519,7 +656,8 @@ export type Ref<T = any, Nullable extends boolean = false> = {
|
|
|
519
656
|
IsPlainObject<T[K]> extends true
|
|
520
657
|
? Ref<T[K], Nullable>
|
|
521
658
|
: RefLeaf<T[K], Nullable>
|
|
522
|
-
} & RefLeaf<T, Nullable>
|
|
659
|
+
} & RefLeaf<T, Nullable> &
|
|
660
|
+
VirtualPropsRef
|
|
523
661
|
|
|
524
662
|
/**
|
|
525
663
|
* Ref - The user-facing ref type with clean IDE display
|
|
@@ -543,7 +681,7 @@ type IsNullableRef<T> = typeof NullableBrand extends keyof T ? true : false
|
|
|
543
681
|
|
|
544
682
|
// Helper type to remove RefBrand and NullableBrand from objects
|
|
545
683
|
type WithoutRefBrand<T> =
|
|
546
|
-
T extends
|
|
684
|
+
IsPlainObject<T> extends true
|
|
547
685
|
? Omit<T, typeof RefBrand | typeof NullableBrand>
|
|
548
686
|
: T
|
|
549
687
|
|
|
@@ -561,6 +699,10 @@ type PreserveSingleResultFlag<TFlag> = [TFlag] extends [true]
|
|
|
561
699
|
? { singleResult: true }
|
|
562
700
|
: {}
|
|
563
701
|
|
|
702
|
+
type PreserveHasResultFlag<TFlag> = [TFlag] extends [true]
|
|
703
|
+
? { hasResult: true }
|
|
704
|
+
: {}
|
|
705
|
+
|
|
564
706
|
/**
|
|
565
707
|
* MergeContextWithJoinType - Creates a new context after a join operation
|
|
566
708
|
*
|
|
@@ -606,7 +748,8 @@ export type MergeContextWithJoinType<
|
|
|
606
748
|
[K in keyof TNewSchema & string]: TJoinType
|
|
607
749
|
}
|
|
608
750
|
result: TContext[`result`]
|
|
609
|
-
} & PreserveSingleResultFlag<TContext[`singleResult`]>
|
|
751
|
+
} & PreserveSingleResultFlag<TContext[`singleResult`]> &
|
|
752
|
+
PreserveHasResultFlag<TContext[`hasResult`]>
|
|
610
753
|
|
|
611
754
|
/**
|
|
612
755
|
* ApplyJoinOptionalityToMergedSchema - Applies optionality rules when merging schemas
|
|
@@ -664,6 +807,17 @@ export type InferResultType<TContext extends Context> =
|
|
|
664
807
|
? GetResult<TContext> | undefined
|
|
665
808
|
: Array<GetResult<TContext>>
|
|
666
809
|
|
|
810
|
+
type WithVirtualPropsIfObject<TResult> = TResult extends object
|
|
811
|
+
? WithVirtualProps<TResult, string | number>
|
|
812
|
+
: TResult
|
|
813
|
+
|
|
814
|
+
type PrettifyIfPlainObject<T> = IsPlainObject<T> extends true ? Prettify<T> : T
|
|
815
|
+
type ResultValue<TContext extends Context> = TContext[`hasResult`] extends true
|
|
816
|
+
? WithVirtualPropsIfObject<TContext[`result`]>
|
|
817
|
+
: TContext[`hasJoins`] extends true
|
|
818
|
+
? TContext[`schema`]
|
|
819
|
+
: TContext[`schema`][TContext[`fromSourceName`]]
|
|
820
|
+
|
|
667
821
|
/**
|
|
668
822
|
* GetResult - Determines the final result type of a query
|
|
669
823
|
*
|
|
@@ -689,16 +843,46 @@ export type InferResultType<TContext extends Context> =
|
|
|
689
843
|
* The `Prettify` wrapper ensures clean type display in IDEs by flattening
|
|
690
844
|
* complex intersection types into readable object types.
|
|
691
845
|
*/
|
|
846
|
+
export type GetRawResult<TContext extends Context> = ResultValue<TContext>
|
|
847
|
+
|
|
692
848
|
export type GetResult<TContext extends Context> = Prettify<
|
|
693
|
-
TContext
|
|
694
|
-
? TContext[`result`]
|
|
695
|
-
: TContext[`hasJoins`] extends true
|
|
696
|
-
? // Optionality is already applied in the schema, just return it
|
|
697
|
-
TContext[`schema`]
|
|
698
|
-
: // Single table query - return the specific table
|
|
699
|
-
TContext[`schema`][TContext[`fromSourceName`]]
|
|
849
|
+
ResultValue<TContext>
|
|
700
850
|
>
|
|
701
851
|
|
|
852
|
+
type IsExactlyContext<TContext extends Context> = [Context] extends [TContext]
|
|
853
|
+
? [TContext] extends [Context]
|
|
854
|
+
? true
|
|
855
|
+
: false
|
|
856
|
+
: false
|
|
857
|
+
|
|
858
|
+
type RootScalarResultError = {
|
|
859
|
+
readonly __tanstackDbRootQueryError__: `Top-level scalar results are not supported by createLiveQueryCollection() or queryOnce(). Return an object, or use the scalar query inside toArray(...) or concat(toArray(...)).`
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
export type RootObjectResultConstraint<TContext extends Context> =
|
|
863
|
+
IsExactlyContext<TContext> extends true
|
|
864
|
+
? unknown
|
|
865
|
+
: GetResult<TContext> extends object
|
|
866
|
+
? unknown
|
|
867
|
+
: RootScalarResultError
|
|
868
|
+
|
|
869
|
+
type ContextFromQueryBuilder<TQuery extends QueryBuilder<any>> =
|
|
870
|
+
TQuery extends QueryBuilder<infer TContext> ? TContext : never
|
|
871
|
+
|
|
872
|
+
export type RootQueryBuilder<TQuery extends QueryBuilder<any>> = TQuery &
|
|
873
|
+
RootObjectResultConstraint<ContextFromQueryBuilder<TQuery>>
|
|
874
|
+
|
|
875
|
+
export type RootQueryFn<TQuery extends QueryBuilder<any>> = (
|
|
876
|
+
q: InitialQueryBuilder,
|
|
877
|
+
) => RootQueryBuilder<TQuery>
|
|
878
|
+
|
|
879
|
+
export type RootQueryResult<TContext extends Context> =
|
|
880
|
+
IsExactlyContext<TContext> extends true
|
|
881
|
+
? any
|
|
882
|
+
: GetResult<TContext> extends object
|
|
883
|
+
? GetResult<TContext>
|
|
884
|
+
: never
|
|
885
|
+
|
|
702
886
|
/**
|
|
703
887
|
* ApplyJoinOptionalityToSchema - Legacy helper for complex join scenarios
|
|
704
888
|
*
|
|
@@ -831,7 +1015,7 @@ export type MergeContextForJoinCallback<
|
|
|
831
1015
|
? TContext[`joinTypes`]
|
|
832
1016
|
: {}
|
|
833
1017
|
result: TContext[`result`]
|
|
834
|
-
}
|
|
1018
|
+
} & PreserveHasResultFlag<TContext[`hasResult`]>
|
|
835
1019
|
|
|
836
1020
|
/**
|
|
837
1021
|
* WithResult - Updates a context with a new result type after select()
|
|
@@ -848,8 +1032,9 @@ export type MergeContextForJoinCallback<
|
|
|
848
1032
|
* result type display cleanly in IDEs.
|
|
849
1033
|
*/
|
|
850
1034
|
export type WithResult<TContext extends Context, TResult> = Prettify<
|
|
851
|
-
Omit<TContext, `result`> & {
|
|
852
|
-
result:
|
|
1035
|
+
Omit<TContext, `result` | `hasResult`> & {
|
|
1036
|
+
result: PrettifyIfPlainObject<TResult>
|
|
1037
|
+
hasResult: true
|
|
853
1038
|
}
|
|
854
1039
|
>
|
|
855
1040
|
|
|
@@ -862,6 +1047,12 @@ export type Prettify<T> = {
|
|
|
862
1047
|
|
|
863
1048
|
/**
|
|
864
1049
|
* IsPlainObject - Utility type to check if T is a plain object
|
|
1050
|
+
*
|
|
1051
|
+
* Returns `false` for:
|
|
1052
|
+
* - Arrays (ReadonlyArray)
|
|
1053
|
+
* - JavaScript built-ins (Date, Map, Set, etc.)
|
|
1054
|
+
* - Objects with `Symbol.toStringTag` (class instances like Temporal types,
|
|
1055
|
+
* TypedArrays not already in JsBuiltIns, etc.) — these are not plain data objects
|
|
865
1056
|
*/
|
|
866
1057
|
type IsPlainObject<T> = T extends unknown
|
|
867
1058
|
? T extends object
|
|
@@ -869,10 +1060,14 @@ type IsPlainObject<T> = T extends unknown
|
|
|
869
1060
|
? false
|
|
870
1061
|
: T extends JsBuiltIns
|
|
871
1062
|
? false
|
|
872
|
-
:
|
|
1063
|
+
: T extends { readonly [Symbol.toStringTag]: string }
|
|
1064
|
+
? false
|
|
1065
|
+
: true
|
|
873
1066
|
: false
|
|
874
1067
|
: false
|
|
875
1068
|
|
|
1069
|
+
type IsAny<T> = 0 extends 1 & T ? true : false
|
|
1070
|
+
|
|
876
1071
|
/**
|
|
877
1072
|
* JsBuiltIns - List of JavaScript built-ins
|
|
878
1073
|
*/
|
|
@@ -14,6 +14,31 @@ function isUnknown(value: any): boolean {
|
|
|
14
14
|
return value === null || value === undefined
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
function toDateValue(value: any): Date | null {
|
|
18
|
+
if (value instanceof Date) {
|
|
19
|
+
return Number.isNaN(value.getTime()) ? null : value
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof value === `string` || typeof value === `number`) {
|
|
23
|
+
const parsed = new Date(value)
|
|
24
|
+
return Number.isNaN(parsed.getTime()) ? null : parsed
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function evaluateStrftime(format: string, date: Date): string {
|
|
31
|
+
if (format === `%Y-%m-%d`) {
|
|
32
|
+
return date.toISOString().slice(0, 10)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (format === `%Y-%m-%dT%H:%M:%fZ`) {
|
|
36
|
+
return date.toISOString()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return date.toISOString()
|
|
40
|
+
}
|
|
41
|
+
|
|
17
42
|
/**
|
|
18
43
|
* Converts a 3-valued logic result to a boolean for use in WHERE/HAVING filters.
|
|
19
44
|
* In SQL, UNKNOWN (null) values in WHERE clauses exclude rows, matching false behavior.
|
|
@@ -471,6 +496,38 @@ function compileFunction(func: Func, isSingleRow: boolean): (data: any) => any {
|
|
|
471
496
|
return divisor !== 0 ? (a ?? 0) / divisor : null
|
|
472
497
|
}
|
|
473
498
|
}
|
|
499
|
+
case `date`: {
|
|
500
|
+
const arg = compiledArgs[0]!
|
|
501
|
+
return (data) => {
|
|
502
|
+
const value = arg(data)
|
|
503
|
+
const dateValue = toDateValue(value)
|
|
504
|
+
return dateValue ? dateValue.toISOString().slice(0, 10) : null
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
case `datetime`: {
|
|
508
|
+
const arg = compiledArgs[0]!
|
|
509
|
+
return (data) => {
|
|
510
|
+
const value = arg(data)
|
|
511
|
+
const dateValue = toDateValue(value)
|
|
512
|
+
return dateValue ? dateValue.toISOString() : null
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
case `strftime`: {
|
|
516
|
+
const formatArg = compiledArgs[0]!
|
|
517
|
+
const sourceArg = compiledArgs[1]!
|
|
518
|
+
return (data) => {
|
|
519
|
+
const format = formatArg(data)
|
|
520
|
+
if (typeof format !== `string`) {
|
|
521
|
+
return null
|
|
522
|
+
}
|
|
523
|
+
const sourceValue = sourceArg(data)
|
|
524
|
+
const dateValue = toDateValue(sourceValue)
|
|
525
|
+
if (!dateValue) {
|
|
526
|
+
return null
|
|
527
|
+
}
|
|
528
|
+
return evaluateStrftime(format, dateValue)
|
|
529
|
+
}
|
|
530
|
+
}
|
|
474
531
|
|
|
475
532
|
// Null/undefined checking functions
|
|
476
533
|
case `isUndefined`: {
|