@tanstack/db 0.0.14 → 0.0.15

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 (198) hide show
  1. package/dist/cjs/collection.cjs +117 -104
  2. package/dist/cjs/collection.cjs.map +1 -1
  3. package/dist/cjs/collection.d.cts +18 -21
  4. package/dist/cjs/index.cjs +35 -13
  5. package/dist/cjs/index.cjs.map +1 -1
  6. package/dist/cjs/index.d.cts +0 -1
  7. package/dist/cjs/query/builder/functions.cjs +107 -0
  8. package/dist/cjs/query/builder/functions.cjs.map +1 -0
  9. package/dist/cjs/query/builder/functions.d.cts +38 -0
  10. package/dist/cjs/query/builder/index.cjs +499 -0
  11. package/dist/cjs/query/builder/index.cjs.map +1 -0
  12. package/dist/cjs/query/builder/index.d.cts +324 -0
  13. package/dist/cjs/query/builder/ref-proxy.cjs +96 -0
  14. package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -0
  15. package/dist/cjs/query/builder/ref-proxy.d.cts +28 -0
  16. package/dist/cjs/query/builder/types.d.cts +80 -0
  17. package/dist/cjs/query/compiler/evaluators.cjs +261 -0
  18. package/dist/cjs/query/compiler/evaluators.cjs.map +1 -0
  19. package/dist/cjs/query/compiler/evaluators.d.cts +11 -0
  20. package/dist/cjs/query/compiler/group-by.cjs +271 -0
  21. package/dist/cjs/query/compiler/group-by.cjs.map +1 -0
  22. package/dist/cjs/query/compiler/group-by.d.cts +7 -0
  23. package/dist/cjs/query/compiler/index.cjs +181 -0
  24. package/dist/cjs/query/compiler/index.cjs.map +1 -0
  25. package/dist/cjs/query/compiler/index.d.cts +15 -0
  26. package/dist/cjs/query/compiler/joins.cjs +116 -0
  27. package/dist/cjs/query/compiler/joins.cjs.map +1 -0
  28. package/dist/cjs/query/compiler/joins.d.cts +11 -0
  29. package/dist/cjs/query/compiler/order-by.cjs +89 -0
  30. package/dist/cjs/query/compiler/order-by.cjs.map +1 -0
  31. package/dist/cjs/query/compiler/order-by.d.cts +9 -0
  32. package/dist/cjs/query/compiler/select.cjs +57 -0
  33. package/dist/cjs/query/compiler/select.cjs.map +1 -0
  34. package/dist/cjs/query/compiler/select.d.cts +15 -0
  35. package/dist/cjs/query/index.d.cts +6 -5
  36. package/dist/cjs/query/ir.cjs +57 -0
  37. package/dist/cjs/query/ir.cjs.map +1 -0
  38. package/dist/cjs/query/ir.d.cts +81 -0
  39. package/dist/cjs/query/live-query-collection.cjs +224 -0
  40. package/dist/cjs/query/live-query-collection.cjs.map +1 -0
  41. package/dist/cjs/query/live-query-collection.d.cts +124 -0
  42. package/dist/cjs/transactions.cjs +20 -13
  43. package/dist/cjs/transactions.cjs.map +1 -1
  44. package/dist/cjs/transactions.d.cts +10 -1
  45. package/dist/cjs/types.d.cts +13 -0
  46. package/dist/esm/collection.d.ts +18 -21
  47. package/dist/esm/collection.js +118 -105
  48. package/dist/esm/collection.js.map +1 -1
  49. package/dist/esm/index.d.ts +0 -1
  50. package/dist/esm/index.js +34 -12
  51. package/dist/esm/index.js.map +1 -1
  52. package/dist/esm/query/builder/functions.d.ts +38 -0
  53. package/dist/esm/query/builder/functions.js +107 -0
  54. package/dist/esm/query/builder/functions.js.map +1 -0
  55. package/dist/esm/query/builder/index.d.ts +324 -0
  56. package/dist/esm/query/builder/index.js +499 -0
  57. package/dist/esm/query/builder/index.js.map +1 -0
  58. package/dist/esm/query/builder/ref-proxy.d.ts +28 -0
  59. package/dist/esm/query/builder/ref-proxy.js +96 -0
  60. package/dist/esm/query/builder/ref-proxy.js.map +1 -0
  61. package/dist/esm/query/builder/types.d.ts +80 -0
  62. package/dist/esm/query/compiler/evaluators.d.ts +11 -0
  63. package/dist/esm/query/compiler/evaluators.js +261 -0
  64. package/dist/esm/query/compiler/evaluators.js.map +1 -0
  65. package/dist/esm/query/compiler/group-by.d.ts +7 -0
  66. package/dist/esm/query/compiler/group-by.js +271 -0
  67. package/dist/esm/query/compiler/group-by.js.map +1 -0
  68. package/dist/esm/query/compiler/index.d.ts +15 -0
  69. package/dist/esm/query/compiler/index.js +181 -0
  70. package/dist/esm/query/compiler/index.js.map +1 -0
  71. package/dist/esm/query/compiler/joins.d.ts +11 -0
  72. package/dist/esm/query/compiler/joins.js +116 -0
  73. package/dist/esm/query/compiler/joins.js.map +1 -0
  74. package/dist/esm/query/compiler/order-by.d.ts +9 -0
  75. package/dist/esm/query/compiler/order-by.js +89 -0
  76. package/dist/esm/query/compiler/order-by.js.map +1 -0
  77. package/dist/esm/query/compiler/select.d.ts +15 -0
  78. package/dist/esm/query/compiler/select.js +57 -0
  79. package/dist/esm/query/compiler/select.js.map +1 -0
  80. package/dist/esm/query/index.d.ts +6 -5
  81. package/dist/esm/query/ir.d.ts +81 -0
  82. package/dist/esm/query/ir.js +57 -0
  83. package/dist/esm/query/ir.js.map +1 -0
  84. package/dist/esm/query/live-query-collection.d.ts +124 -0
  85. package/dist/esm/query/live-query-collection.js +224 -0
  86. package/dist/esm/query/live-query-collection.js.map +1 -0
  87. package/dist/esm/transactions.d.ts +10 -1
  88. package/dist/esm/transactions.js +20 -13
  89. package/dist/esm/transactions.js.map +1 -1
  90. package/dist/esm/types.d.ts +13 -0
  91. package/package.json +3 -4
  92. package/src/collection.ts +152 -129
  93. package/src/index.ts +0 -1
  94. package/src/query/builder/functions.ts +267 -0
  95. package/src/query/builder/index.ts +648 -0
  96. package/src/query/builder/ref-proxy.ts +156 -0
  97. package/src/query/builder/types.ts +278 -0
  98. package/src/query/compiler/evaluators.ts +315 -0
  99. package/src/query/compiler/group-by.ts +428 -0
  100. package/src/query/compiler/index.ts +276 -0
  101. package/src/query/compiler/joins.ts +228 -0
  102. package/src/query/compiler/order-by.ts +139 -0
  103. package/src/query/compiler/select.ts +173 -0
  104. package/src/query/index.ts +64 -5
  105. package/src/query/ir.ts +128 -0
  106. package/src/query/live-query-collection.ts +509 -0
  107. package/src/transactions.ts +27 -16
  108. package/src/types.ts +15 -0
  109. package/dist/cjs/query/compiled-query.cjs +0 -160
  110. package/dist/cjs/query/compiled-query.cjs.map +0 -1
  111. package/dist/cjs/query/compiled-query.d.cts +0 -20
  112. package/dist/cjs/query/evaluators.cjs +0 -161
  113. package/dist/cjs/query/evaluators.cjs.map +0 -1
  114. package/dist/cjs/query/evaluators.d.cts +0 -14
  115. package/dist/cjs/query/extractors.cjs +0 -122
  116. package/dist/cjs/query/extractors.cjs.map +0 -1
  117. package/dist/cjs/query/extractors.d.cts +0 -22
  118. package/dist/cjs/query/functions.cjs +0 -152
  119. package/dist/cjs/query/functions.cjs.map +0 -1
  120. package/dist/cjs/query/functions.d.cts +0 -21
  121. package/dist/cjs/query/group-by.cjs +0 -88
  122. package/dist/cjs/query/group-by.cjs.map +0 -1
  123. package/dist/cjs/query/group-by.d.cts +0 -40
  124. package/dist/cjs/query/joins.cjs +0 -141
  125. package/dist/cjs/query/joins.cjs.map +0 -1
  126. package/dist/cjs/query/joins.d.cts +0 -14
  127. package/dist/cjs/query/order-by.cjs +0 -185
  128. package/dist/cjs/query/order-by.cjs.map +0 -1
  129. package/dist/cjs/query/order-by.d.cts +0 -3
  130. package/dist/cjs/query/pipeline-compiler.cjs +0 -89
  131. package/dist/cjs/query/pipeline-compiler.cjs.map +0 -1
  132. package/dist/cjs/query/pipeline-compiler.d.cts +0 -10
  133. package/dist/cjs/query/query-builder.cjs +0 -307
  134. package/dist/cjs/query/query-builder.cjs.map +0 -1
  135. package/dist/cjs/query/query-builder.d.cts +0 -225
  136. package/dist/cjs/query/schema.d.cts +0 -100
  137. package/dist/cjs/query/select.cjs +0 -130
  138. package/dist/cjs/query/select.cjs.map +0 -1
  139. package/dist/cjs/query/select.d.cts +0 -3
  140. package/dist/cjs/query/types.d.cts +0 -189
  141. package/dist/cjs/query/utils.cjs +0 -154
  142. package/dist/cjs/query/utils.cjs.map +0 -1
  143. package/dist/cjs/query/utils.d.cts +0 -37
  144. package/dist/cjs/utils.cjs +0 -17
  145. package/dist/cjs/utils.cjs.map +0 -1
  146. package/dist/cjs/utils.d.cts +0 -3
  147. package/dist/esm/query/compiled-query.d.ts +0 -20
  148. package/dist/esm/query/compiled-query.js +0 -160
  149. package/dist/esm/query/compiled-query.js.map +0 -1
  150. package/dist/esm/query/evaluators.d.ts +0 -14
  151. package/dist/esm/query/evaluators.js +0 -161
  152. package/dist/esm/query/evaluators.js.map +0 -1
  153. package/dist/esm/query/extractors.d.ts +0 -22
  154. package/dist/esm/query/extractors.js +0 -122
  155. package/dist/esm/query/extractors.js.map +0 -1
  156. package/dist/esm/query/functions.d.ts +0 -21
  157. package/dist/esm/query/functions.js +0 -152
  158. package/dist/esm/query/functions.js.map +0 -1
  159. package/dist/esm/query/group-by.d.ts +0 -40
  160. package/dist/esm/query/group-by.js +0 -88
  161. package/dist/esm/query/group-by.js.map +0 -1
  162. package/dist/esm/query/joins.d.ts +0 -14
  163. package/dist/esm/query/joins.js +0 -141
  164. package/dist/esm/query/joins.js.map +0 -1
  165. package/dist/esm/query/order-by.d.ts +0 -3
  166. package/dist/esm/query/order-by.js +0 -185
  167. package/dist/esm/query/order-by.js.map +0 -1
  168. package/dist/esm/query/pipeline-compiler.d.ts +0 -10
  169. package/dist/esm/query/pipeline-compiler.js +0 -89
  170. package/dist/esm/query/pipeline-compiler.js.map +0 -1
  171. package/dist/esm/query/query-builder.d.ts +0 -225
  172. package/dist/esm/query/query-builder.js +0 -307
  173. package/dist/esm/query/query-builder.js.map +0 -1
  174. package/dist/esm/query/schema.d.ts +0 -100
  175. package/dist/esm/query/select.d.ts +0 -3
  176. package/dist/esm/query/select.js +0 -130
  177. package/dist/esm/query/select.js.map +0 -1
  178. package/dist/esm/query/types.d.ts +0 -189
  179. package/dist/esm/query/utils.d.ts +0 -37
  180. package/dist/esm/query/utils.js +0 -154
  181. package/dist/esm/query/utils.js.map +0 -1
  182. package/dist/esm/utils.d.ts +0 -3
  183. package/dist/esm/utils.js +0 -17
  184. package/dist/esm/utils.js.map +0 -1
  185. package/src/query/compiled-query.ts +0 -234
  186. package/src/query/evaluators.ts +0 -250
  187. package/src/query/extractors.ts +0 -214
  188. package/src/query/functions.ts +0 -297
  189. package/src/query/group-by.ts +0 -139
  190. package/src/query/joins.ts +0 -260
  191. package/src/query/order-by.ts +0 -264
  192. package/src/query/pipeline-compiler.ts +0 -149
  193. package/src/query/query-builder.ts +0 -902
  194. package/src/query/schema.ts +0 -268
  195. package/src/query/select.ts +0 -208
  196. package/src/query/types.ts +0 -418
  197. package/src/query/utils.ts +0 -245
  198. package/src/utils.ts +0 -15
