@tanstack/db 0.0.14 → 0.0.16

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 (197) 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 +31 -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 +92 -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 +81 -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 +5 -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 +30 -12
  51. package/dist/esm/query/builder/functions.d.ts +38 -0
  52. package/dist/esm/query/builder/functions.js +107 -0
  53. package/dist/esm/query/builder/functions.js.map +1 -0
  54. package/dist/esm/query/builder/index.d.ts +324 -0
  55. package/dist/esm/query/builder/index.js +499 -0
  56. package/dist/esm/query/builder/index.js.map +1 -0
  57. package/dist/esm/query/builder/ref-proxy.d.ts +28 -0
  58. package/dist/esm/query/builder/ref-proxy.js +92 -0
  59. package/dist/esm/query/builder/ref-proxy.js.map +1 -0
  60. package/dist/esm/query/builder/types.d.ts +81 -0
  61. package/dist/esm/query/compiler/evaluators.d.ts +11 -0
  62. package/dist/esm/query/compiler/evaluators.js +261 -0
  63. package/dist/esm/query/compiler/evaluators.js.map +1 -0
  64. package/dist/esm/query/compiler/group-by.d.ts +7 -0
  65. package/dist/esm/query/compiler/group-by.js +271 -0
  66. package/dist/esm/query/compiler/group-by.js.map +1 -0
  67. package/dist/esm/query/compiler/index.d.ts +15 -0
  68. package/dist/esm/query/compiler/index.js +181 -0
  69. package/dist/esm/query/compiler/index.js.map +1 -0
  70. package/dist/esm/query/compiler/joins.d.ts +11 -0
  71. package/dist/esm/query/compiler/joins.js +116 -0
  72. package/dist/esm/query/compiler/joins.js.map +1 -0
  73. package/dist/esm/query/compiler/order-by.d.ts +9 -0
  74. package/dist/esm/query/compiler/order-by.js +89 -0
  75. package/dist/esm/query/compiler/order-by.js.map +1 -0
  76. package/dist/esm/query/compiler/select.d.ts +15 -0
  77. package/dist/esm/query/compiler/select.js +57 -0
  78. package/dist/esm/query/compiler/select.js.map +1 -0
  79. package/dist/esm/query/index.d.ts +5 -5
  80. package/dist/esm/query/ir.d.ts +81 -0
  81. package/dist/esm/query/ir.js +57 -0
  82. package/dist/esm/query/ir.js.map +1 -0
  83. package/dist/esm/query/live-query-collection.d.ts +124 -0
  84. package/dist/esm/query/live-query-collection.js +224 -0
  85. package/dist/esm/query/live-query-collection.js.map +1 -0
  86. package/dist/esm/transactions.d.ts +10 -1
  87. package/dist/esm/transactions.js +20 -13
  88. package/dist/esm/transactions.js.map +1 -1
  89. package/dist/esm/types.d.ts +13 -0
  90. package/package.json +3 -4
  91. package/src/collection.ts +152 -129
  92. package/src/index.ts +0 -1
  93. package/src/query/builder/functions.ts +267 -0
  94. package/src/query/builder/index.ts +648 -0
  95. package/src/query/builder/ref-proxy.ts +156 -0
  96. package/src/query/builder/types.ts +282 -0
  97. package/src/query/compiler/evaluators.ts +315 -0
  98. package/src/query/compiler/group-by.ts +428 -0
  99. package/src/query/compiler/index.ts +276 -0
  100. package/src/query/compiler/joins.ts +228 -0
  101. package/src/query/compiler/order-by.ts +139 -0
  102. package/src/query/compiler/select.ts +173 -0
  103. package/src/query/index.ts +54 -5
  104. package/src/query/ir.ts +128 -0
  105. package/src/query/live-query-collection.ts +512 -0
  106. package/src/transactions.ts +27 -16
  107. package/src/types.ts +15 -0
  108. package/dist/cjs/query/compiled-query.cjs +0 -160
  109. package/dist/cjs/query/compiled-query.cjs.map +0 -1
  110. package/dist/cjs/query/compiled-query.d.cts +0 -20
  111. package/dist/cjs/query/evaluators.cjs +0 -161
  112. package/dist/cjs/query/evaluators.cjs.map +0 -1
  113. package/dist/cjs/query/evaluators.d.cts +0 -14
  114. package/dist/cjs/query/extractors.cjs +0 -122
  115. package/dist/cjs/query/extractors.cjs.map +0 -1
  116. package/dist/cjs/query/extractors.d.cts +0 -22
  117. package/dist/cjs/query/functions.cjs +0 -152
  118. package/dist/cjs/query/functions.cjs.map +0 -1
  119. package/dist/cjs/query/functions.d.cts +0 -21
  120. package/dist/cjs/query/group-by.cjs +0 -88
  121. package/dist/cjs/query/group-by.cjs.map +0 -1
  122. package/dist/cjs/query/group-by.d.cts +0 -40
  123. package/dist/cjs/query/joins.cjs +0 -141
  124. package/dist/cjs/query/joins.cjs.map +0 -1
  125. package/dist/cjs/query/joins.d.cts +0 -14
  126. package/dist/cjs/query/order-by.cjs +0 -185
  127. package/dist/cjs/query/order-by.cjs.map +0 -1
  128. package/dist/cjs/query/order-by.d.cts +0 -3
  129. package/dist/cjs/query/pipeline-compiler.cjs +0 -89
  130. package/dist/cjs/query/pipeline-compiler.cjs.map +0 -1
  131. package/dist/cjs/query/pipeline-compiler.d.cts +0 -10
  132. package/dist/cjs/query/query-builder.cjs +0 -307
  133. package/dist/cjs/query/query-builder.cjs.map +0 -1
  134. package/dist/cjs/query/query-builder.d.cts +0 -225
  135. package/dist/cjs/query/schema.d.cts +0 -100
  136. package/dist/cjs/query/select.cjs +0 -130
  137. package/dist/cjs/query/select.cjs.map +0 -1
  138. package/dist/cjs/query/select.d.cts +0 -3
  139. package/dist/cjs/query/types.d.cts +0 -189
  140. package/dist/cjs/query/utils.cjs +0 -154
  141. package/dist/cjs/query/utils.cjs.map +0 -1
  142. package/dist/cjs/query/utils.d.cts +0 -37
  143. package/dist/cjs/utils.cjs +0 -17
  144. package/dist/cjs/utils.cjs.map +0 -1
  145. package/dist/cjs/utils.d.cts +0 -3
  146. package/dist/esm/query/compiled-query.d.ts +0 -20
  147. package/dist/esm/query/compiled-query.js +0 -160
  148. package/dist/esm/query/compiled-query.js.map +0 -1
  149. package/dist/esm/query/evaluators.d.ts +0 -14
  150. package/dist/esm/query/evaluators.js +0 -161
  151. package/dist/esm/query/evaluators.js.map +0 -1
  152. package/dist/esm/query/extractors.d.ts +0 -22
  153. package/dist/esm/query/extractors.js +0 -122
  154. package/dist/esm/query/extractors.js.map +0 -1
  155. package/dist/esm/query/functions.d.ts +0 -21
  156. package/dist/esm/query/functions.js +0 -152
  157. package/dist/esm/query/functions.js.map +0 -1
  158. package/dist/esm/query/group-by.d.ts +0 -40
  159. package/dist/esm/query/group-by.js +0 -88
  160. package/dist/esm/query/group-by.js.map +0 -1
  161. package/dist/esm/query/joins.d.ts +0 -14
  162. package/dist/esm/query/joins.js +0 -141
  163. package/dist/esm/query/joins.js.map +0 -1
  164. package/dist/esm/query/order-by.d.ts +0 -3
  165. package/dist/esm/query/order-by.js +0 -185
  166. package/dist/esm/query/order-by.js.map +0 -1
  167. package/dist/esm/query/pipeline-compiler.d.ts +0 -10
  168. package/dist/esm/query/pipeline-compiler.js +0 -89
  169. package/dist/esm/query/pipeline-compiler.js.map +0 -1
  170. package/dist/esm/query/query-builder.d.ts +0 -225
  171. package/dist/esm/query/query-builder.js +0 -307
  172. package/dist/esm/query/query-builder.js.map +0 -1
  173. package/dist/esm/query/schema.d.ts +0 -100
  174. package/dist/esm/query/select.d.ts +0 -3
  175. package/dist/esm/query/select.js +0 -130
  176. package/dist/esm/query/select.js.map +0 -1
  177. package/dist/esm/query/types.d.ts +0 -189
  178. package/dist/esm/query/utils.d.ts +0 -37
  179. package/dist/esm/query/utils.js +0 -154
  180. package/dist/esm/query/utils.js.map +0 -1
  181. package/dist/esm/utils.d.ts +0 -3
  182. package/dist/esm/utils.js +0 -17
  183. package/dist/esm/utils.js.map +0 -1
  184. package/src/query/compiled-query.ts +0 -234
  185. package/src/query/evaluators.ts +0 -250
  186. package/src/query/extractors.ts +0 -214
  187. package/src/query/functions.ts +0 -297
  188. package/src/query/group-by.ts +0 -139
  189. package/src/query/joins.ts +0 -260
  190. package/src/query/order-by.ts +0 -264
  191. package/src/query/pipeline-compiler.ts +0 -149
  192. package/src/query/query-builder.ts +0 -902
  193. package/src/query/schema.ts +0 -268
  194. package/src/query/select.ts +0 -208
  195. package/src/query/types.ts +0 -418
  196. package/src/query/utils.ts +0 -245
  197. package/src/utils.ts +0 -15
