@tanstack/db 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/cjs/collection.cjs +113 -94
  2. package/dist/cjs/collection.cjs.map +1 -1
  3. package/dist/cjs/collection.d.cts +38 -11
  4. package/dist/cjs/index.cjs +1 -0
  5. package/dist/cjs/index.cjs.map +1 -1
  6. package/dist/cjs/proxy.cjs +87 -248
  7. package/dist/cjs/proxy.cjs.map +1 -1
  8. package/dist/cjs/proxy.d.cts +5 -5
  9. package/dist/cjs/query/compiled-query.cjs +23 -14
  10. package/dist/cjs/query/compiled-query.cjs.map +1 -1
  11. package/dist/cjs/query/compiled-query.d.cts +3 -1
  12. package/dist/cjs/query/evaluators.cjs +20 -20
  13. package/dist/cjs/query/evaluators.cjs.map +1 -1
  14. package/dist/cjs/query/evaluators.d.cts +3 -2
  15. package/dist/cjs/query/extractors.cjs +20 -20
  16. package/dist/cjs/query/extractors.cjs.map +1 -1
  17. package/dist/cjs/query/extractors.d.cts +3 -3
  18. package/dist/cjs/query/group-by.cjs +12 -15
  19. package/dist/cjs/query/group-by.cjs.map +1 -1
  20. package/dist/cjs/query/group-by.d.cts +7 -7
  21. package/dist/cjs/query/joins.cjs +41 -55
  22. package/dist/cjs/query/joins.cjs.map +1 -1
  23. package/dist/cjs/query/joins.d.cts +3 -3
  24. package/dist/cjs/query/order-by.cjs +37 -84
  25. package/dist/cjs/query/order-by.cjs.map +1 -1
  26. package/dist/cjs/query/order-by.d.cts +2 -2
  27. package/dist/cjs/query/pipeline-compiler.cjs +13 -18
  28. package/dist/cjs/query/pipeline-compiler.cjs.map +1 -1
  29. package/dist/cjs/query/pipeline-compiler.d.cts +2 -1
  30. package/dist/cjs/query/query-builder.cjs +0 -12
  31. package/dist/cjs/query/query-builder.cjs.map +1 -1
  32. package/dist/cjs/query/query-builder.d.cts +4 -8
  33. package/dist/cjs/query/schema.d.cts +1 -6
  34. package/dist/cjs/query/select.cjs +35 -24
  35. package/dist/cjs/query/select.cjs.map +1 -1
  36. package/dist/cjs/query/select.d.cts +2 -2
  37. package/dist/cjs/query/types.d.cts +1 -0
  38. package/dist/cjs/transactions.cjs +17 -8
  39. package/dist/cjs/transactions.cjs.map +1 -1
  40. package/dist/cjs/types.d.cts +41 -7
  41. package/dist/esm/collection.d.ts +38 -11
  42. package/dist/esm/collection.js +113 -94
  43. package/dist/esm/collection.js.map +1 -1
  44. package/dist/esm/index.js +2 -1
  45. package/dist/esm/proxy.d.ts +5 -5
  46. package/dist/esm/proxy.js +87 -248
  47. package/dist/esm/proxy.js.map +1 -1
  48. package/dist/esm/query/compiled-query.d.ts +3 -1
  49. package/dist/esm/query/compiled-query.js +23 -14
  50. package/dist/esm/query/compiled-query.js.map +1 -1
  51. package/dist/esm/query/evaluators.d.ts +3 -2
  52. package/dist/esm/query/evaluators.js +21 -21
  53. package/dist/esm/query/evaluators.js.map +1 -1
  54. package/dist/esm/query/extractors.d.ts +3 -3
  55. package/dist/esm/query/extractors.js +20 -20
  56. package/dist/esm/query/extractors.js.map +1 -1
  57. package/dist/esm/query/group-by.d.ts +7 -7
  58. package/dist/esm/query/group-by.js +14 -17
  59. package/dist/esm/query/group-by.js.map +1 -1
  60. package/dist/esm/query/joins.d.ts +3 -3
  61. package/dist/esm/query/joins.js +42 -56
  62. package/dist/esm/query/joins.js.map +1 -1
  63. package/dist/esm/query/order-by.d.ts +2 -2
  64. package/dist/esm/query/order-by.js +39 -86
  65. package/dist/esm/query/order-by.js.map +1 -1
  66. package/dist/esm/query/pipeline-compiler.d.ts +2 -1
  67. package/dist/esm/query/pipeline-compiler.js +14 -19
  68. package/dist/esm/query/pipeline-compiler.js.map +1 -1
  69. package/dist/esm/query/query-builder.d.ts +4 -8
  70. package/dist/esm/query/query-builder.js +0 -12
  71. package/dist/esm/query/query-builder.js.map +1 -1
  72. package/dist/esm/query/schema.d.ts +1 -6
  73. package/dist/esm/query/select.d.ts +2 -2
  74. package/dist/esm/query/select.js +36 -25
  75. package/dist/esm/query/select.js.map +1 -1
  76. package/dist/esm/query/types.d.ts +1 -0
  77. package/dist/esm/transactions.js +17 -8
  78. package/dist/esm/transactions.js.map +1 -1
  79. package/dist/esm/types.d.ts +41 -7
  80. package/package.json +2 -2
  81. package/src/collection.ts +174 -121
  82. package/src/proxy.ts +141 -358
  83. package/src/query/compiled-query.ts +30 -15
  84. package/src/query/evaluators.ts +22 -21
  85. package/src/query/extractors.ts +24 -21
  86. package/src/query/group-by.ts +24 -22
  87. package/src/query/joins.ts +88 -75
  88. package/src/query/order-by.ts +56 -106
  89. package/src/query/pipeline-compiler.ts +34 -37
  90. package/src/query/query-builder.ts +9 -23
  91. package/src/query/schema.ts +1 -10
  92. package/src/query/select.ts +44 -32
  93. package/src/query/types.ts +1 -0
  94. package/src/transactions.ts +22 -13
  95. package/src/types.ts +48 -7
  96. package/dist/cjs/query/key-by.cjs +0 -43
  97. package/dist/cjs/query/key-by.cjs.map +0 -1
  98. package/dist/cjs/query/key-by.d.cts +0 -3
  99. package/dist/esm/query/key-by.d.ts +0 -3
  100. package/dist/esm/query/key-by.js +0 -43
  101. package/dist/esm/query/key-by.js.map +0 -1
  102. package/src/query/key-by.ts +0 -61
