@tanstack/db 0.5.11 → 0.5.13

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 (225) hide show
  1. package/dist/cjs/SortedMap.cjs +40 -26
  2. package/dist/cjs/SortedMap.cjs.map +1 -1
  3. package/dist/cjs/SortedMap.d.cts +10 -15
  4. package/dist/cjs/collection/change-events.cjs.map +1 -1
  5. package/dist/cjs/collection/changes.cjs +2 -0
  6. package/dist/cjs/collection/changes.cjs.map +1 -1
  7. package/dist/cjs/collection/events.cjs.map +1 -1
  8. package/dist/cjs/collection/events.d.cts +12 -4
  9. package/dist/cjs/collection/index.cjs +2 -1
  10. package/dist/cjs/collection/index.cjs.map +1 -1
  11. package/dist/cjs/collection/indexes.cjs.map +1 -1
  12. package/dist/cjs/collection/lifecycle.cjs.map +1 -1
  13. package/dist/cjs/collection/mutations.cjs +5 -2
  14. package/dist/cjs/collection/mutations.cjs.map +1 -1
  15. package/dist/cjs/collection/state.cjs +6 -5
  16. package/dist/cjs/collection/state.cjs.map +1 -1
  17. package/dist/cjs/collection/state.d.cts +4 -1
  18. package/dist/cjs/collection/subscription.cjs +91 -57
  19. package/dist/cjs/collection/subscription.cjs.map +1 -1
  20. package/dist/cjs/collection/subscription.d.cts +26 -4
  21. package/dist/cjs/collection/sync.cjs +11 -6
  22. package/dist/cjs/collection/sync.cjs.map +1 -1
  23. package/dist/cjs/errors.cjs +9 -0
  24. package/dist/cjs/errors.cjs.map +1 -1
  25. package/dist/cjs/errors.d.cts +3 -0
  26. package/dist/cjs/event-emitter.cjs.map +1 -1
  27. package/dist/cjs/index.cjs +2 -0
  28. package/dist/cjs/index.cjs.map +1 -1
  29. package/dist/cjs/index.d.cts +1 -1
  30. package/dist/cjs/indexes/auto-index.cjs.map +1 -1
  31. package/dist/cjs/indexes/base-index.cjs.map +1 -1
  32. package/dist/cjs/indexes/btree-index.cjs +8 -6
  33. package/dist/cjs/indexes/btree-index.cjs.map +1 -1
  34. package/dist/cjs/indexes/lazy-index.cjs.map +1 -1
  35. package/dist/cjs/indexes/reverse-index.cjs.map +1 -1
  36. package/dist/cjs/local-only.cjs.map +1 -1
  37. package/dist/cjs/local-storage.cjs.map +1 -1
  38. package/dist/cjs/optimistic-action.cjs.map +1 -1
  39. package/dist/cjs/paced-mutations.cjs.map +1 -1
  40. package/dist/cjs/proxy.cjs.map +1 -1
  41. package/dist/cjs/query/builder/functions.cjs.map +1 -1
  42. package/dist/cjs/query/builder/index.cjs.map +1 -1
  43. package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -1
  44. package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
  45. package/dist/cjs/query/compiler/expressions.cjs.map +1 -1
  46. package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
  47. package/dist/cjs/query/compiler/index.cjs.map +1 -1
  48. package/dist/cjs/query/compiler/joins.cjs.map +1 -1
  49. package/dist/cjs/query/compiler/order-by.cjs +91 -38
  50. package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
  51. package/dist/cjs/query/compiler/order-by.d.cts +6 -2
  52. package/dist/cjs/query/compiler/select.cjs.map +1 -1
  53. package/dist/cjs/query/expression-helpers.cjs.map +1 -1
  54. package/dist/cjs/query/index.d.cts +1 -1
  55. package/dist/cjs/query/ir.cjs.map +1 -1
  56. package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
  57. package/dist/cjs/query/live/collection-registry.cjs.map +1 -1
  58. package/dist/cjs/query/live/collection-subscriber.cjs +30 -15
  59. package/dist/cjs/query/live/collection-subscriber.cjs.map +1 -1
  60. package/dist/cjs/query/live/internal.cjs.map +1 -1
  61. package/dist/cjs/query/live-query-collection.cjs.map +1 -1
  62. package/dist/cjs/query/optimizer.cjs.map +1 -1
  63. package/dist/cjs/query/predicate-utils.cjs +19 -2
  64. package/dist/cjs/query/predicate-utils.cjs.map +1 -1
  65. package/dist/cjs/query/predicate-utils.d.cts +32 -1
  66. package/dist/cjs/query/subset-dedupe.cjs.map +1 -1
  67. package/dist/cjs/scheduler.cjs.map +1 -1
  68. package/dist/cjs/strategies/debounceStrategy.cjs.map +1 -1
  69. package/dist/cjs/strategies/queueStrategy.cjs.map +1 -1
  70. package/dist/cjs/strategies/throttleStrategy.cjs.map +1 -1
  71. package/dist/cjs/transactions.cjs.map +1 -1
  72. package/dist/cjs/types.d.cts +53 -8
  73. package/dist/cjs/utils/browser-polyfills.cjs.map +1 -1
  74. package/dist/cjs/utils/btree.cjs.map +1 -1
  75. package/dist/cjs/utils/comparison.cjs.map +1 -1
  76. package/dist/cjs/utils/cursor.cjs +39 -0
  77. package/dist/cjs/utils/cursor.cjs.map +1 -0
  78. package/dist/cjs/utils/cursor.d.cts +18 -0
  79. package/dist/cjs/utils/index-optimization.cjs.map +1 -1
  80. package/dist/cjs/utils.cjs.map +1 -1
  81. package/dist/esm/SortedMap.d.ts +10 -15
  82. package/dist/esm/SortedMap.js +40 -26
  83. package/dist/esm/SortedMap.js.map +1 -1
  84. package/dist/esm/collection/change-events.js.map +1 -1
  85. package/dist/esm/collection/changes.js +2 -0
  86. package/dist/esm/collection/changes.js.map +1 -1
  87. package/dist/esm/collection/events.d.ts +12 -4
  88. package/dist/esm/collection/events.js.map +1 -1
  89. package/dist/esm/collection/index.js +2 -1
  90. package/dist/esm/collection/index.js.map +1 -1
  91. package/dist/esm/collection/indexes.js.map +1 -1
  92. package/dist/esm/collection/lifecycle.js.map +1 -1
  93. package/dist/esm/collection/mutations.js +6 -3
  94. package/dist/esm/collection/mutations.js.map +1 -1
  95. package/dist/esm/collection/state.d.ts +4 -1
  96. package/dist/esm/collection/state.js +6 -5
  97. package/dist/esm/collection/state.js.map +1 -1
  98. package/dist/esm/collection/subscription.d.ts +26 -4
  99. package/dist/esm/collection/subscription.js +92 -58
  100. package/dist/esm/collection/subscription.js.map +1 -1
  101. package/dist/esm/collection/sync.js +11 -6
  102. package/dist/esm/collection/sync.js.map +1 -1
  103. package/dist/esm/errors.d.ts +3 -0
  104. package/dist/esm/errors.js +9 -0
  105. package/dist/esm/errors.js.map +1 -1
  106. package/dist/esm/event-emitter.js.map +1 -1
  107. package/dist/esm/index.d.ts +1 -1
  108. package/dist/esm/index.js +4 -2
  109. package/dist/esm/indexes/auto-index.js.map +1 -1
  110. package/dist/esm/indexes/base-index.js.map +1 -1
  111. package/dist/esm/indexes/btree-index.js +8 -6
  112. package/dist/esm/indexes/btree-index.js.map +1 -1
  113. package/dist/esm/indexes/lazy-index.js.map +1 -1
  114. package/dist/esm/indexes/reverse-index.js.map +1 -1
  115. package/dist/esm/local-only.js.map +1 -1
  116. package/dist/esm/local-storage.js.map +1 -1
  117. package/dist/esm/optimistic-action.js.map +1 -1
  118. package/dist/esm/paced-mutations.js.map +1 -1
  119. package/dist/esm/proxy.js.map +1 -1
  120. package/dist/esm/query/builder/functions.js.map +1 -1
  121. package/dist/esm/query/builder/index.js.map +1 -1
  122. package/dist/esm/query/builder/ref-proxy.js.map +1 -1
  123. package/dist/esm/query/compiler/evaluators.js.map +1 -1
  124. package/dist/esm/query/compiler/expressions.js.map +1 -1
  125. package/dist/esm/query/compiler/group-by.js.map +1 -1
  126. package/dist/esm/query/compiler/index.js.map +1 -1
  127. package/dist/esm/query/compiler/joins.js.map +1 -1
  128. package/dist/esm/query/compiler/order-by.d.ts +6 -2
  129. package/dist/esm/query/compiler/order-by.js +91 -38
  130. package/dist/esm/query/compiler/order-by.js.map +1 -1
  131. package/dist/esm/query/compiler/select.js.map +1 -1
  132. package/dist/esm/query/expression-helpers.js.map +1 -1
  133. package/dist/esm/query/index.d.ts +1 -1
  134. package/dist/esm/query/ir.js.map +1 -1
  135. package/dist/esm/query/live/collection-config-builder.js.map +1 -1
  136. package/dist/esm/query/live/collection-registry.js.map +1 -1
  137. package/dist/esm/query/live/collection-subscriber.js +30 -15
  138. package/dist/esm/query/live/collection-subscriber.js.map +1 -1
  139. package/dist/esm/query/live/internal.js.map +1 -1
  140. package/dist/esm/query/live-query-collection.js.map +1 -1
  141. package/dist/esm/query/optimizer.js.map +1 -1
  142. package/dist/esm/query/predicate-utils.d.ts +32 -1
  143. package/dist/esm/query/predicate-utils.js +19 -2
  144. package/dist/esm/query/predicate-utils.js.map +1 -1
  145. package/dist/esm/query/subset-dedupe.js.map +1 -1
  146. package/dist/esm/scheduler.js.map +1 -1
  147. package/dist/esm/strategies/debounceStrategy.js.map +1 -1
  148. package/dist/esm/strategies/queueStrategy.js.map +1 -1
  149. package/dist/esm/strategies/throttleStrategy.js.map +1 -1
  150. package/dist/esm/transactions.js.map +1 -1
  151. package/dist/esm/types.d.ts +53 -8
  152. package/dist/esm/utils/browser-polyfills.js.map +1 -1
  153. package/dist/esm/utils/btree.js.map +1 -1
  154. package/dist/esm/utils/comparison.js.map +1 -1
  155. package/dist/esm/utils/cursor.d.ts +18 -0
  156. package/dist/esm/utils/cursor.js +39 -0
  157. package/dist/esm/utils/cursor.js.map +1 -0
  158. package/dist/esm/utils/index-optimization.js.map +1 -1
  159. package/dist/esm/utils.js.map +1 -1
  160. package/package.json +30 -28
  161. package/src/SortedMap.ts +50 -31
  162. package/src/collection/change-events.ts +20 -20
  163. package/src/collection/changes.ts +16 -12
  164. package/src/collection/events.ts +20 -10
  165. package/src/collection/index.ts +47 -46
  166. package/src/collection/indexes.ts +14 -14
  167. package/src/collection/lifecycle.ts +16 -16
  168. package/src/collection/mutations.ts +25 -20
  169. package/src/collection/state.ts +43 -36
  170. package/src/collection/subscription.ts +171 -90
  171. package/src/collection/sync.ts +34 -22
  172. package/src/duplicate-instance-check.ts +1 -1
  173. package/src/errors.ts +49 -40
  174. package/src/event-emitter.ts +5 -5
  175. package/src/index.ts +21 -21
  176. package/src/indexes/auto-index.ts +11 -11
  177. package/src/indexes/base-index.ts +13 -13
  178. package/src/indexes/btree-index.ts +21 -17
  179. package/src/indexes/index-options.ts +3 -3
  180. package/src/indexes/lazy-index.ts +8 -8
  181. package/src/indexes/reverse-index.ts +5 -5
  182. package/src/local-only.ts +12 -12
  183. package/src/local-storage.ts +17 -17
  184. package/src/optimistic-action.ts +5 -5
  185. package/src/paced-mutations.ts +6 -6
  186. package/src/proxy.ts +43 -43
  187. package/src/query/builder/functions.ts +28 -28
  188. package/src/query/builder/index.ts +22 -22
  189. package/src/query/builder/ref-proxy.ts +4 -4
  190. package/src/query/builder/types.ts +8 -8
  191. package/src/query/compiler/evaluators.ts +9 -9
  192. package/src/query/compiler/expressions.ts +6 -6
  193. package/src/query/compiler/group-by.ts +24 -24
  194. package/src/query/compiler/index.ts +44 -44
  195. package/src/query/compiler/joins.ts +37 -37
  196. package/src/query/compiler/order-by.ts +170 -77
  197. package/src/query/compiler/select.ts +13 -13
  198. package/src/query/compiler/types.ts +2 -2
  199. package/src/query/expression-helpers.ts +16 -16
  200. package/src/query/index.ts +10 -9
  201. package/src/query/ir.ts +13 -13
  202. package/src/query/live/collection-config-builder.ts +53 -53
  203. package/src/query/live/collection-registry.ts +6 -6
  204. package/src/query/live/collection-subscriber.ts +87 -48
  205. package/src/query/live/internal.ts +1 -1
  206. package/src/query/live/types.ts +4 -4
  207. package/src/query/live-query-collection.ts +15 -15
  208. package/src/query/optimizer.ts +29 -29
  209. package/src/query/predicate-utils.ts +105 -50
  210. package/src/query/subset-dedupe.ts +6 -6
  211. package/src/scheduler.ts +3 -3
  212. package/src/strategies/debounceStrategy.ts +6 -6
  213. package/src/strategies/index.ts +4 -4
  214. package/src/strategies/queueStrategy.ts +5 -5
  215. package/src/strategies/throttleStrategy.ts +6 -6
  216. package/src/strategies/types.ts +2 -2
  217. package/src/transactions.ts +9 -9
  218. package/src/types.ts +76 -18
  219. package/src/utils/array-utils.ts +1 -1
  220. package/src/utils/browser-polyfills.ts +2 -2
  221. package/src/utils/btree.ts +22 -22
  222. package/src/utils/comparison.ts +3 -3
  223. package/src/utils/cursor.ts +78 -0
  224. package/src/utils/index-optimization.ts +14 -14
  225. package/src/utils.ts +4 -4
