@tanstack/db 0.0.17 → 0.0.19

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 (51) hide show
  1. package/dist/cjs/SortedMap.cjs.map +1 -1
  2. package/dist/cjs/collection.cjs +47 -6
  3. package/dist/cjs/collection.cjs.map +1 -1
  4. package/dist/cjs/collection.d.cts +150 -45
  5. package/dist/cjs/deferred.cjs.map +1 -1
  6. package/dist/cjs/errors.cjs.map +1 -1
  7. package/dist/cjs/optimistic-action.cjs.map +1 -1
  8. package/dist/cjs/proxy.cjs.map +1 -1
  9. package/dist/cjs/query/builder/functions.cjs.map +1 -1
  10. package/dist/cjs/query/builder/index.cjs.map +1 -1
  11. package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -1
  12. package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
  13. package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
  14. package/dist/cjs/query/compiler/index.cjs.map +1 -1
  15. package/dist/cjs/query/compiler/joins.cjs.map +1 -1
  16. package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
  17. package/dist/cjs/query/compiler/select.cjs.map +1 -1
  18. package/dist/cjs/query/ir.cjs.map +1 -1
  19. package/dist/cjs/query/live-query-collection.cjs.map +1 -1
  20. package/dist/cjs/transactions.cjs +116 -0
  21. package/dist/cjs/transactions.cjs.map +1 -1
  22. package/dist/cjs/transactions.d.cts +179 -0
  23. package/dist/cjs/types.d.cts +169 -13
  24. package/dist/esm/SortedMap.js.map +1 -1
  25. package/dist/esm/collection.d.ts +150 -45
  26. package/dist/esm/collection.js +47 -6
  27. package/dist/esm/collection.js.map +1 -1
  28. package/dist/esm/deferred.js.map +1 -1
  29. package/dist/esm/errors.js.map +1 -1
  30. package/dist/esm/optimistic-action.js.map +1 -1
  31. package/dist/esm/proxy.js.map +1 -1
  32. package/dist/esm/query/builder/functions.js.map +1 -1
  33. package/dist/esm/query/builder/index.js.map +1 -1
  34. package/dist/esm/query/builder/ref-proxy.js.map +1 -1
  35. package/dist/esm/query/compiler/evaluators.js.map +1 -1
  36. package/dist/esm/query/compiler/group-by.js.map +1 -1
  37. package/dist/esm/query/compiler/index.js.map +1 -1
  38. package/dist/esm/query/compiler/joins.js.map +1 -1
  39. package/dist/esm/query/compiler/order-by.js.map +1 -1
  40. package/dist/esm/query/compiler/select.js.map +1 -1
  41. package/dist/esm/query/ir.js.map +1 -1
  42. package/dist/esm/query/live-query-collection.js.map +1 -1
  43. package/dist/esm/transactions.d.ts +179 -0
  44. package/dist/esm/transactions.js +116 -0
  45. package/dist/esm/transactions.js.map +1 -1
  46. package/dist/esm/types.d.ts +169 -13
  47. package/package.json +1 -1
  48. package/src/collection.ts +165 -50
  49. package/src/proxy.ts +0 -1
  50. package/src/transactions.ts +179 -0
  51. package/src/types.ts +199 -28
package/src/types.ts CHANGED
@@ -71,7 +71,7 @@ export interface PendingMutation<
71
71
  syncMetadata: Record<string, unknown>
72
72
  createdAt: Date
73
73
  updatedAt: Date
74
- collection: Collection<T, any>
74
+ collection: Collection<T, any, any>
75
75
  }
76
76
 