@@ -14,7 +14,9 @@ import type { Context, Schema } from "./types.js"
14
14
  export function compileQuery<TContext extends Context<Schema>>(
15
15
  queryBuilder: QueryBuilder<TContext>
16
16
  ) {
17
- return new CompiledQuery<ResultsFromContext<TContext>>(queryBuilder)
17
+ return new CompiledQuery<
18
+ ResultsFromContext<TContext> & { _key?: string | number }
19
+ >(queryBuilder)
18
20
  }
19
21
 
20
22
  export class CompiledQuery<TResults extends object = Record<string, unknown>> {
@@ -67,24 +69,21 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
67
69
  return acc
68
70
  }, new Map<unknown, { deletes: number; inserts: number; value: TResults }>())
69
71
  .forEach((changes, rawKey) => {
70
- const key = (rawKey as any).toString()
71
72
  const { deletes, inserts, value } = changes
73
+ const valueWithKey = { ...value, _key: rawKey }
72
74
  if (inserts && !deletes) {
73
75
  write({
74
- key,
75
- value: value,
76
+ value: valueWithKey,
76
77
  type: `insert`,
77
78
  })
78
79
  } else if (inserts >= deletes) {
79
80
  write({
80
- key,
81
- value: value,
81
+ value: valueWithKey,
82
82
  type: `update`,
83
83
  })
84
84
  } else if (deletes > 0) {
85
85
  write({
86
- key,
87
- value: value,
86
+ value: valueWithKey,
88
87
  type: `delete`,
89
88
  })
90
89
  }
@@ -100,6 +99,9 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
100
99
  this.inputs = inputs
101
100
  this.resultCollection = new Collection<TResults>({
102
101
  id: crypto.randomUUID(), // TODO: remove when we don't require any more
102
+ getId: (val) => {
103
+ return (val as any)._key
104
+ },
103
105
  sync: {
104
106
  sync,
105
107
  },
@@ -110,18 +112,23 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
110
112
  return this.resultCollection
111
113
  }
112
114
 
113
- private sendChangesToInput(inputKey: string, changes: Array<ChangeMessage>) {
115
+ private sendChangesToInput(
116
+ inputKey: string,
117
+ changes: Array<ChangeMessage>,
118
+ getId: (item: ChangeMessage[`value`]) => any
119
+ ) {
114
120
  const input = this.inputs[inputKey]!
115
121
  const multiSetArray: MultiSetArray<unknown> = []
116
122
  for (const change of changes) {
123
+ const key = getId(change.value)
117
124
  if (change.type === `insert`) {
118
- multiSetArray.push([change.value, 1])
125
+ multiSetArray.push([[key, change.value], 1])
119
126
  } else if (change.type === `update`) {
120
- multiSetArray.push([change.previousValue, -1])
121
- multiSetArray.push([change.value, 1])
127
+ multiSetArray.push([[key, change.previousValue], -1])
128
+ multiSetArray.push([[key, change.value], 1])
122
129
  } else {
123
130
  // change.type === `delete`
124
- multiSetArray.push([change.value, -1])
131
+ multiSetArray.push([[key, change.value], -1])
125
132
  }
126
133
  }
127
134
  input.sendData(this.version, new MultiSet(multiSetArray))
@@ -155,7 +162,11 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
155
162
 
156
163
  batch(() => {
157
164
  Object.entries(this.inputCollections).forEach(([key, collection]) => {
158
- this.sendChangesToInput(key, collection.currentStateAsChanges())
165
+ this.sendChangesToInput(
166
+ key,
167
+ collection.currentStateAsChanges(),
168
+ collection.config.getId
169
+ )
159
170
  })
160
171
  this.incrementVersion()
161
172
  this.sendFrontierToAllInputs()
@@ -166,7 +177,11 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
166
177
  fn: () => {
167
178
  batch(() => {
168
179
  Object.entries(this.inputCollections).forEach(([key, collection]) => {
169
- this.sendChangesToInput(key, collection.derivedChanges.state)
180
+ this.sendChangesToInput(
181
+ key,
182
+ collection.derivedChanges.state,
183
+ collection.config.getId
184
+ )
170
185
  })
171
186
  this.incrementVersion()
172
187
  this.sendFrontierToAllInputs()
@@ -1,4 +1,4 @@
1
- import { evaluateOperandOnNestedRow } from "./extractors.js"
1
+ import { evaluateOperandOnNamespacedRow } from "./extractors.js"
2
2
  import { compareValues, convertLikeToRegex, isValueInArray } from "./utils.js"
3
3
  import type {
4
4
  Comparator,
@@ -7,12 +7,13 @@ import type {
7
7
  LogicalOperator,
8
8
  SimpleCondition,
9
9
  } from "./schema.js"
10
+ import type { NamespacedRow } from "../types.js"
10
11
 
11
12
  /**
12
13
  * Evaluates a condition against a nested row structure
13
14
  */
14
- export function evaluateConditionOnNestedRow(
15
- nestedRow: Record<string, unknown>,
15
+ export function evaluateConditionOnNamespacedRow(
16
+ namespacedRow: NamespacedRow,
16
17
  condition: Condition,
17
18
  mainTableAlias?: string,
18
19
  joinedTableAlias?: string
@@ -20,8 +21,8 @@ export function evaluateConditionOnNestedRow(
20
21
  // Handle simple conditions with exactly 3 elements
21
22
  if (condition.length === 3 && !Array.isArray(condition[0])) {
22
23
  const [left, comparator, right] = condition as SimpleCondition
23
- return evaluateSimpleConditionOnNestedRow(
24
- nestedRow,
24
+ return evaluateSimpleConditionOnNamespacedRow(
25
+ namespacedRow,
25
26
  left,
26
27
  comparator,
27
28
  right,
@@ -38,8 +39,8 @@ export function evaluateConditionOnNestedRow(
38
39
  ![`and`, `or`].includes(condition[1] as string)
39
40
  ) {
40
41
  // Start with the first condition (first 3 elements)
41
- let result = evaluateSimpleConditionOnNestedRow(
42
- nestedRow,
42
+ let result = evaluateSimpleConditionOnNamespacedRow(
43
+ namespacedRow,
43
44
  condition[0],
44
45
  condition[1] as Comparator,
45
46
  condition[2],
@@ -53,8 +54,8 @@ export function evaluateConditionOnNestedRow(
53
54
 
54
55
  // Make sure we have a complete condition to evaluate
55
56
  if (i + 3 <= condition.length) {
56
- const nextResult = evaluateSimpleConditionOnNestedRow(
57
- nestedRow,
57
+ const nextResult = evaluateSimpleConditionOnNamespacedRow(
58
+ namespacedRow,
58
59
  condition[i + 1],
59
60
  condition[i + 2] as Comparator,
60
61
  condition[i + 3],
@@ -78,8 +79,8 @@ export function evaluateConditionOnNestedRow(
78
79
  // Handle nested composite conditions where the first element is an array
79
80
  if (condition.length > 0 && Array.isArray(condition[0])) {
80
81
  // Start with the first condition
81
- let result = evaluateConditionOnNestedRow(
82
- nestedRow,
82
+ let result = evaluateConditionOnNamespacedRow(
83
+ namespacedRow,
83
84
  condition[0] as Condition,
84
85
  mainTableAlias,
85
86
  joinedTableAlias
@@ -96,8 +97,8 @@ export function evaluateConditionOnNestedRow(
96
97
  if (operator === `and`) {
97
98
  result =
98
99
  result &&
99
- evaluateConditionOnNestedRow(
100
- nestedRow,
100
+ evaluateConditionOnNamespacedRow(
101
+ namespacedRow,
101
102
  nextCondition,
102
103
  mainTableAlias,
103
104
  joinedTableAlias
@@ -106,8 +107,8 @@ export function evaluateConditionOnNestedRow(
106
107
  // logicalOp === `or`
107
108
  result =
108
109
  result ||
109
- evaluateConditionOnNestedRow(
110
- nestedRow,
110
+ evaluateConditionOnNamespacedRow(
111
+ namespacedRow,
111
112
  nextCondition,
112
113
  mainTableAlias,
113
114
  joinedTableAlias
@@ -125,23 +126,23 @@ export function evaluateConditionOnNestedRow(
125
126
  /**
126
127
  * Evaluates a simple condition against a nested row structure
127
128
  */
128
- export function evaluateSimpleConditionOnNestedRow(
129
- nestedRow: Record<string, unknown>,
129
+ export function evaluateSimpleConditionOnNamespacedRow(
130
+ namespacedRow: Record<string, unknown>,
130
131
  left: ConditionOperand,
131
132
  comparator: Comparator,
132
133
  right: ConditionOperand,
133
134
  mainTableAlias?: string,
134
135
  joinedTableAlias?: string
135
136
  ): boolean {
136
- const leftValue = evaluateOperandOnNestedRow(
137
- nestedRow,
137
+ const leftValue = evaluateOperandOnNamespacedRow(
138
+ namespacedRow,
138
139
  left,
139
140
  mainTableAlias,
140
141
  joinedTableAlias
141
142
  )
142
143
 
143
- const rightValue = evaluateOperandOnNestedRow(
144
- nestedRow,
144
+ const rightValue = evaluateOperandOnNamespacedRow(
145
+ namespacedRow,
145
146
  right,
146
147
  mainTableAlias,
147
148
  joinedTableAlias
@@ -3,14 +3,14 @@ import type { AllowedFunctionName, ConditionOperand } from "./schema.js"
3
3
 
4
4
  /**
5
5
  * Extracts a value from a nested row structure
6
- * @param nestedRow The nested row structure
6
+ * @param namespacedRow The nested row structure
7
7
  * @param columnRef The column reference (may include table.column format)
8
8
  * @param mainTableAlias The main table alias to check first for columns without table reference
9
9
  * @param joinedTableAlias The joined table alias to check second for columns without table reference
10
10
  * @returns The extracted value or undefined if not found
11
11
  */
12
- export function extractValueFromNestedRow(
13
- nestedRow: Record<string, unknown>,
12
+ export function extractValueFromNamespacedRow(
13
+ namespacedRow: Record<string, unknown>,
14
14
  columnRef: string,
15
15
  mainTableAlias?: string,
16
16
  joinedTableAlias?: string
@@ -20,7 +20,7 @@ export function extractValueFromNestedRow(
20
20
  const [tableAlias, colName] = columnRef.split(`.`) as [string, string]
21
21
 
22
22
  // Get the table data
23
- const tableData = nestedRow[tableAlias] as
23
+ const tableData = namespacedRow[tableAlias] as
24
24
  | Record<string, unknown>
25
25
  | null
26
26
  | undefined
@@ -34,16 +34,19 @@ export function extractValueFromNestedRow(
34
34
  return value
35
35
  } else {
36
36
  // If no table is specified, first try to find in the main table if provided
37
- if (mainTableAlias && nestedRow[mainTableAlias]) {
38
- const mainTableData = nestedRow[mainTableAlias] as Record<string, unknown>
37
+ if (mainTableAlias && namespacedRow[mainTableAlias]) {
38
+ const mainTableData = namespacedRow[mainTableAlias] as Record<
39
+ string,
40
+ unknown
41
+ >
39
42
  if (typeof mainTableData === `object` && columnRef in mainTableData) {
40
43
  return mainTableData[columnRef]
41
44
  }
42
45
  }
43
46
 
44
47
  // Then try the joined table if provided
45
- if (joinedTableAlias && nestedRow[joinedTableAlias]) {
46
- const joinedTableData = nestedRow[joinedTableAlias] as Record<
48
+ if (joinedTableAlias && namespacedRow[joinedTableAlias]) {
49
+ const joinedTableData = namespacedRow[joinedTableAlias] as Record<
47
50
  string,
48
51
  unknown
49
52
  >
@@ -53,7 +56,7 @@ export function extractValueFromNestedRow(
53
56
  }
54
57
 
55
58
  // If not found in main or joined table, try to find the column in any table
56
- for (const [_tableAlias, tableData] of Object.entries(nestedRow)) {
59
+ for (const [_tableAlias, tableData] of Object.entries(namespacedRow)) {
57
60
  if (
58
61
  tableData &&
59
62
  typeof tableData === `object` &&
@@ -69,8 +72,8 @@ export function extractValueFromNestedRow(
69
72
  /**
70
73
  * Evaluates an operand against a nested row structure
71
74
  */
72
- export function evaluateOperandOnNestedRow(
73
- nestedRow: Record<string, unknown>,
75
+ export function evaluateOperandOnNamespacedRow(
76
+ namespacedRow: Record<string, unknown>,
74
77
  operand: ConditionOperand,
75
78
  mainTableAlias?: string,
76
79
  joinedTableAlias?: string
@@ -78,8 +81,8 @@ export function evaluateOperandOnNestedRow(
78
81
  // Handle column references
79
82
  if (typeof operand === `string` && operand.startsWith(`@`)) {
80
83
  const columnRef = operand.substring(1)
81
- return extractValueFromNestedRow(
82
- nestedRow,
84
+ return extractValueFromNamespacedRow(
85
+ namespacedRow,
83
86
  columnRef,
84
87
  mainTableAlias,
85
88
  joinedTableAlias
@@ -92,8 +95,8 @@ export function evaluateOperandOnNestedRow(
92
95
 
93
96
  if (typeof colRef === `string`) {
94
97
  // First try to extract from nested row structure
95
- const nestedValue = extractValueFromNestedRow(
96
- nestedRow,
98
+ const nestedValue = extractValueFromNamespacedRow(
99
+ namespacedRow,
97
100
  colRef,
98
101
  mainTableAlias,
99
102
  joinedTableAlias
@@ -101,8 +104,8 @@ export function evaluateOperandOnNestedRow(
101
104
 
102
105
  // If not found in nested structure, check if it's a direct property of the row
103
106
  // This is important for HAVING clauses that reference aggregated values
104
- if (nestedValue === undefined && colRef in nestedRow) {
105
- return nestedRow[colRef]
107
+ if (nestedValue === undefined && colRef in namespacedRow) {
108
+ return namespacedRow[colRef]
106
109
  }
107
110
 
108
111
  return nestedValue
@@ -121,15 +124,15 @@ export function evaluateOperandOnNestedRow(
121
124
  // If the arguments are a reference or another expression, evaluate them first
122
125
  const evaluatedArgs = Array.isArray(args)
123
126
  ? args.map((arg) =>
124
- evaluateOperandOnNestedRow(
125
- nestedRow,
127
+ evaluateOperandOnNamespacedRow(
128
+ namespacedRow,
126
129
  arg as ConditionOperand,
127
130
  mainTableAlias,
128
131
  joinedTableAlias
129
132
  )
130
133
  )
131
- : evaluateOperandOnNestedRow(
132
- nestedRow,
134
+ : evaluateOperandOnNamespacedRow(
135
+ namespacedRow,
133
136
  args as ConditionOperand,
134
137
  mainTableAlias,
135
138
  joinedTableAlias
@@ -1,11 +1,11 @@
1
- import { groupBy, groupByOperators, map } from "@electric-sql/d2ts"
1
+ import { groupBy, groupByOperators } from "@electric-sql/d2ts"
2
2
  import {
3
- evaluateOperandOnNestedRow,
4
- extractValueFromNestedRow,
3
+ evaluateOperandOnNamespacedRow,
4
+ extractValueFromNamespacedRow,
5
5
  } from "./extractors"
6
6
  import { isAggregateFunctionCall } from "./utils"
7
7
  import type { ConditionOperand, FunctionCall, Query } from "./schema"
8
- import type { IStreamBuilder } from "@electric-sql/d2ts"
8
+ import type { NamespacedAndKeyedStream } from "../types.js"
9
9
 
10
10
  const { sum, count, avg, min, max, median, mode } = groupByOperators
11
11
 
@@ -13,7 +13,7 @@ const { sum, count, avg, min, max, median, mode } = groupByOperators
13
13
  * Process the groupBy clause in a D2QL query
14
14
  */
15
15
  export function processGroupBy(
16
- pipeline: IStreamBuilder<Record<string, unknown>>,
16
+ pipeline: NamespacedAndKeyedStream,
17
17
  query: Query,
18
18
  mainTableAlias: string
19
19
  ) {
@@ -23,7 +23,10 @@ export function processGroupBy(
23
23
  : [query.groupBy]
24
24
 
25
25
  // Create a key extractor function for the groupBy operator
26
- const keyExtractor = (nestedRow: Record<string, unknown>) => {
26
+ const keyExtractor = ([_oldKey, namespacedRow]: [
27
+ string,
28
+ Record<string, unknown>,
29
+ ]) => {
27
30
  const key: Record<string, unknown> = {}
28
31
 
29
32
  // Extract each groupBy column value
@@ -34,8 +37,8 @@ export function processGroupBy(
34
37
  ? columnRef.split(`.`)[1]
35
38
  : columnRef
36
39
 
37
- key[columnName!] = extractValueFromNestedRow(
38
- nestedRow,
40
+ key[columnName!] = extractValueFromNamespacedRow(
41
+ namespacedRow,
39
42
  columnRef,
40
43
  mainTableAlias
41
44
  )
@@ -48,6 +51,10 @@ export function processGroupBy(
48
51
  // Create aggregate functions for any aggregated columns in the SELECT clause
49
52
  const aggregates: Record<string, any> = {}
50
53
 
54
+ if (!query.select) {
55
+ throw new Error(`SELECT clause is required for GROUP BY`)
56
+ }
57
+
51
58
  // Scan the SELECT clause for aggregate functions
52
59
  for (const item of query.select) {
53
60
  if (typeof item === `object`) {
@@ -73,15 +80,7 @@ export function processGroupBy(
73
80
 
74
81
  // Apply the groupBy operator if we have any aggregates
75
82
  if (Object.keys(aggregates).length > 0) {
76
- pipeline = pipeline.pipe(
77
- groupBy(keyExtractor, aggregates),
78
- // Convert KeyValue<string, ResultType> to Record<string, unknown>
79
- map(([_key, value]) => {
80
- // After groupBy, the value already contains both the key fields and aggregate results
81
- // We need to return it as is, not wrapped in a nested structure
82
- return value as Record<string, unknown>
83
- })
84
- )
83
+ pipeline = pipeline.pipe(groupBy(keyExtractor, aggregates))
85
84
  }
86
85
 
87
86
  return pipeline
@@ -96,17 +95,20 @@ export function getAggregateFunction(
96
95
  mainTableAlias: string
97
96
  ) {
98
97
  // Create a value extractor function for the column to aggregate
99
- const valueExtractor = (nestedRow: Record<string, unknown>) => {
98
+ const valueExtractor = ([_oldKey, namespacedRow]: [
99
+ string,
100
+ Record<string, unknown>,
101
+ ]) => {
100
102
  let value: unknown
101
103
  if (typeof columnRef === `string` && columnRef.startsWith(`@`)) {
102
- value = extractValueFromNestedRow(
103
- nestedRow,
104
+ value = extractValueFromNamespacedRow(
105
+ namespacedRow,
104
106
  columnRef.substring(1),
105
107
  mainTableAlias
106
108
  )
107
109
  } else {
108
- value = evaluateOperandOnNestedRow(
109
- nestedRow,
110
+ value = evaluateOperandOnNamespacedRow(
111
+ namespacedRow,
110
112
  columnRef as ConditionOperand,
111
113
  mainTableAlias
112
114
  )