@@ -1,3 +0,0 @@
1
- export declare function getLockedObjects(): Set<string>;
2
- export declare function getGlobalVersion(): number;
3
- export declare function advanceGlobalVersion(): number;
package/dist/esm/utils.js DELETED
@@ -1,17 +0,0 @@
1
- function getLockedObjects() {
2
- return /* @__PURE__ */ new Set();
3
- }
4
- let globalVersion = 0;
5
- function getGlobalVersion() {
6
- return globalVersion;
7
- }
8
- function advanceGlobalVersion() {
9
- console.log(`==== advancing global version`, globalVersion + 1);
10
- return globalVersion++;
11
- }
12
- export {
13
- advanceGlobalVersion,
14
- getGlobalVersion,
15
- getLockedObjects
16
- };
17
- //# sourceMappingURL=utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["export function getLockedObjects(): Set<string> {\n // Stub implementation that returns an empty Set\n return new Set()\n}\n\nlet globalVersion = 0\n\nexport function getGlobalVersion(): number {\n return globalVersion\n}\n\nexport function advanceGlobalVersion(): number {\n console.log(`==== advancing global version`, globalVersion + 1)\n return globalVersion++\n}\n"],"names":[],"mappings":"AAAO,SAAS,mBAAgC;AAE9C,6BAAW,IAAI;AACjB;AAEA,IAAI,gBAAgB;AAEb,SAAS,mBAA2B;AAClC,SAAA;AACT;AAEO,SAAS,uBAA+B;AACrC,UAAA,IAAI,iCAAiC,gBAAgB,CAAC;AACvD,SAAA;AACT;"}
@@ -1,234 +0,0 @@
1
- import { D2, MultiSet, output } from "@electric-sql/d2mini"
2
- import { createCollection } from "../collection.js"
3
- import { compileQueryPipeline } from "./pipeline-compiler.js"
4
- import type { StandardSchemaV1 } from "@standard-schema/spec"
5
- import type { Collection } from "../collection.js"
6
- import type { ChangeMessage, ResolveType, SyncConfig } from "../types.js"
7
- import type {
8
- IStreamBuilder,
9
- MultiSetArray,
10
- RootStreamBuilder,
11
- } from "@electric-sql/d2mini"
12
- import type { QueryBuilder, ResultsFromContext } from "./query-builder.js"
13
- import type { Context, Schema } from "./types.js"
14
-
15
- export function compileQuery<TContext extends Context<Schema>>(
16
- queryBuilder: QueryBuilder<TContext>
17
- ) {
18
- return new CompiledQuery<
19
- ResultsFromContext<TContext> & { _key?: string | number }
20
- >(queryBuilder)
21
- }
22
-
23
- export class CompiledQuery<TResults extends object = Record<string, unknown>> {
24
- private graph: D2
25
- private inputs: Record<string, RootStreamBuilder<any>>
26
- private inputCollections: Record<string, Collection<any>>
27
- private resultCollection: Collection<TResults>
28
- public state: `compiled` | `running` | `stopped` = `compiled`
29
- private unsubscribeCallbacks: Array<() => void> = []
30
-
31
- constructor(queryBuilder: QueryBuilder<Context<Schema>>) {
32
- const query = queryBuilder._query
33
- const collections = query.collections
34
-
35
- if (!collections) {
36
- throw new Error(`No collections provided`)
37
- }
38
-
39
- this.inputCollections = collections
40
-
41
- const graph = new D2()
42
- const inputs = Object.fromEntries(
43
- Object.entries(collections).map(([key]) => [key, graph.newInput<any>()])
44
- )
45
-
46
- // Use TResults directly to ensure type compatibility
47
- const sync: SyncConfig<TResults>[`sync`] = ({
48
- begin,
49
- write,
50
- commit,
51
- collection,
52
- }) => {
53
- compileQueryPipeline<IStreamBuilder<[unknown, TResults]>>(
54
- query,
55
- inputs
56
- ).pipe(
57
- output((data) => {
58
- begin()
59
- data
60
- .getInner()
61
- .reduce((acc, [[key, value], multiplicity]) => {
62
- const changes = acc.get(key) || {
63
- deletes: 0,
64
- inserts: 0,
65
- value,
66
- }
67
- if (multiplicity < 0) {
68
- changes.deletes += Math.abs(multiplicity)
69
- } else if (multiplicity > 0) {
70
- changes.inserts += multiplicity
71
- changes.value = value
72
- }
73
- acc.set(key, changes)
74
- return acc
75
- }, new Map<unknown, { deletes: number; inserts: number; value: TResults }>())
76
- .forEach((changes, rawKey) => {
77
- const { deletes, inserts, value } = changes
78
- const valueWithKey = { ...value, _key: rawKey }
79
-
80
- // Simple singular insert.
81
- if (inserts && deletes === 0) {
82
- write({
83
- value: valueWithKey,
84
- type: `insert`,
85
- })
86
- } else if (
87
- // Insert & update(s) (updates are a delete & insert)
88
- inserts > deletes ||
89
- // Just update(s) but the item is already in the collection (so
90
- // was inserted previously).
91
- (inserts === deletes &&
92
- collection.has(valueWithKey._key as string | number))
93
- ) {
94
- write({
95
- value: valueWithKey,
96
- type: `update`,
97
- })
98
- // Only delete is left as an option
99
- } else if (deletes > 0) {
100
- write({
101
- value: valueWithKey,
102
- type: `delete`,
103
- })
104
- } else {
105
- throw new Error(
106
- `This should never happen ${JSON.stringify(changes)}`
107
- )
108
- }
109
- })
110
- commit()
111
- })
112
- )
113
- graph.finalize()
114
- }
115
-
116
- this.graph = graph
117
- this.inputs = inputs
118
-
119
- const compare = query.orderBy
120
- ? (
121
- val1: ResolveType<
122
- TResults,
123
- StandardSchemaV1,
124
- Record<string, unknown>
125
- >,
126
- val2: ResolveType<TResults, StandardSchemaV1, Record<string, unknown>>
127
- ): number => {
128
- // The query builder always adds an _orderByIndex property if the results are ordered
129
- const x = val1 as TResults & { _orderByIndex: number }
130
- const y = val2 as TResults & { _orderByIndex: number }
131
- if (x._orderByIndex < y._orderByIndex) {
132
- return -1
133
- } else if (x._orderByIndex > y._orderByIndex) {
134
- return 1
135
- } else {
136
- return 0
137
- }
138
- }
139
- : undefined
140
-
141
- this.resultCollection = createCollection<TResults>({
142
- getKey: (val: unknown) => {
143
- return (val as any)._key
144
- },
145
- gcTime: 0,
146
- startSync: true,
147
- compare,
148
- sync: {
149
- sync: sync as unknown as (params: {
150
- collection: Collection<
151
- ResolveType<TResults, never, Record<string, unknown>>,
152
- string | number,
153
- {}
154
- >
155
- begin: () => void
156
- write: (
157
- message: Omit<
158
- ChangeMessage<
159
- ResolveType<TResults, never, Record<string, unknown>>,
160
- string | number
161
- >,
162
- `key`
163
- >
164
- ) => void
165
- commit: () => void
166
- }) => void,
167
- },
168
- }) as unknown as Collection<TResults, string | number, {}>
169
- }
170
-
171
- get results() {
172
- return this.resultCollection
173
- }
174
-
175
- private sendChangesToInput(
176
- inputKey: string,
177
- changes: Array<ChangeMessage>,
178
- getKey: (item: ChangeMessage[`value`]) => any
179
- ) {
180
- const input = this.inputs[inputKey]!
181
- const multiSetArray: MultiSetArray<unknown> = []
182
- for (const change of changes) {
183
- const key = getKey(change.value)
184
- if (change.type === `insert`) {
185
- multiSetArray.push([[key, change.value], 1])
186
- } else if (change.type === `update`) {
187
- multiSetArray.push([[key, change.previousValue], -1])
188
- multiSetArray.push([[key, change.value], 1])
189
- } else {
190
- // change.type === `delete`
191
- multiSetArray.push([[key, change.value], -1])
192
- }
193
- }
194
- input.sendData(new MultiSet(multiSetArray))
195
- }
196
-
197
- private runGraph() {
198
- this.graph.run()
199
- }
200
-
201
- start() {
202
- if (this.state === `running`) {
203
- throw new Error(`Query is already running`)
204
- } else if (this.state === `stopped`) {
205
- throw new Error(`Query is stopped`)
206
- }
207
-
208
- // Subscribe to changes
209
- Object.entries(this.inputCollections).forEach(([key, collection]) => {
210
- const unsubscribe = collection.subscribeChanges(
211
- (changes) => {
212
- this.sendChangesToInput(key, changes, collection.config.getKey)
213
- this.runGraph()
214
- },
215
- { includeInitialState: true }
216
- )
217
-
218
- this.unsubscribeCallbacks.push(unsubscribe)
219
- })
220
-
221
- this.runGraph()
222
-
223
- this.state = `running`
224
- return () => {
225
- this.stop()
226
- }
227
- }
228
-
229
- stop() {
230
- this.unsubscribeCallbacks.forEach((unsubscribe) => unsubscribe())
231
- this.unsubscribeCallbacks = []
232
- this.state = `stopped`
233
- }
234
- }
@@ -1,250 +0,0 @@
1
- import { evaluateOperandOnNamespacedRow } from "./extractors.js"
2
- import { compareValues, convertLikeToRegex, isValueInArray } from "./utils.js"
3
- import type {
4
- Comparator,
5
- Condition,
6
- ConditionOperand,
7
- LogicalOperator,
8
- SimpleCondition,
9
- Where,
10
- WhereCallback,
11
- } from "./schema.js"
12
- import type { NamespacedRow } from "../types.js"
13
-
14
- /**
15
- * Evaluates a Where clause (which is always an array of conditions and/or callbacks) against a nested row structure
16
- */
17
- export function evaluateWhereOnNamespacedRow(
18
- namespacedRow: NamespacedRow,
19
- where: Where,
20
- mainTableAlias?: string,
21
- joinedTableAlias?: string
22
- ): boolean {
23
- // Where is always an array of conditions and/or callbacks
24
- // Evaluate all items and combine with AND logic
25
- return where.every((item) => {
26
- if (typeof item === `function`) {
27
- return (item as WhereCallback)(namespacedRow)
28
- } else {
29
- return evaluateConditionOnNamespacedRow(
30
- namespacedRow,
31
- item as Condition,
32
- mainTableAlias,
33
- joinedTableAlias
34
- )
35
- }
36
- })
37
- }
38
-
39
- /**
40
- * Evaluates a condition against a nested row structure
41
- */
42
- export function evaluateConditionOnNamespacedRow(
43
- namespacedRow: NamespacedRow,
44
- condition: Condition,
45
- mainTableAlias?: string,
46
- joinedTableAlias?: string
47
- ): boolean {
48
- // Handle simple conditions with exactly 3 elements
49
- if (condition.length === 3 && !Array.isArray(condition[0])) {
50
- const [left, comparator, right] = condition as SimpleCondition
51
- return evaluateSimpleConditionOnNamespacedRow(
52
- namespacedRow,
53
- left,
54
- comparator,
55
- right,
56
- mainTableAlias,
57
- joinedTableAlias
58
- )
59
- }
60
-
61
- // Handle flat composite conditions (multiple conditions in a single array)
62
- if (
63
- condition.length > 3 &&
64
- !Array.isArray(condition[0]) &&
65
- typeof condition[1] === `string` &&
66
- ![`and`, `or`].includes(condition[1] as string)
67
- ) {
68
- // Start with the first condition (first 3 elements)
69
- let result = evaluateSimpleConditionOnNamespacedRow(
70
- namespacedRow,
71
- condition[0],
72
- condition[1] as Comparator,
73
- condition[2],
74
- mainTableAlias,
75
- joinedTableAlias
76
- )
77
-
78
- // Process the rest in groups: logical operator, then 3 elements for each condition
79
- for (let i = 3; i < condition.length; i += 4) {
80
- const logicalOp = condition[i] as LogicalOperator
81
-
82
- // Make sure we have a complete condition to evaluate
83
- if (i + 3 <= condition.length) {
84
- const nextResult = evaluateSimpleConditionOnNamespacedRow(
85
- namespacedRow,
86
- condition[i + 1],
87
- condition[i + 2] as Comparator,
88
- condition[i + 3],
89
- mainTableAlias,
90
- joinedTableAlias
91
- )
92
-
93
- // Apply the logical operator
94
- if (logicalOp === `and`) {
95
- result = result && nextResult
96
- } else {
97
- // logicalOp === `or`
98
- result = result || nextResult
99
- }
100
- }
101
- }
102
-
103
- return result
104
- }
105
-
106
- // Handle nested composite conditions where the first element is an array
107
- if (condition.length > 0 && Array.isArray(condition[0])) {
108
- // Start with the first condition
109
- let result = evaluateConditionOnNamespacedRow(
110
- namespacedRow,
111
- condition[0] as Condition,
112
- mainTableAlias,
113
- joinedTableAlias
114
- )
115
-
116
- // Process the rest of the conditions and logical operators in pairs
117
- for (let i = 1; i < condition.length; i += 2) {
118
- if (i + 1 >= condition.length) break // Make sure we have a pair
119
-
120
- const operator = condition[i] as LogicalOperator
121
- const nextCondition = condition[i + 1] as Condition
122
-
123
- // Apply the logical operator
124
- if (operator === `and`) {
125
- result =
126
- result &&
127
- evaluateConditionOnNamespacedRow(
128
- namespacedRow,
129
- nextCondition,
130
- mainTableAlias,
131
- joinedTableAlias
132
- )
133
- } else {
134
- // logicalOp === `or`
135
- result =
136
- result ||
137
- evaluateConditionOnNamespacedRow(
138
- namespacedRow,
139
- nextCondition,
140
- mainTableAlias,
141
- joinedTableAlias
142
- )
143
- }
144
- }
145
-
146
- return result
147
- }
148
-
149
- // Fallback - this should not happen with valid conditions
150
- return true
151
- }
152
-
153
- /**
154
- * Evaluates a simple condition against a nested row structure
155
- */
156
- export function evaluateSimpleConditionOnNamespacedRow(
157
- namespacedRow: Record<string, unknown>,
158
- left: ConditionOperand,
159
- comparator: Comparator,
160
- right: ConditionOperand,
161
- mainTableAlias?: string,
162
- joinedTableAlias?: string
163
- ): boolean {
164
- const leftValue = evaluateOperandOnNamespacedRow(
165
- namespacedRow,
166
- left,
167
- mainTableAlias,
168
- joinedTableAlias
169
- )
170
-
171
- const rightValue = evaluateOperandOnNamespacedRow(
172
- namespacedRow,
173
- right,
174
- mainTableAlias,
175
- joinedTableAlias
176
- )
177
-
178
- // The rest of the function remains the same as evaluateSimpleCondition
179
- switch (comparator) {
180
- case `=`:
181
- return leftValue === rightValue
182
- case `!=`:
183
- return leftValue !== rightValue
184
- case `<`:
185
- return compareValues(leftValue, rightValue, `<`)
186
- case `<=`:
187
- return compareValues(leftValue, rightValue, `<=`)
188
- case `>`:
189
- return compareValues(leftValue, rightValue, `>`)
190
- case `>=`:
191
- return compareValues(leftValue, rightValue, `>=`)
192
- case `like`:
193
- case `not like`:
194
- if (typeof leftValue === `string` && typeof rightValue === `string`) {
195
- // Convert SQL LIKE pattern to proper regex pattern
196
- const pattern = convertLikeToRegex(rightValue)
197
- const matches = new RegExp(`^${pattern}$`, `i`).test(leftValue)
198
- return comparator === `like` ? matches : !matches
199
- }
200
- return comparator === `like` ? false : true
201
- case `in`:
202
- // If right value is not an array, we can't do an IN operation
203
- if (!Array.isArray(rightValue)) {
204
- return false
205
- }
206
-
207
- // For empty arrays, nothing is contained in them
208
- if (rightValue.length === 0) {
209
- return false
210
- }
211
-
212
- // Handle array-to-array comparison (check if any element in leftValue exists in rightValue)
213
- if (Array.isArray(leftValue)) {
214
- return leftValue.some((item) => isValueInArray(item, rightValue))
215
- }
216
-
217
- // Handle single value comparison
218
- return isValueInArray(leftValue, rightValue)
219
-
220
- case `not in`:
221
- // If right value is not an array, everything is "not in" it
222
- if (!Array.isArray(rightValue)) {
223
- return true
224
- }
225
-
226
- // For empty arrays, everything is "not in" them
227
- if (rightValue.length === 0) {
228
- return true
229
- }
230
-
231
- // Handle array-to-array comparison (check if no element in leftValue exists in rightValue)
232
- if (Array.isArray(leftValue)) {
233
- return !leftValue.some((item) => isValueInArray(item, rightValue))
234
- }
235
-
236
- // Handle single value comparison
237
- return !isValueInArray(leftValue, rightValue)
238
-
239
- case `is`:
240
- return leftValue === rightValue
241
- case `is not`:
242
- // Properly handle null/undefined checks
243
- if (rightValue === null) {
244
- return leftValue !== null && leftValue !== undefined
245
- }
246
- return leftValue !== rightValue
247
- default:
248
- return false
249
- }
250
- }