77
77
  /**
@@ -209,35 +209,65 @@ export interface InsertConfig {
209
209
  metadata?: Record<string, unknown>
210
210
  }
211
211
 
212
- export type UpdateMutationFnParams<T extends object = Record<string, unknown>> =
213
- {
214
- transaction: TransactionWithMutations<T, `update`>
215
- }
212
+ export type UpdateMutationFnParams<
213
+ T extends object = Record<string, unknown>,
214
+ TKey extends string | number = string | number,
215
+ TUtils extends UtilsRecord = Record<string, Fn>,
216
+ > = {
217
+ transaction: TransactionWithMutations<T, `update`>
218
+ collection: Collection<T, TKey, TUtils>
219
+ }
216
220
 
217
- export type InsertMutationFnParams<T extends object = Record<string, unknown>> =
218
- {
219
- transaction: TransactionWithMutations<T, `insert`>
220
- }
221
+ export type InsertMutationFnParams<
222
+ T extends object = Record<string, unknown>,
223
+ TKey extends string | number = string | number,
224
+ TUtils extends UtilsRecord = Record<string, Fn>,
225
+ > = {
226
+ transaction: TransactionWithMutations<T, `insert`>
227
+ collection: Collection<T, TKey, TUtils>
228
+ }
221
229
 
222
- export type DeleteMutationFnParams<T extends object = Record<string, unknown>> =
223
- {
224
- transaction: TransactionWithMutations<T, `delete`>
225
- }
230
+ export type DeleteMutationFnParams<
231
+ T extends object = Record<string, unknown>,
232
+ TKey extends string | number = string | number,
233
+ TUtils extends UtilsRecord = Record<string, Fn>,
234
+ > = {
235
+ transaction: TransactionWithMutations<T, `delete`>
236
+ collection: Collection<T, TKey, TUtils>
237
+ }
226
238
 
227
- export type InsertMutationFn<T extends object = Record<string, unknown>> = (
228
- params: InsertMutationFnParams<T>
229
- ) => Promise<any>
239
+ export type InsertMutationFn<
240
+ T extends object = Record<string, unknown>,
241
+ TKey extends string | number = string | number,
242
+ TUtils extends UtilsRecord = Record<string, Fn>,
243
+ > = (params: InsertMutationFnParams<T, TKey, TUtils>) => Promise<any>
230
244
 
231
- export type UpdateMutationFn<T extends object = Record<string, unknown>> = (
232
- params: UpdateMutationFnParams<T>
233
- ) => Promise<any>
245
+ export type UpdateMutationFn<
246
+ T extends object = Record<string, unknown>,
247
+ TKey extends string | number = string | number,
248
+ TUtils extends UtilsRecord = Record<string, Fn>,
249
+ > = (params: UpdateMutationFnParams<T, TKey, TUtils>) => Promise<any>
234
250
 
235
- export type DeleteMutationFn<T extends object = Record<string, unknown>> = (
236
- params: DeleteMutationFnParams<T>
237
- ) => Promise<any>
251
+ export type DeleteMutationFn<
252
+ T extends object = Record<string, unknown>,
253
+ TKey extends string | number = string | number,
254
+ TUtils extends UtilsRecord = Record<string, Fn>,
255
+ > = (params: DeleteMutationFnParams<T, TKey, TUtils>) => Promise<any>
238
256
 
239
257
  /**
240
258
  * Collection status values for lifecycle management
259
+ * @example
260
+ * // Check collection status
261
+ * if (collection.status === "loading") {
262
+ * console.log("Collection is loading initial data")
263
+ * } else if (collection.status === "ready") {
264
+ * console.log("Collection is ready for use")
265
+ * }
266
+ *
267
+ * @example
268
+ * // Status transitions
269
+ * // idle → loading → initialCommit → ready
270
+ * // Any status can transition to → error or cleaned-up
241
271
  */
242
272
  export type CollectionStatus =
243
273
  /** Collection is created but sync hasn't started yet (when startSync config is false) */
@@ -296,22 +326,132 @@ export interface CollectionConfig<
296
326
  compare?: (x: T, y: T) => number
297
327
  /**
298
328
  * Optional asynchronous handler function called before an insert operation
299
- * @param params Object containing transaction and mutation information
329
+ * @param params Object containing transaction and collection information
300
330
  * @returns Promise resolving to any value
331
+ * @example
332
+ * // Basic insert handler
333
+ * onInsert: async ({ transaction, collection }) => {
334
+ * const newItem = transaction.mutations[0].modified
335
+ * await api.createTodo(newItem)
336
+ * }
337
+ *
338
+ * @example
339
+ * // Insert handler with multiple items
340
+ * onInsert: async ({ transaction, collection }) => {
341
+ * const items = transaction.mutations.map(m => m.modified)
342
+ * await api.createTodos(items)
343
+ * }
344
+ *
345
+ * @example
346
+ * // Insert handler with error handling
347
+ * onInsert: async ({ transaction, collection }) => {
348
+ * try {
349
+ * const newItem = transaction.mutations[0].modified
350
+ * const result = await api.createTodo(newItem)
351
+ * return result
352
+ * } catch (error) {
353
+ * console.error('Insert failed:', error)
354
+ * throw error // This will cause the transaction to fail
355
+ * }
356
+ * }
357
+ *
358
+ * @example
359
+ * // Insert handler with metadata
360
+ * onInsert: async ({ transaction, collection }) => {
361
+ * const mutation = transaction.mutations[0]
362
+ * await api.createTodo(mutation.modified, {
363
+ * source: mutation.metadata?.source,
364
+ * timestamp: mutation.createdAt
365
+ * })
366
+ * }
301
367
  */
