Skip to content

Commit 1367756

Browse files
KyleAMathewsclaude
andauthored
Add QueryObserver state utility methods to QueryCollectionUtils (#742)
* feat: Add QueryObserver state utilities and convert error utils to getters Adds new utilities to expose TanStack Query's QueryObserver state: - isFetching: Check if query is currently fetching - isRefetching: Check if query is refetching in background - isLoading: Check if query is loading for first time - dataUpdatedAt: Timestamp of last successful data update - fetchStatus: Current fetch status ('fetching' | 'paused' | 'idle') BREAKING CHANGE: Error state utilities are now getters instead of methods: - collection.utils.lastError() → collection.utils.lastError - collection.utils.isError() → collection.utils.isError - collection.utils.errorCount() → collection.utils.errorCount * refactor: Extract QueryCollectionUtilsImpl class from closure Addresses PR feedback from samwillis: refactor QueryCollectionUtilsImpl class to be extracted outside the function scope with required state passed through the constructor instead of relying on closure patterns. This improves code architecture by making dependencies explicit and avoiding nested class definitions within functions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: Update generated docs Re-generate documentation after QueryCollectionUtilsImpl refactoring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: Re-generate documentation after build Regenerated all documentation files after running full build. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: Fix outdated comment about closure usage Update QueryCollectionUtilsImpl class comment to accurately reflect that it now uses explicit dependency injection instead of closure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6c55e16 commit 1367756

11 files changed

Lines changed: 345 additions & 127 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
"@tanstack/query-db-collection": minor
3+
"@tanstack/db": patch
4+
---
5+
6+
Add QueryObserver state utilities and convert error utils to getters
7+
8+
Exposes TanStack Query's QueryObserver state through QueryCollectionUtils, providing visibility into sync status beyond just error states. Also converts existing error state utilities from methods to getters for consistency with TanStack DB/Query patterns.
9+
10+
**Breaking Changes:**
11+
12+
- `lastError()`, `isError()`, and `errorCount()` are now getters instead of methods
13+
- Before: `collection.utils.lastError()`
14+
- After: `collection.utils.lastError`
15+
16+
**New Utilities:**
17+
18+
- `isFetching` - Check if query is currently fetching (initial or background)
19+
- `isRefetching` - Check if query is refetching in background
20+
- `isLoading` - Check if query is loading for first time
21+
- `dataUpdatedAt` - Get timestamp of last successful data update
22+
- `fetchStatus` - Get current fetch status ('fetching' | 'paused' | 'idle')
23+
24+
**Use Cases:**
25+
26+
- Show loading indicators during background refetches
27+
- Implement "Last updated X minutes ago" UI patterns
28+
- Better understanding of query sync behavior
29+
30+
**Example Usage:**
31+
32+
```ts
33+
const collection = queryCollectionOptions({
34+
// ... config
35+
})
36+
37+
// Check sync status
38+
if (collection.utils.isFetching) {
39+
console.log("Syncing with server...")
40+
}
41+
42+
if (collection.utils.isRefetching) {
43+
console.log("Background refresh in progress")
44+
}
45+
46+
// Show last update time
47+
const lastUpdate = new Date(collection.utils.dataUpdatedAt)
48+
console.log(`Last synced: ${lastUpdate.toLocaleTimeString()}`)
49+
50+
// Check error state (now using getters)
51+
if (collection.utils.isError) {
52+
console.error("Sync failed:", collection.utils.lastError)
53+
console.log(`Failed ${collection.utils.errorCount} times`)
54+
}
55+
```

docs/reference/electric-db-collection/interfaces/ElectricCollectionUtils.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Electric collection utilities type
2222
## Indexable
2323

2424
```ts
25-
[key: string]: Fn
25+
[key: string]: any
2626
```
2727

2828
## Properties

docs/reference/interfaces/LocalOnlyCollectionUtils.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Local-only collection utilities type
1616
## Indexable
1717

1818
```ts
19-
[key: string]: Fn
19+
[key: string]: any
2020
```
2121

2222
## Properties

docs/reference/interfaces/LocalStorageCollectionUtils.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ LocalStorage collection utilities type
1616
## Indexable
1717

1818
```ts
19-
[key: string]: Fn
19+
[key: string]: any
2020
```
2121

2222
## Properties

docs/reference/query-db-collection/functions/queryCollectionOptions.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ title: queryCollectionOptions
88
## Call Signature
99

1010
```ts
11-
function queryCollectionOptions<T, TQueryFn, TError, TQueryKey, TKey, TQueryData>(config): CollectionConfig<InferSchemaOutput<T>, TKey, T, UtilsRecord> & object;
11+
function queryCollectionOptions<T, TQueryFn, TError, TQueryKey, TKey, TQueryData>(config): CollectionConfig<InferSchemaOutput<T>, TKey, T, QueryCollectionUtils<InferSchemaOutput<T>, TKey, InferSchemaInput<T>, TError>> & object;
1212
```
1313

14-
Defined in: [packages/query-db-collection/src/query.ts:270](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L270)
14+
Defined in: [packages/query-db-collection/src/query.ts:370](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L370)
1515

1616
Creates query collection options for use with a standard Collection.
1717
This integrates TanStack Query with TanStack DB for automatic synchronization.
@@ -64,7 +64,7 @@ Configuration options for the Query collection
6464

6565
### Returns
6666

67-
`CollectionConfig`\<`InferSchemaOutput`\<`T`\>, `TKey`, `T`, `UtilsRecord`\> & `object`
67+
`CollectionConfig`\<`InferSchemaOutput`\<`T`\>, `TKey`, `T`, [`QueryCollectionUtils`](../../interfaces/QueryCollectionUtils.md)\<`InferSchemaOutput`\<`T`\>, `TKey`, `InferSchemaInput`\<`T`\>, `TError`\>\> & `object`
6868

6969
Collection options with utilities for direct writes and manual operations
7070

@@ -148,10 +148,10 @@ const todosCollection = createCollection(
148148
## Call Signature
149149

150150
```ts
151-
function queryCollectionOptions<T, TQueryFn, TError, TQueryKey, TKey, TQueryData>(config): CollectionConfig<T, TKey, never, UtilsRecord> & object;
151+
function queryCollectionOptions<T, TQueryFn, TError, TQueryKey, TKey, TQueryData>(config): CollectionConfig<T, TKey, never, QueryCollectionUtils<T, TKey, T, TError>> & object;
152152
```
153153

154-
Defined in: [packages/query-db-collection/src/query.ts:300](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L300)
154+
Defined in: [packages/query-db-collection/src/query.ts:405](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L405)
155155

156156
Creates query collection options for use with a standard Collection.
157157
This integrates TanStack Query with TanStack DB for automatic synchronization.
@@ -204,7 +204,7 @@ Configuration options for the Query collection
204204

205205
### Returns
206206

207-
`CollectionConfig`\<`T`, `TKey`, `never`, `UtilsRecord`\> & `object`
207+
`CollectionConfig`\<`T`, `TKey`, `never`, [`QueryCollectionUtils`](../../interfaces/QueryCollectionUtils.md)\<`T`, `TKey`, `T`, `TError`\>\> & `object`
208208

209209
Collection options with utilities for direct writes and manual operations
210210

@@ -288,10 +288,10 @@ const todosCollection = createCollection(
288288
## Call Signature
289289

290290
```ts
291-
function queryCollectionOptions<T, TError, TQueryKey, TKey>(config): CollectionConfig<InferSchemaOutput<T>, TKey, T, UtilsRecord> & object;
291+
function queryCollectionOptions<T, TError, TQueryKey, TKey>(config): CollectionConfig<InferSchemaOutput<T>, TKey, T, QueryCollectionUtils<InferSchemaOutput<T>, TKey, InferSchemaInput<T>, TError>> & object;
292292
```
293293

294-
Defined in: [packages/query-db-collection/src/query.ts:328](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L328)
294+
Defined in: [packages/query-db-collection/src/query.ts:438](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L438)
295295

296296
Creates query collection options for use with a standard Collection.
297297
This integrates TanStack Query with TanStack DB for automatic synchronization.
@@ -336,7 +336,7 @@ Configuration options for the Query collection
336336

337337
### Returns
338338

339-
`CollectionConfig`\<`InferSchemaOutput`\<`T`\>, `TKey`, `T`, `UtilsRecord`\> & `object`
339+
`CollectionConfig`\<`InferSchemaOutput`\<`T`\>, `TKey`, `T`, [`QueryCollectionUtils`](../../interfaces/QueryCollectionUtils.md)\<`InferSchemaOutput`\<`T`\>, `TKey`, `InferSchemaInput`\<`T`\>, `TError`\>\> & `object`
340340

341341
Collection options with utilities for direct writes and manual operations
342342

@@ -420,10 +420,10 @@ const todosCollection = createCollection(
420420
## Call Signature
421421

422422
```ts
423-
function queryCollectionOptions<T, TError, TQueryKey, TKey>(config): CollectionConfig<T, TKey, never, UtilsRecord> & object;
423+
function queryCollectionOptions<T, TError, TQueryKey, TKey>(config): CollectionConfig<T, TKey, never, QueryCollectionUtils<T, TKey, T, TError>> & object;
424424
```
425425

426-
Defined in: [packages/query-db-collection/src/query.ts:357](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L357)
426+
Defined in: [packages/query-db-collection/src/query.ts:472](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L472)
427427

428428
Creates query collection options for use with a standard Collection.
429429
This integrates TanStack Query with TanStack DB for automatic synchronization.
@@ -468,7 +468,7 @@ Configuration options for the Query collection
468468

469469
### Returns
470470

471-
`CollectionConfig`\<`T`, `TKey`, `never`, `UtilsRecord`\> & `object`
471+
`CollectionConfig`\<`T`, `TKey`, `never`, [`QueryCollectionUtils`](../../interfaces/QueryCollectionUtils.md)\<`T`, `TKey`, `T`, `TError`\>\> & `object`
472472

473473
Collection options with utilities for direct writes and manual operations
474474

docs/reference/query-db-collection/interfaces/QueryCollectionUtils.md

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ The type of errors that can occur during queries
4343
## Indexable
4444

4545
```ts
46-
[key: string]: Fn
46+
[key: string]: any
4747
```
4848

4949
## Properties
@@ -54,7 +54,7 @@ The type of errors that can occur during queries
5454
clearError: () => Promise<void>;
5555
```
5656

57-
Defined in: [packages/query-db-collection/src/query.ts:181](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L181)
57+
Defined in: [packages/query-db-collection/src/query.ts:194](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L194)
5858

5959
Clear the error state and trigger a refetch of the query
6060

@@ -70,52 +70,100 @@ Error if the refetch fails
7070

7171
***
7272

73-
### errorCount()
73+
### dataUpdatedAt
7474

7575
```ts
76-
errorCount: () => number;
76+
dataUpdatedAt: number;
7777
```
7878

79-
Defined in: [packages/query-db-collection/src/query.ts:175](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L175)
79+
Defined in: [packages/query-db-collection/src/query.ts:185](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L185)
80+
81+
Get timestamp of last successful data update (in milliseconds)
82+
83+
***
84+
85+
### errorCount
86+
87+
```ts
88+
errorCount: number;
89+
```
90+
91+
Defined in: [packages/query-db-collection/src/query.ts:177](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L177)
8092

8193
Get the number of consecutive sync failures.
8294
Incremented only when query fails completely (not per retry attempt); reset on success.
8395

84-
#### Returns
96+
***
8597

86-
`number`
98+
### fetchStatus
99+
100+
```ts
101+
fetchStatus: "idle" | "fetching" | "paused";
102+
```
103+
104+
Defined in: [packages/query-db-collection/src/query.ts:187](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L187)
105+
106+
Get current fetch status
87107

88108
***
89109

90-
### isError()
110+
### isError
91111

92112
```ts
93-
isError: () => boolean;
113+
isError: boolean;
94114
```
95115

96-
Defined in: [packages/query-db-collection/src/query.ts:170](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L170)
116+
Defined in: [packages/query-db-collection/src/query.ts:172](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L172)
97117

98118
Check if the collection is in an error state
99119

100-
#### Returns
120+
***
121+
122+
### isFetching
101123

102-
`boolean`
124+
```ts
125+
isFetching: boolean;
126+
```
127+
128+
Defined in: [packages/query-db-collection/src/query.ts:179](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L179)
129+
130+
Check if query is currently fetching (initial or background)
103131

104132
***
105133

106-
### lastError()
134+
### isLoading
107135

108136
```ts
109-
lastError: () => TError | undefined;
137+
isLoading: boolean;
110138
```
111139

112-
Defined in: [packages/query-db-collection/src/query.ts:168](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L168)
140+
Defined in: [packages/query-db-collection/src/query.ts:183](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L183)
113141

114-
Get the last error encountered by the query (if any); reset on success
142+
Check if query is loading for the first time (no data yet)
115143

116-
#### Returns
144+
***
145+
146+
### isRefetching
147+
148+
```ts
149+
isRefetching: boolean;
150+
```
151+
152+
Defined in: [packages/query-db-collection/src/query.ts:181](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L181)
117153

118-
`TError` \| `undefined`
154+
Check if query is refetching in background (not initial fetch)
155+
156+
***
157+
158+
### lastError
159+
160+
```ts
161+
lastError: TError | undefined;
162+
```
163+
164+
Defined in: [packages/query-db-collection/src/query.ts:170](https://github.com/TanStack/db/blob/main/packages/query-db-collection/src/query.ts#L170)
165+
166+
Get the last error encountered by the query (if any); reset on success
119167

120168
***
121169

docs/reference/type-aliases/UtilsRecord.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ title: UtilsRecord
66
# Type Alias: UtilsRecord
77

88
```ts
9-
type UtilsRecord = Record<string, Fn>;
9+
type UtilsRecord = Record<string, any>;
1010
```
1111

1212
Defined in: [packages/db/src/types.ts:40](https://github.com/TanStack/db/blob/main/packages/db/src/types.ts#L40)
1313

14-
A record of utility functions that can be attached to a collection
14+
A record of utilities (functions or getters) that can be attached to a collection

packages/db/src/collection/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ export function createCollection(
189189
options
190190
)
191191

192-
// Copy utils to both top level and .utils namespace
192+
// Attach utils to collection
193193
if (options.utils) {
194-
collection.utils = { ...options.utils }
194+
collection.utils = options.utils
195195
} else {
196196
collection.utils = {}
197197
}

packages/db/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ export type TransactionState = `pending` | `persisting` | `completed` | `failed`
3535
export type Fn = (...args: Array<any>) => any
3636

3737
/**
38-
* A record of utility functions that can be attached to a collection
38+
* A record of utilities (functions or getters) that can be attached to a collection
3939
*/
40-
export type UtilsRecord = Record<string, Fn>
40+
export type UtilsRecord = Record<string, any>
4141

4242
/**
4343
*

0 commit comments

Comments
 (0)