@tanstack/db 0.5.33 → 0.6.0

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 (273) hide show
  1. package/dist/cjs/collection/change-events.cjs.map +1 -1
  2. package/dist/cjs/collection/change-events.d.cts +3 -2
  3. package/dist/cjs/collection/changes.cjs +13 -4
  4. package/dist/cjs/collection/changes.cjs.map +1 -1
  5. package/dist/cjs/collection/changes.d.cts +10 -1
  6. package/dist/cjs/collection/cleanup-queue.cjs +89 -0
  7. package/dist/cjs/collection/cleanup-queue.cjs.map +1 -0
  8. package/dist/cjs/collection/cleanup-queue.d.cts +30 -0
  9. package/dist/cjs/collection/events.cjs +14 -0
  10. package/dist/cjs/collection/events.cjs.map +1 -1
  11. package/dist/cjs/collection/events.d.cts +39 -1
  12. package/dist/cjs/collection/index.cjs +66 -28
  13. package/dist/cjs/collection/index.cjs.map +1 -1
  14. package/dist/cjs/collection/index.d.cts +49 -36
  15. package/dist/cjs/collection/indexes.cjs +211 -62
  16. package/dist/cjs/collection/indexes.cjs.map +1 -1
  17. package/dist/cjs/collection/indexes.d.cts +27 -17
  18. package/dist/cjs/collection/lifecycle.cjs +5 -22
  19. package/dist/cjs/collection/lifecycle.cjs.map +1 -1
  20. package/dist/cjs/collection/lifecycle.d.cts +0 -1
  21. package/dist/cjs/collection/mutations.cjs +18 -0
  22. package/dist/cjs/collection/mutations.cjs.map +1 -1
  23. package/dist/cjs/collection/mutations.d.cts +1 -0
  24. package/dist/cjs/collection/state.cjs +381 -53
  25. package/dist/cjs/collection/state.cjs.map +1 -1
  26. package/dist/cjs/collection/state.d.cts +65 -1
  27. package/dist/cjs/collection/subscription.cjs +6 -0
  28. package/dist/cjs/collection/subscription.cjs.map +1 -1
  29. package/dist/cjs/collection/subscription.d.cts +4 -0
  30. package/dist/cjs/collection/sync.cjs +108 -1
  31. package/dist/cjs/collection/sync.cjs.map +1 -1
  32. package/dist/cjs/collection/sync.d.cts +2 -0
  33. package/dist/cjs/collection/transaction-metadata.cjs +5 -0
  34. package/dist/cjs/collection/transaction-metadata.cjs.map +1 -0
  35. package/dist/cjs/collection/transaction-metadata.d.cts +1 -0
  36. package/dist/cjs/errors.cjs +8 -0
  37. package/dist/cjs/errors.cjs.map +1 -1
  38. package/dist/cjs/errors.d.cts +3 -0
  39. package/dist/cjs/index.cjs +22 -4
  40. package/dist/cjs/index.cjs.map +1 -1
  41. package/dist/cjs/index.d.cts +11 -3
  42. package/dist/cjs/indexes/auto-index.cjs +13 -6
  43. package/dist/cjs/indexes/auto-index.cjs.map +1 -1
  44. package/dist/cjs/indexes/base-index.cjs +0 -3
  45. package/dist/cjs/indexes/base-index.cjs.map +1 -1
  46. package/dist/cjs/indexes/base-index.d.cts +2 -6
  47. package/dist/cjs/indexes/basic-index.cjs +361 -0
  48. package/dist/cjs/indexes/basic-index.cjs.map +1 -0
  49. package/dist/cjs/indexes/basic-index.d.cts +102 -0
  50. package/dist/cjs/indexes/btree-index.cjs.map +1 -1
  51. package/dist/cjs/indexes/btree-index.d.cts +1 -1
  52. package/dist/cjs/indexes/index-options.d.cts +8 -9
  53. package/dist/cjs/indexes/index-registry.cjs +89 -0
  54. package/dist/cjs/indexes/index-registry.cjs.map +1 -0
  55. package/dist/cjs/indexes/index-registry.d.cts +61 -0
  56. package/dist/cjs/local-only.cjs +5 -0
  57. package/dist/cjs/local-only.cjs.map +1 -1
  58. package/dist/cjs/query/builder/functions.cjs +27 -11
  59. package/dist/cjs/query/builder/functions.cjs.map +1 -1
  60. package/dist/cjs/query/builder/functions.d.cts +25 -3
  61. package/dist/cjs/query/builder/index.cjs +200 -39
  62. package/dist/cjs/query/builder/index.cjs.map +1 -1
  63. package/dist/cjs/query/builder/index.d.cts +4 -3
  64. package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -1
  65. package/dist/cjs/query/builder/ref-proxy.d.cts +14 -3
  66. package/dist/cjs/query/builder/types.d.cts +84 -19
  67. package/dist/cjs/query/compiler/evaluators.cjs +51 -0
  68. package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
  69. package/dist/cjs/query/compiler/group-by.cjs +100 -28
  70. package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
  71. package/dist/cjs/query/compiler/group-by.d.cts +4 -2
  72. package/dist/cjs/query/compiler/index.cjs +283 -11
  73. package/dist/cjs/query/compiler/index.cjs.map +1 -1
  74. package/dist/cjs/query/compiler/index.d.cts +30 -2
  75. package/dist/cjs/query/compiler/order-by.cjs +29 -10
  76. package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
  77. package/dist/cjs/query/compiler/order-by.d.cts +1 -1
  78. package/dist/cjs/query/compiler/select.cjs +8 -0
  79. package/dist/cjs/query/compiler/select.cjs.map +1 -1
  80. package/dist/cjs/query/index.d.cts +2 -1
  81. package/dist/cjs/query/ir.cjs +18 -1
  82. package/dist/cjs/query/ir.cjs.map +1 -1
  83. package/dist/cjs/query/ir.d.cts +21 -1
  84. package/dist/cjs/query/live/collection-config-builder.cjs +501 -5
  85. package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
  86. package/dist/cjs/query/live/collection-config-builder.d.cts +7 -0
  87. package/dist/cjs/query/live/types.d.cts +3 -3
  88. package/dist/cjs/query/live/utils.cjs +43 -3
  89. package/dist/cjs/query/live/utils.cjs.map +1 -1
  90. package/dist/cjs/query/live/utils.d.cts +1 -0
  91. package/dist/cjs/query/live-query-collection.cjs.map +1 -1
  92. package/dist/cjs/query/live-query-collection.d.cts +9 -6
  93. package/dist/cjs/query/query-once.cjs.map +1 -1
  94. package/dist/cjs/query/query-once.d.cts +7 -5
  95. package/dist/cjs/query/subset-dedupe.cjs +9 -3
  96. package/dist/cjs/query/subset-dedupe.cjs.map +1 -1
  97. package/dist/cjs/types.d.cts +42 -8
  98. package/dist/cjs/utils/array-utils.cjs +27 -0
  99. package/dist/cjs/utils/array-utils.cjs.map +1 -0
  100. package/dist/cjs/utils/array-utils.d.cts +16 -0
  101. package/dist/cjs/utils/comparison.cjs +11 -0
  102. package/dist/cjs/utils/comparison.cjs.map +1 -1
  103. package/dist/cjs/utils/index-optimization.cjs +4 -0
  104. package/dist/cjs/utils/index-optimization.cjs.map +1 -1
  105. package/dist/cjs/utils.cjs +7 -9
  106. package/dist/cjs/utils.cjs.map +1 -1
  107. package/dist/cjs/utils.d.cts +6 -1
  108. package/dist/cjs/virtual-props.cjs +33 -0
  109. package/dist/cjs/virtual-props.cjs.map +1 -0
  110. package/dist/cjs/virtual-props.d.cts +196 -0
  111. package/dist/esm/collection/change-events.d.ts +3 -2
  112. package/dist/esm/collection/change-events.js.map +1 -1
  113. package/dist/esm/collection/changes.d.ts +10 -1
  114. package/dist/esm/collection/changes.js +13 -4
  115. package/dist/esm/collection/changes.js.map +1 -1
  116. package/dist/esm/collection/cleanup-queue.d.ts +30 -0
  117. package/dist/esm/collection/cleanup-queue.js +89 -0
  118. package/dist/esm/collection/cleanup-queue.js.map +1 -0
  119. package/dist/esm/collection/events.d.ts +39 -1
  120. package/dist/esm/collection/events.js +14 -0
  121. package/dist/esm/collection/events.js.map +1 -1
  122. package/dist/esm/collection/index.d.ts +49 -36
  123. package/dist/esm/collection/index.js +67 -29
  124. package/dist/esm/collection/index.js.map +1 -1
  125. package/dist/esm/collection/indexes.d.ts +27 -17
  126. package/dist/esm/collection/indexes.js +211 -62
  127. package/dist/esm/collection/indexes.js.map +1 -1
  128. package/dist/esm/collection/lifecycle.d.ts +0 -1
  129. package/dist/esm/collection/lifecycle.js +5 -22
  130. package/dist/esm/collection/lifecycle.js.map +1 -1
  131. package/dist/esm/collection/mutations.d.ts +1 -0
  132. package/dist/esm/collection/mutations.js +18 -0
  133. package/dist/esm/collection/mutations.js.map +1 -1
  134. package/dist/esm/collection/state.d.ts +65 -1
  135. package/dist/esm/collection/state.js +381 -53
  136. package/dist/esm/collection/state.js.map +1 -1
  137. package/dist/esm/collection/subscription.d.ts +4 -0
  138. package/dist/esm/collection/subscription.js +6 -0
  139. package/dist/esm/collection/subscription.js.map +1 -1
  140. package/dist/esm/collection/sync.d.ts +2 -0
  141. package/dist/esm/collection/sync.js +108 -1
  142. package/dist/esm/collection/sync.js.map +1 -1
  143. package/dist/esm/collection/transaction-metadata.d.ts +1 -0
  144. package/dist/esm/collection/transaction-metadata.js +5 -0
  145. package/dist/esm/collection/transaction-metadata.js.map +1 -0
  146. package/dist/esm/errors.d.ts +3 -0
  147. package/dist/esm/errors.js +8 -0
  148. package/dist/esm/errors.js.map +1 -1
  149. package/dist/esm/index.d.ts +11 -3
  150. package/dist/esm/index.js +25 -7
  151. package/dist/esm/index.js.map +1 -1
  152. package/dist/esm/indexes/auto-index.js +13 -6
  153. package/dist/esm/indexes/auto-index.js.map +1 -1
  154. package/dist/esm/indexes/base-index.d.ts +2 -6
  155. package/dist/esm/indexes/base-index.js +1 -4
  156. package/dist/esm/indexes/base-index.js.map +1 -1
  157. package/dist/esm/indexes/basic-index.d.ts +102 -0
  158. package/dist/esm/indexes/basic-index.js +361 -0
  159. package/dist/esm/indexes/basic-index.js.map +1 -0
  160. package/dist/esm/indexes/btree-index.d.ts +1 -1
  161. package/dist/esm/indexes/btree-index.js.map +1 -1
  162. package/dist/esm/indexes/index-options.d.ts +8 -9
  163. package/dist/esm/indexes/index-registry.d.ts +61 -0
  164. package/dist/esm/indexes/index-registry.js +89 -0
  165. package/dist/esm/indexes/index-registry.js.map +1 -0
  166. package/dist/esm/local-only.js +5 -0
  167. package/dist/esm/local-only.js.map +1 -1
  168. package/dist/esm/query/builder/functions.d.ts +25 -3
  169. package/dist/esm/query/builder/functions.js +27 -11
  170. package/dist/esm/query/builder/functions.js.map +1 -1
  171. package/dist/esm/query/builder/index.d.ts +4 -3
  172. package/dist/esm/query/builder/index.js +201 -40
  173. package/dist/esm/query/builder/index.js.map +1 -1
  174. package/dist/esm/query/builder/ref-proxy.d.ts +14 -3
  175. package/dist/esm/query/builder/ref-proxy.js.map +1 -1
  176. package/dist/esm/query/builder/types.d.ts +84 -19
  177. package/dist/esm/query/compiler/evaluators.js +51 -0
  178. package/dist/esm/query/compiler/evaluators.js.map +1 -1
  179. package/dist/esm/query/compiler/group-by.d.ts +4 -2
  180. package/dist/esm/query/compiler/group-by.js +101 -29
  181. package/dist/esm/query/compiler/group-by.js.map +1 -1
  182. package/dist/esm/query/compiler/index.d.ts +30 -2
  183. package/dist/esm/query/compiler/index.js +285 -13
  184. package/dist/esm/query/compiler/index.js.map +1 -1
  185. package/dist/esm/query/compiler/order-by.d.ts +1 -1
  186. package/dist/esm/query/compiler/order-by.js +30 -11
  187. package/dist/esm/query/compiler/order-by.js.map +1 -1
  188. package/dist/esm/query/compiler/select.js +8 -0
  189. package/dist/esm/query/compiler/select.js.map +1 -1
  190. package/dist/esm/query/index.d.ts +2 -1
  191. package/dist/esm/query/ir.d.ts +21 -1
  192. package/dist/esm/query/ir.js +18 -1
  193. package/dist/esm/query/ir.js.map +1 -1
  194. package/dist/esm/query/live/collection-config-builder.d.ts +7 -0
  195. package/dist/esm/query/live/collection-config-builder.js +503 -7
  196. package/dist/esm/query/live/collection-config-builder.js.map +1 -1
  197. package/dist/esm/query/live/types.d.ts +3 -3
  198. package/dist/esm/query/live/utils.d.ts +1 -0
  199. package/dist/esm/query/live/utils.js +43 -3
  200. package/dist/esm/query/live/utils.js.map +1 -1
  201. package/dist/esm/query/live-query-collection.d.ts +9 -6
  202. package/dist/esm/query/live-query-collection.js.map +1 -1
  203. package/dist/esm/query/query-once.d.ts +7 -5
  204. package/dist/esm/query/query-once.js.map +1 -1
  205. package/dist/esm/query/subset-dedupe.js +9 -3
  206. package/dist/esm/query/subset-dedupe.js.map +1 -1
  207. package/dist/esm/types.d.ts +42 -8
  208. package/dist/esm/utils/array-utils.d.ts +16 -0
  209. package/dist/esm/utils/array-utils.js +27 -0
  210. package/dist/esm/utils/array-utils.js.map +1 -0
  211. package/dist/esm/utils/comparison.js +11 -0
  212. package/dist/esm/utils/comparison.js.map +1 -1
  213. package/dist/esm/utils/index-optimization.js +4 -0
  214. package/dist/esm/utils/index-optimization.js.map +1 -1
  215. package/dist/esm/utils.d.ts +6 -1
  216. package/dist/esm/utils.js +7 -9
  217. package/dist/esm/utils.js.map +1 -1
  218. package/dist/esm/virtual-props.d.ts +196 -0
  219. package/dist/esm/virtual-props.js +33 -0
  220. package/dist/esm/virtual-props.js.map +1 -0
  221. package/package.json +2 -2
  222. package/skills/db-core/collection-setup/references/electric-adapter.md +1 -1
  223. package/src/collection/change-events.ts +13 -9
  224. package/src/collection/changes.ts +30 -7
  225. package/src/collection/cleanup-queue.ts +105 -0
  226. package/src/collection/events.ts +65 -0
  227. package/src/collection/index.ts +110 -45
  228. package/src/collection/indexes.ts +283 -76
  229. package/src/collection/lifecycle.ts +5 -26
  230. package/src/collection/mutations.ts +21 -0
  231. package/src/collection/state.ts +545 -71
  232. package/src/collection/subscription.ts +7 -0
  233. package/src/collection/sync.ts +137 -0
  234. package/src/collection/transaction-metadata.ts +1 -0
  235. package/src/errors.ts +9 -0
  236. package/src/index.ts +46 -3
  237. package/src/indexes/auto-index.ts +18 -8
  238. package/src/indexes/base-index.ts +2 -10
  239. package/src/indexes/basic-index.ts +507 -0
  240. package/src/indexes/btree-index.ts +1 -1
  241. package/src/indexes/index-options.ts +17 -37
  242. package/src/indexes/index-registry.ts +174 -0
  243. package/src/local-only.ts +7 -0
  244. package/src/query/builder/functions.ts +84 -7
  245. package/src/query/builder/index.ts +329 -9
  246. package/src/query/builder/ref-proxy.ts +22 -4
  247. package/src/query/builder/types.ts +257 -62
  248. package/src/query/compiler/evaluators.ts +57 -0
  249. package/src/query/compiler/group-by.ts +156 -35
  250. package/src/query/compiler/index.ts +445 -15
  251. package/src/query/compiler/order-by.ts +51 -12
  252. package/src/query/compiler/select.ts +9 -0
  253. package/src/query/index.ts +7 -0
  254. package/src/query/ir.ts +23 -2
  255. package/src/query/live/collection-config-builder.ts +809 -9
  256. package/src/query/live/types.ts +10 -4
  257. package/src/query/live/utils.ts +64 -3
  258. package/src/query/live-query-collection.ts +43 -18
  259. package/src/query/query-once.ts +31 -12
  260. package/src/query/subset-dedupe.ts +11 -7
  261. package/src/types.ts +49 -9
  262. package/src/utils/array-utils.ts +49 -0
  263. package/src/utils/comparison.ts +14 -0
  264. package/src/utils/index-optimization.ts +4 -0
  265. package/src/utils.ts +12 -9
  266. package/src/virtual-props.ts +282 -0
  267. package/dist/cjs/indexes/lazy-index.cjs +0 -190
  268. package/dist/cjs/indexes/lazy-index.cjs.map +0 -1
  269. package/dist/cjs/indexes/lazy-index.d.cts +0 -96
  270. package/dist/esm/indexes/lazy-index.d.ts +0 -96
  271. package/dist/esm/indexes/lazy-index.js +0 -190
  272. package/dist/esm/indexes/lazy-index.js.map +0 -1
  273. package/src/indexes/lazy-index.ts +0 -251