302
- onInsert?: InsertMutationFn<T>
368
+ onInsert?: InsertMutationFn<T, TKey>
303
369
  /**
304
370
  * Optional asynchronous handler function called before an update operation
305
- * @param params Object containing transaction and mutation information
371
+ * @param params Object containing transaction and collection information
306
372
  * @returns Promise resolving to any value
373
+ * @example
374
+ * // Basic update handler
375
+ * onUpdate: async ({ transaction, collection }) => {
376
+ * const updatedItem = transaction.mutations[0].modified
377
+ * await api.updateTodo(updatedItem.id, updatedItem)
378
+ * }
379
+ *
380
+ * @example
381
+ * // Update handler with partial updates
382
+ * onUpdate: async ({ transaction, collection }) => {
383
+ * const mutation = transaction.mutations[0]
384
+ * const changes = mutation.changes // Only the changed fields
385
+ * await api.updateTodo(mutation.original.id, changes)
386
+ * }
387
+ *
388
+ * @example
389
+ * // Update handler with multiple items
390
+ * onUpdate: async ({ transaction, collection }) => {
391
+ * const updates = transaction.mutations.map(m => ({
392
+ * id: m.key,
393
+ * changes: m.changes
394
+ * }))
395
+ * await api.updateTodos(updates)
396
+ * }
397
+ *
398
+ * @example
399
+ * // Update handler with optimistic rollback
400
+ * onUpdate: async ({ transaction, collection }) => {
401
+ * const mutation = transaction.mutations[0]
402
+ * try {
403
+ * await api.updateTodo(mutation.original.id, mutation.changes)
404
+ * } catch (error) {
405
+ * // Transaction will automatically rollback optimistic changes
406
+ * console.error('Update failed, rolling back:', error)
407
+ * throw error
408
+ * }
409
+ * }
307
410
  */
308
- onUpdate?: UpdateMutationFn<T>
411
+ onUpdate?: UpdateMutationFn<T, TKey>
309
412
  /**
310
413
  * Optional asynchronous handler function called before a delete operation
311
- * @param params Object containing transaction and mutation information
414
+ * @param params Object containing transaction and collection information
312
415
  * @returns Promise resolving to any value
416
+ * @example
417
+ * // Basic delete handler
418
+ * onDelete: async ({ transaction, collection }) => {
419
+ * const deletedKey = transaction.mutations[0].key
420
+ * await api.deleteTodo(deletedKey)
421
+ * }
422
+ *
423
+ * @example
424
+ * // Delete handler with multiple items
425
+ * onDelete: async ({ transaction, collection }) => {
426
+ * const keysToDelete = transaction.mutations.map(m => m.key)
427
+ * await api.deleteTodos(keysToDelete)
428
+ * }
429
+ *
430
+ * @example
431
+ * // Delete handler with confirmation
432
+ * onDelete: async ({ transaction, collection }) => {
433
+ * const mutation = transaction.mutations[0]
434
+ * const shouldDelete = await confirmDeletion(mutation.original)
435
+ * if (!shouldDelete) {
436
+ * throw new Error('Delete cancelled by user')
437
+ * }
438
+ * await api.deleteTodo(mutation.original.id)
439
+ * }
440
+ *
441
+ * @example
442
+ * // Delete handler with optimistic rollback
443
+ * onDelete: async ({ transaction, collection }) => {
444
+ * const mutation = transaction.mutations[0]
445
+ * try {
446
+ * await api.deleteTodo(mutation.original.id)
447
+ * } catch (error) {
448
+ * // Transaction will automatically rollback optimistic changes
449
+ * console.error('Delete failed, rolling back:', error)
450
+ * throw error
451
+ * }
452
+ * }
313
453
  */
314
- onDelete?: DeleteMutationFn<T>
454
+ onDelete?: DeleteMutationFn<T, TKey>
315
455
  }
316
456
 
317
457
  export type ChangesPayload<T extends object = Record<string, unknown>> = Array<
@@ -353,6 +493,37 @@ export type KeyedNamespacedRow = [unknown, NamespacedRow]
353
493
  */
354
494
  export type NamespacedAndKeyedStream = IStreamBuilder<KeyedNamespacedRow>
355
495
 
496
+ /**
497
+ * Function type for listening to collection changes
498
+ * @param changes - Array of change messages describing what happened
499
+ * @example
500
+ * // Basic change listener
501
+ * const listener: ChangeListener = (changes) => {
502
+ * changes.forEach(change => {
503
+ * console.log(`${change.type}: ${change.key}`, change.value)
504
+ * })
505
+ * }
506
+ *
507
+ * collection.subscribeChanges(listener)
508
+ *
509
+ * @example
510
+ * // Handle different change types
511
+ * const listener: ChangeListener<Todo> = (changes) => {
512
+ * for (const change of changes) {
513
+ * switch (change.type) {
514
+ * case 'insert':
515
+ * addToUI(change.value)
516
+ * break
517
+ * case 'update':
518
+ * updateInUI(change.key, change.value, change.previousValue)
519
+ * break
520
+ * case 'delete':
521
+ * removeFromUI(change.key)
522
+ * break
523
+ * }
524
+ * }
525
+ * }
526
+ */
356
527
  export type ChangeListener<
357
528
  T extends object = Record<string, unknown>,
358
529
  TKey extends string | number = string | number,