@tanstack/db 0.0.5 → 0.0.7

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 (55) hide show
  1. package/dist/cjs/collection.cjs +86 -27
  2. package/dist/cjs/collection.cjs.map +1 -1
  3. package/dist/cjs/collection.d.cts +30 -13
  4. package/dist/cjs/index.cjs +1 -1
  5. package/dist/cjs/index.d.cts +1 -1
  6. package/dist/cjs/query/compiled-query.cjs +1 -1
  7. package/dist/cjs/query/compiled-query.cjs.map +1 -1
  8. package/dist/cjs/query/compiled-query.d.cts +1 -1
  9. package/dist/cjs/query/evaluators.cjs +15 -0
  10. package/dist/cjs/query/evaluators.cjs.map +1 -1
  11. package/dist/cjs/query/evaluators.d.cts +5 -1
  12. package/dist/cjs/query/pipeline-compiler.cjs +2 -2
  13. package/dist/cjs/query/pipeline-compiler.cjs.map +1 -1
  14. package/dist/cjs/query/query-builder.cjs +22 -17
  15. package/dist/cjs/query/query-builder.cjs.map +1 -1
  16. package/dist/cjs/query/query-builder.d.cts +12 -2
  17. package/dist/cjs/query/schema.d.cts +11 -5
  18. package/dist/cjs/query/select.cjs +12 -0
  19. package/dist/cjs/query/select.cjs.map +1 -1
  20. package/dist/cjs/transactions.cjs +3 -1
  21. package/dist/cjs/transactions.cjs.map +1 -1
  22. package/dist/cjs/types.d.cts +33 -0
  23. package/dist/esm/collection.d.ts +30 -13
  24. package/dist/esm/collection.js +87 -28
  25. package/dist/esm/collection.js.map +1 -1
  26. package/dist/esm/index.d.ts +1 -1
  27. package/dist/esm/index.js +2 -2
  28. package/dist/esm/query/compiled-query.d.ts +1 -1
  29. package/dist/esm/query/compiled-query.js +2 -2
  30. package/dist/esm/query/compiled-query.js.map +1 -1
  31. package/dist/esm/query/evaluators.d.ts +5 -1
  32. package/dist/esm/query/evaluators.js +16 -1
  33. package/dist/esm/query/evaluators.js.map +1 -1
  34. package/dist/esm/query/pipeline-compiler.js +3 -3
  35. package/dist/esm/query/pipeline-compiler.js.map +1 -1
  36. package/dist/esm/query/query-builder.d.ts +12 -2
  37. package/dist/esm/query/query-builder.js +22 -17
  38. package/dist/esm/query/query-builder.js.map +1 -1
  39. package/dist/esm/query/schema.d.ts +11 -5
  40. package/dist/esm/query/select.js +12 -0
  41. package/dist/esm/query/select.js.map +1 -1
  42. package/dist/esm/transactions.js +3 -1
  43. package/dist/esm/transactions.js.map +1 -1
  44. package/dist/esm/types.d.ts +33 -0
  45. package/package.json +1 -1
  46. package/src/collection.ts +164 -45
  47. package/src/index.ts +1 -1
  48. package/src/query/compiled-query.ts +4 -3
  49. package/src/query/evaluators.ts +27 -0
  50. package/src/query/pipeline-compiler.ts +3 -3
  51. package/src/query/query-builder.ts +40 -23
  52. package/src/query/schema.ts +17 -5
  53. package/src/query/select.ts +24 -1
  54. package/src/transactions.ts +8 -1
  55. package/src/types.ts +38 -0