@@ -7,22 +7,23 @@ import {
7
7
  SyncCleanupError,
8
8
  SyncTransactionAlreadyCommittedError,
9
9
  SyncTransactionAlreadyCommittedWriteError,
10
- } from "../errors"
11
- import { deepEquals } from "../utils"
12
- import { LIVE_QUERY_INTERNAL } from "../query/live/internal.js"
13
- import type { StandardSchemaV1 } from "@standard-schema/spec"
10
+ } from '../errors'
11
+ import { deepEquals } from '../utils'
12
+ import { LIVE_QUERY_INTERNAL } from '../query/live/internal.js'
13
+ import type { StandardSchemaV1 } from '@standard-schema/spec'
14
14
  import type {
15
- ChangeMessage,
15
+ ChangeMessageOrDeleteKeyMessage,
16
16
  CleanupFn,
17
17
  CollectionConfig,
18
18
  LoadSubsetOptions,
19
+ OptimisticChangeMessage,
19
20
  SyncConfigRes,
20
- } from "../types"
21
- import type { CollectionImpl } from "./index.js"
22
- import type { CollectionStateManager } from "./state"
23
- import type { CollectionLifecycleManager } from "./lifecycle"
24
- import type { CollectionEventsManager } from "./events.js"
25
- import type { LiveQueryCollectionUtils } from "../query/live/collection-config-builder.js"
21
+ } from '../types'
22
+ import type { CollectionImpl } from './index.js'
23
+ import type { CollectionStateManager } from './state'
24
+ import type { CollectionLifecycleManager } from './lifecycle'
25
+ import type { CollectionEventsManager } from './events.js'
26
+ import type { LiveQueryCollectionUtils } from '../query/live/collection-config-builder.js'
26
27
 
