@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.
- package/dist/cjs/collection.cjs +112 -6
- package/dist/cjs/collection.cjs.map +1 -1
- package/dist/cjs/collection.d.cts +12 -3
- 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 +29 -3
- 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/builder/index.cjs +9 -2
- package/dist/cjs/query/builder/index.cjs.map +1 -1
- package/dist/cjs/query/builder/index.d.cts +2 -2
- package/dist/cjs/query/builder/types.d.cts +27 -6
- 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 +80 -23
- 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/ir.cjs.map +1 -1
- package/dist/cjs/query/ir.d.cts +2 -1
- 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/cjs/utils/comparison.cjs +29 -7
- package/dist/cjs/utils/comparison.cjs.map +1 -1
- package/dist/cjs/utils/comparison.d.cts +6 -2
- package/dist/esm/collection.d.ts +12 -3
- 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 +29 -3
- package/dist/esm/indexes/btree-index.js.map +1 -1
- package/dist/esm/indexes/index-options.d.ts +1 -1
- package/dist/esm/query/builder/index.d.ts +2 -2
- package/dist/esm/query/builder/index.js +9 -2
- package/dist/esm/query/builder/index.js.map +1 -1
- package/dist/esm/query/builder/types.d.ts +27 -6
- 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 +81 -24
- package/dist/esm/query/compiler/order-by.js.map +1 -1
- package/dist/esm/query/ir.d.ts +2 -1
- package/dist/esm/query/ir.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/dist/esm/utils/comparison.d.ts +6 -2
- package/dist/esm/utils/comparison.js +30 -8
- package/dist/esm/utils/comparison.js.map +1 -1
- package/package.json +2 -2
- package/src/collection.ts +237 -11
- 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 +32 -3
- package/src/indexes/index-options.ts +2 -2
- package/src/query/builder/index.ts +19 -2
- package/src/query/builder/types.ts +48 -15
- 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 +117 -26
- package/src/query/ir.ts +2 -1
- package/src/query/live-query-collection.ts +352 -24
- package/src/types.ts +1 -0
- package/src/utils/btree.ts +17 -0
- package/src/utils/comparison.ts +40 -7
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { CollectionImpl } from "../../collection.js"
|
|
2
|
-
import type { Aggregate, BasicExpression } from "../ir.js"
|
|
2
|
+
import type { Aggregate, BasicExpression, OrderByDirection } from "../ir.js"
|
|
3
3
|
import type { QueryBuilder } from "./index.js"
|
|
4
|
+
import type { ResolveType } from "../../types.js"
|
|
4
5
|
|
|
5
6
|
export interface Context {
|
|
6
7
|
// The collections available in the base schema
|
|
@@ -27,13 +28,16 @@ export type Source = {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
// Helper type to infer collection type from CollectionImpl
|
|
31
|
+
// This uses ResolveType directly to ensure consistency with collection creation logic
|
|
30
32
|
export type InferCollectionType<T> =
|
|
31
|
-
T extends CollectionImpl<infer U
|
|
33
|
+
T extends CollectionImpl<infer U, any, any, infer TSchema, any>
|
|
34
|
+
? ResolveType<U, TSchema, U>
|
|
35
|
+
: never
|
|
32
36
|
|
|
33
37
|
// Helper type to create schema from source
|
|
34
38
|
export type SchemaFromSource<T extends Source> = Prettify<{
|
|
35
|
-
[K in keyof T]: T[K] extends CollectionImpl<
|
|
36
|
-
?
|
|
39
|
+
[K in keyof T]: T[K] extends CollectionImpl<any, any, any, any, any>
|
|
40
|
+
? InferCollectionType<T[K]>
|
|
37
41
|
: T[K] extends QueryBuilder<infer TContext>
|
|
38
42
|
? GetResult<TContext>
|
|
39
43
|
: never
|
|
@@ -58,16 +62,18 @@ export type SelectObject<
|
|
|
58
62
|
// Helper type to get the result type from a select object
|
|
59
63
|
export type ResultTypeFromSelect<TSelectObject> = {
|
|
60
64
|
[K in keyof TSelectObject]: TSelectObject[K] extends RefProxy<infer T>
|
|
61
|
-
?
|
|
62
|
-
T
|
|
65
|
+
? T
|
|
63
66
|
: TSelectObject[K] extends BasicExpression<infer T>
|
|
64
67
|
? T
|
|
65
68
|
: TSelectObject[K] extends Aggregate<infer T>
|
|
66
69
|
? T
|
|
67
70
|
: TSelectObject[K] extends RefProxyFor<infer T>
|
|
68
|
-
?
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
? T
|
|
72
|
+
: TSelectObject[K] extends undefined
|
|
73
|
+
? undefined
|
|
74
|
+
: TSelectObject[K] extends { __type: infer U }
|
|
75
|
+
? U
|
|
76
|
+
: never
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
// Callback type for orderBy clauses
|
|
@@ -75,6 +81,29 @@ export type OrderByCallback<TContext extends Context> = (
|
|
|
75
81
|
refs: RefProxyForContext<TContext>
|
|
76
82
|
) => any
|
|
77
83
|
|
|
84
|
+
export type OrderByOptions = {
|
|
85
|
+
direction?: OrderByDirection
|
|
86
|
+
nulls?: `first` | `last`
|
|
87
|
+
} & StringSortOpts
|
|
88
|
+
|
|
89
|
+
export type StringSortOpts =
|
|
90
|
+
| {
|
|
91
|
+
stringSort?: `lexical`
|
|
92
|
+
}
|
|
93
|
+
| {
|
|
94
|
+
stringSort?: `locale`
|
|
95
|
+
locale?: string
|
|
96
|
+
localeOptions?: object
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type CompareOptions = {
|
|
100
|
+
direction: OrderByDirection
|
|
101
|
+
nulls: `first` | `last`
|
|
102
|
+
stringSort: `lexical` | `locale`
|
|
103
|
+
locale?: string
|
|
104
|
+
localeOptions?: object
|
|
105
|
+
}
|
|
106
|
+
|
|
78
107
|
// Callback type for groupBy clauses
|
|
79
108
|
export type GroupByCallback<TContext extends Context> = (
|
|
80
109
|
refs: RefProxyForContext<TContext>
|
|
@@ -119,12 +148,11 @@ export type RefProxyFor<T> = OmitRefProxy<
|
|
|
119
148
|
? // T is optional (T | undefined) but not exactly undefined
|
|
120
149
|
NonUndefined<T> extends Record<string, any>
|
|
121
150
|
? {
|
|
122
|
-
|
|
123
|
-
[K in keyof NonUndefined<T>]: NonUndefined<T>[K] extends Record<
|
|
151
|
+
[K in keyof NonUndefined<T>]-?: NonUndefined<T>[K] extends Record<
|
|
124
152
|
string,
|
|
125
153
|
any
|
|
126
154
|
>
|
|
127
|
-
? RefProxyFor<NonUndefined<T>[K]
|
|
155
|
+
? RefProxyFor<NonUndefined<T>[K]> &
|
|
128
156
|
RefProxy<NonUndefined<T>[K] | undefined>
|
|
129
157
|
: RefProxy<NonUndefined<T>[K] | undefined>
|
|
130
158
|
} & RefProxy<T>
|
|
@@ -132,9 +160,14 @@ export type RefProxyFor<T> = OmitRefProxy<
|
|
|
132
160
|
: // T is not optional
|
|
133
161
|
T extends Record<string, any>
|
|
134
162
|
? {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
163
|
+
// Make all properties required, but for optional ones, include undefined in the RefProxy type
|
|
164
|
+
[K in keyof T]-?: undefined extends T[K]
|
|
165
|
+
? T[K] extends Record<string, any>
|
|
166
|
+
? RefProxyFor<T[K]> & RefProxy<T[K]>
|
|
167
|
+
: RefProxy<T[K]>
|
|
168
|
+
: T[K] extends Record<string, any>
|
|
169
|
+
? RefProxyFor<T[K]> & RefProxy<T[K]>
|
|
170
|
+
: RefProxy<T[K]>
|
|
138
171
|
} & RefProxy<T>
|
|
139
172
|
: RefProxy<T>
|
|
140
173
|
>
|
|
@@ -20,9 +20,12 @@ export type CompiledSingleRowExpression = (item: Record<string, unknown>) => any
|
|
|
20
20
|
* Compiles an expression into an optimized evaluator function.
|
|
21
21
|
* This eliminates branching during evaluation by pre-compiling the expression structure.
|
|
22
22
|
*/
|
|
23
|
-
export function compileExpression(
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
export function compileExpression(
|
|
24
|
+
expr: BasicExpression,
|
|
25
|
+
isSingleRow: boolean = false
|
|
26
|
+
): CompiledExpression | CompiledSingleRowExpression {
|
|
27
|
+
const compiledFn = compileExpressionInternal(expr, isSingleRow)
|
|
28
|
+
return compiledFn
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
/**
|
|
@@ -166,7 +166,9 @@ export function processGroupBy(
|
|
|
166
166
|
const mapping = validateAndCreateMapping(groupByClause, selectClause)
|
|
167
167
|
|
|
168
168
|
// Pre-compile groupBy expressions
|
|
169
|
-
const compiledGroupByExpressions = groupByClause.map(
|
|
169
|
+
const compiledGroupByExpressions = groupByClause.map((e) =>
|
|
170
|
+
compileExpression(e)
|
|
171
|
+
)
|
|
170
172
|
|
|
171
173
|
// Create a key extractor function using simple __key_X format
|
|
172
174
|
const keyExtractor = ([, row]: [
|
|
@@ -7,17 +7,21 @@ import {
|
|
|
7
7
|
LimitOffsetRequireOrderByError,
|
|
8
8
|
UnsupportedFromTypeError,
|
|
9
9
|
} from "../../errors.js"
|
|
10
|
+
import { PropRef } from "../ir.js"
|
|
10
11
|
import { compileExpression } from "./evaluators.js"
|
|
11
12
|
import { processJoins } from "./joins.js"
|
|
12
13
|
import { processGroupBy } from "./group-by.js"
|
|
13
14
|
import { processOrderBy } from "./order-by.js"
|
|
14
15
|
import { processSelectToResults } from "./select.js"
|
|
16
|
+
import type { OrderByOptimizationInfo } from "./order-by.js"
|
|
15
17
|
import type {
|
|
16
18
|
BasicExpression,
|
|
17
19
|
CollectionRef,
|
|
18
20
|
QueryIR,
|
|
19
21
|
QueryRef,
|
|
20
22
|
} from "../ir.js"
|
|
23
|
+
import type { LazyCollectionCallbacks } from "./joins.js"
|
|
24
|
+
import type { Collection } from "../../collection.js"
|
|
21
25
|
import type {
|
|
22
26
|
KeyedStream,
|
|
23
27
|
NamespacedAndKeyedStream,
|
|
@@ -29,6 +33,8 @@ import type { QueryCache, QueryMapping } from "./types.js"
|
|
|
29
33
|
* Result of query compilation including both the pipeline and collection-specific WHERE clauses
|
|
30
34
|
*/
|
|
31
35
|
export interface CompilationResult {
|
|
36
|
+
/** The ID of the main collection */
|
|
37
|
+
collectionId: string
|
|
32
38
|
/** The compiled query pipeline */
|
|
33
39
|
pipeline: ResultStream
|
|
34
40
|
/** Map of collection aliases to their WHERE clauses for index optimization */
|
|
@@ -46,6 +52,10 @@ export interface CompilationResult {
|
|
|
46
52
|
export function compileQuery(
|
|
47
53
|
rawQuery: QueryIR,
|
|
48
54
|
inputs: Record<string, KeyedStream>,
|
|
55
|
+
collections: Record<string, Collection<any, any, any, any, any>>,
|
|
56
|
+
callbacks: Record<string, LazyCollectionCallbacks>,
|
|
57
|
+
lazyCollections: Set<string>,
|
|
58
|
+
optimizableOrderByCollections: Record<string, OrderByOptimizationInfo>,
|
|
49
59
|
cache: QueryCache = new WeakMap(),
|
|
50
60
|
queryMapping: QueryMapping = new WeakMap()
|
|
51
61
|
): CompilationResult {
|
|
@@ -70,9 +80,17 @@ export function compileQuery(
|
|
|
70
80
|
const tables: Record<string, KeyedStream> = {}
|
|
71
81
|
|
|
72
82
|
// Process the FROM clause to get the main table
|
|
73
|
-
const {
|
|
83
|
+
const {
|
|
84
|
+
alias: mainTableAlias,
|
|
85
|
+
input: mainInput,
|
|
86
|
+
collectionId: mainCollectionId,
|
|
87
|
+
} = processFrom(
|
|
74
88
|
query.from,
|
|
75
89
|
allInputs,
|
|
90
|
+
collections,
|
|
91
|
+
callbacks,
|
|
92
|
+
lazyCollections,
|
|
93
|
+
optimizableOrderByCollections,
|
|
76
94
|
cache,
|
|
77
95
|
queryMapping
|
|
78
96
|
)
|
|
@@ -96,10 +114,16 @@ export function compileQuery(
|
|
|
96
114
|
pipeline,
|
|
97
115
|
query.join,
|
|
98
116
|
tables,
|
|
117
|
+
mainCollectionId,
|
|
99
118
|
mainTableAlias,
|
|
100
119
|
allInputs,
|
|
101
120
|
cache,
|
|
102
|
-
queryMapping
|
|
121
|
+
queryMapping,
|
|
122
|
+
collections,
|
|
123
|
+
callbacks,
|
|
124
|
+
lazyCollections,
|
|
125
|
+
optimizableOrderByCollections,
|
|
126
|
+
rawQuery
|
|
103
127
|
)
|
|
104
128
|
}
|
|
105
129
|
|
|
@@ -231,8 +255,11 @@ export function compileQuery(
|
|
|
231
255
|
// Process orderBy parameter if it exists
|
|
232
256
|
if (query.orderBy && query.orderBy.length > 0) {
|
|
233
257
|
const orderedPipeline = processOrderBy(
|
|
258
|
+
rawQuery,
|
|
234
259
|
pipeline,
|
|
235
260
|
query.orderBy,
|
|
261
|
+
collections[mainCollectionId]!,
|
|
262
|
+
optimizableOrderByCollections,
|
|
236
263
|
query.limit,
|
|
237
264
|
query.offset
|
|
238
265
|
)
|
|
@@ -249,6 +276,7 @@ export function compileQuery(
|
|
|
249
276
|
const result = resultPipeline
|
|
250
277
|
// Cache the result before returning (use original query as key)
|
|
251
278
|
const compilationResult = {
|
|
279
|
+
collectionId: mainCollectionId,
|
|
252
280
|
pipeline: result,
|
|
253
281
|
collectionWhereClauses,
|
|
254
282
|
}
|
|
@@ -275,6 +303,7 @@ export function compileQuery(
|
|
|
275
303
|
const result = resultPipeline
|
|
276
304
|
// Cache the result before returning (use original query as key)
|
|
277
305
|
const compilationResult = {
|
|
306
|
+
collectionId: mainCollectionId,
|
|
278
307
|
pipeline: result,
|
|
279
308
|
collectionWhereClauses,
|
|
280
309
|
}
|
|
@@ -289,16 +318,20 @@ export function compileQuery(
|
|
|
289
318
|
function processFrom(
|
|
290
319
|
from: CollectionRef | QueryRef,
|
|
291
320
|
allInputs: Record<string, KeyedStream>,
|
|
321
|
+
collections: Record<string, Collection>,
|
|
322
|
+
callbacks: Record<string, LazyCollectionCallbacks>,
|
|
323
|
+
lazyCollections: Set<string>,
|
|
324
|
+
optimizableOrderByCollections: Record<string, OrderByOptimizationInfo>,
|
|
292
325
|
cache: QueryCache,
|
|
293
326
|
queryMapping: QueryMapping
|
|
294
|
-
): { alias: string; input: KeyedStream } {
|
|
327
|
+
): { alias: string; input: KeyedStream; collectionId: string } {
|
|
295
328
|
switch (from.type) {
|
|
296
329
|
case `collectionRef`: {
|
|
297
330
|
const input = allInputs[from.collection.id]
|
|
298
331
|
if (!input) {
|
|
299
332
|
throw new CollectionInputNotFoundError(from.collection.id)
|
|
300
333
|
}
|
|
301
|
-
return { alias: from.alias, input }
|
|
334
|
+
return { alias: from.alias, input, collectionId: from.collection.id }
|
|
302
335
|
}
|
|
303
336
|
case `queryRef`: {
|
|
304
337
|
// Find the original query for caching purposes
|
|
@@ -308,6 +341,10 @@ function processFrom(
|
|
|
308
341
|
const subQueryResult = compileQuery(
|
|
309
342
|
originalQuery,
|
|
310
343
|
allInputs,
|
|
344
|
+
collections,
|
|
345
|
+
callbacks,
|
|
346
|
+
lazyCollections,
|
|
347
|
+
optimizableOrderByCollections,
|
|
311
348
|
cache,
|
|
312
349
|
queryMapping
|
|
313
350
|
)
|
|
@@ -324,7 +361,11 @@ function processFrom(
|
|
|
324
361
|
})
|
|
325
362
|
)
|
|
326
363
|
|
|
327
|
-
return {
|
|
364
|
+
return {
|
|
365
|
+
alias: from.alias,
|
|
366
|
+
input: extractedInput,
|
|
367
|
+
collectionId: subQueryResult.collectionId,
|
|
368
|
+
}
|
|
328
369
|
}
|
|
329
370
|
default:
|
|
330
371
|
throw new UnsupportedFromTypeError((from as any).type)
|
|
@@ -380,3 +421,69 @@ function mapNestedQueries(
|
|
|
380
421
|
}
|
|
381
422
|
}
|
|
382
423
|
}
|
|
424
|
+
|
|
425
|
+
function getRefFromAlias(
|
|
426
|
+
query: QueryIR,
|
|
427
|
+
alias: string
|
|
428
|
+
): CollectionRef | QueryRef | void {
|
|
429
|
+
if (query.from.alias === alias) {
|
|
430
|
+
return query.from
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
for (const join of query.join || []) {
|
|
434
|
+
if (join.from.alias === alias) {
|
|
435
|
+
return join.from
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Follows the given reference in a query
|
|
442
|
+
* until its finds the root field the reference points to.
|
|
443
|
+
* @returns The collection, its alias, and the path to the root field in this collection
|
|
444
|
+
*/
|
|
445
|
+
export function followRef(
|
|
446
|
+
query: QueryIR,
|
|
447
|
+
ref: PropRef<any>,
|
|
448
|
+
collection: Collection
|
|
449
|
+
): { collection: Collection; path: Array<string> } | void {
|
|
450
|
+
if (ref.path.length === 0) {
|
|
451
|
+
return
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (ref.path.length === 1) {
|
|
455
|
+
// This field should be part of this collection
|
|
456
|
+
const field = ref.path[0]!
|
|
457
|
+
// is it part of the select clause?
|
|
458
|
+
if (query.select) {
|
|
459
|
+
const selectedField = query.select[field]
|
|
460
|
+
if (selectedField && selectedField.type === `ref`) {
|
|
461
|
+
return followRef(query, selectedField, collection)
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Either this field is not part of the select clause
|
|
466
|
+
// and thus it must be part of the collection itself
|
|
467
|
+
// or it is part of the select but is not a reference
|
|
468
|
+
// so we can stop here and don't have to follow it
|
|
469
|
+
return { collection, path: [field] }
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (ref.path.length > 1) {
|
|
473
|
+
// This is a nested field
|
|
474
|
+
const [alias, ...rest] = ref.path
|
|
475
|
+
const aliasRef = getRefFromAlias(query, alias!)
|
|
476
|
+
if (!aliasRef) {
|
|
477
|
+
return
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (aliasRef.type === `queryRef`) {
|
|
481
|
+
return followRef(aliasRef.query, new PropRef(rest), collection)
|
|
482
|
+
} else {
|
|
483
|
+
// This is a reference to a collection
|
|
484
|
+
// we can't follow it further
|
|
485
|
+
// so the field must be on the collection itself
|
|
486
|
+
return { collection: aliasRef.collection, path: rest }
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|