@@ -39,6 +39,8 @@ class CollectionSyncManager {
39
39
  committed: false,
40
40
  operations: [],
41
41
  deletedKeys: /* @__PURE__ */ new Set(),
42
+ rowMetadataWrites: /* @__PURE__ */ new Map(),
43
+ collectionMetadataWrites: /* @__PURE__ */ new Map(),
42
44
  immediate: options?.immediate
43
45
  });
44
46
  },
@@ -56,6 +58,9 @@ class CollectionSyncManager {
56
58
  } else {
57
59
  key = this.config.getKey(messageWithOptionalKey.value);
58
60
  }
61
+ if (this.state.pendingLocalChanges.has(key)) {
62
+ this.state.pendingLocalOrigins.add(key);
63
+ }
59
64
  let messageType = messageWithOptionalKey.type;
60
65
  if (messageWithOptionalKey.type === `insert`) {
61
66
  const insertingIntoExistingSynced = this.state.syncedData.has(key);
@@ -85,6 +90,23 @@ class CollectionSyncManager {
85
90
  pendingTransaction.operations.push(message);
86
91
  if (messageType === `delete`) {
87
92
  pendingTransaction.deletedKeys.add(key);
93
+ pendingTransaction.rowMetadataWrites.set(key, { type: `delete` });
94
+ } else if (messageType === `insert`) {
95
+ if (message.metadata !== void 0) {
96
+ pendingTransaction.rowMetadataWrites.set(key, {
97
+ type: `set`,
98
+ value: message.metadata
99
+ });
100
+ } else {
101
+ pendingTransaction.rowMetadataWrites.set(key, {
102
+ type: `delete`
103
+ });
104
+ }
105
+ } else if (message.metadata !== void 0) {
106
+ pendingTransaction.rowMetadataWrites.set(key, {
107
+ type: `set`,
108
+ value: message.metadata
109
+ });
88
110
  }
89
111
  },
90
112
  commit: () => {
@@ -111,12 +133,14 @@ class CollectionSyncManager {
111
133
  }
112
134
  pendingTransaction.operations = [];
113
135
  pendingTransaction.deletedKeys.clear();
136
+ pendingTransaction.rowMetadataWrites.clear();
114
137
  pendingTransaction.truncate = true;
115
138
  pendingTransaction.optimisticSnapshot = {
116
139
  upserts: new Map(this.state.optimisticUpserts),
117
140
  deletes: new Set(this.state.optimisticDeletes)
118
141
  };
119
- }
142
+ },
143
+ metadata: this.createSyncMetadataApi()
120
144
  })
121
145
  );
122
146
  this.syncCleanupFn = syncRes?.cleanup ?? null;
@@ -132,6 +156,89 @@ class CollectionSyncManager {
132
156
  throw error;
133
157
  }
134
158
  }