27
28
  export class CollectionSyncManager<
28
29
  TOutput extends object = Record<string, unknown>,
@@ -94,7 +95,12 @@ export class CollectionSyncManager<
94
95
  deletedKeys: new Set(),
95
96
  })
96
97
  },
97
- write: (messageWithoutKey: Omit<ChangeMessage<TOutput>, `key`>) => {
98
+ write: (
99
+ messageWithOptionalKey: ChangeMessageOrDeleteKeyMessage<
100
+ TOutput,
101
+ TKey
102
+ >,
103
+ ) => {
98
104
  const pendingTransaction =
99
105
  this.state.pendingSyncedTransactions[
100
106
  this.state.pendingSyncedTransactions.length - 1
@@ -105,12 +111,18 @@ export class CollectionSyncManager<
105
111
  if (pendingTransaction.committed) {
106
112
  throw new SyncTransactionAlreadyCommittedWriteError()
107
113
  }
108
- const key = this.config.getKey(messageWithoutKey.value)
109
114
 
110
- let messageType = messageWithoutKey.type
115
+ let key: TKey | undefined = undefined
116
+ if (`key` in messageWithOptionalKey) {
117
+ key = messageWithOptionalKey.key
118
+ } else {
119
+ key = this.config.getKey(messageWithOptionalKey.value)
120
+ }
121
+
122
+ let messageType = messageWithOptionalKey.type
111
123
 
112
124
  // Check if an item with this key already exists when inserting
113
- if (messageWithoutKey.type === `insert`) {
125
+ if (messageWithOptionalKey.type === `insert`) {
114
126
  const insertingIntoExistingSynced = this.state.syncedData.has(key)
115
127
  const hasPendingDeleteForKey =
116
128
  pendingTransaction.deletedKeys.has(key)
@@ -124,7 +136,7 @@ export class CollectionSyncManager<
124
136
  const existingValue = this.state.syncedData.get(key)
125
137
  if (
126
138
  existingValue !== undefined &&
127
- deepEquals(existingValue, messageWithoutKey.value)
139
+ deepEquals(existingValue, messageWithOptionalKey.value)
128
140
  ) {
129
141
  // The "insert" is an echo of a value we already have locally.
130
142
  // Treat it as an update so we preserve optimistic intent without
@@ -142,11 +154,11 @@ export class CollectionSyncManager<
142
154
  }
143
155
  }
144
156
 
145
- const message: ChangeMessage<TOutput> = {
146
- ...messageWithoutKey,
157
+ const message = {
158
+ ...messageWithOptionalKey,
147
159
  type: messageType,
148
160
  key,
149
- }
161
+ } as OptimisticChangeMessage<TOutput, TKey>
150
162
  pendingTransaction.operations.push(message)
151
163
 
152
164
  if (messageType === `delete`) {
@@ -202,7 +214,7 @@ export class CollectionSyncManager<
202
214
  deletes: new Set(this.state.optimisticDeletes),
203
215
  }
204
216
  },
205
- })
217
+ }),
206
218
  )
