@tanstack/query-db-collection 1.0.6 → 1.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.
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/global.d.cts +1 -1
- package/dist/cjs/manual-sync.cjs.map +1 -1
- package/dist/cjs/query.cjs.map +1 -1
- package/dist/cjs/serialization.cjs +3 -0
- package/dist/cjs/serialization.cjs.map +1 -1
- package/dist/cjs/serialization.d.cts +3 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/global.d.ts +1 -1
- package/dist/esm/manual-sync.js.map +1 -1
- package/dist/esm/query.js.map +1 -1
- package/dist/esm/serialization.d.ts +3 -1
- package/dist/esm/serialization.js +3 -0
- package/dist/esm/serialization.js.map +1 -1
- package/package.json +28 -28
- package/src/errors.ts +2 -2
- package/src/global.ts +2 -2
- package/src/index.ts +4 -4
- package/src/manual-sync.ts +11 -11
- package/src/query.ts +35 -35
- package/src/serialization.ts +11 -4
package/src/query.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { QueryObserver, hashKey } from
|
|
2
|
-
import { deepEquals } from
|
|
1
|
+
import { QueryObserver, hashKey } from '@tanstack/query-core'
|
|
2
|
+
import { deepEquals } from '@tanstack/db'
|
|
3
3
|
import {
|
|
4
4
|
GetKeyRequiredError,
|
|
5
5
|
QueryClientRequiredError,
|
|
6
6
|
QueryFnRequiredError,
|
|
7
7
|
QueryKeyRequiredError,
|
|
8
|
-
} from
|
|
9
|
-
import { createWriteUtils } from
|
|
10
|
-
import { serializeLoadSubsetOptions } from
|
|
8
|
+
} from './errors'
|
|
9
|
+
import { createWriteUtils } from './manual-sync'
|
|
10
|
+
import { serializeLoadSubsetOptions } from './serialization'
|
|
11
11
|
import type {
|
|
12
12
|
BaseCollectionConfig,
|
|
13
13
|
ChangeMessage,
|
|
@@ -18,7 +18,7 @@ import type {
|
|
|
18
18
|
SyncConfig,
|
|
19
19
|
UpdateMutationFnParams,
|
|
20
20
|
UtilsRecord,
|
|
21
|
-
} from
|
|
21
|
+
} from '@tanstack/db'
|
|
22
22
|
import type {
|
|
23
23
|
FetchStatus,
|
|
24
24
|
QueryClient,
|
|
@@ -26,11 +26,11 @@ import type {
|
|
|
26
26
|
QueryKey,
|
|
27
27
|
QueryObserverOptions,
|
|
28
28
|
QueryObserverResult,
|
|
29
|
-
} from
|
|
30
|
-
import type { StandardSchemaV1 } from
|
|
29
|
+
} from '@tanstack/query-core'
|
|
30
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
|
31
31
|
|
|
32
32
|
// Re-export for external use
|
|
33
|
-
export type { SyncOperation } from
|
|
33
|
+
export type { SyncOperation } from './manual-sync'
|
|
34
34
|
|
|
35
35
|
// Schema output type inference helper (matches electric.ts pattern)
|
|
36
36
|
type InferSchemaOutput<T> = T extends StandardSchemaV1
|
|
@@ -60,7 +60,7 @@ type TQueryKeyBuilder<TQueryKey> = (opts: LoadSubsetOptions) => TQueryKey
|
|
|
60
60
|
export interface QueryCollectionConfig<
|
|
61
61
|
T extends object = object,
|
|
62
62
|
TQueryFn extends (context: QueryFunctionContext<any>) => Promise<any> = (
|
|
63
|
-
context: QueryFunctionContext<any
|
|
63
|
+
context: QueryFunctionContext<any>,
|
|
64
64
|
) => Promise<any>,
|
|
65
65
|
TError = unknown,
|
|
66
66
|
TQueryKey extends QueryKey = QueryKey,
|
|
@@ -72,7 +72,7 @@ export interface QueryCollectionConfig<
|
|
|
72
72
|
queryKey: TQueryKey | TQueryKeyBuilder<TQueryKey>
|
|
73
73
|
/** Function that fetches data from the server. Must return the complete collection state */
|
|
74
74
|
queryFn: TQueryFn extends (
|
|
75
|
-
context: QueryFunctionContext<TQueryKey
|
|
75
|
+
context: QueryFunctionContext<TQueryKey>,
|
|
76
76
|
) => Promise<Array<any>>
|
|
77
77
|
? (context: QueryFunctionContext<TQueryKey>) => Promise<Array<T>>
|
|
78
78
|
: TQueryFn
|
|
@@ -232,7 +232,7 @@ class QueryCollectionUtilsImpl {
|
|
|
232
232
|
constructor(
|
|
233
233
|
state: QueryCollectionState,
|
|
234
234
|
refetch: RefetchFn,
|
|
235
|
-
writeUtils: ReturnType<typeof createWriteUtils
|
|
235
|
+
writeUtils: ReturnType<typeof createWriteUtils>,
|
|
236
236
|
) {
|
|
237
237
|
this.state = state
|
|
238
238
|
this.refetchFn = refetch
|
|
@@ -270,21 +270,21 @@ class QueryCollectionUtilsImpl {
|
|
|
270
270
|
public get isFetching() {
|
|
271
271
|
// check if any observer is fetching
|
|
272
272
|
return Array.from(this.state.observers.values()).some(
|
|
273
|
-
(observer) => observer.getCurrentResult().isFetching
|
|
273
|
+
(observer) => observer.getCurrentResult().isFetching,
|
|
274
274
|
)
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
public get isRefetching() {
|
|
278
278
|
// check if any observer is refetching
|
|
279
279
|
return Array.from(this.state.observers.values()).some(
|
|
280
|
-
(observer) => observer.getCurrentResult().isRefetching
|
|
280
|
+
(observer) => observer.getCurrentResult().isRefetching,
|
|
281
281
|
)
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
public get isLoading() {
|
|
285
285
|
// check if any observer is loading
|
|
286
286
|
return Array.from(this.state.observers.values()).some(
|
|
287
|
-
(observer) => observer.getCurrentResult().isLoading
|
|
287
|
+
(observer) => observer.getCurrentResult().isLoading,
|
|
288
288
|
)
|
|
289
289
|
}
|
|
290
290
|
|
|
@@ -293,14 +293,14 @@ class QueryCollectionUtilsImpl {
|
|
|
293
293
|
return Math.max(
|
|
294
294
|
0,
|
|
295
295
|
...Array.from(this.state.observers.values()).map(
|
|
296
|
-
(observer) => observer.getCurrentResult().dataUpdatedAt
|
|
297
|
-
)
|
|
296
|
+
(observer) => observer.getCurrentResult().dataUpdatedAt,
|
|
297
|
+
),
|
|
298
298
|
)
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
public get fetchStatus(): Array<FetchStatus> {
|
|
302
302
|
return Array.from(this.state.observers.values()).map(
|
|
303
|
-
(observer) => observer.getCurrentResult().fetchStatus
|
|
303
|
+
(observer) => observer.getCurrentResult().fetchStatus,
|
|
304
304
|
)
|
|
305
305
|
}
|
|
306
306
|
}
|
|
@@ -409,7 +409,7 @@ export function queryCollectionOptions<
|
|
|
409
409
|
> & {
|
|
410
410
|
schema: T
|
|
411
411
|
select: (data: TQueryData) => Array<InferSchemaInput<T>>
|
|
412
|
-
}
|
|
412
|
+
},
|
|
413
413
|
): CollectionConfig<
|
|
414
414
|
InferSchemaOutput<T>,
|
|
415
415
|
TKey,
|
|
@@ -429,7 +429,7 @@ export function queryCollectionOptions<
|
|
|
429
429
|
export function queryCollectionOptions<
|
|
430
430
|
T extends object,
|
|
431
431
|
TQueryFn extends (context: QueryFunctionContext<any>) => Promise<any> = (
|
|
432
|
-
context: QueryFunctionContext<any
|
|
432
|
+
context: QueryFunctionContext<any>,
|
|
433
433
|
) => Promise<any>,
|
|
434
434
|
TError = unknown,
|
|
435
435
|
TQueryKey extends QueryKey = QueryKey,
|
|
@@ -447,7 +447,7 @@ export function queryCollectionOptions<
|
|
|
447
447
|
> & {
|
|
448
448
|
schema?: never // prohibit schema
|
|
449
449
|
select: (data: TQueryData) => Array<T>
|
|
450
|
-
}
|
|
450
|
+
},
|
|
451
451
|
): CollectionConfig<
|
|
452
452
|
T,
|
|
453
453
|
TKey,
|
|
@@ -468,7 +468,7 @@ export function queryCollectionOptions<
|
|
|
468
468
|
config: QueryCollectionConfig<
|
|
469
469
|
InferSchemaOutput<T>,
|
|
470
470
|
(
|
|
471
|
-
context: QueryFunctionContext<any
|
|
471
|
+
context: QueryFunctionContext<any>,
|
|
472
472
|
) => Promise<Array<InferSchemaOutput<T>>>,
|
|
473
473
|
TError,
|
|
474
474
|
TQueryKey,
|
|
@@ -476,7 +476,7 @@ export function queryCollectionOptions<
|
|
|
476
476
|
T
|
|
477
477
|
> & {
|
|
478
478
|
schema: T
|
|
479
|
-
}
|
|
479
|
+
},
|
|
480
480
|
): CollectionConfig<
|
|
481
481
|
InferSchemaOutput<T>,
|
|
482
482
|
TKey,
|
|
@@ -507,7 +507,7 @@ export function queryCollectionOptions<
|
|
|
507
507
|
TKey
|
|
508
508
|
> & {
|
|
509
509
|
schema?: never // prohibit schema
|
|
510
|
-
}
|
|
510
|
+
},
|
|
511
511
|
): CollectionConfig<
|
|
512
512
|
T,
|
|
513
513
|
TKey,
|
|
@@ -519,7 +519,7 @@ export function queryCollectionOptions<
|
|
|
519
519
|
}
|
|
520
520
|
|
|
521
521
|
export function queryCollectionOptions(
|
|
522
|
-
config: QueryCollectionConfig<Record<string, unknown
|
|
522
|
+
config: QueryCollectionConfig<Record<string, unknown>>,
|
|
523
523
|
): CollectionConfig<
|
|
524
524
|
Record<string, unknown>,
|
|
525
525
|
string | number,
|
|
@@ -663,7 +663,7 @@ export function queryCollectionOptions(
|
|
|
663
663
|
|
|
664
664
|
const createQueryFromOpts = (
|
|
665
665
|
opts: LoadSubsetOptions = {},
|
|
666
|
-
queryFunction: typeof queryFn = queryFn
|
|
666
|
+
queryFunction: typeof queryFn = queryFn,
|
|
667
667
|
): true | Promise<void> => {
|
|
668
668
|
// Generate key using common function
|
|
669
669
|
const key = generateQueryKeyFromOptions(opts)
|
|
@@ -675,7 +675,7 @@ export function queryCollectionOptions(
|
|
|
675
675
|
// Increment reference count since another consumer is using this observer
|
|
676
676
|
queryRefCounts.set(
|
|
677
677
|
hashedQueryKey,
|
|
678
|
-
(queryRefCounts.get(hashedQueryKey) || 0) + 1
|
|
678
|
+
(queryRefCounts.get(hashedQueryKey) || 0) + 1,
|
|
679
679
|
)
|
|
680
680
|
|
|
681
681
|
// Get the current result and return based on its state
|
|
@@ -739,7 +739,7 @@ export function queryCollectionOptions(
|
|
|
739
739
|
// Increment reference count for this query
|
|
740
740
|
queryRefCounts.set(
|
|
741
741
|
hashedQueryKey,
|
|
742
|
-
(queryRefCounts.get(hashedQueryKey) || 0) + 1
|
|
742
|
+
(queryRefCounts.get(hashedQueryKey) || 0) + 1,
|
|
743
743
|
)
|
|
744
744
|
|
|
745
745
|
// Create a promise that resolves when the query result is first available
|
|
@@ -790,7 +790,7 @@ export function queryCollectionOptions(
|
|
|
790
790
|
}
|
|
791
791
|
|
|
792
792
|
const currentSyncedItems: Map<string | number, any> = new Map(
|
|
793
|
-
collection._state.syncedData.entries()
|
|
793
|
+
collection._state.syncedData.entries(),
|
|
794
794
|
)
|
|
795
795
|
const newItemsMap = new Map<string | number, any>()
|
|
796
796
|
newItemsArray.forEach((item) => {
|
|
@@ -833,7 +833,7 @@ export function queryCollectionOptions(
|
|
|
833
833
|
|
|
834
834
|
console.error(
|
|
835
835
|
`[QueryCollection] Error observing query ${String(queryKey)}:`,
|
|
836
|
-
result.error
|
|
836
|
+
result.error,
|
|
837
837
|
)
|
|
838
838
|
|
|
839
839
|
// Mark collection as ready even on error to avoid blocking apps
|
|
@@ -849,7 +849,7 @@ export function queryCollectionOptions(
|
|
|
849
849
|
|
|
850
850
|
const subscribeToQuery = (
|
|
851
851
|
observer: QueryObserver<Array<any>, any, Array<any>, Array<any>, any>,
|
|
852
|
-
hashedQueryKey: string
|
|
852
|
+
hashedQueryKey: string,
|
|
853
853
|
) => {
|
|
854
854
|
if (!isSubscribed(hashedQueryKey)) {
|
|
855
855
|
const cachedQueryKey = hashToQueryKey.get(hashedQueryKey)!
|
|
@@ -889,7 +889,7 @@ export function queryCollectionOptions(
|
|
|
889
889
|
} else if (subscriberCount === 0) {
|
|
890
890
|
unsubscribeFromQueries()
|
|
891
891
|
}
|
|
892
|
-
}
|
|
892
|
+
},
|
|
893
893
|
)
|
|
894
894
|
|
|
895
895
|
// If syncMode is eager, create the initial query without any predicates
|
|
@@ -989,7 +989,7 @@ export function queryCollectionOptions(
|
|
|
989
989
|
if (refcount > 0) {
|
|
990
990
|
console.warn(
|
|
991
991
|
`[cleanupQueryIfIdle] Invariant violation: refcount=${refcount} but no listeners. Cleaning up to prevent leak.`,
|
|
992
|
-
{ hashedQueryKey }
|
|
992
|
+
{ hashedQueryKey },
|
|
993
993
|
)
|
|
994
994
|
}
|
|
995
995
|
|
|
@@ -1040,7 +1040,7 @@ export function queryCollectionOptions(
|
|
|
1040
1040
|
allQueryKeys.map(async (qKey) => {
|
|
1041
1041
|
await queryClient.cancelQueries({ queryKey: qKey, exact: true })
|
|
1042
1042
|
queryClient.removeQueries({ queryKey: qKey, exact: true })
|
|
1043
|
-
})
|
|
1043
|
+
}),
|
|
1044
1044
|
)
|
|
1045
1045
|
}
|
|
1046
1046
|
|
|
@@ -1162,7 +1162,7 @@ export function queryCollectionOptions(
|
|
|
1162
1162
|
|
|
1163
1163
|
// Create write utils using the manual-sync module
|
|
1164
1164
|
const writeUtils = createWriteUtils<any, string | number, any>(
|
|
1165
|
-
() => writeContext
|
|
1165
|
+
() => writeContext,
|
|
1166
1166
|
)
|
|
1167
1167
|
|
|
1168
1168
|
// Create wrapper handlers for direct persistence operations that handle refetching
|
package/src/serialization.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import type { IR, LoadSubsetOptions } from
|
|
1
|
+
import type { IR, LoadSubsetOptions } from '@tanstack/db'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Serializes LoadSubsetOptions into a stable, hashable format for query keys
|
|
4
|
+
* Serializes LoadSubsetOptions into a stable, hashable format for query keys.
|
|
5
|
+
* Includes where, orderBy, limit, and offset for pagination support.
|
|
6
|
+
* Note: cursor expressions are not serialized as they are backend-specific.
|
|
5
7
|
* @internal
|
|
6
8
|
*/
|
|
7
9
|
export function serializeLoadSubsetOptions(
|
|
8
|
-
options: LoadSubsetOptions | undefined
|
|
10
|
+
options: LoadSubsetOptions | undefined,
|
|
9
11
|
): string | undefined {
|
|
10
12
|
if (!options) {
|
|
11
13
|
return undefined
|
|
@@ -43,6 +45,11 @@ export function serializeLoadSubsetOptions(
|
|
|
43
45
|
result.limit = options.limit
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
// Include offset for pagination support
|
|
49
|
+
if (options.offset !== undefined) {
|
|
50
|
+
result.offset = options.offset
|
|
51
|
+
}
|
|
52
|
+
|
|
46
53
|
return Object.keys(result).length === 0 ? undefined : JSON.stringify(result)
|
|
47
54
|
}
|
|
48
55
|
|
|
@@ -120,7 +127,7 @@ function serializeValue(value: unknown): unknown {
|
|
|
120
127
|
Object.entries(value as Record<string, unknown>).map(([key, val]) => [
|
|
121
128
|
key,
|
|
122
129
|
serializeValue(val),
|
|
123
|
-
])
|
|
130
|
+
]),
|
|
124
131
|
)
|
|
125
132
|
}
|
|
126
133
|
|