@tanstack/db 0.0.13 → 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 +19 -22
  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 +13 -4
  45. package/dist/cjs/types.d.cts +14 -1
  46. package/dist/esm/collection.d.ts +19 -22
  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 +13 -4
  88. package/dist/esm/transactions.js +20 -13
  89. package/dist/esm/transactions.js.map +1 -1
  90. package/dist/esm/types.d.ts +14 -1
  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 +34 -19
  108. package/src/types.ts +16 -1
  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
@@ -0,0 +1,315 @@
1
+ import type { BasicExpression, Func, Ref } 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: Ref): 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
+ }