207
219
 
208
220
  // Store cleanup function if provided
@@ -218,7 +230,7 @@ export class CollectionSyncManager<
218
230
  if (this.syncMode === `on-demand` && !this.syncLoadSubsetFn) {
219
231
  throw new CollectionConfigurationError(
220
232
  `Collection "${this.id}" is configured with syncMode "on-demand" but the sync function did not return a loadSubset handler. ` +
221
- `Either provide a loadSubset handler or use syncMode "eager".`
233
+ `Either provide a loadSubset handler or use syncMode "eager".`,
222
234
  )
223
235
  }
224
236
  } catch (error) {
@@ -242,7 +254,7 @@ export class CollectionSyncManager<
242
254
  `${this.id ? `[${this.id}] ` : ``}Calling .preload() on a collection with syncMode "on-demand" is a no-op. ` +
243
255
  `In on-demand mode, data is only loaded when queries request it. ` +
244
256
  `Instead, create a live query and call .preload() on that to load the specific data you need. ` +
245
- `See https://tanstack.com/blog/tanstack-db-0.5-query-driven-sync for more details.`
257
+ `See https://tanstack.com/blog/tanstack-db-0.5-query-driven-sync for more details.`,
246
258
  )
247
259
  }
248
260
 
@@ -1,4 +1,4 @@
1
- import { DuplicateDbInstanceError } from "./errors"
1
+ import { DuplicateDbInstanceError } from './errors'
2
2
 