@@ -0,0 +1,315 @@
1
+ import type { BasicExpression, Func, PropRef } from "../ir.js"
2
+ import type { NamespacedRow } from "../../types.js"
3
+
4
+ /**
5
+ * Compiled expression evaluator function type
6
+ */
7
+ export type CompiledExpression = (namespacedRow: NamespacedRow) => any
8
+
9
+ /**
10
+ * Compiles an expression into an optimized evaluator function.
11
+ * This eliminates branching during evaluation by pre-compiling the expression structure.
12
+ */
13
+ export function compileExpression(expr: BasicExpression): CompiledExpression {
14
+ switch (expr.type) {
15
+ case `val`: {
16
+ // For constant values, return a function that just returns the value
17
+ const value = expr.value
18
+ return () => value
19
+ }
20
+
21
+ case `ref`: {
22
+ // For references, pre-compile the property path navigation
23
+ return compileRef(expr)
24
+ }
25
+
26
+ case `func`: {
27
+ // For functions, pre-compile the function and its arguments
28
+ return compileFunction(expr)
29
+ }
30
+
31
+ default:
32
+ throw new Error(`Unknown expression type: ${(expr as any).type}`)
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Compiles a reference expression into an optimized evaluator
38
+ */
39
+ function compileRef(ref: PropRef): CompiledExpression {
40
+ const [tableAlias, ...propertyPath] = ref.path
41
+
42
+ if (!tableAlias) {
43
+ throw new Error(`Reference path cannot be empty`)
44
+ }
45
+
46
+ // Pre-compile the property path navigation
47
+ if (propertyPath.length === 0) {
48
+ // Simple table reference
49
+ return (namespacedRow) => namespacedRow[tableAlias]
50
+ } else if (propertyPath.length === 1) {
51
+ // Single property access - most common case
52
+ const prop = propertyPath[0]!
53
+ return (namespacedRow) => {
54
+ const tableData = namespacedRow[tableAlias]
55
+ return tableData?.[prop]
56
+ }
57
+ } else {
58
+ // Multiple property navigation
59
+ return (namespacedRow) => {
60
+ const tableData = namespacedRow[tableAlias]
61
+ if (tableData === undefined) {
62
+ return undefined
63
+ }
64
+
65
+ let value: any = tableData
66
+ for (const prop of propertyPath) {
67
+ if (value == null) {
68
+ return value
69
+ }
70
+ value = value[prop]
71
+ }
72
+ return value
73
+ }
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Compiles a function expression into an optimized evaluator
79
+ */
80
+ function compileFunction(func: Func): CompiledExpression {
81
+ // Pre-compile all arguments
82
+ const compiledArgs = func.args.map(compileExpression)
83
+
84
+ switch (func.name) {
85
+ // Comparison operators
86
+ case `eq`: {
87
+ const argA = compiledArgs[0]!
88
+ const argB = compiledArgs[1]!
89
+ return (namespacedRow) => {
90
+ const a = argA(namespacedRow)
91
+ const b = argB(namespacedRow)
92
+ return a === b
93
+ }
94
+ }
95
+ case `gt`: {
96
+ const argA = compiledArgs[0]!
97
+ const argB = compiledArgs[1]!
98
+ return (namespacedRow) => {
99
+ const a = argA(namespacedRow)
100
+ const b = argB(namespacedRow)
101
+ return a > b
102
+ }
103
+ }
104
+ case `gte`: {
105
+ const argA = compiledArgs[0]!
106
+ const argB = compiledArgs[1]!
107
+ return (namespacedRow) => {
108
+ const a = argA(namespacedRow)
109
+ const b = argB(namespacedRow)
110
+ return a >= b
111
+ }
112
+ }
113
+ case `lt`: {
114
+ const argA = compiledArgs[0]!
115
+ const argB = compiledArgs[1]!
116
+ return (namespacedRow) => {
117
+ const a = argA(namespacedRow)
118
+ const b = argB(namespacedRow)
119
+ return a < b
120
+ }
121
+ }
122
+ case `lte`: {
123
+ const argA = compiledArgs[0]!
124
+ const argB = compiledArgs[1]!
125
+ return (namespacedRow) => {
126
+ const a = argA(namespacedRow)
127
+ const b = argB(namespacedRow)
128
+ return a <= b
129
+ }
130
+ }
131
+
132
+ // Boolean operators
133
+ case `and`:
134
+ return (namespacedRow) => {
135
+ for (const compiledArg of compiledArgs) {
136
+ if (!compiledArg(namespacedRow)) {
137
+ return false
138
+ }
139
+ }
140
+ return true
141
+ }
142
+ case `or`:
143
+ return (namespacedRow) => {
144
+ for (const compiledArg of compiledArgs) {
145
+ if (compiledArg(namespacedRow)) {
146
+ return true
147
+ }
148
+ }
149
+ return false
150
+ }
151
+ case `not`: {
152
+ const arg = compiledArgs[0]!
153
+ return (namespacedRow) => !arg(namespacedRow)
154
+ }
155
+
156
+ // Array operators
157
+ case `in`: {
158
+ const valueEvaluator = compiledArgs[0]!
159
+ const arrayEvaluator = compiledArgs[1]!
160
+ return (namespacedRow) => {
161
+ const value = valueEvaluator(namespacedRow)
162
+ const array = arrayEvaluator(namespacedRow)
163
+ if (!Array.isArray(array)) {
164
+ return false
165
+ }
166
+ return array.includes(value)
167
+ }
168
+ }
169
+
170
+ // String operators
171
+ case `like`: {
172
+ const valueEvaluator = compiledArgs[0]!
173
+ const patternEvaluator = compiledArgs[1]!
174
+ return (namespacedRow) => {
175
+ const value = valueEvaluator(namespacedRow)
176
+ const pattern = patternEvaluator(namespacedRow)
177
+ return evaluateLike(value, pattern, false)
178
+ }
179
+ }
180
+ case `ilike`: {
181
+ const valueEvaluator = compiledArgs[0]!
182
+ const patternEvaluator = compiledArgs[1]!
183
+ return (namespacedRow) => {
184
+ const value = valueEvaluator(namespacedRow)
185
+ const pattern = patternEvaluator(namespacedRow)
186
+ return evaluateLike(value, pattern, true)
187
+ }
188
+ }
189
+
190
+ // String functions
191
+ case `upper`: {
192
+ const arg = compiledArgs[0]!
193
+ return (namespacedRow) => {
194
+ const value = arg(namespacedRow)
195
+ return typeof value === `string` ? value.toUpperCase() : value
196
+ }
197
+ }
198
+ case `lower`: {
199
+ const arg = compiledArgs[0]!
200
+ return (namespacedRow) => {
201
+ const value = arg(namespacedRow)
202
+ return typeof value === `string` ? value.toLowerCase() : value
203
+ }
204
+ }
205
+ case `length`: {
206
+ const arg = compiledArgs[0]!
207
+ return (namespacedRow) => {
208
+ const value = arg(namespacedRow)
209
+ if (typeof value === `string`) {
210
+ return value.length
211
+ }
212
+ if (Array.isArray(value)) {
213
+ return value.length
214
+ }
215
+ return 0
216
+ }
217
+ }
218
+ case `concat`:
219
+ return (namespacedRow) => {
220
+ return compiledArgs
221
+ .map((evaluator) => {
222
+ const arg = evaluator(namespacedRow)
223
+ try {
224
+ return String(arg ?? ``)
225
+ } catch {
226
+ try {
227
+ return JSON.stringify(arg) || ``
228
+ } catch {
229
+ return `[object]`
230
+ }
231
+ }
232
+ })
233
+ .join(``)
234
+ }
235
+ case `coalesce`:
236
+ return (namespacedRow) => {
237
+ for (const evaluator of compiledArgs) {
238
+ const value = evaluator(namespacedRow)
239
+ if (value !== null && value !== undefined) {
240
+ return value
241
+ }
242
+ }
243
+ return null
244
+ }
245
+
246
+ // Math functions
247
+ case `add`: {
248
+ const argA = compiledArgs[0]!
249
+ const argB = compiledArgs[1]!
250
+ return (namespacedRow) => {
251
+ const a = argA(namespacedRow)
252
+ const b = argB(namespacedRow)
253
+ return (a ?? 0) + (b ?? 0)
254
+ }
255
+ }
256
+ case `subtract`: {
257
+ const argA = compiledArgs[0]!
258
+ const argB = compiledArgs[1]!
259
+ return (namespacedRow) => {
260
+ const a = argA(namespacedRow)
261
+ const b = argB(namespacedRow)
262
+ return (a ?? 0) - (b ?? 0)
263
+ }
264
+ }
265
+ case `multiply`: {
266
+ const argA = compiledArgs[0]!
267
+ const argB = compiledArgs[1]!
268
+ return (namespacedRow) => {
269
+ const a = argA(namespacedRow)
270
+ const b = argB(namespacedRow)
271
+ return (a ?? 0) * (b ?? 0)
272
+ }
273
+ }
274
+ case `divide`: {
275
+ const argA = compiledArgs[0]!
276
+ const argB = compiledArgs[1]!
277
+ return (namespacedRow) => {
278
+ const a = argA(namespacedRow)
279
+ const b = argB(namespacedRow)
280
+ const divisor = b ?? 0
281
+ return divisor !== 0 ? (a ?? 0) / divisor : null
282
+ }
283
+ }
284
+
285
+ default:
286
+ throw new Error(`Unknown function: ${func.name}`)
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Evaluates LIKE/ILIKE patterns
292
+ */
293
+ function evaluateLike(
294
+ value: any,
295
+ pattern: any,
296
+ caseInsensitive: boolean
297
+ ): boolean {
298
+ if (typeof value !== `string` || typeof pattern !== `string`) {
299
+ return false
300
+ }
301
+
302
+ const searchValue = caseInsensitive ? value.toLowerCase() : value
303
+ const searchPattern = caseInsensitive ? pattern.toLowerCase() : pattern
304
+
305
+ // Convert SQL LIKE pattern to regex
306
+ // First escape all regex special chars except % and _
307
+ let regexPattern = searchPattern.replace(/[.*+?^${}()|[\]\\]/g, `\\$&`)
308
+
309
+ // Then convert SQL wildcards to regex
310
+ regexPattern = regexPattern.replace(/%/g, `.*`) // % matches any sequence
311
+ regexPattern = regexPattern.replace(/_/g, `.`) // _ matches any single char
312
+
313
+ const regex = new RegExp(`^${regexPattern}$`)
314
+ return regex.test(searchValue)
315
+ }