@robohall/react-query-factory 1.0.5 → 1.2.0
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/README.md +25 -24
- package/dist/index.d.mts +29 -42
- package/dist/index.d.ts +29 -42
- package/dist/index.js +8 -6
- package/dist/index.mjs +8 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,7 +38,6 @@ const describeInstances = queryFactory({
|
|
|
38
38
|
queryKey: ['ec2:DescribeInstances'],
|
|
39
39
|
queryFn: (params: DescribeInstancesCommandInput, ctx) =>
|
|
40
40
|
ec2.send(new DescribeInstancesCommand(params), { abortSignal: ctx.signal }),
|
|
41
|
-
staleTime: 30_000,
|
|
42
41
|
});
|
|
43
42
|
|
|
44
43
|
function InstanceList() {
|
|
@@ -46,7 +45,6 @@ function InstanceList() {
|
|
|
46
45
|
describeInstances({ Filters: [{ Name: 'instance-state-name', Values: ['running'] }] })
|
|
47
46
|
);
|
|
48
47
|
// query key: ['ec2:DescribeInstances', { Filters: [...] }]
|
|
49
|
-
// staleTime: 30 000 ms, no repetition required
|
|
50
48
|
}
|
|
51
49
|
```
|
|
52
50
|
|
|
@@ -56,9 +54,9 @@ function InstanceList() {
|
|
|
56
54
|
|
|
57
55
|
## Crawling
|
|
58
56
|
|
|
59
|
-
`DescribeInstances` is paginated. If you have more than
|
|
57
|
+
`DescribeInstances` is paginated. If you have more than 20 instances, one call won't get them all. The standard approach — chaining `fetchNextPage` calls, accumulating results, checking `NextToken` — is correct but tedious to repeat everywhere.
|
|
60
58
|
|
|
61
|
-
Add `getNextPageParam
|
|
59
|
+
Add `getNextPageParam` and `shouldFetchNextPage` to activate crawling — those two are the only required pieces. `initialPageParam` types `ctx.pageParam` in your `queryFn` (without it and without a `getNextPageParam` that provides inference, `ctx.pageParam` is `never`). `reduce` folds crawled pages into a single value; without it the result is an array of all fetched raw pages (`TData[]`). **`shouldFetchNextPage`** is called after each page — return `true` to keep fetching, `false` to stop. Use `() => true` to walk every page:
|
|
62
60
|
|
|
63
61
|
```typescript
|
|
64
62
|
import type { Instance, DescribeInstancesCommandInput } from '@aws-sdk/client-ec2';
|
|
@@ -72,32 +70,35 @@ const describeInstances = queryFactory({
|
|
|
72
70
|
),
|
|
73
71
|
getNextPageParam: response => response.NextToken,
|
|
74
72
|
initialPageParam: undefined as string | undefined,
|
|
73
|
+
shouldFetchNextPage: () => true,
|
|
75
74
|
reduce: (acc, page): Instance[] => [
|
|
76
75
|
...(acc ?? []),
|
|
77
76
|
...(page.Reservations?.flatMap(r => r.Instances ?? []) ?? []),
|
|
78
77
|
],
|
|
79
|
-
staleTime: 30_000,
|
|
80
78
|
});
|
|
81
79
|
|
|
82
80
|
function InstanceList() {
|
|
83
81
|
// one useQuery call; data is Instance[], not DescribeInstancesResponse[]
|
|
84
|
-
const { data } = useQuery(describeInstances({ MaxResults:
|
|
82
|
+
const { data } = useQuery(describeInstances({ MaxResults: 20 }));
|
|
85
83
|
}
|
|
86
84
|
```
|
|
87
85
|
|
|
88
|
-
|
|
86
|
+
`shouldFetchNextPage` also accepts a `crawlOptions` object passed at call time, letting each call site control the crawl independently:
|
|
89
87
|
|
|
90
88
|
```typescript
|
|
91
89
|
const describeInstances = queryFactory({
|
|
92
90
|
// ...
|
|
93
91
|
reduce: (acc, page): Instance[] => [...(acc ?? []), ...page.Reservations.flatMap(r => r.Instances)],
|
|
94
92
|
shouldFetchNextPage: (instances, opts: { minResults?: number }) =>
|
|
95
|
-
opts.minResults
|
|
93
|
+
opts.minResults == null || instances.length < opts.minResults,
|
|
96
94
|
});
|
|
97
95
|
|
|
98
|
-
//
|
|
99
|
-
const { data } = useQuery(
|
|
100
|
-
|
|
96
|
+
// fetch all pages
|
|
97
|
+
const { data: all } = useQuery(describeInstances({ MaxResults: 20 }));
|
|
98
|
+
|
|
99
|
+
// stop after accumulating at least 50 instances (≥ 3 API calls)
|
|
100
|
+
const { data: partial } = useQuery(
|
|
101
|
+
describeInstances({ MaxResults: 20 }, { minResults: 50 })
|
|
101
102
|
);
|
|
102
103
|
```
|
|
103
104
|
|
|
@@ -116,9 +117,9 @@ const runningInstances = queryFactory(describeInstances, {
|
|
|
116
117
|
select: instances => instances.filter(i => i.State?.Name === 'running'),
|
|
117
118
|
});
|
|
118
119
|
|
|
119
|
-
// query key: ['ec2:DescribeInstances', { MaxResults:
|
|
120
|
+
// query key: ['ec2:DescribeInstances', { MaxResults: 20 }] (same cache entry as parent)
|
|
120
121
|
// data: Instance[] filtered to State.Name === 'running'
|
|
121
|
-
const { data } = useQuery(runningInstances({ MaxResults:
|
|
122
|
+
const { data } = useQuery(runningInstances({ MaxResults: 20 }));
|
|
122
123
|
```
|
|
123
124
|
|
|
124
125
|
Parent and child `select` functions compose automatically — if the parent already has a `select`, the child's `select` receives the parent's output, not the raw API response.
|
|
@@ -131,13 +132,13 @@ const findInstance = queryFactory(describeInstances, {
|
|
|
131
132
|
// queryFn, getNextPageParam, initialPageParam, and reduce are all inherited
|
|
132
133
|
shouldFetchNextPage: (instances, opts: { instanceId?: string }) =>
|
|
133
134
|
opts.instanceId != null &&
|
|
134
|
-
!instances
|
|
135
|
+
!instances.some(i => i.InstanceId === opts.instanceId),
|
|
135
136
|
});
|
|
136
137
|
|
|
137
|
-
// query key: ['ec2:DescribeInstances', 'find', { MaxResults:
|
|
138
|
+
// query key: ['ec2:DescribeInstances', 'find', { MaxResults: 20 }, { instanceId: 'i-0abc123def456' }]
|
|
138
139
|
// crawls pages until the target instance appears, then stops
|
|
139
140
|
const { data } = useQuery(
|
|
140
|
-
findInstance({ MaxResults:
|
|
141
|
+
findInstance({ MaxResults: 20 }, { instanceId: 'i-0abc123def456' })
|
|
141
142
|
);
|
|
142
143
|
```
|
|
143
144
|
|
|
@@ -159,15 +160,15 @@ Every factory exposes a `.infinite()` method that returns `useInfiniteQuery`-com
|
|
|
159
160
|
```typescript
|
|
160
161
|
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery(
|
|
161
162
|
// load 50 instances per UI page, each backed by up to 5 DescribeInstances calls
|
|
162
|
-
describeInstances.infinite({ MaxResults:
|
|
163
|
+
describeInstances.infinite({ MaxResults: 20 }, { minResults: 50 })
|
|
163
164
|
);
|
|
164
165
|
|
|
165
166
|
// data.pages is Instance[][], one array per virtual page
|
|
166
167
|
```
|
|
167
168
|
|
|
168
169
|
The `.infinite()` key includes an `'infinite'` segment to keep it separate from the regular `useQuery` cache entry:
|
|
169
|
-
- `describeInstances({ MaxResults:
|
|
170
|
-
- `describeInstances.infinite({ MaxResults:
|
|
170
|
+
- `describeInstances({ MaxResults: 20 })` → `['ec2:DescribeInstances', { MaxResults: 20 }]`
|
|
171
|
+
- `describeInstances.infinite({ MaxResults: 20 })` → `['ec2:DescribeInstances', 'infinite', { MaxResults: 20 }]`
|
|
171
172
|
|
|
172
173
|
---
|
|
173
174
|
|
|
@@ -187,7 +188,7 @@ queryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>(
|
|
|
187
188
|
|
|
188
189
|
Creates a child factory. Two overloads:
|
|
189
190
|
- **With a new `queryFn`** — inherits key namespace and standard options; crawling config must be re-declared if needed.
|
|
190
|
-
- **Without a `queryFn`** — inherits everything; accepts
|
|
191
|
+
- **Without a `queryFn`** — inherits everything; accepts `queryKey`, `select`, standard options, and any crawling fields (`shouldFetchNextPage`, `reduce`, `getNextPageParam`, `getPreviousPageParam`, `initialPageParam`) to override the parent's. `select` is composed with the parent's.
|
|
191
192
|
|
|
192
193
|
### `QueryFactoryConfig`
|
|
193
194
|
|
|
@@ -198,11 +199,11 @@ All fields except `reduce` and `shouldFetchNextPage` are the standard TanStack Q
|
|
|
198
199
|
| `queryKey` | `QueryKey` | Namespace segments. Params are appended at call time. |
|
|
199
200
|
| `queryFn` | `(params: TParams, ctx: QueryFunctionContext) => TData \| Promise<TData>` | Same as TanStack, with an extra leading `params` argument. |
|
|
200
201
|
| `select` | `(data: TData) => TSelected` | Exact TanStack API. Composed automatically on child factories. |
|
|
201
|
-
| `getNextPageParam` | `GetNextPageParamFunction<TPageParam, TData>` | Exact TanStack API.
|
|
202
|
-
| `initialPageParam` | `TPageParam` | Exact TanStack API.
|
|
202
|
+
| `getNextPageParam` | `GetNextPageParamFunction<TPageParam, TData>` | Exact TanStack API. Required (with `shouldFetchNextPage`) to activate crawling. Required (with `initialPageParam`) for `.infinite()`. |
|
|
203
|
+
| `initialPageParam` | `TPageParam` | Exact TanStack API. Drives `TPageParam` inference — without it and without a `getNextPageParam` that provides inference, `ctx.pageParam` is typed `never`. Required for `.infinite()` to work at runtime. |
|
|
203
204
|
| `getPreviousPageParam` | `GetPreviousPageParamFunction<TPageParam, TData>` | Exact TanStack API. Passed through on `.infinite()`. |
|
|
204
|
-
| `
|
|
205
|
-
| `
|
|
205
|
+
| `shouldFetchNextPage` | `(combined: TSelected \| undefined, crawlOptions: TCrawlOptions) => boolean` | Library addition. **Required (with `getNextPageParam`) to activate crawling.** Called after each page — return `true` to keep fetching, `false` to stop. |
|
|
206
|
+
| `reduce` | `(acc: TSelected \| undefined, page: TData) => TSelected` | Library addition. Optional. Folds crawled pages into a single `TSelected` value; when omitted the result is an array of all fetched raw pages (`TData[]`). |
|
|
206
207
|
| + all `StandardQueryOptions` fields | | All options accepted by TanStack's `useQuery` / `useInfiniteQuery` except `queryKey`, `queryFn`, and `select` (which the factory owns). Includes `staleTime`, `gcTime`, `retry`, `retryOnMount`, `enabled`, `refetchOnWindowFocus`, `refetchOnReconnect`, `refetchOnMount`, `refetchInterval`, `refetchIntervalInBackground`, `networkMode`, `notifyOnChangeProps`, `throwOnError`, `structuralSharing`, `initialData`, `initialDataUpdatedAt`, `placeholderData`, `queryKeyHashFn`, `persister`, `meta`, `maxPages`, `experimental_prefetchInRender`. Function-form callbacks (e.g. `enabled: (query) => boolean`) are supported wherever TanStack accepts them. |
|
|
207
208
|
|
|
208
209
|
### `QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>`
|
package/dist/index.d.mts
CHANGED
|
@@ -31,27 +31,21 @@ type QueryFactoryConfig<TParams = void, TData = unknown, TError = Error, TSelect
|
|
|
31
31
|
unknown
|
|
32
32
|
] extends [TPageParam] ? never : TPageParam>) => TData | Promise<TData>;
|
|
33
33
|
select?: (data: TData) => TSelected;
|
|
34
|
-
} & ({
|
|
35
34
|
/** TanStack v5 generic order: GetNextPageParamFunction<TPageParam, TData> */
|
|
36
|
-
getNextPageParam
|
|
37
|
-
/**
|
|
38
|
-
* ctx.pageParam
|
|
39
|
-
|
|
35
|
+
getNextPageParam?: GetNextPageParamFunction<TPageParam, TData>;
|
|
36
|
+
/** Drives TPageParam inference so ctx.pageParam in queryFn is typed as TPageParam.
|
|
37
|
+
* When omitted TPageParam stays unknown and ctx.pageParam is typed as never.
|
|
38
|
+
* Required for .infinite() to work correctly at runtime. */
|
|
39
|
+
initialPageParam?: TPageParam;
|
|
40
40
|
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
41
41
|
/** Reduces crawled pages incrementally into the final query result.
|
|
42
42
|
* Called once per page; accumulator is undefined on the first call.
|
|
43
|
-
* When
|
|
43
|
+
* When omitted, the crawl result is the last fetched page (TSelected = TData). */
|
|
44
44
|
reduce?: (accumulator: TSelected | undefined, page: TData) => TSelected;
|
|
45
45
|
/** Called after each page to decide whether to keep crawling.
|
|
46
|
-
*
|
|
46
|
+
* Required (along with getNextPageParam) to activate crawling. */
|
|
47
47
|
shouldFetchNextPage?: (combined: TSelected | undefined, crawlOptions: TCrawlOptions) => boolean;
|
|
48
|
-
}
|
|
49
|
-
getNextPageParam?: never;
|
|
50
|
-
initialPageParam?: never;
|
|
51
|
-
getPreviousPageParam?: never;
|
|
52
|
-
shouldFetchNextPage?: never;
|
|
53
|
-
reduce?: never;
|
|
54
|
-
});
|
|
48
|
+
};
|
|
55
49
|
/**
|
|
56
50
|
* What `factory(params)` returns — pass directly to `useQuery()`.
|
|
57
51
|
*
|
|
@@ -68,15 +62,20 @@ type ResolvedQueryOptions<TData = unknown, TError = Error, TSelected = TData> =
|
|
|
68
62
|
/**
|
|
69
63
|
* What `factory.infinite(params)` returns — pass directly to `useInfiniteQuery()`.
|
|
70
64
|
*
|
|
71
|
-
* The `select` field
|
|
72
|
-
* guard making this type incompatible with `useQuery`.
|
|
65
|
+
* The `select` field input type (`InfiniteData<TData, TPageParam>`) is a structural
|
|
66
|
+
* guard making this type incompatible with `useQuery`, whose select expects `(data: TData)`.
|
|
67
|
+
*
|
|
68
|
+
* `TResult` is the concrete type that `useInfiniteQuery` will use as its `TData` — i.e.
|
|
69
|
+
* what `select` returns (or `InfiniteData<TData, TPageParam>` when no select is set).
|
|
70
|
+
* Carrying it explicitly avoids returning `any`, which would poison TResult inference
|
|
71
|
+
* in TypeScript 6 when callers spread this type and add their own `select`.
|
|
73
72
|
*/
|
|
74
|
-
type ResolvedInfiniteOptions<TData = unknown, TError = Error, TPageParam = unknown
|
|
73
|
+
type ResolvedInfiniteOptions<TData = unknown, TError = Error, TPageParam = unknown, TResult = InfiniteData<TData, TPageParam>> = Omit<StandardQueryOptions<TError, any>, 'persister'> & {
|
|
75
74
|
queryKey: QueryKey;
|
|
76
75
|
queryFn?: (context: QueryFunctionContext<QueryKey, TPageParam>) => TData | Promise<TData>;
|
|
77
|
-
/** Structural guard: the InfiniteData
|
|
76
|
+
/** Structural guard: the InfiniteData input type makes this incompatible with useQuery,
|
|
78
77
|
* whose select expects (data: TData) rather than (data: InfiniteData<TData, TPageParam>). */
|
|
79
|
-
select?: (data: InfiniteData<TData, TPageParam>) =>
|
|
78
|
+
select?: (data: InfiniteData<TData, TPageParam>) => TResult;
|
|
80
79
|
/** Required so this type satisfies useInfiniteQuery, which requires getNextPageParam. */
|
|
81
80
|
getNextPageParam: GetNextPageParamFunction<TPageParam, TData>;
|
|
82
81
|
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
@@ -97,9 +96,9 @@ type ResolvedInfiniteOptions<TData = unknown, TError = Error, TPageParam = unkno
|
|
|
97
96
|
* namespace key, which is useful for broad cache invalidation:
|
|
98
97
|
* `queryClient.invalidateQueries(factory())`
|
|
99
98
|
*/
|
|
100
|
-
interface QueryFactory<TParams = void, TData = unknown, TError = Error, TSelected = TData, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown
|
|
99
|
+
interface QueryFactory<TParams = void, TData = unknown, TError = Error, TSelected = TData, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>, THasReduce extends boolean = boolean> {
|
|
101
100
|
(params?: TParams, crawlOptions?: TCrawlOptions): ResolvedQueryOptions<TData, TError, TSelected>;
|
|
102
|
-
infinite(params?: TParams, crawlOptions?: TCrawlOptions): ResolvedInfiniteOptions<TData, TError, TPageParam
|
|
101
|
+
infinite(params?: TParams, crawlOptions?: TCrawlOptions): ResolvedInfiniteOptions<TData, TError, TPageParam, InfiniteData<TSelected, TPageParam>>;
|
|
103
102
|
}
|
|
104
103
|
/**
|
|
105
104
|
* Creates a standalone query factory with pagination and reduce. When `reduce` is
|
|
@@ -112,12 +111,12 @@ declare function queryFactory<TParams = void, TData = unknown, TError = Error, T
|
|
|
112
111
|
unknown
|
|
113
112
|
] extends [TPageParam] ? never : TPageParam>) => TData | Promise<TData>;
|
|
114
113
|
select?: (data: TData) => TSelected;
|
|
115
|
-
getNextPageParam
|
|
116
|
-
initialPageParam
|
|
114
|
+
getNextPageParam?: GetNextPageParamFunction<TPageParam, TData>;
|
|
115
|
+
initialPageParam?: TPageParam;
|
|
117
116
|
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
118
117
|
reduce: (accumulator: TSelected | undefined, page: TData) => TSelected;
|
|
119
118
|
shouldFetchNextPage?: (combined: TSelected, crawlOptions: TCrawlOptions) => boolean;
|
|
120
|
-
}): QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>;
|
|
119
|
+
}): QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions, true>;
|
|
121
120
|
/**
|
|
122
121
|
* Creates a standalone query factory from a config object.
|
|
123
122
|
*
|
|
@@ -128,7 +127,7 @@ declare function queryFactory<TParams = void, TData = unknown, TError = Error, T
|
|
|
128
127
|
* });
|
|
129
128
|
* // useQuery(usersFactory({ page: 1 }))
|
|
130
129
|
*/
|
|
131
|
-
declare function queryFactory<TParams = void, TData = unknown, TError = Error, TSelected = TData, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>>(config: QueryFactoryConfig<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>): QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>;
|
|
130
|
+
declare function queryFactory<TParams = void, TData = unknown, TError = Error, TSelected = TData, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>>(config: QueryFactoryConfig<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>): QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions, false>;
|
|
132
131
|
/**
|
|
133
132
|
* Creates a child factory that inherits the query key and standard options from
|
|
134
133
|
* `parent` and introduces a new `queryFn`. The child's query key is appended to
|
|
@@ -136,22 +135,10 @@ declare function queryFactory<TParams = void, TData = unknown, TError = Error, T
|
|
|
136
135
|
*
|
|
137
136
|
* Use this overload when the child fetches different data than the parent.
|
|
138
137
|
*/
|
|
139
|
-
declare function queryFactory<TChildParams extends TParentParams, TData = unknown, TError = Error, TChildSelected = TData, TParentParams = TChildParams, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>>(parent: QueryFactory<TParentParams, any, any, any, any, any>, config: Omit<QueryFactoryConfig<TChildParams, TData, TError, TChildSelected, TPageParam, TCrawlOptions>, 'queryKey' | '
|
|
138
|
+
declare function queryFactory<TChildParams extends TParentParams, TData = unknown, TError = Error, TChildSelected = TData, TParentParams = TChildParams, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>>(parent: QueryFactory<TParentParams, any, any, any, any, any, any>, config: Omit<QueryFactoryConfig<TChildParams, TData, TError, TChildSelected, TPageParam, TCrawlOptions>, 'queryKey' | 'queryFn'> & {
|
|
140
139
|
queryKey?: QueryKey;
|
|
141
140
|
queryFn: NonNullable<QueryFactoryConfig<TChildParams, TData, TError, TChildSelected, TPageParam>['queryFn']>;
|
|
142
|
-
}
|
|
143
|
-
getNextPageParam: GetNextPageParamFunction<TPageParam, TData>;
|
|
144
|
-
initialPageParam: TPageParam;
|
|
145
|
-
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
146
|
-
shouldFetchNextPage?: (combined: TChildSelected | undefined, crawlOptions: TCrawlOptions) => boolean;
|
|
147
|
-
reduce?: (accumulator: TChildSelected | undefined, page: TData) => TChildSelected;
|
|
148
|
-
} | {
|
|
149
|
-
getNextPageParam?: never;
|
|
150
|
-
initialPageParam?: never;
|
|
151
|
-
getPreviousPageParam?: never;
|
|
152
|
-
shouldFetchNextPage?: never;
|
|
153
|
-
reduce?: never;
|
|
154
|
-
})): QueryFactory<TChildParams, TData, TError, TChildSelected, TPageParam, TCrawlOptions>;
|
|
141
|
+
}): QueryFactory<TChildParams, TData, TError, TChildSelected, TPageParam, TCrawlOptions, boolean>;
|
|
155
142
|
/**
|
|
156
143
|
* Creates a child factory that reuses the parent's `queryFn` and pagination
|
|
157
144
|
* config. Useful for adding a `select` transform, narrowing params, or
|
|
@@ -159,7 +146,7 @@ declare function queryFactory<TChildParams extends TParentParams, TData = unknow
|
|
|
159
146
|
* without changing what data is fetched. Parent and child `select` functions
|
|
160
147
|
* are automatically composed: `child.select(parent.select(data))`.
|
|
161
148
|
*/
|
|
162
|
-
declare function queryFactory<TChildParams extends TParentParams, TData = unknown, TError = Error, TParentSelected = TData, TChildSelected = TParentSelected, TParentParams = TChildParams, TPageParam = unknown, TParentCrawlOptions extends Record<string, unknown> = Record<string, unknown>, TChildCrawlOptions extends Record<string, unknown> = TParentCrawlOptions>(parent: QueryFactory<TParentParams, TData, any, TParentSelected, TPageParam, TParentCrawlOptions>, config: StandardQueryOptions<TError, TData> & {
|
|
149
|
+
declare function queryFactory<TChildParams extends TParentParams, TData = unknown, TError = Error, TParentSelected = TData, TChildSelected = TParentSelected, TParentParams = TChildParams, TPageParam = unknown, TParentCrawlOptions extends Record<string, unknown> = Record<string, unknown>, TChildCrawlOptions extends Record<string, unknown> = TParentCrawlOptions, TParentHasReduce extends boolean = boolean>(parent: QueryFactory<TParentParams, TData, any, TParentSelected, TPageParam, TParentCrawlOptions, TParentHasReduce>, config: StandardQueryOptions<TError, TData> & {
|
|
163
150
|
queryKey?: QueryKey;
|
|
164
151
|
queryFn?: never;
|
|
165
152
|
select?: (data: TParentSelected) => TChildSelected;
|
|
@@ -167,7 +154,7 @@ declare function queryFactory<TChildParams extends TParentParams, TData = unknow
|
|
|
167
154
|
initialPageParam?: TPageParam;
|
|
168
155
|
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
169
156
|
reduce?: (accumulator: TChildSelected | undefined, page: TData) => TChildSelected;
|
|
170
|
-
shouldFetchNextPage?: (combined: TChildSelected | undefined, crawlOptions: TChildCrawlOptions) => boolean;
|
|
171
|
-
}): QueryFactory<TChildParams, TData, TError, TChildSelected, TPageParam, TChildCrawlOptions>;
|
|
157
|
+
shouldFetchNextPage?: (combined: TParentHasReduce extends true ? TChildSelected : TChildSelected | undefined, crawlOptions: TChildCrawlOptions) => boolean;
|
|
158
|
+
}): QueryFactory<TChildParams, TData, TError, TChildSelected, TPageParam, TChildCrawlOptions, TParentHasReduce>;
|
|
172
159
|
|
|
173
160
|
export { type QueryFactory, type QueryFactoryConfig, type ResolvedInfiniteOptions, type ResolvedQueryOptions, type StandardQueryOptions, queryFactory };
|
package/dist/index.d.ts
CHANGED
|
@@ -31,27 +31,21 @@ type QueryFactoryConfig<TParams = void, TData = unknown, TError = Error, TSelect
|
|
|
31
31
|
unknown
|
|
32
32
|
] extends [TPageParam] ? never : TPageParam>) => TData | Promise<TData>;
|
|
33
33
|
select?: (data: TData) => TSelected;
|
|
34
|
-
} & ({
|
|
35
34
|
/** TanStack v5 generic order: GetNextPageParamFunction<TPageParam, TData> */
|
|
36
|
-
getNextPageParam
|
|
37
|
-
/**
|
|
38
|
-
* ctx.pageParam
|
|
39
|
-
|
|
35
|
+
getNextPageParam?: GetNextPageParamFunction<TPageParam, TData>;
|
|
36
|
+
/** Drives TPageParam inference so ctx.pageParam in queryFn is typed as TPageParam.
|
|
37
|
+
* When omitted TPageParam stays unknown and ctx.pageParam is typed as never.
|
|
38
|
+
* Required for .infinite() to work correctly at runtime. */
|
|
39
|
+
initialPageParam?: TPageParam;
|
|
40
40
|
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
41
41
|
/** Reduces crawled pages incrementally into the final query result.
|
|
42
42
|
* Called once per page; accumulator is undefined on the first call.
|
|
43
|
-
* When
|
|
43
|
+
* When omitted, the crawl result is the last fetched page (TSelected = TData). */
|
|
44
44
|
reduce?: (accumulator: TSelected | undefined, page: TData) => TSelected;
|
|
45
45
|
/** Called after each page to decide whether to keep crawling.
|
|
46
|
-
*
|
|
46
|
+
* Required (along with getNextPageParam) to activate crawling. */
|
|
47
47
|
shouldFetchNextPage?: (combined: TSelected | undefined, crawlOptions: TCrawlOptions) => boolean;
|
|
48
|
-
}
|
|
49
|
-
getNextPageParam?: never;
|
|
50
|
-
initialPageParam?: never;
|
|
51
|
-
getPreviousPageParam?: never;
|
|
52
|
-
shouldFetchNextPage?: never;
|
|
53
|
-
reduce?: never;
|
|
54
|
-
});
|
|
48
|
+
};
|
|
55
49
|
/**
|
|
56
50
|
* What `factory(params)` returns — pass directly to `useQuery()`.
|
|
57
51
|
*
|
|
@@ -68,15 +62,20 @@ type ResolvedQueryOptions<TData = unknown, TError = Error, TSelected = TData> =
|
|
|
68
62
|
/**
|
|
69
63
|
* What `factory.infinite(params)` returns — pass directly to `useInfiniteQuery()`.
|
|
70
64
|
*
|
|
71
|
-
* The `select` field
|
|
72
|
-
* guard making this type incompatible with `useQuery`.
|
|
65
|
+
* The `select` field input type (`InfiniteData<TData, TPageParam>`) is a structural
|
|
66
|
+
* guard making this type incompatible with `useQuery`, whose select expects `(data: TData)`.
|
|
67
|
+
*
|
|
68
|
+
* `TResult` is the concrete type that `useInfiniteQuery` will use as its `TData` — i.e.
|
|
69
|
+
* what `select` returns (or `InfiniteData<TData, TPageParam>` when no select is set).
|
|
70
|
+
* Carrying it explicitly avoids returning `any`, which would poison TResult inference
|
|
71
|
+
* in TypeScript 6 when callers spread this type and add their own `select`.
|
|
73
72
|
*/
|
|
74
|
-
type ResolvedInfiniteOptions<TData = unknown, TError = Error, TPageParam = unknown
|
|
73
|
+
type ResolvedInfiniteOptions<TData = unknown, TError = Error, TPageParam = unknown, TResult = InfiniteData<TData, TPageParam>> = Omit<StandardQueryOptions<TError, any>, 'persister'> & {
|
|
75
74
|
queryKey: QueryKey;
|
|
76
75
|
queryFn?: (context: QueryFunctionContext<QueryKey, TPageParam>) => TData | Promise<TData>;
|
|
77
|
-
/** Structural guard: the InfiniteData
|
|
76
|
+
/** Structural guard: the InfiniteData input type makes this incompatible with useQuery,
|
|
78
77
|
* whose select expects (data: TData) rather than (data: InfiniteData<TData, TPageParam>). */
|
|
79
|
-
select?: (data: InfiniteData<TData, TPageParam>) =>
|
|
78
|
+
select?: (data: InfiniteData<TData, TPageParam>) => TResult;
|
|
80
79
|
/** Required so this type satisfies useInfiniteQuery, which requires getNextPageParam. */
|
|
81
80
|
getNextPageParam: GetNextPageParamFunction<TPageParam, TData>;
|
|
82
81
|
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
@@ -97,9 +96,9 @@ type ResolvedInfiniteOptions<TData = unknown, TError = Error, TPageParam = unkno
|
|
|
97
96
|
* namespace key, which is useful for broad cache invalidation:
|
|
98
97
|
* `queryClient.invalidateQueries(factory())`
|
|
99
98
|
*/
|
|
100
|
-
interface QueryFactory<TParams = void, TData = unknown, TError = Error, TSelected = TData, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown
|
|
99
|
+
interface QueryFactory<TParams = void, TData = unknown, TError = Error, TSelected = TData, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>, THasReduce extends boolean = boolean> {
|
|
101
100
|
(params?: TParams, crawlOptions?: TCrawlOptions): ResolvedQueryOptions<TData, TError, TSelected>;
|
|
102
|
-
infinite(params?: TParams, crawlOptions?: TCrawlOptions): ResolvedInfiniteOptions<TData, TError, TPageParam
|
|
101
|
+
infinite(params?: TParams, crawlOptions?: TCrawlOptions): ResolvedInfiniteOptions<TData, TError, TPageParam, InfiniteData<TSelected, TPageParam>>;
|
|
103
102
|
}
|
|
104
103
|
/**
|
|
105
104
|
* Creates a standalone query factory with pagination and reduce. When `reduce` is
|
|
@@ -112,12 +111,12 @@ declare function queryFactory<TParams = void, TData = unknown, TError = Error, T
|
|
|
112
111
|
unknown
|
|
113
112
|
] extends [TPageParam] ? never : TPageParam>) => TData | Promise<TData>;
|
|
114
113
|
select?: (data: TData) => TSelected;
|
|
115
|
-
getNextPageParam
|
|
116
|
-
initialPageParam
|
|
114
|
+
getNextPageParam?: GetNextPageParamFunction<TPageParam, TData>;
|
|
115
|
+
initialPageParam?: TPageParam;
|
|
117
116
|
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
118
117
|
reduce: (accumulator: TSelected | undefined, page: TData) => TSelected;
|
|
119
118
|
shouldFetchNextPage?: (combined: TSelected, crawlOptions: TCrawlOptions) => boolean;
|
|
120
|
-
}): QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>;
|
|
119
|
+
}): QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions, true>;
|
|
121
120
|
/**
|
|
122
121
|
* Creates a standalone query factory from a config object.
|
|
123
122
|
*
|
|
@@ -128,7 +127,7 @@ declare function queryFactory<TParams = void, TData = unknown, TError = Error, T
|
|
|
128
127
|
* });
|
|
129
128
|
* // useQuery(usersFactory({ page: 1 }))
|
|
130
129
|
*/
|
|
131
|
-
declare function queryFactory<TParams = void, TData = unknown, TError = Error, TSelected = TData, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>>(config: QueryFactoryConfig<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>): QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>;
|
|
130
|
+
declare function queryFactory<TParams = void, TData = unknown, TError = Error, TSelected = TData, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>>(config: QueryFactoryConfig<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions>): QueryFactory<TParams, TData, TError, TSelected, TPageParam, TCrawlOptions, false>;
|
|
132
131
|
/**
|
|
133
132
|
* Creates a child factory that inherits the query key and standard options from
|
|
134
133
|
* `parent` and introduces a new `queryFn`. The child's query key is appended to
|
|
@@ -136,22 +135,10 @@ declare function queryFactory<TParams = void, TData = unknown, TError = Error, T
|
|
|
136
135
|
*
|
|
137
136
|
* Use this overload when the child fetches different data than the parent.
|
|
138
137
|
*/
|
|
139
|
-
declare function queryFactory<TChildParams extends TParentParams, TData = unknown, TError = Error, TChildSelected = TData, TParentParams = TChildParams, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>>(parent: QueryFactory<TParentParams, any, any, any, any, any>, config: Omit<QueryFactoryConfig<TChildParams, TData, TError, TChildSelected, TPageParam, TCrawlOptions>, 'queryKey' | '
|
|
138
|
+
declare function queryFactory<TChildParams extends TParentParams, TData = unknown, TError = Error, TChildSelected = TData, TParentParams = TChildParams, TPageParam = unknown, TCrawlOptions extends Record<string, unknown> = Record<string, unknown>>(parent: QueryFactory<TParentParams, any, any, any, any, any, any>, config: Omit<QueryFactoryConfig<TChildParams, TData, TError, TChildSelected, TPageParam, TCrawlOptions>, 'queryKey' | 'queryFn'> & {
|
|
140
139
|
queryKey?: QueryKey;
|
|
141
140
|
queryFn: NonNullable<QueryFactoryConfig<TChildParams, TData, TError, TChildSelected, TPageParam>['queryFn']>;
|
|
142
|
-
}
|
|
143
|
-
getNextPageParam: GetNextPageParamFunction<TPageParam, TData>;
|
|
144
|
-
initialPageParam: TPageParam;
|
|
145
|
-
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
146
|
-
shouldFetchNextPage?: (combined: TChildSelected | undefined, crawlOptions: TCrawlOptions) => boolean;
|
|
147
|
-
reduce?: (accumulator: TChildSelected | undefined, page: TData) => TChildSelected;
|
|
148
|
-
} | {
|
|
149
|
-
getNextPageParam?: never;
|
|
150
|
-
initialPageParam?: never;
|
|
151
|
-
getPreviousPageParam?: never;
|
|
152
|
-
shouldFetchNextPage?: never;
|
|
153
|
-
reduce?: never;
|
|
154
|
-
})): QueryFactory<TChildParams, TData, TError, TChildSelected, TPageParam, TCrawlOptions>;
|
|
141
|
+
}): QueryFactory<TChildParams, TData, TError, TChildSelected, TPageParam, TCrawlOptions, boolean>;
|
|
155
142
|
/**
|
|
156
143
|
* Creates a child factory that reuses the parent's `queryFn` and pagination
|
|
157
144
|
* config. Useful for adding a `select` transform, narrowing params, or
|
|
@@ -159,7 +146,7 @@ declare function queryFactory<TChildParams extends TParentParams, TData = unknow
|
|
|
159
146
|
* without changing what data is fetched. Parent and child `select` functions
|
|
160
147
|
* are automatically composed: `child.select(parent.select(data))`.
|
|
161
148
|
*/
|
|
162
|
-
declare function queryFactory<TChildParams extends TParentParams, TData = unknown, TError = Error, TParentSelected = TData, TChildSelected = TParentSelected, TParentParams = TChildParams, TPageParam = unknown, TParentCrawlOptions extends Record<string, unknown> = Record<string, unknown>, TChildCrawlOptions extends Record<string, unknown> = TParentCrawlOptions>(parent: QueryFactory<TParentParams, TData, any, TParentSelected, TPageParam, TParentCrawlOptions>, config: StandardQueryOptions<TError, TData> & {
|
|
149
|
+
declare function queryFactory<TChildParams extends TParentParams, TData = unknown, TError = Error, TParentSelected = TData, TChildSelected = TParentSelected, TParentParams = TChildParams, TPageParam = unknown, TParentCrawlOptions extends Record<string, unknown> = Record<string, unknown>, TChildCrawlOptions extends Record<string, unknown> = TParentCrawlOptions, TParentHasReduce extends boolean = boolean>(parent: QueryFactory<TParentParams, TData, any, TParentSelected, TPageParam, TParentCrawlOptions, TParentHasReduce>, config: StandardQueryOptions<TError, TData> & {
|
|
163
150
|
queryKey?: QueryKey;
|
|
164
151
|
queryFn?: never;
|
|
165
152
|
select?: (data: TParentSelected) => TChildSelected;
|
|
@@ -167,7 +154,7 @@ declare function queryFactory<TChildParams extends TParentParams, TData = unknow
|
|
|
167
154
|
initialPageParam?: TPageParam;
|
|
168
155
|
getPreviousPageParam?: GetPreviousPageParamFunction<TPageParam, TData>;
|
|
169
156
|
reduce?: (accumulator: TChildSelected | undefined, page: TData) => TChildSelected;
|
|
170
|
-
shouldFetchNextPage?: (combined: TChildSelected | undefined, crawlOptions: TChildCrawlOptions) => boolean;
|
|
171
|
-
}): QueryFactory<TChildParams, TData, TError, TChildSelected, TPageParam, TChildCrawlOptions>;
|
|
157
|
+
shouldFetchNextPage?: (combined: TParentHasReduce extends true ? TChildSelected : TChildSelected | undefined, crawlOptions: TChildCrawlOptions) => boolean;
|
|
158
|
+
}): QueryFactory<TChildParams, TData, TError, TChildSelected, TPageParam, TChildCrawlOptions, TParentHasReduce>;
|
|
172
159
|
|
|
173
160
|
export { type QueryFactory, type QueryFactoryConfig, type ResolvedInfiniteOptions, type ResolvedQueryOptions, type StandardQueryOptions, queryFactory };
|
package/dist/index.js
CHANGED
|
@@ -40,9 +40,10 @@ function resolveKey(namespace, params, crawlOptions) {
|
|
|
40
40
|
}
|
|
41
41
|
return defined ? [...withParams, defined] : withParams;
|
|
42
42
|
}
|
|
43
|
-
function wrapGetNextPageParam(getNextPageParam, shouldFetchNextPage, crawlOptions) {
|
|
43
|
+
function wrapGetNextPageParam(getNextPageParam, shouldFetchNextPage, crawlOptions, select) {
|
|
44
44
|
return (lastPage, allPages, lastPageParam, allPageParams) => {
|
|
45
|
-
|
|
45
|
+
const combined = select ? select(lastPage) : lastPage;
|
|
46
|
+
if (!shouldFetchNextPage(combined, crawlOptions))
|
|
46
47
|
return void 0;
|
|
47
48
|
return getNextPageParam(lastPage, allPages, lastPageParam, allPageParams);
|
|
48
49
|
};
|
|
@@ -63,7 +64,7 @@ function buildCrawlingQueryFn(queryFn, getNextPageParam, initialPageParam, shoul
|
|
|
63
64
|
pageParams.push(currentParam);
|
|
64
65
|
if (reduce) acc = reduce(acc, page);
|
|
65
66
|
if ((_b = context.signal) == null ? void 0 : _b.aborted) break;
|
|
66
|
-
if (
|
|
67
|
+
if (!shouldFetchNextPage(acc, crawlOptions)) break;
|
|
67
68
|
const nextParam = getNextPageParam(page, pages, currentParam, pageParams);
|
|
68
69
|
if (nextParam == null) break;
|
|
69
70
|
currentParam = nextParam;
|
|
@@ -95,7 +96,7 @@ function buildInfiniteCrawlingQueryFn(queryFn, getNextPageParam, shouldFetchNext
|
|
|
95
96
|
const nextParam = getNextPageParam(page, pages, currentParam, pageParams);
|
|
96
97
|
nextBatchParam = nextParam != null ? nextParam : null;
|
|
97
98
|
if (nextParam == null) break;
|
|
98
|
-
if (
|
|
99
|
+
if (!shouldFetchNextPage(acc, crawlOptions)) break;
|
|
99
100
|
currentParam = nextParam;
|
|
100
101
|
}
|
|
101
102
|
if (acc === void 0) throw new DOMException("Aborted", "AbortError");
|
|
@@ -114,7 +115,7 @@ function buildFactory(cfg) {
|
|
|
114
115
|
reduce,
|
|
115
116
|
standardOptions
|
|
116
117
|
} = cfg;
|
|
117
|
-
const hasCrawling = rawQueryFn !== void 0 && getNextPageParam !== void 0;
|
|
118
|
+
const hasCrawling = rawQueryFn !== void 0 && getNextPageParam !== void 0 && shouldFetchNextPage !== void 0;
|
|
118
119
|
const hasInfiniteCrawling = hasCrawling && reduce !== void 0;
|
|
119
120
|
const crawlingFn = hasCrawling ? buildCrawlingQueryFn(
|
|
120
121
|
rawQueryFn,
|
|
@@ -167,7 +168,8 @@ function buildFactory(cfg) {
|
|
|
167
168
|
const infiniteGetNextPageParam = getNextPageParam && shouldFetchNextPage ? wrapGetNextPageParam(
|
|
168
169
|
getNextPageParam,
|
|
169
170
|
shouldFetchNextPage,
|
|
170
|
-
crawlOptions
|
|
171
|
+
crawlOptions,
|
|
172
|
+
select
|
|
171
173
|
) : getNextPageParam != null ? getNextPageParam : noNextPage;
|
|
172
174
|
return {
|
|
173
175
|
...standardOptions,
|
package/dist/index.mjs
CHANGED
|
@@ -14,9 +14,10 @@ function resolveKey(namespace, params, crawlOptions) {
|
|
|
14
14
|
}
|
|
15
15
|
return defined ? [...withParams, defined] : withParams;
|
|
16
16
|
}
|
|
17
|
-
function wrapGetNextPageParam(getNextPageParam, shouldFetchNextPage, crawlOptions) {
|
|
17
|
+
function wrapGetNextPageParam(getNextPageParam, shouldFetchNextPage, crawlOptions, select) {
|
|
18
18
|
return (lastPage, allPages, lastPageParam, allPageParams) => {
|
|
19
|
-
|
|
19
|
+
const combined = select ? select(lastPage) : lastPage;
|
|
20
|
+
if (!shouldFetchNextPage(combined, crawlOptions))
|
|
20
21
|
return void 0;
|
|
21
22
|
return getNextPageParam(lastPage, allPages, lastPageParam, allPageParams);
|
|
22
23
|
};
|
|
@@ -37,7 +38,7 @@ function buildCrawlingQueryFn(queryFn, getNextPageParam, initialPageParam, shoul
|
|
|
37
38
|
pageParams.push(currentParam);
|
|
38
39
|
if (reduce) acc = reduce(acc, page);
|
|
39
40
|
if ((_b = context.signal) == null ? void 0 : _b.aborted) break;
|
|
40
|
-
if (
|
|
41
|
+
if (!shouldFetchNextPage(acc, crawlOptions)) break;
|
|
41
42
|
const nextParam = getNextPageParam(page, pages, currentParam, pageParams);
|
|
42
43
|
if (nextParam == null) break;
|
|
43
44
|
currentParam = nextParam;
|
|
@@ -69,7 +70,7 @@ function buildInfiniteCrawlingQueryFn(queryFn, getNextPageParam, shouldFetchNext
|
|
|
69
70
|
const nextParam = getNextPageParam(page, pages, currentParam, pageParams);
|
|
70
71
|
nextBatchParam = nextParam != null ? nextParam : null;
|
|
71
72
|
if (nextParam == null) break;
|
|
72
|
-
if (
|
|
73
|
+
if (!shouldFetchNextPage(acc, crawlOptions)) break;
|
|
73
74
|
currentParam = nextParam;
|
|
74
75
|
}
|
|
75
76
|
if (acc === void 0) throw new DOMException("Aborted", "AbortError");
|
|
@@ -88,7 +89,7 @@ function buildFactory(cfg) {
|
|
|
88
89
|
reduce,
|
|
89
90
|
standardOptions
|
|
90
91
|
} = cfg;
|
|
91
|
-
const hasCrawling = rawQueryFn !== void 0 && getNextPageParam !== void 0;
|
|
92
|
+
const hasCrawling = rawQueryFn !== void 0 && getNextPageParam !== void 0 && shouldFetchNextPage !== void 0;
|
|
92
93
|
const hasInfiniteCrawling = hasCrawling && reduce !== void 0;
|
|
93
94
|
const crawlingFn = hasCrawling ? buildCrawlingQueryFn(
|
|
94
95
|
rawQueryFn,
|
|
@@ -141,7 +142,8 @@ function buildFactory(cfg) {
|
|
|
141
142
|
const infiniteGetNextPageParam = getNextPageParam && shouldFetchNextPage ? wrapGetNextPageParam(
|
|
142
143
|
getNextPageParam,
|
|
143
144
|
shouldFetchNextPage,
|
|
144
|
-
crawlOptions
|
|
145
|
+
crawlOptions,
|
|
146
|
+
select
|
|
145
147
|
) : getNextPageParam != null ? getNextPageParam : noNextPage;
|
|
146
148
|
return {
|
|
147
149
|
...standardOptions,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robohall/react-query-factory",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A factory abstraction for TanStack Query (React Query) with composable keys, crawling support, and automatic infinite query generation",
|
|
5
5
|
"author": "Robert Hall",
|
|
6
6
|
"license": "MIT",
|