3
3
  /**
4
4
  * Check if we're in a browser top-level window (not a worker, SSR, or iframe).
package/src/errors.ts CHANGED
@@ -28,7 +28,7 @@ export class SchemaValidationError extends TanStackDBError {
28
28
  message: string
29
29
  path?: ReadonlyArray<string | number | symbol>
30
30
  }>,
31
- message?: string
31
+ message?: string,
32
32
  ) {
33
33
  const defaultMessage = `${type === `insert` ? `Insert` : `Update`} validation failed: ${issues
34
34
  .map((issue) => `\n- ${issue.message} - path: ${issue.path}`)
@@ -61,7 +61,7 @@ export class DuplicateDbInstanceError extends TanStackDBError {
61
61
  `3. Clear node_modules and lockfile, then reinstall\n\n` +
62
62
  `To temporarily disable this check (not recommended):\n` +
63
63
  `Set environment variable: TANSTACK_DB_DISABLE_DUP_CHECK=1\n\n` +
64
- `See: https://tanstack.com/db/latest/docs/troubleshooting#duplicate-instances`
64
+ `See: https://tanstack.com/db/latest/docs/troubleshooting#duplicate-instances`,
65
65
  )
66
66
  this.name = `DuplicateDbInstanceError`
67
67
  }
@@ -110,7 +110,7 @@ export class CollectionStateError extends TanStackDBError {
110
110
  export class CollectionInErrorStateError extends CollectionStateError {
111
111
  constructor(operation: string, collectionId: string) {
112
112
  super(
113
- `Cannot perform ${operation} on collection "${collectionId}" - collection is in error state. Try calling cleanup() and restarting the collection.`
113
+ `Cannot perform ${operation} on collection "${collectionId}" - collection is in error state. Try calling cleanup() and restarting the collection.`,
114
114
  )
115
115
  }
116
116
  }
@@ -118,7 +118,7 @@ export class CollectionInErrorStateError extends CollectionStateError {
118
118
  export class InvalidCollectionStatusTransitionError extends CollectionStateError {
119
119
  constructor(from: string, to: string, collectionId: string) {
120
120
  super(
121
- `Invalid collection status transition from "${from}" to "${to}" for collection "${collectionId}"`
121
+ `Invalid collection status transition from "${from}" to "${to}" for collection "${collectionId}"`,
122
122
  )
123
123
  }
124
124
  }
@@ -146,7 +146,16 @@ export class CollectionOperationError extends TanStackDBError {
146
146
  export class UndefinedKeyError extends CollectionOperationError {
147
147
  constructor(item: any) {
148
148
  super(
149
- `An object was created without a defined key: ${JSON.stringify(item)}`
149
+ `An object was created without a defined key: ${JSON.stringify(item)}`,
150
+ )
151
+ }
152
+ }
153
+
154
+ export class InvalidKeyError extends CollectionOperationError {
155
+ constructor(key: unknown, item: unknown) {
156
+ const keyType = key === null ? `null` : typeof key
157
+ super(
158
+ `getKey returned an invalid key type. Expected string or number, but got ${keyType}: ${JSON.stringify(key)}. Item: ${JSON.stringify(item)}`,
150
159
  )
151
160
  }
152
161
  }
@@ -154,7 +163,7 @@ export class UndefinedKeyError extends CollectionOperationError {
154
163
  export class DuplicateKeyError extends CollectionOperationError {
155
164
  constructor(key: string | number) {
156
165
  super(
157
- `Cannot insert document with ID "${key}" because it already exists in the collection`
166
+ `Cannot insert document with ID "${key}" because it already exists in the collection`,
158
167
  )
159
168
  }
160
169
  }
@@ -163,7 +172,7 @@ export class DuplicateKeySyncError extends CollectionOperationError {
163
172
  constructor(
164
173
  key: string | number,
165
174
  collectionId: string,
166
- options?: { hasCustomGetKey?: boolean; hasJoins?: boolean }
175
+ options?: { hasCustomGetKey?: boolean; hasJoins?: boolean },
167
176
  ) {
168
177
  const baseMessage = `Cannot insert document with key "${key}" from sync because it already exists in the collection "${collectionId}"`
169
178
 
@@ -175,7 +184,7 @@ export class DuplicateKeySyncError extends CollectionOperationError {
175
184
  `Joined queries can produce multiple rows with the same key when relationships are not 1:1. ` +
176
185
  `Consider: (1) using a composite key in your getKey function (e.g., \`\${item.key1}-\${item.key2}\`), ` +
177
186
  `(2) ensuring your join produces unique rows per key, or (3) removing the custom getKey ` +
178
- `to use the default composite key behavior.`
187
+ `to use the default composite key behavior.`,
179
188
  )
180
189
  } else {
181
190
  super(baseMessage)
@@ -198,7 +207,7 @@ export class NoKeysPassedToUpdateError extends CollectionOperationError {
198
207
  export class UpdateKeyNotFoundError extends CollectionOperationError {
199
208
  constructor(key: string | number) {
200
209
  super(
201
- `The key "${key}" was passed to update but an object for this key was not found in the collection`
210
+ `The key "${key}" was passed to update but an object for this key was not found in the collection`,
202
211
  )
203
212
  }
204
213
  }
@@ -206,7 +215,7 @@ export class UpdateKeyNotFoundError extends CollectionOperationError {
206
215
  export class KeyUpdateNotAllowedError extends CollectionOperationError {
207
216
  constructor(originalKey: string | number, newKey: string | number) {
208
217
  super(
209
- `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.`
218
+ `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.`,
210
219
  )
211
220
  }
212
221
  }
@@ -220,7 +229,7 @@ export class NoKeysPassedToDeleteError extends CollectionOperationError {
220
229
  export class DeleteKeyNotFoundError extends CollectionOperationError {
221
230
  constructor(key: string | number) {
222
231
  super(
223
- `Collection.delete was called with key '${key}' but there is no item in the collection with this key`
232
+ `Collection.delete was called with key '${key}' but there is no item in the collection with this key`,
224
233
  )
225
234
  }
226
235
  }
@@ -236,7 +245,7 @@ export class MissingHandlerError extends TanStackDBError {
236
245
  export class MissingInsertHandlerError extends MissingHandlerError {
237
246
  constructor() {
238
247
  super(
239
- `Collection.insert called directly (not within an explicit transaction) but no 'onInsert' handler is configured.`
248
+ `Collection.insert called directly (not within an explicit transaction) but no 'onInsert' handler is configured.`,
240
249
  )
241
250
  }
242
251
  }
@@ -244,7 +253,7 @@ export class MissingInsertHandlerError extends MissingHandlerError {
244
253
  export class MissingUpdateHandlerError extends MissingHandlerError {
245
254
  constructor() {
246
255
  super(
247
- `Collection.update called directly (not within an explicit transaction) but no 'onUpdate' handler is configured.`
256
+ `Collection.update called directly (not within an explicit transaction) but no 'onUpdate' handler is configured.`,
248
257
  )
249
258
  }
250
259
  }
@@ -252,7 +261,7 @@ export class MissingUpdateHandlerError extends MissingHandlerError {
252
261
  export class MissingDeleteHandlerError extends MissingHandlerError {
253
262
  constructor() {
254
263
  super(
255
- `Collection.delete called directly (not within an explicit transaction) but no 'onDelete' handler is configured.`
264
+ `Collection.delete called directly (not within an explicit transaction) but no 'onDelete' handler is configured.`,
256
265
  )
257
266
  }
258
267
  }
@@ -274,7 +283,7 @@ export class MissingMutationFunctionError extends TransactionError {
274
283
  export class OnMutateMustBeSynchronousError extends TransactionError {
275
284
  constructor() {
276
285
  super(
277
- `onMutate must be synchronous and cannot return a promise. Remove async/await or returned promises from onMutate.`
286
+ `onMutate must be synchronous and cannot return a promise. Remove async/await or returned promises from onMutate.`,
278
287
  )
279
288
  this.name = `OnMutateMustBeSynchronousError`
280
289
  }
@@ -283,7 +292,7 @@ export class OnMutateMustBeSynchronousError extends TransactionError {
283
292
  export class TransactionNotPendingMutateError extends TransactionError {
284
293
  constructor() {
285
294
  super(
286
- `You can no longer call .mutate() as the transaction is no longer pending`
295
+ `You can no longer call .mutate() as the transaction is no longer pending`,
287
296
  )
288
297
  }
289
298
  }
@@ -291,7 +300,7 @@ export class TransactionNotPendingMutateError extends TransactionError {
291
300
  export class TransactionAlreadyCompletedRollbackError extends TransactionError {
292
301
  constructor() {
293
302
  super(
294
- `You can no longer call .rollback() as the transaction is already completed`
303
+ `You can no longer call .rollback() as the transaction is already completed`,
295
304
  )
296
305
  }
297
306
  }
@@ -299,7 +308,7 @@ export class TransactionAlreadyCompletedRollbackError extends TransactionError {
299
308
  export class TransactionNotPendingCommitError extends TransactionError {
300
309
  constructor() {
301
310
  super(
302
- `You can no longer call .commit() as the transaction is no longer pending`
311
+ `You can no longer call .commit() as the transaction is no longer pending`,
303
312
  )
304
313
  }
305
314
  }
@@ -313,7 +322,7 @@ export class NoPendingSyncTransactionWriteError extends TransactionError {
313
322
  export class SyncTransactionAlreadyCommittedWriteError extends TransactionError {
314
323
  constructor() {
315
324
  super(
316
- `The pending sync transaction is already committed, you can't still write to it.`
325
+ `The pending sync transaction is already committed, you can't still write to it.`,
317
326
  )
318
327
  }
319
328
  }
@@ -327,7 +336,7 @@ export class NoPendingSyncTransactionCommitError extends TransactionError {
327
336
  export class SyncTransactionAlreadyCommittedError extends TransactionError {
328
337
  constructor() {
329
338
  super(
330
- `The pending sync transaction is already committed, you can't commit it again.`
339
+ `The pending sync transaction is already committed, you can't commit it again.`,
331
340
  )
332
341
  }
333
342
  }
@@ -355,7 +364,7 @@ export class SubQueryMustHaveFromClauseError extends QueryBuilderError {
355
364
  export class InvalidSourceError extends QueryBuilderError {
356
365
  constructor(alias: string) {
357
366
  super(
358
- `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.`
367
+ `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.`,
359
368
  )
360
369
  }
361
370
  }
@@ -364,7 +373,7 @@ export class InvalidSourceTypeError extends QueryBuilderError {
364
373
  constructor(context: string, type: string) {
365
374
  super(
366
375
  `Invalid source for ${context}: Expected an object with a single key-value pair like { alias: collection }. ` +
367
- `For example: .from({ todos: todosCollection }). Got: ${type}`
376
+ `For example: .from({ todos: todosCollection }). Got: ${type}`,
368
377
  )
369
378
  }
370
379
  }
@@ -404,7 +413,7 @@ export class HavingRequiresGroupByError extends QueryCompilationError {
404
413
  export class LimitOffsetRequireOrderByError extends QueryCompilationError {
405
414
  constructor() {
406
415
  super(
407
- `LIMIT and OFFSET require an ORDER BY clause to ensure deterministic results`
416
+ `LIMIT and OFFSET require an ORDER BY clause to ensure deterministic results`,
408
417
  )
409
418
  }
410
419
  }
@@ -417,7 +426,7 @@ export class CollectionInputNotFoundError extends QueryCompilationError {
417
426
  constructor(
418
427
  alias: string,
419
428
  collectionId?: string,
420
- availableKeys?: Array<string>
429
+ availableKeys?: Array<string>,
421
430
  ) {
422
431
  const details = collectionId
423
432
  ? `alias "${alias}" (collection "${collectionId}")`
@@ -440,7 +449,7 @@ export class DuplicateAliasInSubqueryError extends QueryCompilationError {
440
449
  `Subquery uses alias "${alias}" which is already used in the parent query. ` +
441
450
  `Each alias must be unique across parent and subquery contexts. ` +
442
451
  `Parent query aliases: ${parentAliases.join(`, `)}. ` +
443
- `Please rename "${alias}" in either the parent query or subquery to avoid conflicts.`
452
+ `Please rename "${alias}" in either the parent query or subquery to avoid conflicts.`,
444
453
  )
445
454
  }
446
455
  }
@@ -492,7 +501,7 @@ export class UnsupportedJoinTypeError extends JoinError {
492
501
  export class InvalidJoinConditionSameSourceError extends JoinError {
493
502
  constructor(sourceAlias: string) {
494
503
  super(
495
- `Invalid join condition: both expressions refer to the same source "${sourceAlias}"`
504
+ `Invalid join condition: both expressions refer to the same source "${sourceAlias}"`,
496
505
  )
497
506
  }
498
507
  }
@@ -506,7 +515,7 @@ export class InvalidJoinConditionSourceMismatchError extends JoinError {
506
515
  export class InvalidJoinConditionLeftSourceError extends JoinError {
507
516
  constructor(sourceAlias: string) {
508
517
  super(
509
- `Invalid join condition: left expression refers to an unavailable source "${sourceAlias}"`
518
+ `Invalid join condition: left expression refers to an unavailable source "${sourceAlias}"`,
510
519
  )
511
520
  }
512
521
  }
@@ -514,7 +523,7 @@ export class InvalidJoinConditionLeftSourceError extends JoinError {
514
523
  export class InvalidJoinConditionRightSourceError extends JoinError {
515
524
  constructor(sourceAlias: string) {
516
525
  super(
517
- `Invalid join condition: right expression does not refer to the joined source "${sourceAlias}"`
526
+ `Invalid join condition: right expression does not refer to the joined source "${sourceAlias}"`,
518
527
  )
519
528
  }
520
529
  }
@@ -542,7 +551,7 @@ export class GroupByError extends TanStackDBError {
542
551
  export class NonAggregateExpressionNotInGroupByError extends GroupByError {
543
552
  constructor(alias: string) {
544
553
  super(
545
- `Non-aggregate expression '${alias}' in SELECT must also appear in GROUP BY clause`
554
+ `Non-aggregate expression '${alias}' in SELECT must also appear in GROUP BY clause`,
546
555
  )
547
556
  }
548
557
  }
@@ -556,7 +565,7 @@ export class UnsupportedAggregateFunctionError extends GroupByError {
556
565
  export class AggregateFunctionNotInSelectError extends GroupByError {
557
566
  constructor(functionName: string) {
558
567
  super(
559
- `Aggregate function in HAVING clause must also be in SELECT clause: ${functionName}`
568
+ `Aggregate function in HAVING clause must also be in SELECT clause: ${functionName}`,
560
569
  )
561
570
  }
562
571
  }
@@ -578,7 +587,7 @@ export class StorageError extends TanStackDBError {
578
587
  export class SerializationError extends StorageError {
579
588
  constructor(operation: string, originalError: string) {
580
589
  super(
581
- `Cannot ${operation} item because it cannot be JSON serialized: ${originalError}`
590
+ `Cannot ${operation} item because it cannot be JSON serialized: ${originalError}`,
582
591
  )
583
592
  }
584
593
  }
@@ -600,7 +609,7 @@ export class StorageKeyRequiredError extends LocalStorageCollectionError {
600
609
  export class InvalidStorageDataFormatError extends LocalStorageCollectionError {
601
610
  constructor(storageKey: string, key: string) {
602
611
  super(
603
- `[LocalStorageCollection] Invalid data format in storage key "${storageKey}" for key "${key}".`
612
+ `[LocalStorageCollection] Invalid data format in storage key "${storageKey}" for key "${key}".`,
604
613
  )
605
614
  }
606
615
  }
@@ -608,7 +617,7 @@ export class InvalidStorageDataFormatError extends LocalStorageCollectionError {
608
617
  export class InvalidStorageObjectFormatError extends LocalStorageCollectionError {
609
618
  constructor(storageKey: string) {
610
619
  super(
611
- `[LocalStorageCollection] Invalid data format in storage key "${storageKey}". Expected object format.`
620
+ `[LocalStorageCollection] Invalid data format in storage key "${storageKey}". Expected object format.`,
612
621
  )
613
622
  }
614
623
  }
@@ -618,7 +627,7 @@ export class SyncCleanupError extends TanStackDBError {
618
627
  constructor(collectionId: string, error: Error | string) {
619
628
  const message = error instanceof Error ? error.message : String(error)
620
629
  super(
621
- `Collection "${collectionId}" sync cleanup function threw an error: ${message}`
630
+ `Collection "${collectionId}" sync cleanup function threw an error: ${message}`,
622
631
  )
623
632
  this.name = `SyncCleanupError`
624
633
  }
@@ -644,7 +653,7 @@ export class CannotCombineEmptyExpressionListError extends QueryOptimizerError {
644
653
  export class WhereClauseConversionError extends QueryOptimizerError {
645
654
  constructor(collectionId: string, alias: string) {
646
655
  super(
647
- `Failed to convert WHERE clause to collection filter for collection '${collectionId}' alias '${alias}'. This indicates a bug in the query optimization logic.`
656
+ `Failed to convert WHERE clause to collection filter for collection '${collectionId}' alias '${alias}'. This indicates a bug in the query optimization logic.`,
648
657
  )
649
658
  }
650
659
  }
@@ -658,10 +667,10 @@ export class SubscriptionNotFoundError extends QueryCompilationError {
658
667
  resolvedAlias: string,
659
668
  originalAlias: string,
660
669
  collectionId: string,
661
- availableAliases: Array<string>
670
+ availableAliases: Array<string>,
662
671
  ) {
663
672
  super(
664
- `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.`
673
+ `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.`,
665
674
  )
666
675
  }
667
676
  }
@@ -672,7 +681,7 @@ export class SubscriptionNotFoundError extends QueryCompilationError {
672
681
  export class AggregateNotSupportedError extends QueryCompilationError {
673
682
  constructor() {
674
683
  super(
675
- `Aggregate expressions are not supported in this context. Use GROUP BY clause for aggregates.`
684
+ `Aggregate expressions are not supported in this context. Use GROUP BY clause for aggregates.`,
676
685
  )
677
686
  }
678
687
  }
@@ -685,7 +694,7 @@ export class MissingAliasInputsError extends QueryCompilationError {
685
694
  constructor(missingAliases: Array<string>) {
686
695
  super(
687
696
  `Internal error: compiler returned aliases without inputs: ${missingAliases.join(`, `)}. ` +
688
- `This indicates a bug in query compilation. Please report this issue.`
697
+ `This indicates a bug in query compilation. Please report this issue.`,
689
698
  )
690
699
  }
691
700
  }
@@ -697,7 +706,7 @@ export class SetWindowRequiresOrderByError extends QueryCompilationError {
697
706
  constructor() {
698
707
  super(
699
708
  `setWindow() can only be called on collections with an ORDER BY clause. ` +
700
- `Add .orderBy() to your query to enable window movement.`
709
+ `Add .orderBy() to your query to enable window movement.`,
701
710
  )
702
711
  }
703
712
  }
@@ -16,7 +16,7 @@ export class EventEmitter<TEvents extends Record<string, any>> {
16
16
  */
