@tanstack/db 0.4.9 → 0.4.11
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.
- package/dist/cjs/collection/events.cjs +9 -51
- package/dist/cjs/collection/events.cjs.map +1 -1
- package/dist/cjs/collection/events.d.cts +18 -7
- package/dist/cjs/collection/index.cjs +9 -12
- package/dist/cjs/collection/index.cjs.map +1 -1
- package/dist/cjs/collection/index.d.cts +13 -14
- package/dist/cjs/collection/subscription.cjs +62 -6
- package/dist/cjs/collection/subscription.cjs.map +1 -1
- package/dist/cjs/collection/subscription.d.cts +16 -3
- package/dist/cjs/collection/sync.cjs +58 -6
- package/dist/cjs/collection/sync.cjs.map +1 -1
- package/dist/cjs/collection/sync.d.cts +18 -4
- package/dist/cjs/errors.cjs +8 -0
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/errors.d.cts +6 -0
- package/dist/cjs/event-emitter.cjs +94 -0
- package/dist/cjs/event-emitter.cjs.map +1 -0
- package/dist/cjs/event-emitter.d.cts +45 -0
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/local-only.cjs.map +1 -1
- package/dist/cjs/local-only.d.cts +2 -5
- package/dist/cjs/query/compiler/index.cjs +6 -2
- package/dist/cjs/query/compiler/index.cjs.map +1 -1
- package/dist/cjs/query/compiler/index.d.cts +3 -2
- package/dist/cjs/query/compiler/joins.cjs +6 -3
- package/dist/cjs/query/compiler/joins.cjs.map +1 -1
- package/dist/cjs/query/compiler/joins.d.cts +2 -2
- package/dist/cjs/query/compiler/order-by.cjs +18 -4
- package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.d.cts +2 -1
- package/dist/cjs/query/compiler/types.d.cts +4 -0
- package/dist/cjs/query/index.d.cts +1 -0
- package/dist/cjs/query/live/collection-config-builder.cjs +43 -6
- package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
- package/dist/cjs/query/live/collection-config-builder.d.cts +27 -1
- package/dist/cjs/query/live/collection-subscriber.cjs +29 -0
- package/dist/cjs/query/live/collection-subscriber.cjs.map +1 -1
- package/dist/cjs/query/live/collection-subscriber.d.cts +1 -0
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/query/live-query-collection.d.cts +2 -2
- package/dist/cjs/types.d.cts +82 -11
- package/dist/esm/collection/events.d.ts +18 -7
- package/dist/esm/collection/events.js +9 -51
- package/dist/esm/collection/events.js.map +1 -1
- package/dist/esm/collection/index.d.ts +13 -14
- package/dist/esm/collection/index.js +9 -12
- package/dist/esm/collection/index.js.map +1 -1
- package/dist/esm/collection/subscription.d.ts +16 -3
- package/dist/esm/collection/subscription.js +62 -6
- package/dist/esm/collection/subscription.js.map +1 -1
- package/dist/esm/collection/sync.d.ts +18 -4
- package/dist/esm/collection/sync.js +59 -7
- package/dist/esm/collection/sync.js.map +1 -1
- package/dist/esm/errors.d.ts +6 -0
- package/dist/esm/errors.js +8 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/event-emitter.d.ts +45 -0
- package/dist/esm/event-emitter.js +94 -0
- package/dist/esm/event-emitter.js.map +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/local-only.d.ts +2 -5
- package/dist/esm/local-only.js.map +1 -1
- package/dist/esm/query/compiler/index.d.ts +3 -2
- package/dist/esm/query/compiler/index.js +6 -2
- package/dist/esm/query/compiler/index.js.map +1 -1
- package/dist/esm/query/compiler/joins.d.ts +2 -2
- package/dist/esm/query/compiler/joins.js +6 -3
- package/dist/esm/query/compiler/joins.js.map +1 -1
- package/dist/esm/query/compiler/order-by.d.ts +2 -1
- package/dist/esm/query/compiler/order-by.js +18 -4
- package/dist/esm/query/compiler/order-by.js.map +1 -1
- package/dist/esm/query/compiler/types.d.ts +4 -0
- package/dist/esm/query/index.d.ts +1 -0
- package/dist/esm/query/live/collection-config-builder.d.ts +27 -1
- package/dist/esm/query/live/collection-config-builder.js +44 -7
- package/dist/esm/query/live/collection-config-builder.js.map +1 -1
- package/dist/esm/query/live/collection-subscriber.d.ts +1 -0
- package/dist/esm/query/live/collection-subscriber.js +29 -0
- package/dist/esm/query/live/collection-subscriber.js.map +1 -1
- package/dist/esm/query/live-query-collection.d.ts +2 -2
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/types.d.ts +82 -11
- package/package.json +2 -2
- package/src/collection/events.ts +25 -74
- package/src/collection/index.ts +15 -19
- package/src/collection/subscription.ts +88 -6
- package/src/collection/sync.ts +81 -9
- package/src/errors.ts +12 -0
- package/src/event-emitter.ts +118 -0
- package/src/local-only.ts +5 -12
- package/src/query/compiler/index.ts +9 -1
- package/src/query/compiler/joins.ts +7 -1
- package/src/query/compiler/order-by.ts +23 -2
- package/src/query/compiler/types.ts +5 -0
- package/src/query/index.ts +1 -0
- package/src/query/live/collection-config-builder.ts +76 -7
- package/src/query/live/collection-subscriber.ts +50 -0
- package/src/query/live-query-collection.ts +8 -4
- package/src/types.ts +93 -11
|
@@ -24,6 +24,12 @@ export class CollectionSubscriber<
|
|
|
24
24
|
// Keep track of the biggest value we've sent so far (needed for orderBy optimization)
|
|
25
25
|
private biggest: any = undefined
|
|
26
26
|
|
|
27
|
+
// Track deferred promises for subscription loading states
|
|
28
|
+
private subscriptionLoadingPromises = new Map<
|
|
29
|
+
CollectionSubscription,
|
|
30
|
+
{ resolve: () => void }
|
|
31
|
+
>()
|
|
32
|
+
|
|
27
33
|
constructor(
|
|
28
34
|
private alias: string,
|
|
29
35
|
private collectionId: string,
|
|
@@ -66,7 +72,51 @@ export class CollectionSubscriber<
|
|
|
66
72
|
includeInitialState
|
|
67
73
|
)
|
|
68
74
|
}
|
|
75
|
+
|
|
76
|
+
// Subscribe to subscription status changes to propagate loading state
|
|
77
|
+
const statusUnsubscribe = subscription.on(`status:change`, (event) => {
|
|
78
|
+
// TODO: For now we are setting this loading state whenever the subscription
|
|
79
|
+
// status changes to 'loadingSubset'. But we have discussed it only happening
|
|
80
|
+
// when the the live query has it's offset/limit changed, and that triggers the
|
|
81
|
+
// subscription to request a snapshot. This will require more work to implement,
|
|
82
|
+
// and builds on https://github.com/TanStack/db/pull/663 which this PR
|
|
83
|
+
// does not yet depend on.
|
|
84
|
+
if (event.status === `loadingSubset`) {
|
|
85
|
+
// Guard against duplicate transitions
|
|
86
|
+
if (!this.subscriptionLoadingPromises.has(subscription)) {
|
|
87
|
+
let resolve: () => void
|
|
88
|
+
const promise = new Promise<void>((res) => {
|
|
89
|
+
resolve = res
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
this.subscriptionLoadingPromises.set(subscription, {
|
|
93
|
+
resolve: resolve!,
|
|
94
|
+
})
|
|
95
|
+
this.collectionConfigBuilder.liveQueryCollection!._sync.trackLoadPromise(
|
|
96
|
+
promise
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
// status is 'ready'
|
|
101
|
+
const deferred = this.subscriptionLoadingPromises.get(subscription)
|
|
102
|
+
if (deferred) {
|
|
103
|
+
// Clear the map entry FIRST (before resolving)
|
|
104
|
+
this.subscriptionLoadingPromises.delete(subscription)
|
|
105
|
+
deferred.resolve()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
69
110
|
const unsubscribe = () => {
|
|
111
|
+
// If subscription has a pending promise, resolve it before unsubscribing
|
|
112
|
+
const deferred = this.subscriptionLoadingPromises.get(subscription)
|
|
113
|
+
if (deferred) {
|
|
114
|
+
// Clear the map entry FIRST (before resolving)
|
|
115
|
+
this.subscriptionLoadingPromises.delete(subscription)
|
|
116
|
+
deferred.resolve()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
statusUnsubscribe()
|
|
70
120
|
subscription.unsubscribe()
|
|
71
121
|
}
|
|
72
122
|
// currentSyncState is always defined when subscribe() is called
|
|
@@ -20,16 +20,20 @@ import type { Context, GetResult } from "./builder/types.js"
|
|
|
20
20
|
type CollectionConfigForContext<
|
|
21
21
|
TContext extends Context,
|
|
22
22
|
TResult extends object,
|
|
23
|
+
TUtils extends UtilsRecord = {},
|
|
23
24
|
> = TContext extends SingleResult
|
|
24
|
-
? CollectionConfigSingleRowOption<TResult> &
|
|
25
|
-
|
|
25
|
+
? CollectionConfigSingleRowOption<TResult, string | number, never, TUtils> &
|
|
26
|
+
SingleResult
|
|
27
|
+
: CollectionConfigSingleRowOption<TResult, string | number, never, TUtils> &
|
|
28
|
+
NonSingleResult
|
|
26
29
|
|
|
27
30
|
type CollectionForContext<
|
|
28
31
|
TContext extends Context,
|
|
29
32
|
TResult extends object,
|
|
33
|
+
TUtils extends UtilsRecord = {},
|
|
30
34
|
> = TContext extends SingleResult
|
|
31
|
-
? Collection<TResult> & SingleResult
|
|
32
|
-
: Collection<TResult> & NonSingleResult
|
|
35
|
+
? Collection<TResult, string | number, TUtils> & SingleResult
|
|
36
|
+
: Collection<TResult, string | number, TUtils> & NonSingleResult
|
|
33
37
|
|
|
34
38
|
/**
|
|
35
39
|
* Creates live query collection options for use with createCollection
|
package/src/types.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Collection } from "./collection/index.js"
|
|
|
3
3
|
import type { StandardSchemaV1 } from "@standard-schema/spec"
|
|
4
4
|
import type { Transaction } from "./transactions"
|
|
5
5
|
import type { BasicExpression, OrderBy } from "./query/ir.js"
|
|
6
|
+
import type { EventEmitter } from "./event-emitter.js"
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Helper type to extract the output type from a standard schema
|
|
@@ -150,17 +151,83 @@ export type Row<TExtensions = never> = Record<string, Value<TExtensions>>
|
|
|
150
151
|
|
|
151
152
|
export type OperationType = `insert` | `update` | `delete`
|
|
152
153
|
|
|
153
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Subscription status values
|
|
156
|
+
*/
|
|
157
|
+
export type SubscriptionStatus = `ready` | `loadingSubset`
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Event emitted when subscription status changes
|
|
161
|
+
*/
|
|
162
|
+
export interface SubscriptionStatusChangeEvent {
|
|
163
|
+
type: `status:change`
|
|
164
|
+
subscription: Subscription
|
|
165
|
+
previousStatus: SubscriptionStatus
|
|
166
|
+
status: SubscriptionStatus
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Event emitted when subscription status changes to a specific status
|
|
171
|
+
*/
|
|
172
|
+
export interface SubscriptionStatusEvent<T extends SubscriptionStatus> {
|
|
173
|
+
type: `status:${T}`
|
|
174
|
+
subscription: Subscription
|
|
175
|
+
previousStatus: SubscriptionStatus
|
|
176
|
+
status: T
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Event emitted when subscription is unsubscribed
|
|
181
|
+
*/
|
|
182
|
+
export interface SubscriptionUnsubscribedEvent {
|
|
183
|
+
type: `unsubscribed`
|
|
184
|
+
subscription: Subscription
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* All subscription events
|
|
189
|
+
*/
|
|
190
|
+
export type SubscriptionEvents = {
|
|
191
|
+
"status:change": SubscriptionStatusChangeEvent
|
|
192
|
+
"status:ready": SubscriptionStatusEvent<`ready`>
|
|
193
|
+
"status:loadingSubset": SubscriptionStatusEvent<`loadingSubset`>
|
|
194
|
+
unsubscribed: SubscriptionUnsubscribedEvent
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Public interface for a collection subscription
|
|
199
|
+
* Used by sync implementations to track subscription lifecycle
|
|
200
|
+
*/
|
|
201
|
+
export interface Subscription extends EventEmitter<SubscriptionEvents> {
|
|
202
|
+
/** Current status of the subscription */
|
|
203
|
+
readonly status: SubscriptionStatus
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export type LoadSubsetOptions = {
|
|
207
|
+
/** The where expression to filter the data */
|
|
154
208
|
where?: BasicExpression<boolean>
|
|
209
|
+
/** The order by clause to sort the data */
|
|
155
210
|
orderBy?: OrderBy
|
|
211
|
+
/** The limit of the data to load */
|
|
156
212
|
limit?: number
|
|
213
|
+
/**
|
|
214
|
+
* The subscription that triggered the load.
|
|
215
|
+
* Advanced sync implementations can use this for:
|
|
216
|
+
* - LRU caching keyed by subscription
|
|
217
|
+
* - Reference counting to track active subscriptions
|
|
218
|
+
* - Subscribing to subscription events (e.g., finalization/unsubscribe)
|
|
219
|
+
* @optional Available when called from CollectionSubscription, may be undefined for direct calls
|
|
220
|
+
*/
|
|
221
|
+
subscription?: Subscription
|
|
157
222
|
}
|
|
158
223
|
|
|
224
|
+
export type LoadSubsetFn = (options: LoadSubsetOptions) => true | Promise<void>
|
|
225
|
+
|
|
159
226
|
export type CleanupFn = () => void
|
|
160
227
|
|
|
161
228
|
export type SyncConfigRes = {
|
|
162
229
|
cleanup?: CleanupFn
|
|
163
|
-
|
|
230
|
+
loadSubset?: LoadSubsetFn
|
|
164
231
|
}
|
|
165
232
|
export interface SyncConfig<
|
|
166
233
|
T extends object = Record<string, unknown>,
|
|
@@ -242,7 +309,7 @@ export interface InsertConfig {
|
|
|
242
309
|
export type UpdateMutationFnParams<
|
|
243
310
|
T extends object = Record<string, unknown>,
|
|
244
311
|
TKey extends string | number = string | number,
|
|
245
|
-
TUtils extends UtilsRecord =
|
|
312
|
+
TUtils extends UtilsRecord = UtilsRecord,
|
|
246
313
|
> = {
|
|
247
314
|
transaction: TransactionWithMutations<T, `update`>
|
|
248
315
|
collection: Collection<T, TKey, TUtils>
|
|
@@ -251,7 +318,7 @@ export type UpdateMutationFnParams<
|
|
|
251
318
|
export type InsertMutationFnParams<
|
|
252
319
|
T extends object = Record<string, unknown>,
|
|
253
320
|
TKey extends string | number = string | number,
|
|
254
|
-
TUtils extends UtilsRecord =
|
|
321
|
+
TUtils extends UtilsRecord = UtilsRecord,
|
|
255
322
|
> = {
|
|
256
323
|
transaction: TransactionWithMutations<T, `insert`>
|
|
257
324
|
collection: Collection<T, TKey, TUtils>
|
|
@@ -259,7 +326,7 @@ export type InsertMutationFnParams<
|
|
|
259
326
|
export type DeleteMutationFnParams<
|
|
260
327
|
T extends object = Record<string, unknown>,
|
|
261
328
|
TKey extends string | number = string | number,
|
|
262
|
-
TUtils extends UtilsRecord =
|
|
329
|
+
TUtils extends UtilsRecord = UtilsRecord,
|
|
263
330
|
> = {
|
|
264
331
|
transaction: TransactionWithMutations<T, `delete`>
|
|
265
332
|
collection: Collection<T, TKey, TUtils>
|
|
@@ -268,21 +335,21 @@ export type DeleteMutationFnParams<
|
|
|
268
335
|
export type InsertMutationFn<
|
|
269
336
|
T extends object = Record<string, unknown>,
|
|
270
337
|
TKey extends string | number = string | number,
|
|
271
|
-
TUtils extends UtilsRecord =
|
|
338
|
+
TUtils extends UtilsRecord = UtilsRecord,
|
|
272
339
|
TReturn = any,
|
|
273
340
|
> = (params: InsertMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>
|
|
274
341
|
|
|
275
342
|
export type UpdateMutationFn<
|
|
276
343
|
T extends object = Record<string, unknown>,
|
|
277
344
|
TKey extends string | number = string | number,
|
|
278
|
-
TUtils extends UtilsRecord =
|
|
345
|
+
TUtils extends UtilsRecord = UtilsRecord,
|
|
279
346
|
TReturn = any,
|
|
280
347
|
> = (params: UpdateMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>
|
|
281
348
|
|
|
282
349
|
export type DeleteMutationFn<
|
|
283
350
|
T extends object = Record<string, unknown>,
|
|
284
351
|
TKey extends string | number = string | number,
|
|
285
|
-
TUtils extends UtilsRecord =
|
|
352
|
+
TUtils extends UtilsRecord = UtilsRecord,
|
|
286
353
|
TReturn = any,
|
|
287
354
|
> = (params: DeleteMutationFnParams<T, TKey, TUtils>) => Promise<TReturn>
|
|
288
355
|
|
|
@@ -313,6 +380,8 @@ export type CollectionStatus =
|
|
|
313
380
|
/** Collection has been cleaned up and resources freed */
|
|
314
381
|
| `cleaned-up`
|
|
315
382
|
|
|
383
|
+
export type SyncMode = `eager` | `on-demand`
|
|
384
|
+
|
|
316
385
|
export interface BaseCollectionConfig<
|
|
317
386
|
T extends object = Record<string, unknown>,
|
|
318
387
|
TKey extends string | number = string | number,
|
|
@@ -321,7 +390,7 @@ export interface BaseCollectionConfig<
|
|
|
321
390
|
// then it would conflict with the overloads of createCollection which
|
|
322
391
|
// requires either T to be provided or a schema to be provided but not both!
|
|
323
392
|
TSchema extends StandardSchemaV1 = never,
|
|
324
|
-
TUtils extends UtilsRecord =
|
|
393
|
+
TUtils extends UtilsRecord = UtilsRecord,
|
|
325
394
|
TReturn = any,
|
|
326
395
|
> {
|
|
327
396
|
// If an id isn't passed in, a UUID will be
|
|
@@ -374,6 +443,15 @@ export interface BaseCollectionConfig<
|
|
|
374
443
|
* compare: (x, y) => x.createdAt.getTime() - y.createdAt.getTime()
|
|
375
444
|
*/
|
|
376
445
|
compare?: (x: T, y: T) => number
|
|
446
|
+
/**
|
|
447
|
+
* The mode of sync to use for the collection.
|
|
448
|
+
* @default `eager`
|
|
449
|
+
* @description
|
|
450
|
+
* - `eager`: syncs all data immediately on preload
|
|
451
|
+
* - `on-demand`: syncs data in incremental snapshots when the collection is queried
|
|
452
|
+
* The exact implementation of the sync mode is up to the sync implementation.
|
|
453
|
+
*/
|
|
454
|
+
syncMode?: SyncMode
|
|
377
455
|
/**
|
|
378
456
|
* Optional asynchronous handler function called before an insert operation
|
|
379
457
|
* @param params Object containing transaction and collection information
|
|
@@ -503,13 +581,16 @@ export interface BaseCollectionConfig<
|
|
|
503
581
|
* }
|
|
504
582
|
*/
|
|
505
583
|
onDelete?: DeleteMutationFn<T, TKey, TUtils, TReturn>
|
|
584
|
+
|
|
585
|
+
utils?: TUtils
|
|
506
586
|
}
|
|
507
587
|
|
|
508
588
|
export interface CollectionConfig<
|
|
509
589
|
T extends object = Record<string, unknown>,
|
|
510
590
|
TKey extends string | number = string | number,
|
|
511
591
|
TSchema extends StandardSchemaV1 = never,
|
|
512
|
-
|
|
592
|
+
TUtils extends UtilsRecord = UtilsRecord,
|
|
593
|
+
> extends BaseCollectionConfig<T, TKey, TSchema, TUtils> {
|
|
513
594
|
sync: SyncConfig<T, TKey>
|
|
514
595
|
}
|
|
515
596
|
|
|
@@ -533,7 +614,8 @@ export type CollectionConfigSingleRowOption<
|
|
|
533
614
|
T extends object = Record<string, unknown>,
|
|
534
615
|
TKey extends string | number = string | number,
|
|
535
616
|
TSchema extends StandardSchemaV1 = never,
|
|
536
|
-
|
|
617
|
+
TUtils extends UtilsRecord = {},
|
|
618
|
+
> = CollectionConfig<T, TKey, TSchema, TUtils> & MaybeSingleResult
|
|
537
619
|
|
|
538
620
|
export type ChangesPayload<T extends object = Record<string, unknown>> = Array<
|
|
539
621
|
ChangeMessage<T>
|