@@ -1 +1 @@
1
- {"version":3,"file":"transactions.js","sources":["../../src/transactions.ts"],"sourcesContent":["import { createDeferred } from \"./deferred\"\nimport type { Deferred } from \"./deferred\"\nimport type {\n PendingMutation,\n TransactionConfig,\n TransactionState,\n} from \"./types\"\n\nfunction generateUUID() {\n // Check if crypto.randomUUID is available (modern browsers and Node.js 15+)\n if (\n typeof crypto !== `undefined` &&\n typeof crypto.randomUUID === `function`\n ) {\n return crypto.randomUUID()\n }\n\n // Fallback implementation for older environments\n return `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0\n const v = c === `x` ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n}\n\nconst transactions: Array<Transaction> = []\nlet transactionStack: Array<Transaction> = []\n\nexport function createTransaction(config: TransactionConfig): Transaction {\n if (typeof config.mutationFn === `undefined`) {\n throw `mutationFn is required when creating a transaction`\n }\n\n let transactionId = config.id\n if (!transactionId) {\n transactionId = generateUUID()\n }\n const newTransaction = new Transaction({ ...config, id: transactionId })\n\n transactions.push(newTransaction)\n\n return newTransaction\n}\n\nexport function getActiveTransaction(): Transaction | undefined {\n if (transactionStack.length > 0) {\n return transactionStack.slice(-1)[0]\n } else {\n return undefined\n }\n}\n\nfunction registerTransaction(tx: Transaction) {\n transactionStack.push(tx)\n}\n\nfunction unregisterTransaction(tx: Transaction) {\n transactionStack = transactionStack.filter((t) => t.id !== tx.id)\n}\n\nfunction removeFromPendingList(tx: Transaction) {\n const index = transactions.findIndex((t) => t.id === tx.id)\n if (index !== -1) {\n transactions.splice(index, 1)\n }\n}\n\nexport class Transaction {\n public id: string\n public state: TransactionState\n public mutationFn\n public mutations: Array<PendingMutation<any>>\n public isPersisted: Deferred<Transaction>\n public autoCommit: boolean\n public createdAt: Date\n public metadata: Record<string, unknown>\n public error?: {\n message: string\n error: Error\n }\n\n constructor(config: TransactionConfig) {\n this.id = config.id!\n this.mutationFn = config.mutationFn\n this.state = `pending`\n this.mutations = []\n this.isPersisted = createDeferred()\n this.autoCommit = config.autoCommit ?? true\n this.createdAt = new Date()\n this.metadata = config.metadata ?? {}\n }\n\n setState(newState: TransactionState) {\n this.state = newState\n\n if (newState === `completed` || newState === `failed`) {\n removeFromPendingList(this)\n }\n }\n\n mutate(callback: () => void): Transaction {\n if (this.state !== `pending`) {\n throw `You can no longer call .mutate() as the transaction is no longer pending`\n }\n\n registerTransaction(this)\n try {\n callback()\n } finally {\n unregisterTransaction(this)\n }\n\n if (this.autoCommit) {\n this.commit()\n }\n\n return this\n }\n\n applyMutations(mutations: Array<PendingMutation<any>>): void {\n for (const newMutation of mutations) {\n const existingIndex = this.mutations.findIndex(\n (m) => m.key === newMutation.key\n )\n\n if (existingIndex >= 0) {\n // Replace existing mutation\n this.mutations[existingIndex] = newMutation\n } else {\n // Insert new mutation\n this.mutations.push(newMutation)\n }\n }\n }\n\n rollback(config?: { isSecondaryRollback?: boolean }): Transaction {\n const isSecondaryRollback = config?.isSecondaryRollback ?? false\n if (this.state === `completed`) {\n throw `You can no longer call .rollback() as the transaction is already completed`\n }\n\n this.setState(`failed`)\n\n // See if there's any other transactions w/ mutations on the same ids\n // and roll them back as well.\n if (!isSecondaryRollback) {\n const mutationIds = new Set()\n this.mutations.forEach((m) => mutationIds.add(m.key))\n for (const t of transactions) {\n t.state === `pending` &&\n t.mutations.some((m) => mutationIds.has(m.key)) &&\n t.rollback({ isSecondaryRollback: true })\n }\n }\n\n // Reject the promise\n this.isPersisted.reject(this.error?.error)\n this.touchCollection()\n\n return this\n }\n\n // Tell collection that something has changed with the transaction\n touchCollection(): void {\n const hasCalled = new Set()\n for (const mutation of this.mutations) {\n if (!hasCalled.has(mutation.collection.id)) {\n mutation.collection.transactions.setState((state) => state)\n mutation.collection.commitPendingTransactions()\n hasCalled.add(mutation.collection.id)\n }\n }\n }\n\n async commit(): Promise<Transaction> {\n if (this.state !== `pending`) {\n throw `You can no longer call .commit() as the transaction is no longer pending`\n }\n\n this.setState(`persisting`)\n\n if (this.mutations.length === 0) {\n this.setState(`completed`)\n }\n\n // Run mutationFn\n try {\n await this.mutationFn({ transaction: this })\n\n this.setState(`completed`)\n this.touchCollection()\n\n this.isPersisted.resolve(this)\n } catch (error) {\n // Update transaction with error information\n this.error = {\n message: error instanceof Error ? error.message : String(error),\n error: error instanceof Error ? error : new Error(String(error)),\n }\n\n // rollback the transaction\n return this.rollback()\n }\n\n return this\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transactions.js","sources":["../../src/transactions.ts"],"sourcesContent":["import { createDeferred } from \"./deferred\"\nimport type { Deferred } from \"./deferred\"\nimport type {\n PendingMutation,\n TransactionConfig,\n TransactionState,\n TransactionWithMutations,\n} from \"./types\"\n\nfunction generateUUID() {\n // Check if crypto.randomUUID is available (modern browsers and Node.js 15+)\n if (\n typeof crypto !== `undefined` &&\n typeof crypto.randomUUID === `function`\n ) {\n return crypto.randomUUID()\n }\n\n // Fallback implementation for older environments\n return `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0\n const v = c === `x` ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n}\n\nconst transactions: Array<Transaction> = []\nlet transactionStack: Array<Transaction> = []\n\nexport function createTransaction(config: TransactionConfig): Transaction {\n if (typeof config.mutationFn === `undefined`) {\n throw `mutationFn is required when creating a transaction`\n }\n\n let transactionId = config.id\n if (!transactionId) {\n transactionId = generateUUID()\n }\n const newTransaction = new Transaction({ ...config, id: transactionId })\n\n transactions.push(newTransaction)\n\n return newTransaction\n}\n\nexport function getActiveTransaction(): Transaction | undefined {\n if (transactionStack.length > 0) {\n return transactionStack.slice(-1)[0]\n } else {\n return undefined\n }\n}\n\nfunction registerTransaction(tx: Transaction) {\n transactionStack.push(tx)\n}\n\nfunction unregisterTransaction(tx: Transaction) {\n transactionStack = transactionStack.filter((t) => t.id !== tx.id)\n}\n\nfunction removeFromPendingList(tx: Transaction) {\n const index = transactions.findIndex((t) => t.id === tx.id)\n if (index !== -1) {\n transactions.splice(index, 1)\n }\n}\n\nexport class Transaction {\n public id: string\n public state: TransactionState\n public mutationFn\n public mutations: Array<PendingMutation<any>>\n public isPersisted: Deferred<Transaction>\n public autoCommit: boolean\n public createdAt: Date\n public metadata: Record<string, unknown>\n public error?: {\n message: string\n error: Error\n }\n\n constructor(config: TransactionConfig) {\n this.id = config.id!\n this.mutationFn = config.mutationFn\n this.state = `pending`\n this.mutations = []\n this.isPersisted = createDeferred()\n this.autoCommit = config.autoCommit ?? true\n this.createdAt = new Date()\n this.metadata = config.metadata ?? {}\n }\n\n setState(newState: TransactionState) {\n this.state = newState\n\n if (newState === `completed` || newState === `failed`) {\n removeFromPendingList(this)\n }\n }\n\n mutate(callback: () => void): Transaction {\n if (this.state !== `pending`) {\n throw `You can no longer call .mutate() as the transaction is no longer pending`\n }\n\n registerTransaction(this)\n try {\n callback()\n } finally {\n unregisterTransaction(this)\n }\n\n if (this.autoCommit) {\n this.commit()\n }\n\n return this\n }\n\n applyMutations(mutations: Array<PendingMutation<any>>): void {\n for (const newMutation of mutations) {\n const existingIndex = this.mutations.findIndex(\n (m) => m.key === newMutation.key\n )\n\n if (existingIndex >= 0) {\n // Replace existing mutation\n this.mutations[existingIndex] = newMutation\n } else {\n // Insert new mutation\n this.mutations.push(newMutation)\n }\n }\n }\n\n rollback(config?: { isSecondaryRollback?: boolean }): Transaction {\n const isSecondaryRollback = config?.isSecondaryRollback ?? false\n if (this.state === `completed`) {\n throw `You can no longer call .rollback() as the transaction is already completed`\n }\n\n this.setState(`failed`)\n\n // See if there's any other transactions w/ mutations on the same ids\n // and roll them back as well.\n if (!isSecondaryRollback) {\n const mutationIds = new Set()\n this.mutations.forEach((m) => mutationIds.add(m.key))\n for (const t of transactions) {\n t.state === `pending` &&\n t.mutations.some((m) => mutationIds.has(m.key)) &&\n t.rollback({ isSecondaryRollback: true })\n }\n }\n\n // Reject the promise\n this.isPersisted.reject(this.error?.error)\n this.touchCollection()\n\n return this\n }\n\n // Tell collection that something has changed with the transaction\n touchCollection(): void {\n const hasCalled = new Set()\n for (const mutation of this.mutations) {\n if (!hasCalled.has(mutation.collection.id)) {\n mutation.collection.transactions.setState((state) => state)\n mutation.collection.commitPendingTransactions()\n hasCalled.add(mutation.collection.id)\n }\n }\n }\n\n async commit(): Promise<Transaction> {\n if (this.state !== `pending`) {\n throw `You can no longer call .commit() as the transaction is no longer pending`\n }\n\n this.setState(`persisting`)\n\n if (this.mutations.length === 0) {\n this.setState(`completed`)\n\n return this\n }\n\n // Run mutationFn\n try {\n // At this point we know there's at least one mutation\n // Use type assertion to tell TypeScript about this guarantee\n const transactionWithMutations =\n this as unknown as TransactionWithMutations\n await this.mutationFn({ transaction: transactionWithMutations })\n\n this.setState(`completed`)\n this.touchCollection()\n\n this.isPersisted.resolve(this)\n } catch (error) {\n // Update transaction with error information\n this.error = {\n message: error instanceof Error ? error.message : String(error),\n error: error instanceof Error ? error : new Error(String(error)),\n }\n\n // rollback the transaction\n return this.rollback()\n }\n\n return this\n }\n}\n"],"names":[],"mappings":"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"}
@@ -3,6 +3,14 @@ import { Collection } from './collection.js';
3
3
  import { StandardSchemaV1 } from '@standard-schema/spec';
4
4
  import { Transaction } from './transactions.js';
5
5
  export type TransactionState = `pending` | `persisting` | `completed` | `failed`;
6
+ /**
7
+ * Represents a utility function that can be attached to a collection
8
+ */
9
+ export type Fn = (...args: Array<any>) => any;
10
+ /**
11
+ * A record of utility functions that can be attached to a collection
12
+ */
13
+ export type UtilsRecord = Record<string, Fn>;
6
14
  /**
7
15
  * Represents a pending mutation within a transaction
8
16
  * Contains information about the original and modified data, as well as metadata
@@ -27,6 +35,13 @@ export type MutationFnParams = {
27
35
  transaction: Transaction;
28
36
  };
29
37
  export type MutationFn = (params: MutationFnParams) => Promise<any>;
38
+ /**
39
+ * Utility type for a Transaction with at least one mutation
40
+ * This is used internally by the Transaction.commit method
41
+ */
42
+ export type TransactionWithMutations<T extends object = Record<string, unknown>> = Transaction & {
43
+ mutations: [PendingMutation<T>, ...Array<PendingMutation<T>>];
44
+ };
30
45
  export interface TransactionConfig {
31
46
  /** Unique identifier for the transaction */
32
47
  id?: string;
@@ -100,6 +115,24 @@ export interface CollectionConfig<T extends object = Record<string, unknown>> {
100
115
  * getId: (item) => item.uuid
101
116
  */
102
117
  getId: (item: T) => any;
118
+ /**
119
+ * Optional asynchronous handler function called before an insert operation
120
+ * @param params Object containing transaction and mutation information
121
+ * @returns Promise resolving to any value
122
+ */
123
+ onInsert?: MutationFn;
124
+ /**
125
+ * Optional asynchronous handler function called before an update operation
126
+ * @param params Object containing transaction and mutation information
127
+ * @returns Promise resolving to any value
128
+ */
129
+ onUpdate?: MutationFn;
130
+ /**
131
+ * Optional asynchronous handler function called before a delete operation
132
+ * @param params Object containing transaction and mutation information
133
+ * @returns Promise resolving to any value
134
+ */
135
+ onDelete?: MutationFn;
103
136
  }
104
137
  export type ChangesPayload<T extends object = Record<string, unknown>> = Array<ChangeMessage<T>>;
105
138
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/db",
3
3
  "description": "A reactive client store for building super fast apps on sync",
4
- "version": "0.0.5",
4
+ "version": "0.0.7",
5
5
  "dependencies": {
6
6
  "@electric-sql/d2ts": "^0.1.6",
7
7
  "@standard-schema/spec": "^1.0.0",
package/src/collection.ts CHANGED
@@ -1,26 +1,30 @@
1
1
  import { Derived, Store, batch } from "@tanstack/store"
2
2
  import { withArrayChangeTracking, withChangeTracking } from "./proxy"
3
- import { getActiveTransaction } from "./transactions"
3
+ import { Transaction, getActiveTransaction } from "./transactions"
4
4
  import { SortedMap } from "./SortedMap"
5
5
  import type {
6
6
  ChangeMessage,
7
7
  CollectionConfig,
8
+ Fn,
8
9
  InsertConfig,
9
10
  OperationConfig,
10
11
  OptimisticChangeMessage,
11
12
  PendingMutation,
12
13
  StandardSchema,
13
- Transaction,
14
+ Transaction as TransactionType,
15
+ UtilsRecord,
14
16
  } from "./types"
15
17
 
16
18
  // Store collections in memory using Tanstack store
17
- export const collectionsStore = new Store(new Map<string, Collection<any>>())
19
+ export const collectionsStore = new Store(
20
+ new Map<string, CollectionImpl<any>>()
21
+ )
18
22
 
19
23
  // Map to track loading collections
20
24
 
21
25
  const loadingCollections = new Map<
22
26
  string,
23
- Promise<Collection<Record<string, unknown>>>
27
+ Promise<CollectionImpl<Record<string, unknown>>>
24
28
  >()
25
29
 
26
30
  interface PendingSyncedTransaction<T extends object = Record<string, unknown>> {
@@ -28,17 +32,40 @@ interface PendingSyncedTransaction<T extends object = Record<string, unknown>> {
28
32
  operations: Array<OptimisticChangeMessage<T>>
29
33
  }
30
34
 
35
+ /**
36
+ * Enhanced Collection interface that includes both data type T and utilities TUtils
37
+ * @template T - The type of items in the collection
38
+ * @template TUtils - The utilities record type
39
+ */
40
+ export interface Collection<
41
+ T extends object = Record<string, unknown>,
42
+ TUtils extends UtilsRecord = {},
43
+ > extends CollectionImpl<T> {
44
+ readonly utils: TUtils
45
+ }
46
+
31
47
  /**
32
48
  * Creates a new Collection instance with the given configuration
33
49
  *
34
50
  * @template T - The type of items in the collection
35
- * @param config - Configuration for the collection, including id and sync
36
- * @returns A new Collection instance
51
+ * @template TUtils - The utilities record type
52
+ * @param options - Collection options with optional utilities
53
+ * @returns A new Collection with utilities exposed both at top level and under .utils
37
54
  */
38
- export function createCollection<T extends object = Record<string, unknown>>(
39
- config: CollectionConfig<T>
40
- ): Collection<T> {
41
- return new Collection<T>(config)
55
+ export function createCollection<
56
+ T extends object = Record<string, unknown>,
57
+ TUtils extends UtilsRecord = {},
58
+ >(options: CollectionConfig<T> & { utils?: TUtils }): Collection<T, TUtils> {
59
+ const collection = new CollectionImpl<T>(options)
60
+
61
+ // Copy utils to both top level and .utils namespace
62
+ if (options.utils) {
63
+ collection.utils = { ...options.utils }
64
+ } else {
65
+ collection.utils = {} as TUtils
66
+ }
67
+
68
+ return collection as Collection<T, TUtils>
42
69
  }
43
70
 
44
71
  /**
@@ -69,7 +96,7 @@ export function createCollection<T extends object = Record<string, unknown>>(
69
96
  */
70
97
  export function preloadCollection<T extends object = Record<string, unknown>>(
71
98
  config: CollectionConfig<T>
72
- ): Promise<Collection<T>> {
99
+ ): Promise<CollectionImpl<T>> {
73
100
  if (!config.id) {
74
101
  throw new Error(`The id property is required for preloadCollection`)
75
102
  }
@@ -86,7 +113,7 @@ export function preloadCollection<T extends object = Record<string, unknown>>(
86
113
 
87
114
  // If the collection is in the process of loading, return its promise
88
115
  if (loadingCollections.has(config.id)) {
89
- return loadingCollections.get(config.id)! as Promise<Collection<T>>
116
+ return loadingCollections.get(config.id)! as Promise<CollectionImpl<T>>
90
117
  }
91
118
 
92
119
  // Create a new collection instance if it doesn't exist
@@ -98,7 +125,7 @@ export function preloadCollection<T extends object = Record<string, unknown>>(
98
125
  }
99
126
  next.set(
100
127
  config.id,
101
- new Collection<T>({
128
+ createCollection<T>({
102
129
  id: config.id,
103
130
  getId: config.getId,
104
131
  sync: config.sync,
@@ -113,9 +140,9 @@ export function preloadCollection<T extends object = Record<string, unknown>>(
113
140
 
114
141
  // Create a promise that will resolve after the first commit
115
142
  let resolveFirstCommit: () => void
116
- const firstCommitPromise = new Promise<Collection<T>>((resolve) => {
143
+ const firstCommitPromise = new Promise<CollectionImpl<T>>((resolve) => {
117
144
  resolveFirstCommit = () => {
118
- resolve(collection)
145
+ resolve(collection as CollectionImpl<T>)
119
146
  }
120
147
  })
121
148
 
@@ -133,7 +160,7 @@ export function preloadCollection<T extends object = Record<string, unknown>>(
133
160
  // Store the loading promise
134
161
  loadingCollections.set(
135
162
  config.id,
136
- firstCommitPromise as Promise<Collection<Record<string, unknown>>>
163
+ firstCommitPromise as Promise<CollectionImpl<Record<string, unknown>>>
137
164
  )
138
165
 
139
166
  return firstCommitPromise
@@ -168,8 +195,13 @@ export class SchemaValidationError extends Error {
168
195
  }
169
196
  }
170
197
 
171
- export class Collection<T extends object = Record<string, unknown>> {
172
- public transactions: Store<SortedMap<string, Transaction>>
198
+ export class CollectionImpl<T extends object = Record<string, unknown>> {
199
+ /**
200
+ * Utilities namespace
201
+ * This is populated by createCollection
202
+ */
203
+ public utils: Record<string, Fn> = {}
204
+ public transactions: Store<SortedMap<string, TransactionType>>
173
205
  public optimisticOperations: Derived<Array<OptimisticChangeMessage<T>>>
174
206
  public derivedState: Derived<Map<string, T>>
175
207
  public derivedArray: Derived<Array<T>>
@@ -218,7 +250,7 @@ export class Collection<T extends object = Record<string, unknown>> {
218
250
  }
219
251
 
220
252
  this.transactions = new Store(
221
- new SortedMap<string, Transaction>(
253
+ new SortedMap<string, TransactionType>(
222
254
  (a, b) => a.createdAt.getTime() - b.createdAt.getTime()
223
255
  )
224
256
  )
@@ -604,7 +636,7 @@ export class Collection<T extends object = Record<string, unknown>> {
604
636
  * Inserts one or more items into the collection
605
637
  * @param items - Single item or array of items to insert
606
638
  * @param config - Optional configuration including metadata and custom keys
607
- * @returns A Transaction object representing the insert operation(s)
639
+ * @returns A TransactionType object representing the insert operation(s)
608
640
  * @throws {SchemaValidationError} If the data fails schema validation
609
641
  * @example
610
642
  * // Insert a single item
@@ -620,9 +652,13 @@ export class Collection<T extends object = Record<string, unknown>> {
620
652
  * insert({ text: "Buy groceries" }, { key: "grocery-task" })
621
653
  */
622
654
  insert = (data: T | Array<T>, config?: InsertConfig) => {
623
- const transaction = getActiveTransaction()
624
- if (typeof transaction === `undefined`) {
625
- throw `no transaction found when calling collection.insert`
655
+ const ambientTransaction = getActiveTransaction()
656
+
657
+ // If no ambient transaction exists, check for an onInsert handler early
658
+ if (!ambientTransaction && !this.config.onInsert) {
659
+ throw new Error(
660
+ `Collection.insert called directly (not within an explicit transaction) but no 'onInsert' handler is configured.`
661
+ )
626
662
  }
627
663
 
628
664
  const items = Array.isArray(data) ? data : [data]
@@ -662,14 +698,37 @@ export class Collection<T extends object = Record<string, unknown>> {
662
698
  mutations.push(mutation)
663
699
  })
664
700
 
665
- transaction.applyMutations(mutations)
701
+ // If an ambient transaction exists, use it
702
+ if (ambientTransaction) {
703
+ ambientTransaction.applyMutations(mutations)
666
704
 
667
- this.transactions.setState((sortedMap) => {
668
- sortedMap.set(transaction.id, transaction)
669
- return sortedMap
670
- })
705
+ this.transactions.setState((sortedMap) => {
706
+ sortedMap.set(ambientTransaction.id, ambientTransaction)
707
+ return sortedMap
708
+ })
709
+
710
+ return ambientTransaction
711
+ } else {
712
+ // Create a new transaction with a mutation function that calls the onInsert handler
713
+ const directOpTransaction = new Transaction({
714
+ mutationFn: async (params) => {
715
+ // Call the onInsert handler with the transaction
716
+ return this.config.onInsert!(params)
717
+ },
718
+ })
719
+
720
+ // Apply mutations to the new transaction
721
+ directOpTransaction.applyMutations(mutations)
722
+ directOpTransaction.commit()
723
+
724
+ // Add the transaction to the collection's transactions store
725
+ this.transactions.setState((sortedMap) => {
726
+ sortedMap.set(directOpTransaction.id, directOpTransaction)
727
+ return sortedMap
728
+ })
671
729
 
672
- return transaction
730
+ return directOpTransaction
731
+ }
673
732
  }
674
733
 
675
734
  /**
@@ -715,13 +774,13 @@ export class Collection<T extends object = Record<string, unknown>> {
715
774
  id: unknown,
716
775
  configOrCallback: ((draft: TItem) => void) | OperationConfig,
717
776
  maybeCallback?: (draft: TItem) => void
718
- ): Transaction
777
+ ): TransactionType
719
778
 
720
779
  update<TItem extends object = T>(
721
780
  ids: Array<unknown>,
722
781
  configOrCallback: ((draft: Array<TItem>) => void) | OperationConfig,
723
782
  maybeCallback?: (draft: Array<TItem>) => void
724
- ): Transaction
783
+ ): TransactionType
725
784
 
726
785
  update<TItem extends object = T>(
727
786
  ids: unknown | Array<unknown>,
@@ -732,9 +791,13 @@ export class Collection<T extends object = Record<string, unknown>> {
732
791
  throw new Error(`The first argument to update is missing`)
733
792
  }
734
793
 
735
- const transaction = getActiveTransaction()
736
- if (typeof transaction === `undefined`) {
737
- throw `no transaction found when calling collection.update`
794
+ const ambientTransaction = getActiveTransaction()
795
+
796
+ // If no ambient transaction exists, check for an onUpdate handler early
797
+ if (!ambientTransaction && !this.config.onUpdate) {
798
+ throw new Error(
799
+ `Collection.update called directly (not within an explicit transaction) but no 'onUpdate' handler is configured.`
800
+ )
738
801
  }
739
802
 
740
803
  const isArray = Array.isArray(ids)
@@ -828,21 +891,46 @@ export class Collection<T extends object = Record<string, unknown>> {
828
891
  throw new Error(`No changes were made to any of the objects`)
829
892
  }
830
893
 
831
- transaction.applyMutations(mutations)
894
+ // If an ambient transaction exists, use it
895
+ if (ambientTransaction) {
896
+ ambientTransaction.applyMutations(mutations)
897
+
898
+ this.transactions.setState((sortedMap) => {
899
+ sortedMap.set(ambientTransaction.id, ambientTransaction)
900
+ return sortedMap
901
+ })
902
+
903
+ return ambientTransaction
904
+ }
905
+
906
+ // No need to check for onUpdate handler here as we've already checked at the beginning
907
+
908
+ // Create a new transaction with a mutation function that calls the onUpdate handler
909
+ const directOpTransaction = new Transaction({
910
+ mutationFn: async (transaction) => {
911
+ // Call the onUpdate handler with the transaction
912
+ return this.config.onUpdate!(transaction)
913
+ },
914
+ })
832
915
 
916
+ // Apply mutations to the new transaction
917
+ directOpTransaction.applyMutations(mutations)
918
+ directOpTransaction.commit()
919
+
920
+ // Add the transaction to the collection's transactions store
833
921
  this.transactions.setState((sortedMap) => {
834
- sortedMap.set(transaction.id, transaction)
922
+ sortedMap.set(directOpTransaction.id, directOpTransaction)
835
923
  return sortedMap
836
924
  })
837
925
 
838
- return transaction
926
+ return directOpTransaction
839
927
  }
840
928
 
841
929
  /**
842
930
  * Deletes one or more items from the collection
843
931
  * @param ids - Single ID or array of IDs to delete
844
932
  * @param config - Optional configuration including metadata
845
- * @returns A Transaction object representing the delete operation(s)
933
+ * @returns A TransactionType object representing the delete operation(s)
846
934
  * @example
847
935
  * // Delete a single item
848
936
  * delete("todo-1")
@@ -853,10 +941,17 @@ export class Collection<T extends object = Record<string, unknown>> {
853
941
  * // Delete with metadata
854
942
  * delete("todo-1", { metadata: { reason: "completed" } })
855
943
  */
856
- delete = (ids: Array<string> | string, config?: OperationConfig) => {
857
- const transaction = getActiveTransaction()
858
- if (typeof transaction === `undefined`) {
859
- throw `no transaction found when calling collection.delete`
944
+ delete = (
945
+ ids: Array<string> | string,
946
+ config?: OperationConfig
947
+ ): TransactionType => {
948
+ const ambientTransaction = getActiveTransaction()
949
+
950
+ // If no ambient transaction exists, check for an onDelete handler early
951
+ if (!ambientTransaction && !this.config.onDelete) {
952
+ throw new Error(
953
+ `Collection.delete called directly (not within an explicit transaction) but no 'onDelete' handler is configured.`
954
+ )
860
955
  }
861
956
 
862
957
  const idsArray = (Array.isArray(ids) ? ids : [ids]).map((id) =>
@@ -885,14 +980,38 @@ export class Collection<T extends object = Record<string, unknown>> {
885
980
  mutations.push(mutation)
886
981
  }
887
982
 
888
- transaction.applyMutations(mutations)
983
+ // If an ambient transaction exists, use it
984
+ if (ambientTransaction) {
985
+ ambientTransaction.applyMutations(mutations)
986
+
987
+ this.transactions.setState((sortedMap) => {
988
+ sortedMap.set(ambientTransaction.id, ambientTransaction)
989
+ return sortedMap
990
+ })
991
+
992
+ return ambientTransaction
993
+ }
994
+
995
+ // Create a new transaction with a mutation function that calls the onDelete handler
996
+ const directOpTransaction = new Transaction({
997
+ autoCommit: true,
998
+ mutationFn: async (transaction) => {
999
+ // Call the onDelete handler with the transaction
1000
+ return this.config.onDelete!(transaction)
1001
+ },
1002
+ })
1003
+
1004
+ // Apply mutations to the new transaction
1005
+ directOpTransaction.applyMutations(mutations)
1006
+ directOpTransaction.commit()
889
1007
 
1008
+ // Add the transaction to the collection's transactions store
890
1009
  this.transactions.setState((sortedMap) => {
891
- sortedMap.set(transaction.id, transaction)
1010
+ sortedMap.set(directOpTransaction.id, directOpTransaction)
892
1011
  return sortedMap
893
1012
  })
894
1013
 
895
- return transaction
1014
+ return directOpTransaction
896
1015
  }
897
1016
 
898
1017
  /**
package/src/index.ts CHANGED
@@ -9,4 +9,4 @@ export * from "./proxy"
9
9
  export * from "./query/index.js"
10
10
 
11
11
  // Re-export some stuff explicitly to ensure the type & value is exported
12
- export { Collection } from "./collection"
12
+ export type { Collection } from "./collection"
@@ -1,7 +1,8 @@
1
1
  import { D2, MessageType, MultiSet, output } from "@electric-sql/d2ts"
2
2
  import { Effect, batch } from "@tanstack/store"
3
- import { Collection } from "../collection.js"
3
+ import { createCollection } from "../collection.js"
4
4
  import { compileQueryPipeline } from "./pipeline-compiler.js"
5
+ import type { Collection } from "../collection.js"
5
6
  import type { ChangeMessage, SyncConfig } from "../types.js"
6
7
  import type {
7
8
  IStreamBuilder,
@@ -97,9 +98,9 @@ export class CompiledQuery<TResults extends object = Record<string, unknown>> {
97
98
 
98
99
  this.graph = graph
99
100
  this.inputs = inputs
100
- this.resultCollection = new Collection<TResults>({
101
+ this.resultCollection = createCollection<TResults>({
101
102
  id: crypto.randomUUID(), // TODO: remove when we don't require any more
102
- getId: (val) => {
103
+ getId: (val: unknown) => {
103
104
  return (val as any)._key
104
105
  },
105
106
  sync: {
@@ -6,9 +6,36 @@ import type {
6
6
  ConditionOperand,
7
7
  LogicalOperator,
8
8
  SimpleCondition,
9
+ Where,
10
+ WhereCallback,
9
11
  } from "./schema.js"
10
12
  import type { NamespacedRow } from "../types.js"
11
13
 
14
+ /**
15
+ * Evaluates a Where clause (which is always an array of conditions and/or callbacks) against a nested row structure
16
+ */
17
+ export function evaluateWhereOnNamespacedRow(
18
+ namespacedRow: NamespacedRow,
19
+ where: Where,
20
+ mainTableAlias?: string,
21
+ joinedTableAlias?: string
22
+ ): boolean {
23
+ // Where is always an array of conditions and/or callbacks
24
+ // Evaluate all items and combine with AND logic
25
+ return where.every((item) => {
26
+ if (typeof item === `function`) {
27
+ return (item as WhereCallback)(namespacedRow)
28
+ } else {
29
+ return evaluateConditionOnNamespacedRow(
30
+ namespacedRow,
31
+ item as Condition,
32
+ mainTableAlias,
33
+ joinedTableAlias
34
+ )
35
+ }
36
+ })
37
+ }
38
+
12
39
  /**
13
40
  * Evaluates a condition against a nested row structure
14
41
  */
@@ -1,5 +1,5 @@
1
1
  import { filter, map } from "@electric-sql/d2ts"
2
- import { evaluateConditionOnNamespacedRow } from "./evaluators.js"
2
+ import { evaluateWhereOnNamespacedRow } from "./evaluators.js"
3
3
  import { processJoinClause } from "./joins.js"
4
4
  import { processGroupBy } from "./group-by.js"
5
5
  import { processOrderBy } from "./order-by.js"
@@ -95,7 +95,7 @@ export function compileQueryPipeline<T extends IStreamBuilder<unknown>>(
95
95
  if (query.where) {
96
96
  pipeline = pipeline.pipe(
97
97
  filter(([_key, row]) => {
98
- const result = evaluateConditionOnNamespacedRow(
98
+ const result = evaluateWhereOnNamespacedRow(
99
99
  row,
100
100
  query.where!,
101
101
  mainTableAlias
@@ -117,7 +117,7 @@ export function compileQueryPipeline<T extends IStreamBuilder<unknown>>(
117
117
  filter(([_key, row]) => {
118
118
  // For HAVING, we're working with the flattened row that contains both
119
119
  // the group by keys and the aggregate results directly
120
- const result = evaluateConditionOnNamespacedRow(
120
+ const result = evaluateWhereOnNamespacedRow(
121
121
  row,
122
122
  query.having!,
123
123
  mainTableAlias