17
17
  on<T extends keyof TEvents>(
18
18
  event: T,
19
- callback: (event: TEvents[T]) => void
19
+ callback: (event: TEvents[T]) => void,
20
20
  ): () => void {
21
21
  if (!this.listeners.has(event)) {
22
22
  this.listeners.set(event, new Set())
@@ -36,7 +36,7 @@ export class EventEmitter<TEvents extends Record<string, any>> {
36
36
  */
37
37
  once<T extends keyof TEvents>(
38
38
  event: T,
39
- callback: (event: TEvents[T]) => void
39
+ callback: (event: TEvents[T]) => void,
40
40
  ): () => void {
41
41
  const unsubscribe = this.on(event, (eventPayload) => {
42
42
  callback(eventPayload)
@@ -52,7 +52,7 @@ export class EventEmitter<TEvents extends Record<string, any>> {
52
52
  */
53
53
  off<T extends keyof TEvents>(
54
54
  event: T,
55
- callback: (event: TEvents[T]) => void
55
+ callback: (event: TEvents[T]) => void,
56
56
  ): void {
57
57
  this.listeners.get(event)?.delete(callback as (event: any) => void)
58
58
  }
@@ -65,7 +65,7 @@ export class EventEmitter<TEvents extends Record<string, any>> {
65
65
  */
66
66
  waitFor<T extends keyof TEvents>(
67
67
  event: T,
68
- timeout?: number
68
+ timeout?: number,
69
69
  ): Promise<TEvents[T]> {
70
70
  return new Promise((resolve, reject) => {
71
71
  let timeoutId: NodeJS.Timeout | undefined
@@ -95,7 +95,7 @@ export class EventEmitter<TEvents extends Record<string, any>> {
95
95
  */
96
96
  protected emitInner<T extends keyof TEvents>(
97
97
  event: T,
98
- eventPayload: TEvents[T]
98
+ eventPayload: TEvents[T],
99
99
  ): void {
100
100
  this.listeners.get(event)?.forEach((listener) => {
101
101
  try {
package/src/index.ts CHANGED
@@ -1,32 +1,32 @@
1
1
  // Re-export all public APIs
2
2
  // Re-export IR types under their own namespace
3
3
  // because custom collections need access to the IR types
4
- import * as IR from "./query/ir.js"
4
+ import * as IR from './query/ir.js'
5
5
 
6
- export * from "./collection/index.js"
7
- export * from "./SortedMap"
8
- export * from "./transactions"
9
- export * from "./types"
10
- export * from "./proxy"
11
- export * from "./query/index.js"
12
- export * from "./optimistic-action"
13
- export * from "./local-only"
14
- export * from "./local-storage"
15
- export * from "./errors"
16
- export { deepEquals } from "./utils"
17
- export * from "./paced-mutations"
18
- export * from "./strategies/index.js"
6
+ export * from './collection/index.js'
7
+ export * from './SortedMap'
8
+ export * from './transactions'
9
+ export * from './types'
10
+ export * from './proxy'
11
+ export * from './query/index.js'
12
+ export * from './optimistic-action'
13
+ export * from './local-only'
14
+ export * from './local-storage'
15
+ export * from './errors'
16
+ export { deepEquals } from './utils'
17
+ export * from './paced-mutations'
18
+ export * from './strategies/index.js'
19
19
 
20
20
  // Index system exports
21
- export * from "./indexes/base-index.js"
22
- export * from "./indexes/btree-index.js"
23
- export * from "./indexes/lazy-index.js"
24
- export { type IndexOptions } from "./indexes/index-options.js"
21
+ export * from './indexes/base-index.js'
22
+ export * from './indexes/btree-index.js'
23
+ export * from './indexes/lazy-index.js'
24
+ export { type IndexOptions } from './indexes/index-options.js'
25
25
 
26
26
  // Expression helpers
27
- export * from "./query/expression-helpers.js"
27
+ export * from './query/expression-helpers.js'
28
28
 
29
29
  // Re-export some stuff explicitly to ensure the type & value is exported
30
- export type { Collection } from "./collection/index.js"
30
+ export type { Collection } from './collection/index.js'
31
31
  export { IR }
32
- export { operators, type OperatorName } from "./query/builder/functions.js"
32
+ export { operators, type OperatorName } from './query/builder/functions.js'
@@ -1,8 +1,8 @@
1
- import { DEFAULT_COMPARE_OPTIONS } from "../utils"
2
- import { BTreeIndex } from "./btree-index"
3
- import type { CompareOptions } from "../query/builder/types"
4
- import type { BasicExpression } from "../query/ir"
5
- import type { CollectionImpl } from "../collection/index.js"
1
+ import { DEFAULT_COMPARE_OPTIONS } from '../utils'
2
+ import { BTreeIndex } from './btree-index'
3
+ import type { CompareOptions } from '../query/builder/types'
4
+ import type { BasicExpression } from '../query/ir'
5
+ import type { CollectionImpl } from '../collection/index.js'
6
6
 
7
7
  export interface AutoIndexConfig {
8
8
  autoIndex?: `off` | `eager`
@@ -25,7 +25,7 @@ export function ensureIndexForField<
25
25
  fieldPath: Array<string>,
26
26
  collection: CollectionImpl<T, TKey, any, any, any>,
27
27
  compareOptions?: CompareOptions,
28
- compareFn?: (a: any, b: any) => number
28
+ compareFn?: (a: any, b: any) => number,
29
29
  ) {
30
30
  if (!shouldAutoIndex(collection)) {
31
31
  return
@@ -39,7 +39,7 @@ export function ensureIndexForField<
39
39
  // Check if we already have an index for this field
40
40
  const existingIndex = Array.from(collection.indexes.values()).find(
41
41
  (index) =>
42
- index.matchesField(fieldPath) && index.matchesCompareOptions(compareOpts)
42
+ index.matchesField(fieldPath) && index.matchesCompareOptions(compareOpts),
43
43
  )
44
44
 
45
45
  if (existingIndex) {
@@ -62,12 +62,12 @@ export function ensureIndexForField<
62
62
  name: `auto:${fieldPath.join(`.`)}`,
63
63
  indexType: BTreeIndex,
64
64
  options: compareFn ? { compareFn, compareOptions: compareOpts } : {},
65
- }
65
+ },
66
66
  )
67
67
  } catch (error) {
68
68
  console.warn(
69
69
  `${collection.id ? `[${collection.id}] ` : ``}Failed to create auto-index for field path "${fieldPath.join(`.`)}":`,
70
- error
70
+ error,
71
71
  )
72
72
  }
73
73
  }
@@ -80,7 +80,7 @@ export function ensureIndexForExpression<
80
80
  TKey extends string | number,
81
81
  >(
82
82
  expression: BasicExpression,
83
- collection: CollectionImpl<T, TKey, any, any, any>
83
+ collection: CollectionImpl<T, TKey, any, any, any>,
84
84
  ): void {
85
85
  if (!shouldAutoIndex(collection)) {
86
86
  return
@@ -98,7 +98,7 @@ export function ensureIndexForExpression<
98
98
  * Extracts all indexable expressions from a where expression
99
99
  */
100
100
  function extractIndexableExpressions(
101
- expression: BasicExpression
101
+ expression: BasicExpression,
102
102
  ): Array<{ fieldName: string; fieldPath: Array<string> }> {
103
103
  const results: Array<{ fieldName: string; fieldPath: Array<string> }> = []
104
104