159
+ getActivePendingSyncTransaction() {
160
+ const pendingTransaction = this.state.pendingSyncedTransactions[this.state.pendingSyncedTransactions.length - 1];
161
+ if (!pendingTransaction) {
162
+ throw new NoPendingSyncTransactionWriteError();
163
+ }
164
+ if (pendingTransaction.committed) {
165
+ throw new SyncTransactionAlreadyCommittedWriteError();
166
+ }
167
+ return pendingTransaction;
168
+ }
169
+ createSyncMetadataApi() {
170
+ return {
171
+ row: {
172
+ get: (key) => {
173
+ const pendingTransaction = this.state.pendingSyncedTransactions[this.state.pendingSyncedTransactions.length - 1];
174
+ const pendingWrite = pendingTransaction?.rowMetadataWrites.get(key);
175
+ if (pendingWrite) {
176
+ return pendingWrite.type === `delete` ? void 0 : pendingWrite.value;
177
+ }
178
+ if (pendingTransaction?.truncate) {
179
+ return void 0;
180
+ }
181
+ return this.state.syncedMetadata.get(key);
182
+ },
183
+ set: (key, metadata) => {
184
+ const pendingTransaction = this.getActivePendingSyncTransaction();
185
+ pendingTransaction.rowMetadataWrites.set(key, {
186
+ type: `set`,
187
+ value: metadata
188
+ });
189
+ },
190
+ delete: (key) => {
191
+ const pendingTransaction = this.getActivePendingSyncTransaction();
192
+ pendingTransaction.rowMetadataWrites.set(key, {
193
+ type: `delete`
194
+ });
195
+ }
196
+ },
197
+ collection: {
198
+ get: (key) => {
199
+ const pendingTransaction = this.state.pendingSyncedTransactions[this.state.pendingSyncedTransactions.length - 1];
200
+ const pendingWrite = pendingTransaction?.collectionMetadataWrites.get(key);
201
+ if (pendingWrite) {
202
+ return pendingWrite.type === `delete` ? void 0 : pendingWrite.value;
203
+ }
204
+ return this.state.syncedCollectionMetadata.get(key);
205
+ },
206
+ set: (key, value) => {
207
+ const pendingTransaction = this.getActivePendingSyncTransaction();
208
+ pendingTransaction.collectionMetadataWrites.set(key, {
209
+ type: `set`,
210
+ value
211
+ });
212
+ },
213
+ delete: (key) => {
214
+ const pendingTransaction = this.getActivePendingSyncTransaction();
215
+ pendingTransaction.collectionMetadataWrites.set(key, {
216
+ type: `delete`
217
+ });
218
+ },
219
+ list: (prefix) => {
220
+ const merged = new Map(this.state.syncedCollectionMetadata);
221
+ const pendingTransaction = this.state.pendingSyncedTransactions[this.state.pendingSyncedTransactions.length - 1];
222
+ if (pendingTransaction) {
223
+ for (const [
224
+ key,
225
+ pendingWrite
226
+ ] of pendingTransaction.collectionMetadataWrites) {
227
+ if (pendingWrite.type === `delete`) {
228
+ merged.delete(key);
229
+ } else {
230
+ merged.set(key, pendingWrite.value);
231
+ }
232
+ }
233
+ }
234
+ return Array.from(merged.entries()).filter(([key]) => prefix ? key.startsWith(prefix) : true).map(([key, value]) => ({
235
+ key,
236
+ value
237
+ }));
238
+ }
239
+ }
240
+ };
241
+ }
135
242
  /**
136
243
  * Preload the collection data by starting sync if not already started
137
244
  * Multiple concurrent calls will share the same promise
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","sources":["../../../src/collection/sync.ts"],"sourcesContent":["import {\n CollectionConfigurationError,\n CollectionIsInErrorStateError,\n DuplicateKeySyncError,\n NoPendingSyncTransactionCommitError,\n NoPendingSyncTransactionWriteError,\n SyncCleanupError,\n SyncTransactionAlreadyCommittedError,\n SyncTransactionAlreadyCommittedWriteError,\n} from '../errors'\nimport { deepEquals } from '../utils'\nimport { LIVE_QUERY_INTERNAL } from '../query/live/internal.js'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type {\n ChangeMessageOrDeleteKeyMessage,\n CleanupFn,\n CollectionConfig,\n LoadSubsetOptions,\n OptimisticChangeMessage,\n SyncConfigRes,\n} from '../types'\nimport type { CollectionImpl } from './index.js'\nimport type { CollectionStateManager } from './state'\nimport type { CollectionLifecycleManager } from './lifecycle'\nimport type { CollectionEventsManager } from './events.js'\nimport type { LiveQueryCollectionUtils } from '../query/live/collection-config-builder.js'\n\nexport class CollectionSyncManager<\n TOutput extends object = Record<string, unknown>,\n TKey extends string | number = string | number,\n TSchema extends StandardSchemaV1 = StandardSchemaV1,\n TInput extends object = TOutput,\n> {\n private collection!: CollectionImpl<TOutput, TKey, any, TSchema, TInput>\n private state!: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n private lifecycle!: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n private _events!: CollectionEventsManager\n private config!: CollectionConfig<TOutput, TKey, TSchema>\n private id: string\n private syncMode: `eager` | `on-demand`\n\n public preloadPromise: Promise<void> | null = null\n public syncCleanupFn: (() => void) | null = null\n public syncLoadSubsetFn:\n | ((options: LoadSubsetOptions) => true | Promise<void>)\n | null = null\n public syncUnloadSubsetFn: ((options: LoadSubsetOptions) => void) | null =\n null\n\n private pendingLoadSubsetPromises: Set<Promise<void>> = new Set()\n\n /**\n * Creates a new CollectionSyncManager instance\n */\n constructor(config: CollectionConfig<TOutput, TKey, TSchema>, id: string) {\n this.config = config\n this.id = id\n this.syncMode = config.syncMode ?? `eager`\n }\n\n setDeps(deps: {\n collection: CollectionImpl<TOutput, TKey, any, TSchema, TInput>\n state: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n lifecycle: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n events: CollectionEventsManager\n }) {\n this.collection = deps.collection\n this.state = deps.state\n this.lifecycle = deps.lifecycle\n this._events = deps.events\n }\n\n /**\n * Start the sync process for this collection\n * This is called when the collection is first accessed or preloaded\n */\n public startSync(): void {\n if (\n this.lifecycle.status !== `idle` &&\n this.lifecycle.status !== `cleaned-up`\n ) {\n return // Already started or in progress\n }\n\n this.lifecycle.setStatus(`loading`)\n\n try {\n const syncRes = normalizeSyncFnResult(\n this.config.sync.sync({\n collection: this.collection,\n begin: (options?: { immediate?: boolean }) => {\n this.state.pendingSyncedTransactions.push({\n committed: false,\n operations: [],\n deletedKeys: new Set(),\n immediate: options?.immediate,\n })\n },\n write: (\n messageWithOptionalKey: ChangeMessageOrDeleteKeyMessage<\n TOutput,\n TKey\n >,\n ) => {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n if (!pendingTransaction) {\n throw new NoPendingSyncTransactionWriteError()\n }\n if (pendingTransaction.committed) {\n throw new SyncTransactionAlreadyCommittedWriteError()\n }\n\n let key: TKey | undefined = undefined\n if (`key` in messageWithOptionalKey) {\n key = messageWithOptionalKey.key\n } else {\n key = this.config.getKey(messageWithOptionalKey.value)\n }\n\n let messageType = messageWithOptionalKey.type\n\n // Check if an item with this key already exists when inserting\n if (messageWithOptionalKey.type === `insert`) {\n const insertingIntoExistingSynced = this.state.syncedData.has(key)\n const hasPendingDeleteForKey =\n pendingTransaction.deletedKeys.has(key)\n const isTruncateTransaction = pendingTransaction.truncate === true\n // Allow insert after truncate in the same transaction even if it existed in syncedData\n if (\n insertingIntoExistingSynced &&\n !hasPendingDeleteForKey &&\n !isTruncateTransaction\n ) {\n const existingValue = this.state.syncedData.get(key)\n const valuesEqual =\n existingValue !== undefined &&\n deepEquals(existingValue, messageWithOptionalKey.value)\n if (valuesEqual) {\n // The \"insert\" is an echo of a value we already have locally.\n // Treat it as an update so we preserve optimistic intent without\n // throwing a duplicate-key error during reconciliation.\n messageType = `update`\n } else {\n const utils = this.config\n .utils as Partial<LiveQueryCollectionUtils>\n const internal = utils[LIVE_QUERY_INTERNAL]\n throw new DuplicateKeySyncError(key, this.id, {\n hasCustomGetKey: internal?.hasCustomGetKey ?? false,\n hasJoins: internal?.hasJoins ?? false,\n hasDistinct: internal?.hasDistinct ?? false,\n })\n }\n }\n }\n\n const message = {\n ...messageWithOptionalKey,\n type: messageType,\n key,\n } as OptimisticChangeMessage<TOutput, TKey>\n pendingTransaction.operations.push(message)\n\n if (messageType === `delete`) {\n pendingTransaction.deletedKeys.add(key)\n }\n },\n commit: () => {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n if (!pendingTransaction) {\n throw new NoPendingSyncTransactionCommitError()\n }\n if (pendingTransaction.committed) {\n throw new SyncTransactionAlreadyCommittedError()\n }\n\n pendingTransaction.committed = true\n\n this.state.commitPendingTransactions()\n },\n markReady: () => {\n this.lifecycle.markReady()\n },\n truncate: () => {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n if (!pendingTransaction) {\n throw new NoPendingSyncTransactionWriteError()\n }\n if (pendingTransaction.committed) {\n throw new SyncTransactionAlreadyCommittedWriteError()\n }\n\n // Clear all operations from the current transaction\n pendingTransaction.operations = []\n pendingTransaction.deletedKeys.clear()\n\n // Mark the transaction as a truncate operation. During commit, this triggers:\n // - Delete events for all previously synced keys (excluding optimistic-deleted keys)\n // - Clearing of syncedData/syncedMetadata\n // - Subsequent synced ops applied on the fresh base\n // - Finally, optimistic mutations re-applied on top (single batch)\n pendingTransaction.truncate = true\n\n // Capture optimistic state NOW to preserve it even if transactions complete\n // before this truncate transaction is committed\n pendingTransaction.optimisticSnapshot = {\n upserts: new Map(this.state.optimisticUpserts),\n deletes: new Set(this.state.optimisticDeletes),\n }\n },\n }),\n )\n\n // Store cleanup function if provided\n this.syncCleanupFn = syncRes?.cleanup ?? null\n\n // Store loadSubset function if provided\n this.syncLoadSubsetFn = syncRes?.loadSubset ?? null\n\n // Store unloadSubset function if provided\n this.syncUnloadSubsetFn = syncRes?.unloadSubset ?? null\n\n // Validate: on-demand mode requires a loadSubset function\n if (this.syncMode === `on-demand` && !this.syncLoadSubsetFn) {\n throw new CollectionConfigurationError(\n `Collection \"${this.id}\" is configured with syncMode \"on-demand\" but the sync function did not return a loadSubset handler. ` +\n `Either provide a loadSubset handler or use syncMode \"eager\".`,\n )\n }\n } catch (error) {\n this.lifecycle.setStatus(`error`)\n throw error\n }\n }\n\n /**\n * Preload the collection data by starting sync if not already started\n * Multiple concurrent calls will share the same promise\n */\n public preload(): Promise<void> {\n if (this.preloadPromise) {\n return this.preloadPromise\n }\n\n // Warn when calling preload on an on-demand collection\n if (this.syncMode === `on-demand`) {\n console.warn(\n `${this.id ? `[${this.id}] ` : ``}Calling .preload() on a collection with syncMode \"on-demand\" is a no-op. ` +\n `In on-demand mode, data is only loaded when queries request it. ` +\n `Instead, create a live query and call .preload() on that to load the specific data you need. ` +\n `See https://tanstack.com/blog/tanstack-db-0.5-query-driven-sync for more details.`,\n )\n }\n\n this.preloadPromise = new Promise<void>((resolve, reject) => {\n if (this.lifecycle.status === `ready`) {\n resolve()\n return\n }\n\n if (this.lifecycle.status === `error`) {\n reject(new CollectionIsInErrorStateError())\n return\n }\n\n // Register callback BEFORE starting sync to avoid race condition\n this.lifecycle.onFirstReady(() => {\n resolve()\n })\n\n // Start sync if collection hasn't started yet or was cleaned up\n if (\n this.lifecycle.status === `idle` ||\n this.lifecycle.status === `cleaned-up`\n ) {\n try {\n this.startSync()\n } catch (error) {\n reject(error)\n return\n }\n }\n })\n\n return this.preloadPromise\n }\n\n /**\n * Gets whether the collection is currently loading more data\n */\n public get isLoadingSubset(): boolean {\n return this.pendingLoadSubsetPromises.size > 0\n }\n\n /**\n * Tracks a load promise for isLoadingSubset state.\n * @internal This is for internal coordination (e.g., live-query glue code), not for general use.\n */\n public trackLoadPromise(promise: Promise<void>): void {\n const loadingStarting = !this.isLoadingSubset\n this.pendingLoadSubsetPromises.add(promise)\n\n if (loadingStarting) {\n this._events.emit(`loadingSubset:change`, {\n type: `loadingSubset:change`,\n collection: this.collection,\n isLoadingSubset: true,\n previousIsLoadingSubset: false,\n loadingSubsetTransition: `start`,\n })\n }\n\n promise.finally(() => {\n const loadingEnding =\n this.pendingLoadSubsetPromises.size === 1 &&\n this.pendingLoadSubsetPromises.has(promise)\n this.pendingLoadSubsetPromises.delete(promise)\n\n if (loadingEnding) {\n this._events.emit(`loadingSubset:change`, {\n type: `loadingSubset:change`,\n collection: this.collection,\n isLoadingSubset: false,\n previousIsLoadingSubset: true,\n loadingSubsetTransition: `end`,\n })\n }\n })\n }\n\n /**\n * Requests the sync layer to load more data.\n * @param options Options to control what data is being loaded\n * @returns If data loading is asynchronous, this method returns a promise that resolves when the data is loaded.\n * Returns true if no sync function is configured, if syncMode is 'eager', or if there is no work to do.\n */\n public loadSubset(options: LoadSubsetOptions): Promise<void> | true {\n // Bypass loadSubset when syncMode is 'eager'\n if (this.syncMode === `eager`) {\n return true\n }\n\n if (this.syncLoadSubsetFn) {\n const result = this.syncLoadSubsetFn(options)\n // If the result is a promise, track it\n if (result instanceof Promise) {\n this.trackLoadPromise(result)\n return result\n }\n }\n\n return true\n }\n\n /**\n * Notifies the sync layer that a subset is no longer needed.\n * @param options Options that identify what data is being unloaded\n */\n public unloadSubset(options: LoadSubsetOptions): void {\n if (this.syncUnloadSubsetFn) {\n this.syncUnloadSubsetFn(options)\n }\n }\n\n public cleanup(): void {\n try {\n if (this.syncCleanupFn) {\n this.syncCleanupFn()\n this.syncCleanupFn = null\n }\n } catch (error) {\n // Re-throw in a microtask to surface the error after cleanup completes\n queueMicrotask(() => {\n if (error instanceof Error) {\n // Preserve the original error and stack trace\n const wrappedError = new SyncCleanupError(this.id, error)\n wrappedError.cause = error\n wrappedError.stack = error.stack\n throw wrappedError\n } else {\n throw new SyncCleanupError(this.id, error as Error | string)\n }\n })\n }\n this.preloadPromise = null\n }\n}\n\nfunction normalizeSyncFnResult(result: void | CleanupFn | SyncConfigRes) {\n if (typeof result === `function`) {\n return { cleanup: result }\n }\n\n if (typeof result === `object`) {\n return result\n }\n\n return undefined\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync.js","sources":["../../../src/collection/sync.ts"],"sourcesContent":["import {\n CollectionConfigurationError,\n CollectionIsInErrorStateError,\n DuplicateKeySyncError,\n NoPendingSyncTransactionCommitError,\n NoPendingSyncTransactionWriteError,\n SyncCleanupError,\n SyncTransactionAlreadyCommittedError,\n SyncTransactionAlreadyCommittedWriteError,\n} from '../errors'\nimport { deepEquals } from '../utils'\nimport { LIVE_QUERY_INTERNAL } from '../query/live/internal.js'\nimport type { StandardSchemaV1 } from '@standard-schema/spec'\nimport type {\n ChangeMessageOrDeleteKeyMessage,\n CleanupFn,\n CollectionConfig,\n LoadSubsetOptions,\n OptimisticChangeMessage,\n SyncConfigRes,\n SyncMetadataApi,\n} from '../types'\nimport type { CollectionImpl } from './index.js'\nimport type { CollectionStateManager } from './state'\nimport type { CollectionLifecycleManager } from './lifecycle'\nimport type { CollectionEventsManager } from './events.js'\nimport type { LiveQueryCollectionUtils } from '../query/live/collection-config-builder.js'\n\nexport class CollectionSyncManager<\n TOutput extends object = Record<string, unknown>,\n TKey extends string | number = string | number,\n TSchema extends StandardSchemaV1 = StandardSchemaV1,\n TInput extends object = TOutput,\n> {\n private collection!: CollectionImpl<TOutput, TKey, any, TSchema, TInput>\n private state!: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n private lifecycle!: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n private _events!: CollectionEventsManager\n private config!: CollectionConfig<TOutput, TKey, TSchema>\n private id: string\n private syncMode: `eager` | `on-demand`\n\n public preloadPromise: Promise<void> | null = null\n public syncCleanupFn: (() => void) | null = null\n public syncLoadSubsetFn:\n | ((options: LoadSubsetOptions) => true | Promise<void>)\n | null = null\n public syncUnloadSubsetFn: ((options: LoadSubsetOptions) => void) | null =\n null\n\n private pendingLoadSubsetPromises: Set<Promise<void>> = new Set()\n\n /**\n * Creates a new CollectionSyncManager instance\n */\n constructor(config: CollectionConfig<TOutput, TKey, TSchema>, id: string) {\n this.config = config\n this.id = id\n this.syncMode = config.syncMode ?? `eager`\n }\n\n setDeps(deps: {\n collection: CollectionImpl<TOutput, TKey, any, TSchema, TInput>\n state: CollectionStateManager<TOutput, TKey, TSchema, TInput>\n lifecycle: CollectionLifecycleManager<TOutput, TKey, TSchema, TInput>\n events: CollectionEventsManager\n }) {\n this.collection = deps.collection\n this.state = deps.state\n this.lifecycle = deps.lifecycle\n this._events = deps.events\n }\n\n /**\n * Start the sync process for this collection\n * This is called when the collection is first accessed or preloaded\n */\n public startSync(): void {\n if (\n this.lifecycle.status !== `idle` &&\n this.lifecycle.status !== `cleaned-up`\n ) {\n return // Already started or in progress\n }\n\n this.lifecycle.setStatus(`loading`)\n\n try {\n const syncRes = normalizeSyncFnResult(\n this.config.sync.sync({\n collection: this.collection,\n begin: (options?: { immediate?: boolean }) => {\n this.state.pendingSyncedTransactions.push({\n committed: false,\n operations: [],\n deletedKeys: new Set(),\n rowMetadataWrites: new Map(),\n collectionMetadataWrites: new Map(),\n immediate: options?.immediate,\n })\n },\n write: (\n messageWithOptionalKey: ChangeMessageOrDeleteKeyMessage<\n TOutput,\n TKey\n >,\n ) => {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n if (!pendingTransaction) {\n throw new NoPendingSyncTransactionWriteError()\n }\n if (pendingTransaction.committed) {\n throw new SyncTransactionAlreadyCommittedWriteError()\n }\n\n let key: TKey | undefined = undefined\n if (`key` in messageWithOptionalKey) {\n key = messageWithOptionalKey.key\n } else {\n key = this.config.getKey(messageWithOptionalKey.value)\n }\n\n if (this.state.pendingLocalChanges.has(key)) {\n this.state.pendingLocalOrigins.add(key)\n }\n\n let messageType = messageWithOptionalKey.type\n\n // Check if an item with this key already exists when inserting\n if (messageWithOptionalKey.type === `insert`) {\n const insertingIntoExistingSynced = this.state.syncedData.has(key)\n const hasPendingDeleteForKey =\n pendingTransaction.deletedKeys.has(key)\n const isTruncateTransaction = pendingTransaction.truncate === true\n // Allow insert after truncate in the same transaction even if it existed in syncedData\n if (\n insertingIntoExistingSynced &&\n !hasPendingDeleteForKey &&\n !isTruncateTransaction\n ) {\n const existingValue = this.state.syncedData.get(key)\n const valuesEqual =\n existingValue !== undefined &&\n deepEquals(existingValue, messageWithOptionalKey.value)\n if (valuesEqual) {\n // The \"insert\" is an echo of a value we already have locally.\n // Treat it as an update so we preserve optimistic intent without\n // throwing a duplicate-key error during reconciliation.\n messageType = `update`\n } else {\n const utils = this.config\n .utils as Partial<LiveQueryCollectionUtils>\n const internal = utils[LIVE_QUERY_INTERNAL]\n throw new DuplicateKeySyncError(key, this.id, {\n hasCustomGetKey: internal?.hasCustomGetKey ?? false,\n hasJoins: internal?.hasJoins ?? false,\n hasDistinct: internal?.hasDistinct ?? false,\n })\n }\n }\n }\n\n const message = {\n ...messageWithOptionalKey,\n type: messageType,\n key,\n } as OptimisticChangeMessage<TOutput, TKey>\n pendingTransaction.operations.push(message)\n\n if (messageType === `delete`) {\n pendingTransaction.deletedKeys.add(key)\n pendingTransaction.rowMetadataWrites.set(key, { type: `delete` })\n } else if (messageType === `insert`) {\n if (message.metadata !== undefined) {\n pendingTransaction.rowMetadataWrites.set(key, {\n type: `set`,\n value: message.metadata,\n })\n } else {\n pendingTransaction.rowMetadataWrites.set(key, {\n type: `delete`,\n })\n }\n } else if (message.metadata !== undefined) {\n pendingTransaction.rowMetadataWrites.set(key, {\n type: `set`,\n value: message.metadata,\n })\n }\n },\n commit: () => {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n if (!pendingTransaction) {\n throw new NoPendingSyncTransactionCommitError()\n }\n if (pendingTransaction.committed) {\n throw new SyncTransactionAlreadyCommittedError()\n }\n\n pendingTransaction.committed = true\n\n this.state.commitPendingTransactions()\n },\n markReady: () => {\n this.lifecycle.markReady()\n },\n truncate: () => {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n if (!pendingTransaction) {\n throw new NoPendingSyncTransactionWriteError()\n }\n if (pendingTransaction.committed) {\n throw new SyncTransactionAlreadyCommittedWriteError()\n }\n\n // Clear all operations from the current transaction\n pendingTransaction.operations = []\n pendingTransaction.deletedKeys.clear()\n pendingTransaction.rowMetadataWrites.clear()\n // Intentionally preserve collectionMetadataWrites across truncate.\n // Collection-scoped metadata (for example persisted resume/reset\n // state) can be staged before truncate and should commit atomically\n // with the truncate transaction.\n\n // Mark the transaction as a truncate operation. During commit, this triggers:\n // - Delete events for all previously synced keys (excluding optimistic-deleted keys)\n // - Clearing of syncedData/syncedMetadata\n // - Subsequent synced ops applied on the fresh base\n // - Finally, optimistic mutations re-applied on top (single batch)\n pendingTransaction.truncate = true\n\n // Capture optimistic state NOW to preserve it even if transactions complete\n // before this truncate transaction is committed\n pendingTransaction.optimisticSnapshot = {\n upserts: new Map(this.state.optimisticUpserts),\n deletes: new Set(this.state.optimisticDeletes),\n }\n },\n metadata: this.createSyncMetadataApi(),\n }),\n )\n\n // Store cleanup function if provided\n this.syncCleanupFn = syncRes?.cleanup ?? null\n\n // Store loadSubset function if provided\n this.syncLoadSubsetFn = syncRes?.loadSubset ?? null\n\n // Store unloadSubset function if provided\n this.syncUnloadSubsetFn = syncRes?.unloadSubset ?? null\n\n // Validate: on-demand mode requires a loadSubset function\n if (this.syncMode === `on-demand` && !this.syncLoadSubsetFn) {\n throw new CollectionConfigurationError(\n `Collection \"${this.id}\" is configured with syncMode \"on-demand\" but the sync function did not return a loadSubset handler. ` +\n `Either provide a loadSubset handler or use syncMode \"eager\".`,\n )\n }\n } catch (error) {\n this.lifecycle.setStatus(`error`)\n throw error\n }\n }\n\n private getActivePendingSyncTransaction() {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n\n if (!pendingTransaction) {\n throw new NoPendingSyncTransactionWriteError()\n }\n if (pendingTransaction.committed) {\n throw new SyncTransactionAlreadyCommittedWriteError()\n }\n\n return pendingTransaction\n }\n\n private createSyncMetadataApi(): SyncMetadataApi<TKey> {\n return {\n row: {\n get: (key) => {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n const pendingWrite = pendingTransaction?.rowMetadataWrites.get(key)\n if (pendingWrite) {\n return pendingWrite.type === `delete`\n ? undefined\n : pendingWrite.value\n }\n if (pendingTransaction?.truncate) {\n return undefined\n }\n return this.state.syncedMetadata.get(key)\n },\n set: (key, metadata) => {\n const pendingTransaction = this.getActivePendingSyncTransaction()\n pendingTransaction.rowMetadataWrites.set(key, {\n type: `set`,\n value: metadata,\n })\n },\n delete: (key) => {\n const pendingTransaction = this.getActivePendingSyncTransaction()\n pendingTransaction.rowMetadataWrites.set(key, {\n type: `delete`,\n })\n },\n },\n collection: {\n get: (key) => {\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n const pendingWrite =\n pendingTransaction?.collectionMetadataWrites.get(key)\n if (pendingWrite) {\n return pendingWrite.type === `delete`\n ? undefined\n : pendingWrite.value\n }\n return this.state.syncedCollectionMetadata.get(key)\n },\n set: (key, value) => {\n const pendingTransaction = this.getActivePendingSyncTransaction()\n pendingTransaction.collectionMetadataWrites.set(key, {\n type: `set`,\n value,\n })\n },\n delete: (key) => {\n const pendingTransaction = this.getActivePendingSyncTransaction()\n pendingTransaction.collectionMetadataWrites.set(key, {\n type: `delete`,\n })\n },\n list: (prefix) => {\n const merged = new Map(this.state.syncedCollectionMetadata)\n const pendingTransaction =\n this.state.pendingSyncedTransactions[\n this.state.pendingSyncedTransactions.length - 1\n ]\n if (pendingTransaction) {\n for (const [\n key,\n pendingWrite,\n ] of pendingTransaction.collectionMetadataWrites) {\n if (pendingWrite.type === `delete`) {\n merged.delete(key)\n } else {\n merged.set(key, pendingWrite.value)\n }\n }\n }\n\n return Array.from(merged.entries())\n .filter(([key]) => (prefix ? key.startsWith(prefix) : true))\n .map(([key, value]) => ({\n key,\n value,\n }))\n },\n },\n }\n }\n\n /**\n * Preload the collection data by starting sync if not already started\n * Multiple concurrent calls will share the same promise\n */\n public preload(): Promise<void> {\n if (this.preloadPromise) {\n return this.preloadPromise\n }\n\n // Warn when calling preload on an on-demand collection\n if (this.syncMode === `on-demand`) {\n console.warn(\n `${this.id ? `[${this.id}] ` : ``}Calling .preload() on a collection with syncMode \"on-demand\" is a no-op. ` +\n `In on-demand mode, data is only loaded when queries request it. ` +\n `Instead, create a live query and call .preload() on that to load the specific data you need. ` +\n `See https://tanstack.com/blog/tanstack-db-0.5-query-driven-sync for more details.`,\n )\n }\n\n this.preloadPromise = new Promise<void>((resolve, reject) => {\n if (this.lifecycle.status === `ready`) {\n resolve()\n return\n }\n\n if (this.lifecycle.status === `error`) {\n reject(new CollectionIsInErrorStateError())\n return\n }\n\n // Register callback BEFORE starting sync to avoid race condition\n this.lifecycle.onFirstReady(() => {\n resolve()\n })\n\n // Start sync if collection hasn't started yet or was cleaned up\n if (\n this.lifecycle.status === `idle` ||\n this.lifecycle.status === `cleaned-up`\n ) {\n try {\n this.startSync()\n } catch (error) {\n reject(error)\n return\n }\n }\n })\n\n return this.preloadPromise\n }\n\n /**\n * Gets whether the collection is currently loading more data\n */\n public get isLoadingSubset(): boolean {\n return this.pendingLoadSubsetPromises.size > 0\n }\n\n /**\n * Tracks a load promise for isLoadingSubset state.\n * @internal This is for internal coordination (e.g., live-query glue code), not for general use.\n */\n public trackLoadPromise(promise: Promise<void>): void {\n const loadingStarting = !this.isLoadingSubset\n this.pendingLoadSubsetPromises.add(promise)\n\n if (loadingStarting) {\n this._events.emit(`loadingSubset:change`, {\n type: `loadingSubset:change`,\n collection: this.collection,\n isLoadingSubset: true,\n previousIsLoadingSubset: false,\n loadingSubsetTransition: `start`,\n })\n }\n\n promise.finally(() => {\n const loadingEnding =\n this.pendingLoadSubsetPromises.size === 1 &&\n this.pendingLoadSubsetPromises.has(promise)\n this.pendingLoadSubsetPromises.delete(promise)\n\n if (loadingEnding) {\n this._events.emit(`loadingSubset:change`, {\n type: `loadingSubset:change`,\n collection: this.collection,\n isLoadingSubset: false,\n previousIsLoadingSubset: true,\n loadingSubsetTransition: `end`,\n })\n }\n })\n }\n\n /**\n * Requests the sync layer to load more data.\n * @param options Options to control what data is being loaded\n * @returns If data loading is asynchronous, this method returns a promise that resolves when the data is loaded.\n * Returns true if no sync function is configured, if syncMode is 'eager', or if there is no work to do.\n */\n public loadSubset(options: LoadSubsetOptions): Promise<void> | true {\n // Bypass loadSubset when syncMode is 'eager'\n if (this.syncMode === `eager`) {\n return true\n }\n\n if (this.syncLoadSubsetFn) {\n const result = this.syncLoadSubsetFn(options)\n // If the result is a promise, track it\n if (result instanceof Promise) {\n this.trackLoadPromise(result)\n return result\n }\n }\n\n return true\n }\n\n /**\n * Notifies the sync layer that a subset is no longer needed.\n * @param options Options that identify what data is being unloaded\n */\n public unloadSubset(options: LoadSubsetOptions): void {\n if (this.syncUnloadSubsetFn) {\n this.syncUnloadSubsetFn(options)\n }\n }\n\n public cleanup(): void {\n try {\n if (this.syncCleanupFn) {\n this.syncCleanupFn()\n this.syncCleanupFn = null\n }\n } catch (error) {\n // Re-throw in a microtask to surface the error after cleanup completes\n queueMicrotask(() => {\n if (error instanceof Error) {\n // Preserve the original error and stack trace\n const wrappedError = new SyncCleanupError(this.id, error)\n wrappedError.cause = error\n wrappedError.stack = error.stack\n throw wrappedError\n } else {\n throw new SyncCleanupError(this.id, error as Error | string)\n }\n })\n }\n this.preloadPromise = null\n }\n}\n\nfunction normalizeSyncFnResult(result: void | CleanupFn | SyncConfigRes) {\n if (typeof result === `function`) {\n return { cleanup: result }\n }\n\n if (typeof result === `object`) {\n return result\n }\n\n return undefined\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const DIRECT_TRANSACTION_METADATA_KEY = "__tanstack_db_direct";
@@ -0,0 +1,5 @@
1
+ const DIRECT_TRANSACTION_METADATA_KEY = `__tanstack_db_direct`;
2
+ export {
3
+ DIRECT_TRANSACTION_METADATA_KEY
4
+ };
5
+ //# sourceMappingURL=transaction-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-metadata.js","sources":["../../../src/collection/transaction-metadata.ts"],"sourcesContent":["export const DIRECT_TRANSACTION_METADATA_KEY = `__tanstack_db_direct`\n"],"names":[],"mappings":"AAAO,MAAM,kCAAkC;"}
@@ -160,6 +160,9 @@ export declare class DistinctRequiresSelectError extends QueryCompilationError {
160
160
  export declare class FnSelectWithGroupByError extends QueryCompilationError {
161
161
  constructor();
162
162
  }
163
+ export declare class UnsupportedRootScalarSelectError extends QueryCompilationError {
164
+ constructor();
165
+ }
163
166
  export declare class HavingRequiresGroupByError extends QueryCompilationError {
164
167
  constructor();
165
168
  }
@@ -345,6 +345,13 @@ class FnSelectWithGroupByError extends QueryCompilationError {
345
345
  );
346
346
  }
347
347
  }
348
+ class UnsupportedRootScalarSelectError extends QueryCompilationError {
349
+ constructor() {
350
+ super(
351
+ `Top-level scalar select() is not supported by createLiveQueryCollection() or queryOnce(). Return an object from .select(), or use the scalar query inside toArray(...) or concat(toArray(...)).`
352
+ );
353
+ }
354
+ }
348
355
  class HavingRequiresGroupByError extends QueryCompilationError {
349
356
  constructor() {
350
357
  super(`HAVING clause requires GROUP BY clause`);
@@ -651,6 +658,7 @@ export {
651
658
  UnsupportedFromTypeError,
652
659
  UnsupportedJoinSourceTypeError,
653
660
  UnsupportedJoinTypeError,
661
+ UnsupportedRootScalarSelectError,
654
662
  UpdateKeyNotFoundError,
655
663
  WhereClauseConversionError
656
664
  };
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sources":["../../src/errors.ts"],"sourcesContent":["// Root error class for all TanStack DB errors\nexport class TanStackDBError extends Error {\n constructor(message: string) {\n super(message)\n this.name = `TanStackDBError`\n }\n}\n\n// Base error classes\nexport class NonRetriableError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `NonRetriableError`\n }\n}\n\n// Schema validation error (exported from index for backward compatibility)\nexport class SchemaValidationError extends TanStackDBError {\n type: `insert` | `update`\n issues: ReadonlyArray<{\n message: string\n path?: ReadonlyArray<string | number | symbol>\n }>\n\n constructor(\n type: `insert` | `update`,\n issues: ReadonlyArray<{\n message: string\n path?: ReadonlyArray<string | number | symbol>\n }>,\n message?: string,\n ) {\n const defaultMessage = `${type === `insert` ? `Insert` : `Update`} validation failed: ${issues\n .map((issue) => `\\n- ${issue.message} - path: ${issue.path}`)\n .join(``)}`\n\n super(message || defaultMessage)\n this.name = `SchemaValidationError`\n this.type = type\n this.issues = issues\n }\n}\n\n// Module Instance Errors\nexport class DuplicateDbInstanceError extends TanStackDBError {\n constructor() {\n super(\n `Multiple instances of @tanstack/db detected!\\n\\n` +\n `This causes transaction context to be lost because each instance maintains ` +\n `its own transaction stack.\\n\\n` +\n `Common causes:\\n` +\n `1. Different versions of @tanstack/db installed\\n` +\n `2. Incompatible peer dependency versions in packages\\n` +\n `3. Module resolution issues in bundler configuration\\n\\n` +\n `To fix:\\n` +\n `1. Check installed versions: npm list @tanstack/db (or pnpm/yarn list)\\n` +\n `2. Force a single version using package manager overrides:\\n` +\n ` - npm: \"overrides\" in package.json\\n` +\n ` - pnpm: \"pnpm.overrides\" in package.json\\n` +\n ` - yarn: \"resolutions\" in package.json\\n` +\n `3. Clear node_modules and lockfile, then reinstall\\n\\n` +\n `To temporarily disable this check (not recommended):\\n` +\n `Set environment variable: TANSTACK_DB_DISABLE_DUP_CHECK=1\\n\\n` +\n `See: https://tanstack.com/db/latest/docs/troubleshooting#duplicate-instances`,\n )\n this.name = `DuplicateDbInstanceError`\n }\n}\n\n// Collection Configuration Errors\nexport class CollectionConfigurationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionConfigurationError`\n }\n}\n\nexport class CollectionRequiresConfigError extends CollectionConfigurationError {\n constructor() {\n super(`Collection requires a config`)\n }\n}\n\nexport class CollectionRequiresSyncConfigError extends CollectionConfigurationError {\n constructor() {\n super(`Collection requires a sync config`)\n }\n}\n\nexport class InvalidSchemaError extends CollectionConfigurationError {\n constructor() {\n super(`Schema must implement the standard-schema interface`)\n }\n}\n\nexport class SchemaMustBeSynchronousError extends CollectionConfigurationError {\n constructor() {\n super(`Schema validation must be synchronous`)\n }\n}\n\n// Collection State Errors\nexport class CollectionStateError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionStateError`\n }\n}\n\nexport class CollectionInErrorStateError extends CollectionStateError {\n constructor(operation: string, collectionId: string) {\n super(\n `Cannot perform ${operation} on collection \"${collectionId}\" - collection is in error state. Try calling cleanup() and restarting the collection.`,\n )\n }\n}\n\nexport class InvalidCollectionStatusTransitionError extends CollectionStateError {\n constructor(from: string, to: string, collectionId: string) {\n super(\n `Invalid collection status transition from \"${from}\" to \"${to}\" for collection \"${collectionId}\"`,\n )\n }\n}\n\nexport class CollectionIsInErrorStateError extends CollectionStateError {\n constructor() {\n super(`Collection is in error state`)\n }\n}\n\nexport class NegativeActiveSubscribersError extends CollectionStateError {\n constructor() {\n super(`Active subscribers count is negative - this should never happen`)\n }\n}\n\n// Collection Operation Errors\nexport class CollectionOperationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionOperationError`\n }\n}\n\nexport class UndefinedKeyError extends CollectionOperationError {\n constructor(item: any) {\n super(\n `An object was created without a defined key: ${JSON.stringify(item)}`,\n )\n }\n}\n\nexport class InvalidKeyError extends CollectionOperationError {\n constructor(key: unknown, item: unknown) {\n const keyType = key === null ? `null` : typeof key\n super(\n `getKey returned an invalid key type. Expected string or number, but got ${keyType}: ${JSON.stringify(key)}. Item: ${JSON.stringify(item)}`,\n )\n }\n}\n\nexport class DuplicateKeyError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `Cannot insert document with ID \"${key}\" because it already exists in the collection`,\n )\n }\n}\n\nexport class DuplicateKeySyncError extends CollectionOperationError {\n constructor(\n key: string | number,\n collectionId: string,\n options?: {\n hasCustomGetKey?: boolean\n hasJoins?: boolean\n hasDistinct?: boolean\n },\n ) {\n const baseMessage = `Cannot insert document with key \"${key}\" from sync because it already exists in the collection \"${collectionId}\"`\n\n // Provide enhanced guidance when custom getKey is used with distinct\n if (options?.hasCustomGetKey && options.hasDistinct) {\n super(\n `${baseMessage}. ` +\n `This collection uses a custom getKey with .distinct(). ` +\n `The .distinct() operator deduplicates by the ENTIRE selected object (standard SQL behavior), ` +\n `but your custom getKey extracts only a subset of fields. This causes multiple distinct rows ` +\n `(with different values in non-key fields) to receive the same key. ` +\n `To fix this, either: (1) ensure your SELECT only includes fields that uniquely identify each row, ` +\n `(2) use .groupBy() with min()/max() aggregates to select one value per group, or ` +\n `(3) remove the custom getKey to use the default key behavior.`,\n )\n } else if (options?.hasCustomGetKey && options.hasJoins) {\n // Provide enhanced guidance when custom getKey is used with joins\n super(\n `${baseMessage}. ` +\n `This collection uses a custom getKey with joined queries. ` +\n `Joined queries can produce multiple rows with the same key when relationships are not 1:1. ` +\n `Consider: (1) using a composite key in your getKey function (e.g., \\`\\${item.key1}-\\${item.key2}\\`), ` +\n `(2) ensuring your join produces unique rows per key, or (3) removing the custom getKey ` +\n `to use the default composite key behavior.`,\n )\n } else {\n super(baseMessage)\n }\n }\n}\n\nexport class MissingUpdateArgumentError extends CollectionOperationError {\n constructor() {\n super(`The first argument to update is missing`)\n }\n}\n\nexport class NoKeysPassedToUpdateError extends CollectionOperationError {\n constructor() {\n super(`No keys were passed to update`)\n }\n}\n\nexport class UpdateKeyNotFoundError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `The key \"${key}\" was passed to update but an object for this key was not found in the collection`,\n )\n }\n}\n\nexport class KeyUpdateNotAllowedError extends CollectionOperationError {\n constructor(originalKey: string | number, newKey: string | number) {\n super(\n `Updating the key of an item is not allowed. Original key: \"${originalKey}\", Attempted new key: \"${newKey}\". Please delete the old item and create a new one if a key change is necessary.`,\n )\n }\n}\n\nexport class NoKeysPassedToDeleteError extends CollectionOperationError {\n constructor() {\n super(`No keys were passed to delete`)\n }\n}\n\nexport class DeleteKeyNotFoundError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `Collection.delete was called with key '${key}' but there is no item in the collection with this key`,\n )\n }\n}\n\n// Collection Handler Errors\nexport class MissingHandlerError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `MissingHandlerError`\n }\n}\n\nexport class MissingInsertHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.insert called directly (not within an explicit transaction) but no 'onInsert' handler is configured.`,\n )\n }\n}\n\nexport class MissingUpdateHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.update called directly (not within an explicit transaction) but no 'onUpdate' handler is configured.`,\n )\n }\n}\n\nexport class MissingDeleteHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.delete called directly (not within an explicit transaction) but no 'onDelete' handler is configured.`,\n )\n }\n}\n\n// Transaction Errors\nexport class TransactionError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `TransactionError`\n }\n}\n\nexport class MissingMutationFunctionError extends TransactionError {\n constructor() {\n super(`mutationFn is required when creating a transaction`)\n }\n}\n\nexport class OnMutateMustBeSynchronousError extends TransactionError {\n constructor() {\n super(\n `onMutate must be synchronous and cannot return a promise. Remove async/await or returned promises from onMutate.`,\n )\n this.name = `OnMutateMustBeSynchronousError`\n }\n}\n\nexport class TransactionNotPendingMutateError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .mutate() as the transaction is no longer pending`,\n )\n }\n}\n\nexport class TransactionAlreadyCompletedRollbackError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .rollback() as the transaction is already completed`,\n )\n }\n}\n\nexport class TransactionNotPendingCommitError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .commit() as the transaction is no longer pending`,\n )\n }\n}\n\nexport class NoPendingSyncTransactionWriteError extends TransactionError {\n constructor() {\n super(`No pending sync transaction to write to`)\n }\n}\n\nexport class SyncTransactionAlreadyCommittedWriteError extends TransactionError {\n constructor() {\n super(\n `The pending sync transaction is already committed, you can't still write to it.`,\n )\n }\n}\n\nexport class NoPendingSyncTransactionCommitError extends TransactionError {\n constructor() {\n super(`No pending sync transaction to commit`)\n }\n}\n\nexport class SyncTransactionAlreadyCommittedError extends TransactionError {\n constructor() {\n super(\n `The pending sync transaction is already committed, you can't commit it again.`,\n )\n }\n}\n\n// Query Builder Errors\nexport class QueryBuilderError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryBuilderError`\n }\n}\n\nexport class OnlyOneSourceAllowedError extends QueryBuilderError {\n constructor(context: string) {\n super(`Only one source is allowed in the ${context}`)\n }\n}\n\nexport class SubQueryMustHaveFromClauseError extends QueryBuilderError {\n constructor(context: string) {\n super(`A sub query passed to a ${context} must have a from clause itself`)\n }\n}\n\nexport class InvalidSourceError extends QueryBuilderError {\n constructor(alias: string) {\n super(\n `Invalid source for live query: The value provided for alias \"${alias}\" is not a Collection or subquery. Live queries only accept Collection instances or subqueries. Please ensure you're passing a valid Collection or QueryBuilder, not a plain array or other data type.`,\n )\n }\n}\n\nexport class InvalidSourceTypeError extends QueryBuilderError {\n constructor(context: string, type: string) {\n super(\n `Invalid source for ${context}: Expected an object with a single key-value pair like { alias: collection }. ` +\n `For example: .from({ todos: todosCollection }). Got: ${type}`,\n )\n }\n}\n\nexport class JoinConditionMustBeEqualityError extends QueryBuilderError {\n constructor() {\n super(`Join condition must be an equality expression`)\n }\n}\n\nexport class QueryMustHaveFromClauseError extends QueryBuilderError {\n constructor() {\n super(`Query must have a from clause`)\n }\n}\n\nexport class InvalidWhereExpressionError extends QueryBuilderError {\n constructor(valueType: string) {\n super(\n `Invalid where() expression: Expected a query expression, but received a ${valueType}. ` +\n `This usually happens when using JavaScript's comparison operators (===, !==, <, >, etc.) directly. ` +\n `Instead, use the query builder functions:\\n\\n` +\n ` ❌ .where(({ user }) => user.id === 'abc')\\n` +\n ` ✅ .where(({ user }) => eq(user.id, 'abc'))\\n\\n` +\n `Available comparison functions: eq, gt, gte, lt, lte, and, or, not, like, ilike, isNull, isUndefined`,\n )\n }\n}\n\n// Query Compilation Errors\nexport class QueryCompilationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryCompilationError`\n }\n}\n\nexport class DistinctRequiresSelectError extends QueryCompilationError {\n constructor() {\n super(`DISTINCT requires a SELECT clause.`)\n }\n}\n\nexport class FnSelectWithGroupByError extends QueryCompilationError {\n constructor() {\n super(\n `fn.select() cannot be used with groupBy(). ` +\n `groupBy requires the compiler to statically analyze aggregate functions (count, sum, max, etc.) in the SELECT clause, ` +\n `which is not possible with fn.select() since it is an opaque function. ` +\n `Use .select() instead of .fn.select() when combining with groupBy().`,\n )\n }\n}\n\nexport class HavingRequiresGroupByError extends QueryCompilationError {\n constructor() {\n super(`HAVING clause requires GROUP BY clause`)\n }\n}\n\nexport class LimitOffsetRequireOrderByError extends QueryCompilationError {\n constructor() {\n super(\n `LIMIT and OFFSET require an ORDER BY clause to ensure deterministic results`,\n )\n }\n}\n\n/**\n * Error thrown when a collection input stream is not found during query compilation.\n * In self-joins, each alias (e.g., 'employee', 'manager') requires its own input stream.\n */\nexport class CollectionInputNotFoundError extends QueryCompilationError {\n constructor(\n alias: string,\n collectionId?: string,\n availableKeys?: Array<string>,\n ) {\n const details = collectionId\n ? `alias \"${alias}\" (collection \"${collectionId}\")`\n : `collection \"${alias}\"`\n const availableKeysMsg = availableKeys?.length\n ? `. Available keys: ${availableKeys.join(`, `)}`\n : ``\n super(`Input for ${details} not found in inputs map${availableKeysMsg}`)\n }\n}\n\n/**\n * Error thrown when a subquery uses the same alias as its parent query.\n * This causes issues because parent and subquery would share the same input streams,\n * leading to empty results or incorrect data (aggregation cross-leaking).\n */\nexport class DuplicateAliasInSubqueryError extends QueryCompilationError {\n constructor(alias: string, parentAliases: Array<string>) {\n super(\n `Subquery uses alias \"${alias}\" which is already used in the parent query. ` +\n `Each alias must be unique across parent and subquery contexts. ` +\n `Parent query aliases: ${parentAliases.join(`, `)}. ` +\n `Please rename \"${alias}\" in either the parent query or subquery to avoid conflicts.`,\n )\n }\n}\n\nexport class UnsupportedFromTypeError extends QueryCompilationError {\n constructor(type: string) {\n super(`Unsupported FROM type: ${type}`)\n }\n}\n\nexport class UnknownExpressionTypeError extends QueryCompilationError {\n constructor(type: string) {\n super(`Unknown expression type: ${type}`)\n }\n}\n\nexport class EmptyReferencePathError extends QueryCompilationError {\n constructor() {\n super(`Reference path cannot be empty`)\n }\n}\n\nexport class UnknownFunctionError extends QueryCompilationError {\n constructor(functionName: string) {\n super(`Unknown function: ${functionName}`)\n }\n}\n\nexport class JoinCollectionNotFoundError extends QueryCompilationError {\n constructor(collectionId: string) {\n super(`Collection \"${collectionId}\" not found during compilation of join`)\n }\n}\n\n// JOIN Operation Errors\nexport class JoinError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `JoinError`\n }\n}\n\nexport class UnsupportedJoinTypeError extends JoinError {\n constructor(joinType: string) {\n super(`Unsupported join type: ${joinType}`)\n }\n}\n\nexport class InvalidJoinConditionSameSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: both expressions refer to the same source \"${sourceAlias}\"`,\n )\n }\n}\n\nexport class InvalidJoinConditionSourceMismatchError extends JoinError {\n constructor() {\n super(`Invalid join condition: expressions must reference source aliases`)\n }\n}\n\nexport class InvalidJoinConditionLeftSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: left expression refers to an unavailable source \"${sourceAlias}\"`,\n )\n }\n}\n\nexport class InvalidJoinConditionRightSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: right expression does not refer to the joined source \"${sourceAlias}\"`,\n )\n }\n}\n\nexport class InvalidJoinCondition extends JoinError {\n constructor() {\n super(`Invalid join condition`)\n }\n}\n\nexport class UnsupportedJoinSourceTypeError extends JoinError {\n constructor(type: string) {\n super(`Unsupported join source type: ${type}`)\n }\n}\n\n// GROUP BY and Aggregation Errors\nexport class GroupByError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `GroupByError`\n }\n}\n\nexport class NonAggregateExpressionNotInGroupByError extends GroupByError {\n constructor(alias: string) {\n super(\n `Non-aggregate expression '${alias}' in SELECT must also appear in GROUP BY clause`,\n )\n }\n}\n\nexport class UnsupportedAggregateFunctionError extends GroupByError {\n constructor(functionName: string) {\n super(`Unsupported aggregate function: ${functionName}`)\n }\n}\n\nexport class AggregateFunctionNotInSelectError extends GroupByError {\n constructor(functionName: string) {\n super(\n `Aggregate function in HAVING clause must also be in SELECT clause: ${functionName}`,\n )\n }\n}\n\nexport class UnknownHavingExpressionTypeError extends GroupByError {\n constructor(type: string) {\n super(`Unknown expression type in HAVING clause: ${type}`)\n }\n}\n\n// Storage Errors\nexport class StorageError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `StorageError`\n }\n}\n\nexport class SerializationError extends StorageError {\n constructor(operation: string, originalError: string) {\n super(\n `Cannot ${operation} item because it cannot be JSON serialized: ${originalError}`,\n )\n }\n}\n\n// LocalStorage Collection Errors\nexport class LocalStorageCollectionError extends StorageError {\n constructor(message: string) {\n super(message)\n this.name = `LocalStorageCollectionError`\n }\n}\n\nexport class StorageKeyRequiredError extends LocalStorageCollectionError {\n constructor() {\n super(`[LocalStorageCollection] storageKey must be provided.`)\n }\n}\n\nexport class InvalidStorageDataFormatError extends LocalStorageCollectionError {\n constructor(storageKey: string, key: string) {\n super(\n `[LocalStorageCollection] Invalid data format in storage key \"${storageKey}\" for key \"${key}\".`,\n )\n }\n}\n\nexport class InvalidStorageObjectFormatError extends LocalStorageCollectionError {\n constructor(storageKey: string) {\n super(\n `[LocalStorageCollection] Invalid data format in storage key \"${storageKey}\". Expected object format.`,\n )\n }\n}\n\n// Sync Cleanup Errors\nexport class SyncCleanupError extends TanStackDBError {\n constructor(collectionId: string, error: Error | string) {\n const message = error instanceof Error ? error.message : String(error)\n super(\n `Collection \"${collectionId}\" sync cleanup function threw an error: ${message}`,\n )\n this.name = `SyncCleanupError`\n }\n}\n\n// Query Optimizer Errors\nexport class QueryOptimizerError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryOptimizerError`\n }\n}\n\nexport class CannotCombineEmptyExpressionListError extends QueryOptimizerError {\n constructor() {\n super(`Cannot combine empty expression list`)\n }\n}\n\n/**\n * Internal error when the query optimizer fails to convert a WHERE clause to a collection filter.\n */\nexport class WhereClauseConversionError extends QueryOptimizerError {\n constructor(collectionId: string, alias: string) {\n super(\n `Failed to convert WHERE clause to collection filter for collection '${collectionId}' alias '${alias}'. This indicates a bug in the query optimization logic.`,\n )\n }\n}\n\n/**\n * Error when a subscription cannot be found during lazy join processing.\n * For subqueries, aliases may be remapped (e.g., 'activeUser' → 'user').\n */\nexport class SubscriptionNotFoundError extends QueryCompilationError {\n constructor(\n resolvedAlias: string,\n originalAlias: string,\n collectionId: string,\n availableAliases: Array<string>,\n ) {\n super(\n `Internal error: subscription for alias '${resolvedAlias}' (remapped from '${originalAlias}', collection '${collectionId}') is missing in join pipeline. Available aliases: ${availableAliases.join(`, `)}. This indicates a bug in alias tracking.`,\n )\n }\n}\n\n/**\n * Error thrown when aggregate expressions are used outside of a GROUP BY context.\n */\nexport class AggregateNotSupportedError extends QueryCompilationError {\n constructor() {\n super(\n `Aggregate expressions are not supported in this context. Use GROUP BY clause for aggregates.`,\n )\n }\n}\n\n/**\n * Internal error when the compiler returns aliases that don't have corresponding input streams.\n * This should never happen since all aliases come from user declarations.\n */\nexport class MissingAliasInputsError extends QueryCompilationError {\n constructor(missingAliases: Array<string>) {\n super(\n `Internal error: compiler returned aliases without inputs: ${missingAliases.join(`, `)}. ` +\n `This indicates a bug in query compilation. Please report this issue.`,\n )\n }\n}\n\n/**\n * Error thrown when setWindow is called on a collection without an ORDER BY clause.\n */\nexport class SetWindowRequiresOrderByError extends QueryCompilationError {\n constructor() {\n super(\n `setWindow() can only be called on collections with an ORDER BY clause. ` +\n `Add .orderBy() to your query to enable window movement.`,\n )\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sources":["../../src/errors.ts"],"sourcesContent":["// Root error class for all TanStack DB errors\nexport class TanStackDBError extends Error {\n constructor(message: string) {\n super(message)\n this.name = `TanStackDBError`\n }\n}\n\n// Base error classes\nexport class NonRetriableError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `NonRetriableError`\n }\n}\n\n// Schema validation error (exported from index for backward compatibility)\nexport class SchemaValidationError extends TanStackDBError {\n type: `insert` | `update`\n issues: ReadonlyArray<{\n message: string\n path?: ReadonlyArray<string | number | symbol>\n }>\n\n constructor(\n type: `insert` | `update`,\n issues: ReadonlyArray<{\n message: string\n path?: ReadonlyArray<string | number | symbol>\n }>,\n message?: string,\n ) {\n const defaultMessage = `${type === `insert` ? `Insert` : `Update`} validation failed: ${issues\n .map((issue) => `\\n- ${issue.message} - path: ${issue.path}`)\n .join(``)}`\n\n super(message || defaultMessage)\n this.name = `SchemaValidationError`\n this.type = type\n this.issues = issues\n }\n}\n\n// Module Instance Errors\nexport class DuplicateDbInstanceError extends TanStackDBError {\n constructor() {\n super(\n `Multiple instances of @tanstack/db detected!\\n\\n` +\n `This causes transaction context to be lost because each instance maintains ` +\n `its own transaction stack.\\n\\n` +\n `Common causes:\\n` +\n `1. Different versions of @tanstack/db installed\\n` +\n `2. Incompatible peer dependency versions in packages\\n` +\n `3. Module resolution issues in bundler configuration\\n\\n` +\n `To fix:\\n` +\n `1. Check installed versions: npm list @tanstack/db (or pnpm/yarn list)\\n` +\n `2. Force a single version using package manager overrides:\\n` +\n ` - npm: \"overrides\" in package.json\\n` +\n ` - pnpm: \"pnpm.overrides\" in package.json\\n` +\n ` - yarn: \"resolutions\" in package.json\\n` +\n `3. Clear node_modules and lockfile, then reinstall\\n\\n` +\n `To temporarily disable this check (not recommended):\\n` +\n `Set environment variable: TANSTACK_DB_DISABLE_DUP_CHECK=1\\n\\n` +\n `See: https://tanstack.com/db/latest/docs/troubleshooting#duplicate-instances`,\n )\n this.name = `DuplicateDbInstanceError`\n }\n}\n\n// Collection Configuration Errors\nexport class CollectionConfigurationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionConfigurationError`\n }\n}\n\nexport class CollectionRequiresConfigError extends CollectionConfigurationError {\n constructor() {\n super(`Collection requires a config`)\n }\n}\n\nexport class CollectionRequiresSyncConfigError extends CollectionConfigurationError {\n constructor() {\n super(`Collection requires a sync config`)\n }\n}\n\nexport class InvalidSchemaError extends CollectionConfigurationError {\n constructor() {\n super(`Schema must implement the standard-schema interface`)\n }\n}\n\nexport class SchemaMustBeSynchronousError extends CollectionConfigurationError {\n constructor() {\n super(`Schema validation must be synchronous`)\n }\n}\n\n// Collection State Errors\nexport class CollectionStateError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionStateError`\n }\n}\n\nexport class CollectionInErrorStateError extends CollectionStateError {\n constructor(operation: string, collectionId: string) {\n super(\n `Cannot perform ${operation} on collection \"${collectionId}\" - collection is in error state. Try calling cleanup() and restarting the collection.`,\n )\n }\n}\n\nexport class InvalidCollectionStatusTransitionError extends CollectionStateError {\n constructor(from: string, to: string, collectionId: string) {\n super(\n `Invalid collection status transition from \"${from}\" to \"${to}\" for collection \"${collectionId}\"`,\n )\n }\n}\n\nexport class CollectionIsInErrorStateError extends CollectionStateError {\n constructor() {\n super(`Collection is in error state`)\n }\n}\n\nexport class NegativeActiveSubscribersError extends CollectionStateError {\n constructor() {\n super(`Active subscribers count is negative - this should never happen`)\n }\n}\n\n// Collection Operation Errors\nexport class CollectionOperationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionOperationError`\n }\n}\n\nexport class UndefinedKeyError extends CollectionOperationError {\n constructor(item: any) {\n super(\n `An object was created without a defined key: ${JSON.stringify(item)}`,\n )\n }\n}\n\nexport class InvalidKeyError extends CollectionOperationError {\n constructor(key: unknown, item: unknown) {\n const keyType = key === null ? `null` : typeof key\n super(\n `getKey returned an invalid key type. Expected string or number, but got ${keyType}: ${JSON.stringify(key)}. Item: ${JSON.stringify(item)}`,\n )\n }\n}\n\nexport class DuplicateKeyError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `Cannot insert document with ID \"${key}\" because it already exists in the collection`,\n )\n }\n}\n\nexport class DuplicateKeySyncError extends CollectionOperationError {\n constructor(\n key: string | number,\n collectionId: string,\n options?: {\n hasCustomGetKey?: boolean\n hasJoins?: boolean\n hasDistinct?: boolean\n },\n ) {\n const baseMessage = `Cannot insert document with key \"${key}\" from sync because it already exists in the collection \"${collectionId}\"`\n\n // Provide enhanced guidance when custom getKey is used with distinct\n if (options?.hasCustomGetKey && options.hasDistinct) {\n super(\n `${baseMessage}. ` +\n `This collection uses a custom getKey with .distinct(). ` +\n `The .distinct() operator deduplicates by the ENTIRE selected object (standard SQL behavior), ` +\n `but your custom getKey extracts only a subset of fields. This causes multiple distinct rows ` +\n `(with different values in non-key fields) to receive the same key. ` +\n `To fix this, either: (1) ensure your SELECT only includes fields that uniquely identify each row, ` +\n `(2) use .groupBy() with min()/max() aggregates to select one value per group, or ` +\n `(3) remove the custom getKey to use the default key behavior.`,\n )\n } else if (options?.hasCustomGetKey && options.hasJoins) {\n // Provide enhanced guidance when custom getKey is used with joins\n super(\n `${baseMessage}. ` +\n `This collection uses a custom getKey with joined queries. ` +\n `Joined queries can produce multiple rows with the same key when relationships are not 1:1. ` +\n `Consider: (1) using a composite key in your getKey function (e.g., \\`\\${item.key1}-\\${item.key2}\\`), ` +\n `(2) ensuring your join produces unique rows per key, or (3) removing the custom getKey ` +\n `to use the default composite key behavior.`,\n )\n } else {\n super(baseMessage)\n }\n }\n}\n\nexport class MissingUpdateArgumentError extends CollectionOperationError {\n constructor() {\n super(`The first argument to update is missing`)\n }\n}\n\nexport class NoKeysPassedToUpdateError extends CollectionOperationError {\n constructor() {\n super(`No keys were passed to update`)\n }\n}\n\nexport class UpdateKeyNotFoundError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `The key \"${key}\" was passed to update but an object for this key was not found in the collection`,\n )\n }\n}\n\nexport class KeyUpdateNotAllowedError extends CollectionOperationError {\n constructor(originalKey: string | number, newKey: string | number) {\n super(\n `Updating the key of an item is not allowed. Original key: \"${originalKey}\", Attempted new key: \"${newKey}\". Please delete the old item and create a new one if a key change is necessary.`,\n )\n }\n}\n\nexport class NoKeysPassedToDeleteError extends CollectionOperationError {\n constructor() {\n super(`No keys were passed to delete`)\n }\n}\n\nexport class DeleteKeyNotFoundError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `Collection.delete was called with key '${key}' but there is no item in the collection with this key`,\n )\n }\n}\n\n// Collection Handler Errors\nexport class MissingHandlerError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `MissingHandlerError`\n }\n}\n\nexport class MissingInsertHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.insert called directly (not within an explicit transaction) but no 'onInsert' handler is configured.`,\n )\n }\n}\n\nexport class MissingUpdateHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.update called directly (not within an explicit transaction) but no 'onUpdate' handler is configured.`,\n )\n }\n}\n\nexport class MissingDeleteHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.delete called directly (not within an explicit transaction) but no 'onDelete' handler is configured.`,\n )\n }\n}\n\n// Transaction Errors\nexport class TransactionError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `TransactionError`\n }\n}\n\nexport class MissingMutationFunctionError extends TransactionError {\n constructor() {\n super(`mutationFn is required when creating a transaction`)\n }\n}\n\nexport class OnMutateMustBeSynchronousError extends TransactionError {\n constructor() {\n super(\n `onMutate must be synchronous and cannot return a promise. Remove async/await or returned promises from onMutate.`,\n )\n this.name = `OnMutateMustBeSynchronousError`\n }\n}\n\nexport class TransactionNotPendingMutateError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .mutate() as the transaction is no longer pending`,\n )\n }\n}\n\nexport class TransactionAlreadyCompletedRollbackError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .rollback() as the transaction is already completed`,\n )\n }\n}\n\nexport class TransactionNotPendingCommitError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .commit() as the transaction is no longer pending`,\n )\n }\n}\n\nexport class NoPendingSyncTransactionWriteError extends TransactionError {\n constructor() {\n super(`No pending sync transaction to write to`)\n }\n}\n\nexport class SyncTransactionAlreadyCommittedWriteError extends TransactionError {\n constructor() {\n super(\n `The pending sync transaction is already committed, you can't still write to it.`,\n )\n }\n}\n\nexport class NoPendingSyncTransactionCommitError extends TransactionError {\n constructor() {\n super(`No pending sync transaction to commit`)\n }\n}\n\nexport class SyncTransactionAlreadyCommittedError extends TransactionError {\n constructor() {\n super(\n `The pending sync transaction is already committed, you can't commit it again.`,\n )\n }\n}\n\n// Query Builder Errors\nexport class QueryBuilderError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryBuilderError`\n }\n}\n\nexport class OnlyOneSourceAllowedError extends QueryBuilderError {\n constructor(context: string) {\n super(`Only one source is allowed in the ${context}`)\n }\n}\n\nexport class SubQueryMustHaveFromClauseError extends QueryBuilderError {\n constructor(context: string) {\n super(`A sub query passed to a ${context} must have a from clause itself`)\n }\n}\n\nexport class InvalidSourceError extends QueryBuilderError {\n constructor(alias: string) {\n super(\n `Invalid source for live query: The value provided for alias \"${alias}\" is not a Collection or subquery. Live queries only accept Collection instances or subqueries. Please ensure you're passing a valid Collection or QueryBuilder, not a plain array or other data type.`,\n )\n }\n}\n\nexport class InvalidSourceTypeError extends QueryBuilderError {\n constructor(context: string, type: string) {\n super(\n `Invalid source for ${context}: Expected an object with a single key-value pair like { alias: collection }. ` +\n `For example: .from({ todos: todosCollection }). Got: ${type}`,\n )\n }\n}\n\nexport class JoinConditionMustBeEqualityError extends QueryBuilderError {\n constructor() {\n super(`Join condition must be an equality expression`)\n }\n}\n\nexport class QueryMustHaveFromClauseError extends QueryBuilderError {\n constructor() {\n super(`Query must have a from clause`)\n }\n}\n\nexport class InvalidWhereExpressionError extends QueryBuilderError {\n constructor(valueType: string) {\n super(\n `Invalid where() expression: Expected a query expression, but received a ${valueType}. ` +\n `This usually happens when using JavaScript's comparison operators (===, !==, <, >, etc.) directly. ` +\n `Instead, use the query builder functions:\\n\\n` +\n ` ❌ .where(({ user }) => user.id === 'abc')\\n` +\n ` ✅ .where(({ user }) => eq(user.id, 'abc'))\\n\\n` +\n `Available comparison functions: eq, gt, gte, lt, lte, and, or, not, like, ilike, isNull, isUndefined`,\n )\n }\n}\n\n// Query Compilation Errors\nexport class QueryCompilationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryCompilationError`\n }\n}\n\nexport class DistinctRequiresSelectError extends QueryCompilationError {\n constructor() {\n super(`DISTINCT requires a SELECT clause.`)\n }\n}\n\nexport class FnSelectWithGroupByError extends QueryCompilationError {\n constructor() {\n super(\n `fn.select() cannot be used with groupBy(). ` +\n `groupBy requires the compiler to statically analyze aggregate functions (count, sum, max, etc.) in the SELECT clause, ` +\n `which is not possible with fn.select() since it is an opaque function. ` +\n `Use .select() instead of .fn.select() when combining with groupBy().`,\n )\n }\n}\n\nexport class UnsupportedRootScalarSelectError extends QueryCompilationError {\n constructor() {\n super(\n `Top-level scalar select() is not supported by createLiveQueryCollection() or queryOnce(). ` +\n `Return an object from .select(), or use the scalar query inside toArray(...) or concat(toArray(...)).`,\n )\n }\n}\n\nexport class HavingRequiresGroupByError extends QueryCompilationError {\n constructor() {\n super(`HAVING clause requires GROUP BY clause`)\n }\n}\n\nexport class LimitOffsetRequireOrderByError extends QueryCompilationError {\n constructor() {\n super(\n `LIMIT and OFFSET require an ORDER BY clause to ensure deterministic results`,\n )\n }\n}\n\n/**\n * Error thrown when a collection input stream is not found during query compilation.\n * In self-joins, each alias (e.g., 'employee', 'manager') requires its own input stream.\n */\nexport class CollectionInputNotFoundError extends QueryCompilationError {\n constructor(\n alias: string,\n collectionId?: string,\n availableKeys?: Array<string>,\n ) {\n const details = collectionId\n ? `alias \"${alias}\" (collection \"${collectionId}\")`\n : `collection \"${alias}\"`\n const availableKeysMsg = availableKeys?.length\n ? `. Available keys: ${availableKeys.join(`, `)}`\n : ``\n super(`Input for ${details} not found in inputs map${availableKeysMsg}`)\n }\n}\n\n/**\n * Error thrown when a subquery uses the same alias as its parent query.\n * This causes issues because parent and subquery would share the same input streams,\n * leading to empty results or incorrect data (aggregation cross-leaking).\n */\nexport class DuplicateAliasInSubqueryError extends QueryCompilationError {\n constructor(alias: string, parentAliases: Array<string>) {\n super(\n `Subquery uses alias \"${alias}\" which is already used in the parent query. ` +\n `Each alias must be unique across parent and subquery contexts. ` +\n `Parent query aliases: ${parentAliases.join(`, `)}. ` +\n `Please rename \"${alias}\" in either the parent query or subquery to avoid conflicts.`,\n )\n }\n}\n\nexport class UnsupportedFromTypeError extends QueryCompilationError {\n constructor(type: string) {\n super(`Unsupported FROM type: ${type}`)\n }\n}\n\nexport class UnknownExpressionTypeError extends QueryCompilationError {\n constructor(type: string) {\n super(`Unknown expression type: ${type}`)\n }\n}\n\nexport class EmptyReferencePathError extends QueryCompilationError {\n constructor() {\n super(`Reference path cannot be empty`)\n }\n}\n\nexport class UnknownFunctionError extends QueryCompilationError {\n constructor(functionName: string) {\n super(`Unknown function: ${functionName}`)\n }\n}\n\nexport class JoinCollectionNotFoundError extends QueryCompilationError {\n constructor(collectionId: string) {\n super(`Collection \"${collectionId}\" not found during compilation of join`)\n }\n}\n\n// JOIN Operation Errors\nexport class JoinError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `JoinError`\n }\n}\n\nexport class UnsupportedJoinTypeError extends JoinError {\n constructor(joinType: string) {\n super(`Unsupported join type: ${joinType}`)\n }\n}\n\nexport class InvalidJoinConditionSameSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: both expressions refer to the same source \"${sourceAlias}\"`,\n )\n }\n}\n\nexport class InvalidJoinConditionSourceMismatchError extends JoinError {\n constructor() {\n super(`Invalid join condition: expressions must reference source aliases`)\n }\n}\n\nexport class InvalidJoinConditionLeftSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: left expression refers to an unavailable source \"${sourceAlias}\"`,\n )\n }\n}\n\nexport class InvalidJoinConditionRightSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: right expression does not refer to the joined source \"${sourceAlias}\"`,\n )\n }\n}\n\nexport class InvalidJoinCondition extends JoinError {\n constructor() {\n super(`Invalid join condition`)\n }\n}\n\nexport class UnsupportedJoinSourceTypeError extends JoinError {\n constructor(type: string) {\n super(`Unsupported join source type: ${type}`)\n }\n}\n\n// GROUP BY and Aggregation Errors\nexport class GroupByError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `GroupByError`\n }\n}\n\nexport class NonAggregateExpressionNotInGroupByError extends GroupByError {\n constructor(alias: string) {\n super(\n `Non-aggregate expression '${alias}' in SELECT must also appear in GROUP BY clause`,\n )\n }\n}\n\nexport class UnsupportedAggregateFunctionError extends GroupByError {\n constructor(functionName: string) {\n super(`Unsupported aggregate function: ${functionName}`)\n }\n}\n\nexport class AggregateFunctionNotInSelectError extends GroupByError {\n constructor(functionName: string) {\n super(\n `Aggregate function in HAVING clause must also be in SELECT clause: ${functionName}`,\n )\n }\n}\n\nexport class UnknownHavingExpressionTypeError extends GroupByError {\n constructor(type: string) {\n super(`Unknown expression type in HAVING clause: ${type}`)\n }\n}\n\n// Storage Errors\nexport class StorageError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `StorageError`\n }\n}\n\nexport class SerializationError extends StorageError {\n constructor(operation: string, originalError: string) {\n super(\n `Cannot ${operation} item because it cannot be JSON serialized: ${originalError}`,\n )\n }\n}\n\n// LocalStorage Collection Errors\nexport class LocalStorageCollectionError extends StorageError {\n constructor(message: string) {\n super(message)\n this.name = `LocalStorageCollectionError`\n }\n}\n\nexport class StorageKeyRequiredError extends LocalStorageCollectionError {\n constructor() {\n super(`[LocalStorageCollection] storageKey must be provided.`)\n }\n}\n\nexport class InvalidStorageDataFormatError extends LocalStorageCollectionError {\n constructor(storageKey: string, key: string) {\n super(\n `[LocalStorageCollection] Invalid data format in storage key \"${storageKey}\" for key \"${key}\".`,\n )\n }\n}\n\nexport class InvalidStorageObjectFormatError extends LocalStorageCollectionError {\n constructor(storageKey: string) {\n super(\n `[LocalStorageCollection] Invalid data format in storage key \"${storageKey}\". Expected object format.`,\n )\n }\n}\n\n// Sync Cleanup Errors\nexport class SyncCleanupError extends TanStackDBError {\n constructor(collectionId: string, error: Error | string) {\n const message = error instanceof Error ? error.message : String(error)\n super(\n `Collection \"${collectionId}\" sync cleanup function threw an error: ${message}`,\n )\n this.name = `SyncCleanupError`\n }\n}\n\n// Query Optimizer Errors\nexport class QueryOptimizerError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryOptimizerError`\n }\n}\n\nexport class CannotCombineEmptyExpressionListError extends QueryOptimizerError {\n constructor() {\n super(`Cannot combine empty expression list`)\n }\n}\n\n/**\n * Internal error when the query optimizer fails to convert a WHERE clause to a collection filter.\n */\nexport class WhereClauseConversionError extends QueryOptimizerError {\n constructor(collectionId: string, alias: string) {\n super(\n `Failed to convert WHERE clause to collection filter for collection '${collectionId}' alias '${alias}'. This indicates a bug in the query optimization logic.`,\n )\n }\n}\n\n/**\n * Error when a subscription cannot be found during lazy join processing.\n * For subqueries, aliases may be remapped (e.g., 'activeUser' → 'user').\n */\nexport class SubscriptionNotFoundError extends QueryCompilationError {\n constructor(\n resolvedAlias: string,\n originalAlias: string,\n collectionId: string,\n availableAliases: Array<string>,\n ) {\n super(\n `Internal error: subscription for alias '${resolvedAlias}' (remapped from '${originalAlias}', collection '${collectionId}') is missing in join pipeline. Available aliases: ${availableAliases.join(`, `)}. This indicates a bug in alias tracking.`,\n )\n }\n}\n\n/**\n * Error thrown when aggregate expressions are used outside of a GROUP BY context.\n */\nexport class AggregateNotSupportedError extends QueryCompilationError {\n constructor() {\n super(\n `Aggregate expressions are not supported in this context. Use GROUP BY clause for aggregates.`,\n )\n }\n}\n\n/**\n * Internal error when the compiler returns aliases that don't have corresponding input streams.\n * This should never happen since all aliases come from user declarations.\n */\nexport class MissingAliasInputsError extends QueryCompilationError {\n constructor(missingAliases: Array<string>) {\n super(\n `Internal error: compiler returned aliases without inputs: ${missingAliases.join(`, `)}. ` +\n `This indicates a bug in query compilation. Please report this issue.`,\n )\n }\n}\n\n/**\n * Error thrown when setWindow is called on a collection without an ORDER BY clause.\n */\nexport class SetWindowRequiresOrderByError extends QueryCompilationError {\n constructor() {\n super(\n `setWindow() can only be called on collections with an ORDER BY clause. ` +\n `Add .orderBy() to your query to enable window movement.`,\n )\n }\n}\n"],"names":[],"mappings":"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"}
@@ -12,10 +12,18 @@ export * from './errors.js';
12
12
  export { deepEquals } from './utils.js';
13
13
  export * from './paced-mutations.js';
14
14
  export * from './strategies/index.js';
15
- export * from './indexes/base-index.js';
16
- export * from './indexes/btree-index.js';
17
- export * from './indexes/lazy-index.js';
15
+ export { type VirtualRowProps, type VirtualOrigin, type WithVirtualProps, type WithoutVirtualProps, hasVirtualProps, } from './virtual-props.js';
16
+ export { BaseIndex } from './indexes/base-index.js';
17
+ export type { IndexInterface, IndexConstructor, IndexStats, IndexOperation, } from './indexes/base-index.js';
18
18
  export { type IndexOptions } from './indexes/index-options.js';
19
+ export { BasicIndex } from './indexes/basic-index.js';
20
+ export type { BasicIndexOptions, RangeQueryOptions, } from './indexes/basic-index.js';
21
+ export { BTreeIndex } from './indexes/btree-index.js';
22
+ export type { RangeQueryOptions as BTreeRangeQueryOptions } from './indexes/btree-index.js';
23
+ export { ReverseIndex } from './indexes/reverse-index.js';
24
+ export { optimizeExpressionWithIndexes, findIndexForField, } from './utils/index-optimization.js';
25
+ export { configureIndexDevMode, isDevModeEnabled, getIndexDevModeConfig, trackQuery, clearQueryPatterns, getQueryPatterns, } from './indexes/index-registry.js';
26
+ export type { IndexDevModeConfig, IndexSuggestion, } from './indexes/index-registry.js';
19
27
  export * from './query/expression-helpers.js';
20
28
  export { createEffect, type DeltaEvent, type DeltaType, type EffectConfig, type EffectContext, type Effect, type EffectQueryInput, } from './query/effect.js';
21
29
  export type { Collection } from './collection/index.js';
package/dist/esm/index.js CHANGED
@@ -6,17 +6,22 @@ import { createArrayChangeProxy, createChangeProxy, withArrayChangeTracking, wit
6
6
  import { createOptimisticAction } from "./optimistic-action.js";
7
7
  import { localOnlyCollectionOptions } from "./local-only.js";
8
8
  import { localStorageCollectionOptions } from "./local-storage.js";
9
- import { AggregateFunctionNotInSelectError, AggregateNotSupportedError, CannotCombineEmptyExpressionListError, CollectionConfigurationError, CollectionInErrorStateError, CollectionInputNotFoundError, CollectionIsInErrorStateError, CollectionOperationError, CollectionRequiresConfigError, CollectionRequiresSyncConfigError, CollectionStateError, DeleteKeyNotFoundError, DistinctRequiresSelectError, DuplicateAliasInSubqueryError, DuplicateDbInstanceError, DuplicateKeyError, DuplicateKeySyncError, EmptyReferencePathError, FnSelectWithGroupByError, GroupByError, HavingRequiresGroupByError, InvalidCollectionStatusTransitionError, InvalidJoinCondition, InvalidJoinConditionLeftSourceError, InvalidJoinConditionRightSourceError, InvalidJoinConditionSameSourceError, InvalidJoinConditionSourceMismatchError, InvalidKeyError, InvalidSchemaError, InvalidSourceError, InvalidSourceTypeError, InvalidStorageDataFormatError, InvalidStorageObjectFormatError, InvalidWhereExpressionError, JoinCollectionNotFoundError, JoinConditionMustBeEqualityError, JoinError, KeyUpdateNotAllowedError, LimitOffsetRequireOrderByError, LocalStorageCollectionError, MissingAliasInputsError, MissingDeleteHandlerError, MissingHandlerError, MissingInsertHandlerError, MissingMutationFunctionError, MissingUpdateArgumentError, MissingUpdateHandlerError, NegativeActiveSubscribersError, NoKeysPassedToDeleteError, NoKeysPassedToUpdateError, NoPendingSyncTransactionCommitError, NoPendingSyncTransactionWriteError, NonAggregateExpressionNotInGroupByError, NonRetriableError, OnMutateMustBeSynchronousError, OnlyOneSourceAllowedError, QueryBuilderError, QueryCompilationError, QueryMustHaveFromClauseError, QueryOptimizerError, SchemaMustBeSynchronousError, SchemaValidationError, SerializationError, SetWindowRequiresOrderByError, StorageError, StorageKeyRequiredError, SubQueryMustHaveFromClauseError, SubscriptionNotFoundError, SyncCleanupError, SyncTransactionAlreadyCommittedError, SyncTransactionAlreadyCommittedWriteError, TanStackDBError, TransactionAlreadyCompletedRollbackError, TransactionError, TransactionNotPendingCommitError, TransactionNotPendingMutateError, UndefinedKeyError, UnknownExpressionTypeError, UnknownFunctionError, UnknownHavingExpressionTypeError, UnsupportedAggregateFunctionError, UnsupportedFromTypeError, UnsupportedJoinSourceTypeError, UnsupportedJoinTypeError, UpdateKeyNotFoundError, WhereClauseConversionError } from "./errors.js";
9
+ import { AggregateFunctionNotInSelectError, AggregateNotSupportedError, CannotCombineEmptyExpressionListError, CollectionConfigurationError, CollectionInErrorStateError, CollectionInputNotFoundError, CollectionIsInErrorStateError, CollectionOperationError, CollectionRequiresConfigError, CollectionRequiresSyncConfigError, CollectionStateError, DeleteKeyNotFoundError, DistinctRequiresSelectError, DuplicateAliasInSubqueryError, DuplicateDbInstanceError, DuplicateKeyError, DuplicateKeySyncError, EmptyReferencePathError, FnSelectWithGroupByError, GroupByError, HavingRequiresGroupByError, InvalidCollectionStatusTransitionError, InvalidJoinCondition, InvalidJoinConditionLeftSourceError, InvalidJoinConditionRightSourceError, InvalidJoinConditionSameSourceError, InvalidJoinConditionSourceMismatchError, InvalidKeyError, InvalidSchemaError, InvalidSourceError, InvalidSourceTypeError, InvalidStorageDataFormatError, InvalidStorageObjectFormatError, InvalidWhereExpressionError, JoinCollectionNotFoundError, JoinConditionMustBeEqualityError, JoinError, KeyUpdateNotAllowedError, LimitOffsetRequireOrderByError, LocalStorageCollectionError, MissingAliasInputsError, MissingDeleteHandlerError, MissingHandlerError, MissingInsertHandlerError, MissingMutationFunctionError, MissingUpdateArgumentError, MissingUpdateHandlerError, NegativeActiveSubscribersError, NoKeysPassedToDeleteError, NoKeysPassedToUpdateError, NoPendingSyncTransactionCommitError, NoPendingSyncTransactionWriteError, NonAggregateExpressionNotInGroupByError, NonRetriableError, OnMutateMustBeSynchronousError, OnlyOneSourceAllowedError, QueryBuilderError, QueryCompilationError, QueryMustHaveFromClauseError, QueryOptimizerError, SchemaMustBeSynchronousError, SchemaValidationError, SerializationError, SetWindowRequiresOrderByError, StorageError, StorageKeyRequiredError, SubQueryMustHaveFromClauseError, SubscriptionNotFoundError, SyncCleanupError, SyncTransactionAlreadyCommittedError, SyncTransactionAlreadyCommittedWriteError, TanStackDBError, TransactionAlreadyCompletedRollbackError, TransactionError, TransactionNotPendingCommitError, TransactionNotPendingMutateError, UndefinedKeyError, UnknownExpressionTypeError, UnknownFunctionError, UnknownHavingExpressionTypeError, UnsupportedAggregateFunctionError, UnsupportedFromTypeError, UnsupportedJoinSourceTypeError, UnsupportedJoinTypeError, UnsupportedRootScalarSelectError, UpdateKeyNotFoundError, WhereClauseConversionError } from "./errors.js";
10
10
  import { deepEquals } from "./utils.js";
11
11
  import { createPacedMutations } from "./paced-mutations.js";
12
- import { BaseIndex, IndexOperation } from "./indexes/base-index.js";
12
+ import { hasVirtualProps } from "./virtual-props.js";
13
+ import { BaseIndex } from "./indexes/base-index.js";
14
+ import { BasicIndex } from "./indexes/basic-index.js";
13
15
  import { BTreeIndex } from "./indexes/btree-index.js";
14
- import { IndexProxy, LazyIndexWrapper } from "./indexes/lazy-index.js";
16
+ import { ReverseIndex } from "./indexes/reverse-index.js";
17
+ import { findIndexForField, optimizeExpressionWithIndexes } from "./utils/index-optimization.js";
18
+ import { clearQueryPatterns, configureIndexDevMode, getIndexDevModeConfig, getQueryPatterns, isDevModeEnabled, trackQuery } from "./indexes/index-registry.js";
15
19
  import { extractFieldPath, extractSimpleComparisons, extractValue, parseLoadSubsetOptions, parseOrderByExpression, parseWhereExpression, walkExpression } from "./query/expression-helpers.js";
16
20
  import { createEffect } from "./query/effect.js";
17
- import { add, and, avg, coalesce, concat, count, eq, gt, gte, ilike, inArray, isNull, isUndefined, length, like, lower, lt, lte, max, min, not, operators, or, sum, upper } from "./query/builder/functions.js";
21
+ import { add, and, avg, coalesce, concat, count, eq, gt, gte, ilike, inArray, isNull, isUndefined, length, like, lower, lt, lte, max, min, not, operators, or, sum, toArray, upper } from "./query/builder/functions.js";
18
22
  import { BaseQueryBuilder, Query } from "./query/builder/index.js";
19
23
  import { DeduplicatedLoadSubset } from "./query/subset-dedupe.js";
24
+ import { compileExpression, compileSingleRowExpression, toBooleanPredicate } from "./query/compiler/evaluators.js";
20
25
  import { compileQuery } from "./query/compiler/index.js";
21
26
  import { createLiveQueryCollection, liveQueryCollectionOptions } from "./query/live-query-collection.js";
22
27
  import { debounceStrategy } from "./strategies/debounceStrategy.js";
@@ -30,6 +35,7 @@ export {
30
35
  BTreeIndex,
31
36
  BaseIndex,
32
37
  BaseQueryBuilder,
38
+ BasicIndex,
33
39
  CannotCombineEmptyExpressionListError,
34
40
  CollectionConfigurationError,
35
41
  CollectionImpl,
@@ -52,8 +58,6 @@ export {
52
58
  GroupByError,
53
59
  HavingRequiresGroupByError,
54
60
  ir as IR,
55
- IndexOperation,
56
- IndexProxy,
57
61
  InvalidCollectionStatusTransitionError,
58
62
  InvalidJoinCondition,
59
63
  InvalidJoinConditionLeftSourceError,
@@ -71,7 +75,6 @@ export {
71
75
  JoinConditionMustBeEqualityError,
72
76
  JoinError,
73
77
  KeyUpdateNotAllowedError,
74
- LazyIndexWrapper,
75
78
  LimitOffsetRequireOrderByError,
76
79
  LocalStorageCollectionError,
77
80
  MissingAliasInputsError,
@@ -95,6 +98,7 @@ export {
95
98
  QueryCompilationError,
96
99
  QueryMustHaveFromClauseError,
97
100
  QueryOptimizerError,
101
+ ReverseIndex,
98
102
  SchemaMustBeSynchronousError,
99
103
  SchemaValidationError,
100
104
  SerializationError,
@@ -120,14 +124,19 @@ export {
120
124
  UnsupportedFromTypeError,
121
125
  UnsupportedJoinSourceTypeError,
122
126
  UnsupportedJoinTypeError,
127
+ UnsupportedRootScalarSelectError,
123
128
  UpdateKeyNotFoundError,
124
129
  WhereClauseConversionError,
125
130
  add,
126
131
  and,
127
132
  avg,
133
+ clearQueryPatterns,
128
134
  coalesce,
135
+ compileExpression,
129
136
  compileQuery,
137
+ compileSingleRowExpression,
130
138
  concat,
139
+ configureIndexDevMode,
131
140
  count,
132
141
  createArrayChangeProxy,
133
142
  createChangeProxy,
@@ -143,11 +152,16 @@ export {
143
152
  extractFieldPath,
144
153
  extractSimpleComparisons,
145
154
  extractValue,
155
+ findIndexForField,
146
156
  getActiveTransaction,
157
+ getIndexDevModeConfig,
158
+ getQueryPatterns,
147
159
  gt,
148
160
  gte,
161
+ hasVirtualProps,
149
162
  ilike,
150
163
  inArray,
164
+ isDevModeEnabled,
151
165
  isLimitSubset,
152
166
  isNull,
153
167
  isOffsetLimitSubset,
@@ -168,6 +182,7 @@ export {
168
182
  minusWherePredicates,
169
183
  not,
170
184
  operators,
185
+ optimizeExpressionWithIndexes,
171
186
  or,
172
187
  parseLoadSubsetOptions,
173
188
  parseOrderByExpression,
@@ -176,6 +191,9 @@ export {
176
191
  queueStrategy,
177
192
  sum,
178
193
  throttleStrategy,
194
+ toArray,
195
+ toBooleanPredicate,
196
+ trackQuery,
179
197
  unionWherePredicates,
180
198
  upper,
181
199
  walkExpression,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}