@ic-reactor/react 3.13.0 → 4.0.0-beta.2
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 +237 -787
- package/dist/index.d.ts +260 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +471 -23
- package/dist/index.js.map +1 -1
- package/llms.txt +82 -278
- package/package.json +11 -39
- package/src/index.tsx +612 -0
- package/dist/auth/auth-client-compat.d.ts +0 -122
- package/dist/auth/auth-client-compat.d.ts.map +0 -1
- package/dist/auth/auth-client-compat.js +0 -162
- package/dist/auth/auth-client-compat.js.map +0 -1
- package/dist/auth/authentication-manager.d.ts +0 -405
- package/dist/auth/authentication-manager.d.ts.map +0 -1
- package/dist/auth/authentication-manager.js +0 -1537
- package/dist/auth/authentication-manager.js.map +0 -1
- package/dist/auth/constants.d.ts +0 -24
- package/dist/auth/constants.d.ts.map +0 -1
- package/dist/auth/constants.js +0 -24
- package/dist/auth/constants.js.map +0 -1
- package/dist/auth/createIdentityAttributeHooks.d.ts +0 -14
- package/dist/auth/createIdentityAttributeHooks.d.ts.map +0 -1
- package/dist/auth/createIdentityAttributeHooks.js +0 -122
- package/dist/auth/createIdentityAttributeHooks.js.map +0 -1
- package/dist/auth/identity-attributes-manager.d.ts +0 -27
- package/dist/auth/identity-attributes-manager.d.ts.map +0 -1
- package/dist/auth/identity-attributes-manager.js +0 -191
- package/dist/auth/identity-attributes-manager.js.map +0 -1
- package/dist/auth/identity-attributes.d.ts +0 -19
- package/dist/auth/identity-attributes.d.ts.map +0 -1
- package/dist/auth/identity-attributes.js +0 -227
- package/dist/auth/identity-attributes.js.map +0 -1
- package/dist/auth/index.d.ts +0 -8
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js +0 -8
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/local-ii-probe.d.ts +0 -57
- package/dist/auth/local-ii-probe.d.ts.map +0 -1
- package/dist/auth/local-ii-probe.js +0 -121
- package/dist/auth/local-ii-probe.js.map +0 -1
- package/dist/auth/types.d.ts +0 -222
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js +0 -2
- package/dist/auth/types.js.map +0 -1
- package/dist/createActorHooks.d.ts +0 -41
- package/dist/createActorHooks.d.ts.map +0 -1
- package/dist/createActorHooks.js +0 -17
- package/dist/createActorHooks.js.map +0 -1
- package/dist/createInfiniteQuery.d.ts +0 -185
- package/dist/createInfiniteQuery.d.ts.map +0 -1
- package/dist/createInfiniteQuery.js +0 -198
- package/dist/createInfiniteQuery.js.map +0 -1
- package/dist/createMutation.d.ts +0 -33
- package/dist/createMutation.d.ts.map +0 -1
- package/dist/createMutation.js +0 -199
- package/dist/createMutation.js.map +0 -1
- package/dist/createQuery.d.ts +0 -63
- package/dist/createQuery.d.ts.map +0 -1
- package/dist/createQuery.js +0 -204
- package/dist/createQuery.js.map +0 -1
- package/dist/createReactorProvider.d.ts +0 -158
- package/dist/createReactorProvider.d.ts.map +0 -1
- package/dist/createReactorProvider.js +0 -256
- package/dist/createReactorProvider.js.map +0 -1
- package/dist/createSuspenseInfiniteQuery.d.ts +0 -154
- package/dist/createSuspenseInfiniteQuery.d.ts.map +0 -1
- package/dist/createSuspenseInfiniteQuery.js +0 -209
- package/dist/createSuspenseInfiniteQuery.js.map +0 -1
- package/dist/createSuspenseQuery.d.ts +0 -46
- package/dist/createSuspenseQuery.d.ts.map +0 -1
- package/dist/createSuspenseQuery.js +0 -158
- package/dist/createSuspenseQuery.js.map +0 -1
- package/dist/defineDisplayReactor.d.ts +0 -43
- package/dist/defineDisplayReactor.d.ts.map +0 -1
- package/dist/defineDisplayReactor.js +0 -42
- package/dist/defineDisplayReactor.js.map +0 -1
- package/dist/defineReactor.d.ts +0 -99
- package/dist/defineReactor.d.ts.map +0 -1
- package/dist/defineReactor.js +0 -15
- package/dist/defineReactor.js.map +0 -1
- package/dist/defineReactorShared.d.ts +0 -84
- package/dist/defineReactorShared.d.ts.map +0 -1
- package/dist/defineReactorShared.js +0 -139
- package/dist/defineReactorShared.js.map +0 -1
- package/dist/hooks/createAuthHooks.d.ts +0 -50
- package/dist/hooks/createAuthHooks.d.ts.map +0 -1
- package/dist/hooks/createAuthHooks.js +0 -291
- package/dist/hooks/createAuthHooks.js.map +0 -1
- package/dist/hooks/index.d.ts +0 -21
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -24
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/useActorInfiniteQuery.d.ts +0 -67
- package/dist/hooks/useActorInfiniteQuery.d.ts.map +0 -1
- package/dist/hooks/useActorInfiniteQuery.js +0 -89
- package/dist/hooks/useActorInfiniteQuery.js.map +0 -1
- package/dist/hooks/useActorMethod.d.ts +0 -148
- package/dist/hooks/useActorMethod.d.ts.map +0 -1
- package/dist/hooks/useActorMethod.js +0 -394
- package/dist/hooks/useActorMethod.js.map +0 -1
- package/dist/hooks/useActorMutation.d.ts +0 -51
- package/dist/hooks/useActorMutation.d.ts.map +0 -1
- package/dist/hooks/useActorMutation.js +0 -70
- package/dist/hooks/useActorMutation.js.map +0 -1
- package/dist/hooks/useActorQuery.d.ts +0 -45
- package/dist/hooks/useActorQuery.d.ts.map +0 -1
- package/dist/hooks/useActorQuery.js +0 -67
- package/dist/hooks/useActorQuery.js.map +0 -1
- package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts +0 -51
- package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts.map +0 -1
- package/dist/hooks/useActorSuspenseInfiniteQuery.js +0 -76
- package/dist/hooks/useActorSuspenseInfiniteQuery.js.map +0 -1
- package/dist/hooks/useActorSuspenseQuery.d.ts +0 -32
- package/dist/hooks/useActorSuspenseQuery.d.ts.map +0 -1
- package/dist/hooks/useActorSuspenseQuery.js +0 -58
- package/dist/hooks/useActorSuspenseQuery.js.map +0 -1
- package/dist/ownedAuthentication.d.ts +0 -52
- package/dist/ownedAuthentication.d.ts.map +0 -1
- package/dist/ownedAuthentication.js +0 -49
- package/dist/ownedAuthentication.js.map +0 -1
- package/dist/server.d.ts +0 -21
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -23
- package/dist/server.js.map +0 -1
- package/dist/testing.d.ts +0 -19
- package/dist/testing.d.ts.map +0 -1
- package/dist/testing.js +0 -19
- package/dist/testing.js.map +0 -1
- package/dist/types.d.ts +0 -671
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -5
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts +0 -207
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -405
- package/dist/utils.js.map +0 -1
- package/dist/validation.d.ts +0 -136
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -144
- package/dist/validation.js.map +0 -1
- package/src/auth/auth-client-compat.ts +0 -273
- package/src/auth/authentication-manager.ts +0 -1682
- package/src/auth/constants.ts +0 -32
- package/src/auth/createIdentityAttributeHooks.ts +0 -169
- package/src/auth/identity-attributes-manager.ts +0 -226
- package/src/auth/identity-attributes.ts +0 -345
- package/src/auth/index.ts +0 -7
- package/src/auth/local-ii-probe.ts +0 -173
- package/src/auth/types.ts +0 -243
- package/src/createActorHooks.ts +0 -208
- package/src/createInfiniteQuery.ts +0 -670
- package/src/createMutation.ts +0 -324
- package/src/createQuery.ts +0 -369
- package/src/createReactorProvider.ts +0 -365
- package/src/createSuspenseInfiniteQuery.ts +0 -651
- package/src/createSuspenseQuery.ts +0 -304
- package/src/defineDisplayReactor.ts +0 -62
- package/src/defineReactor.ts +0 -142
- package/src/defineReactorShared.ts +0 -268
- package/src/hooks/createAuthHooks.ts +0 -371
- package/src/hooks/index.ts +0 -103
- package/src/hooks/useActorInfiniteQuery.ts +0 -278
- package/src/hooks/useActorMethod.ts +0 -710
- package/src/hooks/useActorMutation.ts +0 -205
- package/src/hooks/useActorQuery.ts +0 -157
- package/src/hooks/useActorSuspenseInfiniteQuery.ts +0 -248
- package/src/hooks/useActorSuspenseQuery.ts +0 -147
- package/src/index.ts +0 -31
- package/src/ownedAuthentication.ts +0 -81
- package/src/server.ts +0 -23
- package/src/testing.ts +0 -18
- package/src/types.ts +0 -948
- package/src/utils.ts +0 -505
- package/src/validation.ts +0 -226
|
@@ -1,670 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infinite Query Factory - Generic wrapper for React Query paginated canister data
|
|
3
|
-
*
|
|
4
|
-
* Creates unified fetch/hook/invalidate functions for any paginated canister method.
|
|
5
|
-
* Works with any Reactor instance.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* const postsQuery = createInfiniteQuery(reactor, {
|
|
9
|
-
* functionName: "get_posts",
|
|
10
|
-
* initialPageParam: 0,
|
|
11
|
-
* getArgs: (cursor) => [{ cursor, limit: 10 }] as const,
|
|
12
|
-
* getNextPageParam: (lastPage) => lastPage.nextCursor,
|
|
13
|
-
* })
|
|
14
|
-
*
|
|
15
|
-
* // In component
|
|
16
|
-
* const { data, fetchNextPage, hasNextPage } = postsQuery.useInfiniteQuery()
|
|
17
|
-
*
|
|
18
|
-
* // Flatten all pages
|
|
19
|
-
* const allPosts = data?.pages.flatMap(page => page.posts)
|
|
20
|
-
*
|
|
21
|
-
* // Invalidate cache
|
|
22
|
-
* postsQuery.invalidate()
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
import { useMemo } from "react"
|
|
26
|
-
import type {
|
|
27
|
-
Reactor,
|
|
28
|
-
FunctionName,
|
|
29
|
-
ReactorArgs,
|
|
30
|
-
BaseActor,
|
|
31
|
-
TransformKey,
|
|
32
|
-
ReactorReturnOk,
|
|
33
|
-
ReactorQueryData,
|
|
34
|
-
ReactorReturnErr,
|
|
35
|
-
} from "@ic-reactor/core"
|
|
36
|
-
import {
|
|
37
|
-
QueryKey,
|
|
38
|
-
useInfiniteQuery,
|
|
39
|
-
InfiniteData,
|
|
40
|
-
UseInfiniteQueryResult,
|
|
41
|
-
UseInfiniteQueryOptions,
|
|
42
|
-
QueryFunctionContext,
|
|
43
|
-
FetchInfiniteQueryOptions,
|
|
44
|
-
InfiniteQueryObserverOptions,
|
|
45
|
-
SkipToken,
|
|
46
|
-
} from "@tanstack/react-query"
|
|
47
|
-
import { CallConfig } from "@icp-sdk/core/agent"
|
|
48
|
-
import type {
|
|
49
|
-
NoInfer,
|
|
50
|
-
QueryCacheControls,
|
|
51
|
-
QueryFactoryMethods,
|
|
52
|
-
} from "./types.js"
|
|
53
|
-
import {
|
|
54
|
-
buildChainedSelect,
|
|
55
|
-
callConfigForKey,
|
|
56
|
-
mergeFactoryQueryKey,
|
|
57
|
-
normalizeQueryData,
|
|
58
|
-
pickFetchOptions,
|
|
59
|
-
queryCacheControls,
|
|
60
|
-
retryOption,
|
|
61
|
-
useMountQueryClient,
|
|
62
|
-
withQueryFactoryMethods,
|
|
63
|
-
} from "./utils.js"
|
|
64
|
-
|
|
65
|
-
type InfiniteQueryFactoryFn<
|
|
66
|
-
Service,
|
|
67
|
-
Method extends FunctionName<Service>,
|
|
68
|
-
Transform extends TransformKey,
|
|
69
|
-
TPageParam,
|
|
70
|
-
Selected,
|
|
71
|
-
> = QueryFactoryMethods & {
|
|
72
|
-
(
|
|
73
|
-
getArgs: (pageParam: TPageParam) => ReactorArgs<Service, Method, Transform>
|
|
74
|
-
): InfiniteQueryResult<
|
|
75
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
76
|
-
TPageParam,
|
|
77
|
-
Selected,
|
|
78
|
-
InfiniteQueryError<Service, Method, Transform>
|
|
79
|
-
>
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// ============================================================================
|
|
83
|
-
// Type Definitions
|
|
84
|
-
// ============================================================================
|
|
85
|
-
|
|
86
|
-
/** The raw page data type returned by the query function */
|
|
87
|
-
export type InfiniteQueryPageData<
|
|
88
|
-
Service = BaseActor,
|
|
89
|
-
Method extends FunctionName<Service> = FunctionName<Service>,
|
|
90
|
-
Transform extends TransformKey = "candid",
|
|
91
|
-
> = ReactorQueryData<ReactorReturnOk<Service, Method, Transform>>
|
|
92
|
-
|
|
93
|
-
/** The error type for infinite queries */
|
|
94
|
-
export type InfiniteQueryError<
|
|
95
|
-
Service = BaseActor,
|
|
96
|
-
Method extends FunctionName<Service> = FunctionName<Service>,
|
|
97
|
-
Transform extends TransformKey = "candid",
|
|
98
|
-
> = ReactorReturnErr<Service, Method, Transform>
|
|
99
|
-
|
|
100
|
-
// ============================================================================
|
|
101
|
-
// Configuration Types
|
|
102
|
-
// ============================================================================
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Configuration for createInfiniteQuery.
|
|
106
|
-
* Extends InfiniteQueryObserverOptions to accept standard TanStack Query
|
|
107
|
-
* infinite-query options at the create level (e.g. refetchInterval,
|
|
108
|
-
* refetchOnMount, refetchOnWindowFocus, retry, gcTime, networkMode).
|
|
109
|
-
*
|
|
110
|
-
* @template Service - The actor interface type
|
|
111
|
-
* @template Method - The method name on the actor
|
|
112
|
-
* @template Transform - The transformation key (identity, display, etc.)
|
|
113
|
-
* @template TPageParam - The type of the page parameter
|
|
114
|
-
* @template Selected - The type returned after select transformation
|
|
115
|
-
*/
|
|
116
|
-
export interface InfiniteQueryConfig<
|
|
117
|
-
Service = BaseActor,
|
|
118
|
-
Method extends FunctionName<Service> = FunctionName<Service>,
|
|
119
|
-
Transform extends TransformKey = "candid",
|
|
120
|
-
TPageParam = unknown,
|
|
121
|
-
Selected = InfiniteData<
|
|
122
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
123
|
-
TPageParam
|
|
124
|
-
>,
|
|
125
|
-
> extends Omit<
|
|
126
|
-
InfiniteQueryObserverOptions<
|
|
127
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
128
|
-
InfiniteQueryError<Service, Method, Transform>,
|
|
129
|
-
Selected,
|
|
130
|
-
QueryKey,
|
|
131
|
-
TPageParam
|
|
132
|
-
>,
|
|
133
|
-
"queryKey" | "queryFn"
|
|
134
|
-
> {
|
|
135
|
-
/** The method to call on the canister */
|
|
136
|
-
functionName: Method
|
|
137
|
-
/** Call configuration for the actor method */
|
|
138
|
-
callConfig?: CallConfig
|
|
139
|
-
/** Custom query key (optional, auto-generated if not provided) */
|
|
140
|
-
queryKey?: QueryKey
|
|
141
|
-
/** Initial page parameter */
|
|
142
|
-
initialPageParam: TPageParam
|
|
143
|
-
/** Function to get args from page parameter */
|
|
144
|
-
getArgs: (pageParam: TPageParam) => ReactorArgs<Service, Method, Transform>
|
|
145
|
-
/**
|
|
146
|
-
* Narrows what the cache key derives from the call arguments.
|
|
147
|
-
*
|
|
148
|
-
* By default the key is scoped by `getArgs(initialPageParam)`, so two
|
|
149
|
-
* infinite queries on the same method with different arguments stay in
|
|
150
|
-
* separate cache entries. Supply this when those args embed the cursor and
|
|
151
|
-
* only part of them identifies the query — return the stable, serializable
|
|
152
|
-
* portion (typically everything except the pagination field).
|
|
153
|
-
*/
|
|
154
|
-
getKeyArgs?: (args: ReactorArgs<Service, Method, Transform>) => unknown
|
|
155
|
-
/** Function to determine next page parameter */
|
|
156
|
-
getNextPageParam: (
|
|
157
|
-
lastPage: InfiniteQueryPageData<Service, Method, Transform>,
|
|
158
|
-
allPages: InfiniteQueryPageData<Service, Method, Transform>[],
|
|
159
|
-
lastPageParam: TPageParam,
|
|
160
|
-
allPageParams: TPageParam[]
|
|
161
|
-
) => TPageParam | undefined | null
|
|
162
|
-
/** Function to determine previous page parameter (for bi-directional) */
|
|
163
|
-
getPreviousPageParam?: (
|
|
164
|
-
firstPage: InfiniteQueryPageData<Service, Method, Transform>,
|
|
165
|
-
allPages: InfiniteQueryPageData<Service, Method, Transform>[],
|
|
166
|
-
firstPageParam: TPageParam,
|
|
167
|
-
allPageParams: TPageParam[]
|
|
168
|
-
) => TPageParam | undefined | null
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Configuration for the non-suspense infinite query hook of
|
|
173
|
-
* `createActorHooks` and `defineReactor` (`useActorInfiniteQuery`): an
|
|
174
|
-
* {@link InfiniteQueryConfig} whose `getArgs` may also be TanStack Query's
|
|
175
|
-
* `skipToken`, for a list whose arguments are not known yet.
|
|
176
|
-
*
|
|
177
|
-
* A skipped list does not fetch. It has an entry of its own under its method
|
|
178
|
-
* and config `queryKey` (at the canister and agent `callConfig` names), which
|
|
179
|
-
* no call's key shares, so it shows no data until the arguments arrive. Once
|
|
180
|
-
* `getArgs` is a function, the list is keyed and fetched as usual. Its
|
|
181
|
-
* `refetch()` has nothing to run: TanStack Query answers it with a "Missing
|
|
182
|
-
* queryFn" error. `useActorSuspenseInfiniteQuery` does not take `skipToken`.
|
|
183
|
-
*
|
|
184
|
-
* @example
|
|
185
|
-
* ```typescript
|
|
186
|
-
* import { skipToken } from "@ic-reactor/react"
|
|
187
|
-
*
|
|
188
|
-
* const { data } = useActorInfiniteQuery({
|
|
189
|
-
* functionName: "get_transactions",
|
|
190
|
-
* getArgs: account
|
|
191
|
-
* ? (start: bigint) => [{ account, start, length: 20n }]
|
|
192
|
-
* : skipToken,
|
|
193
|
-
* initialPageParam: 0n,
|
|
194
|
-
* getNextPageParam: (lastPage) => lastPage.next[0],
|
|
195
|
-
* })
|
|
196
|
-
* ```
|
|
197
|
-
*/
|
|
198
|
-
export interface SkippableInfiniteQueryConfig<
|
|
199
|
-
Service = BaseActor,
|
|
200
|
-
Method extends FunctionName<Service> = FunctionName<Service>,
|
|
201
|
-
Transform extends TransformKey = "candid",
|
|
202
|
-
TPageParam = unknown,
|
|
203
|
-
Selected = InfiniteData<
|
|
204
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
205
|
-
TPageParam
|
|
206
|
-
>,
|
|
207
|
-
> extends Omit<
|
|
208
|
-
InfiniteQueryConfig<Service, Method, Transform, TPageParam, Selected>,
|
|
209
|
-
"getArgs"
|
|
210
|
-
> {
|
|
211
|
-
/**
|
|
212
|
-
* Function to get args from page parameter, or `skipToken` while the args
|
|
213
|
-
* are not known: the list then waits without fetching.
|
|
214
|
-
*/
|
|
215
|
-
getArgs:
|
|
216
|
-
| ((pageParam: TPageParam) => ReactorArgs<Service, Method, Transform>)
|
|
217
|
-
| SkipToken
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Configuration for createInfiniteQueryFactory (without getArgs; provided at call time).
|
|
222
|
-
*/
|
|
223
|
-
export type InfiniteQueryFactoryConfig<
|
|
224
|
-
Service = BaseActor,
|
|
225
|
-
Method extends FunctionName<Service> = FunctionName<Service>,
|
|
226
|
-
Transform extends TransformKey = "candid",
|
|
227
|
-
TPageParam = unknown,
|
|
228
|
-
Selected = InfiniteData<
|
|
229
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
230
|
-
TPageParam
|
|
231
|
-
>,
|
|
232
|
-
> = Omit<
|
|
233
|
-
// `getArgs` is supplied per factory call. `getKeyArgs` is inherited from
|
|
234
|
-
// InfiniteQueryConfig, which now applies it for every infinite query rather
|
|
235
|
-
// than only for factory-created ones.
|
|
236
|
-
InfiniteQueryConfig<Service, Method, Transform, TPageParam, Selected>,
|
|
237
|
-
"getArgs"
|
|
238
|
-
>
|
|
239
|
-
|
|
240
|
-
// ============================================================================
|
|
241
|
-
// Hook Interface
|
|
242
|
-
// ============================================================================
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* useInfiniteQuery hook with chained select support.
|
|
246
|
-
*/
|
|
247
|
-
export interface UseInfiniteQueryWithSelect<
|
|
248
|
-
TPageData,
|
|
249
|
-
TPageParam,
|
|
250
|
-
Selected = InfiniteData<TPageData, TPageParam>,
|
|
251
|
-
TError = Error,
|
|
252
|
-
> {
|
|
253
|
-
// Overload 1: Without select - returns Selected
|
|
254
|
-
(
|
|
255
|
-
options?: Omit<
|
|
256
|
-
UseInfiniteQueryOptions<
|
|
257
|
-
TPageData,
|
|
258
|
-
TError,
|
|
259
|
-
Selected,
|
|
260
|
-
QueryKey,
|
|
261
|
-
TPageParam
|
|
262
|
-
>,
|
|
263
|
-
| "select"
|
|
264
|
-
| "queryKey"
|
|
265
|
-
| "queryFn"
|
|
266
|
-
| "initialPageParam"
|
|
267
|
-
| "getNextPageParam"
|
|
268
|
-
| "getPreviousPageParam"
|
|
269
|
-
>
|
|
270
|
-
): UseInfiniteQueryResult<Selected, TError>
|
|
271
|
-
|
|
272
|
-
// Overload 2: With select - chains on top and returns TFinal
|
|
273
|
-
<TFinal = Selected>(
|
|
274
|
-
options: Omit<
|
|
275
|
-
UseInfiniteQueryOptions<TPageData, TError, TFinal, QueryKey, TPageParam>,
|
|
276
|
-
| "queryKey"
|
|
277
|
-
| "queryFn"
|
|
278
|
-
| "select"
|
|
279
|
-
| "initialPageParam"
|
|
280
|
-
| "getNextPageParam"
|
|
281
|
-
| "getPreviousPageParam"
|
|
282
|
-
> & {
|
|
283
|
-
select: (data: Selected) => TFinal
|
|
284
|
-
}
|
|
285
|
-
): UseInfiniteQueryResult<TFinal, TError>
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// ============================================================================
|
|
289
|
-
// Result Interface
|
|
290
|
-
// ============================================================================
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Result from createInfiniteQuery
|
|
294
|
-
*
|
|
295
|
-
* `cancel()`, `reset()` and `optimisticUpdate()` act on the whole page set:
|
|
296
|
-
* `optimisticUpdate` gets and returns the raw `InfiniteData`, `{ pages,
|
|
297
|
-
* pageParams }`.
|
|
298
|
-
*
|
|
299
|
-
* @template TPageData - The raw page data type
|
|
300
|
-
* @template TPageParam - The page parameter type
|
|
301
|
-
* @template Selected - The type after select transformation
|
|
302
|
-
* @template TError - The error type
|
|
303
|
-
*/
|
|
304
|
-
export interface InfiniteQueryResult<
|
|
305
|
-
TPageData,
|
|
306
|
-
TPageParam,
|
|
307
|
-
Selected = InfiniteData<TPageData, TPageParam>,
|
|
308
|
-
TError = Error,
|
|
309
|
-
> extends QueryCacheControls<InfiniteData<TPageData, TPageParam>> {
|
|
310
|
-
/** Fetch first page in loader (uses ensureQueryData for cache-first) */
|
|
311
|
-
fetch: () => Promise<Selected>
|
|
312
|
-
|
|
313
|
-
/** React hook for components - supports pagination */
|
|
314
|
-
useInfiniteQuery: UseInfiniteQueryWithSelect<
|
|
315
|
-
TPageData,
|
|
316
|
-
TPageParam,
|
|
317
|
-
Selected,
|
|
318
|
-
TError
|
|
319
|
-
>
|
|
320
|
-
|
|
321
|
-
/** Invalidate the cache (refetches if query is active) */
|
|
322
|
-
invalidate: () => Promise<void>
|
|
323
|
-
|
|
324
|
-
/** Get query key (for advanced React Query usage) */
|
|
325
|
-
getQueryKey: () => QueryKey
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Read data directly from cache without fetching.
|
|
329
|
-
* Returns undefined if data is not in cache.
|
|
330
|
-
*/
|
|
331
|
-
getCacheData: {
|
|
332
|
-
(): Selected | undefined
|
|
333
|
-
<TFinal>(select: (data: Selected) => TFinal): TFinal | undefined
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// ============================================================================
|
|
338
|
-
// Internal Implementation
|
|
339
|
-
// ============================================================================
|
|
340
|
-
|
|
341
|
-
const createInfiniteQueryImpl = <
|
|
342
|
-
Service,
|
|
343
|
-
Method extends FunctionName<Service> = FunctionName<Service>,
|
|
344
|
-
Transform extends TransformKey = "candid",
|
|
345
|
-
TPageParam = unknown,
|
|
346
|
-
Selected = InfiniteData<
|
|
347
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
348
|
-
TPageParam
|
|
349
|
-
>,
|
|
350
|
-
>(
|
|
351
|
-
reactor: Reactor<Service, Transform>,
|
|
352
|
-
config: InfiniteQueryConfig<Service, Method, Transform, TPageParam, Selected>
|
|
353
|
-
): InfiniteQueryResult<
|
|
354
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
355
|
-
TPageParam,
|
|
356
|
-
Selected,
|
|
357
|
-
InfiniteQueryError<Service, Method, Transform>
|
|
358
|
-
> => {
|
|
359
|
-
type TPageData = InfiniteQueryPageData<Service, Method, Transform>
|
|
360
|
-
type TError = InfiniteQueryError<Service, Method, Transform>
|
|
361
|
-
type TInfiniteData = InfiniteData<TPageData, TPageParam>
|
|
362
|
-
|
|
363
|
-
const {
|
|
364
|
-
functionName,
|
|
365
|
-
callConfig,
|
|
366
|
-
queryKey: customQueryKey,
|
|
367
|
-
initialPageParam,
|
|
368
|
-
getArgs,
|
|
369
|
-
getKeyArgs,
|
|
370
|
-
getNextPageParam,
|
|
371
|
-
getPreviousPageParam,
|
|
372
|
-
maxPages,
|
|
373
|
-
staleTime = 5 * 60 * 1000,
|
|
374
|
-
select,
|
|
375
|
-
...rest
|
|
376
|
-
} = config
|
|
377
|
-
|
|
378
|
-
// Fold the call arguments into the key. Without them every infinite query on
|
|
379
|
-
// a method shares one cache entry, so two lists with different `getArgs` (a
|
|
380
|
-
// different page size, a different filter) serve each other's pages — the
|
|
381
|
-
// arguments live in a closure, not in the config, so nothing else
|
|
382
|
-
// distinguishes them.
|
|
383
|
-
//
|
|
384
|
-
// The first page's args stand for the query's identity; `getKeyArgs` lets a
|
|
385
|
-
// caller drop the cursor field when it is part of those args.
|
|
386
|
-
const getQueryKey = (): QueryKey => {
|
|
387
|
-
const initialArgs = getArgs(initialPageParam)
|
|
388
|
-
const keyArgs = getKeyArgs?.(initialArgs) ?? initialArgs
|
|
389
|
-
|
|
390
|
-
return reactor.generateQueryKey(
|
|
391
|
-
{
|
|
392
|
-
functionName,
|
|
393
|
-
queryKey: mergeFactoryQueryKey(customQueryKey, undefined, keyArgs),
|
|
394
|
-
},
|
|
395
|
-
callConfig
|
|
396
|
-
)
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// Query function - accepts QueryFunctionContext
|
|
400
|
-
const queryFn = async (
|
|
401
|
-
context: QueryFunctionContext<QueryKey, TPageParam>
|
|
402
|
-
): Promise<TPageData> => {
|
|
403
|
-
// pageParam is typed as unknown in QueryFunctionContext, but we know its type
|
|
404
|
-
const pageParam = context.pageParam as TPageParam
|
|
405
|
-
const args = getArgs(pageParam)
|
|
406
|
-
const result = await reactor.callMethod({
|
|
407
|
-
functionName,
|
|
408
|
-
args,
|
|
409
|
-
callConfig: callConfigForKey(context.queryKey, callConfig),
|
|
410
|
-
})
|
|
411
|
-
return normalizeQueryData<ReactorReturnOk<Service, Method, Transform>>(
|
|
412
|
-
result as ReactorReturnOk<Service, Method, Transform>
|
|
413
|
-
)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Get infinite query options for fetchInfiniteQuery
|
|
417
|
-
const getInfiniteQueryOptions = (): FetchInfiniteQueryOptions<
|
|
418
|
-
TPageData,
|
|
419
|
-
TError,
|
|
420
|
-
TPageData,
|
|
421
|
-
QueryKey,
|
|
422
|
-
TPageParam
|
|
423
|
-
> => {
|
|
424
|
-
const queryKey = getQueryKey()
|
|
425
|
-
return {
|
|
426
|
-
// How the query function runs, shared with the hook; see
|
|
427
|
-
// pickFetchOptions. An update method's `retry` defaults as
|
|
428
|
-
// `Reactor.getQueryRetry` says.
|
|
429
|
-
...pickFetchOptions(rest),
|
|
430
|
-
...retryOption(rest.retry, reactor.getQueryRetry(functionName, queryKey)),
|
|
431
|
-
queryKey,
|
|
432
|
-
queryFn,
|
|
433
|
-
initialPageParam,
|
|
434
|
-
getNextPageParam,
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// Fetch function for loaders (cache-first, fetches first page)
|
|
439
|
-
const fetch = async (): Promise<Selected> => {
|
|
440
|
-
// Check cache first
|
|
441
|
-
const cachedData = reactor.queryClient.getQueryData(getQueryKey()) as
|
|
442
|
-
TInfiniteData | undefined
|
|
443
|
-
|
|
444
|
-
if (cachedData !== undefined) {
|
|
445
|
-
return select ? select(cachedData) : (cachedData as Selected)
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// Fetch if not in cache. A sign-in or sign-out while it is in flight
|
|
449
|
-
// cancels it; it then runs again for the new identity rather than
|
|
450
|
-
// rejecting with TanStack's CancelledError, as `reactor.fetchQuery` does.
|
|
451
|
-
const result = await reactor.clientManager.fetchAcrossIdentitySwitch(() =>
|
|
452
|
-
reactor.queryClient.fetchInfiniteQuery(getInfiniteQueryOptions())
|
|
453
|
-
)
|
|
454
|
-
|
|
455
|
-
// Result is already InfiniteData format
|
|
456
|
-
return select ? select(result) : (result as unknown as Selected)
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// Implementation
|
|
460
|
-
const useInfiniteQueryHook: UseInfiniteQueryWithSelect<
|
|
461
|
-
TPageData,
|
|
462
|
-
TPageParam,
|
|
463
|
-
Selected,
|
|
464
|
-
TError
|
|
465
|
-
> = (options: any): any => {
|
|
466
|
-
useMountQueryClient(reactor.queryClient)
|
|
467
|
-
|
|
468
|
-
// Memoized and identity-preserving; see buildChainedSelect for why the
|
|
469
|
-
// function identity matters to the observer's select-result cache.
|
|
470
|
-
const chainedSelect = useMemo(
|
|
471
|
-
() => buildChainedSelect(select as never, options?.select),
|
|
472
|
-
[options?.select]
|
|
473
|
-
)
|
|
474
|
-
|
|
475
|
-
const queryKey = getQueryKey()
|
|
476
|
-
|
|
477
|
-
return useInfiniteQuery(
|
|
478
|
-
{
|
|
479
|
-
queryKey,
|
|
480
|
-
queryFn,
|
|
481
|
-
initialPageParam,
|
|
482
|
-
getNextPageParam,
|
|
483
|
-
getPreviousPageParam,
|
|
484
|
-
maxPages,
|
|
485
|
-
staleTime,
|
|
486
|
-
...rest,
|
|
487
|
-
...options,
|
|
488
|
-
select: chainedSelect,
|
|
489
|
-
// The hook's `retry`, else the config's, else an update method's
|
|
490
|
-
// default; see `Reactor.getQueryRetry`.
|
|
491
|
-
...retryOption(
|
|
492
|
-
options?.retry ?? rest.retry,
|
|
493
|
-
reactor.getQueryRetry(functionName, queryKey)
|
|
494
|
-
),
|
|
495
|
-
} as any,
|
|
496
|
-
reactor.queryClient
|
|
497
|
-
)
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
// Invalidate function
|
|
501
|
-
const invalidate = async (): Promise<void> => {
|
|
502
|
-
const queryKey = getQueryKey()
|
|
503
|
-
await reactor.queryClient.invalidateQueries({ queryKey })
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// Get data from cache without fetching
|
|
507
|
-
const getCacheData: any = (selectFn?: (data: Selected) => any) => {
|
|
508
|
-
const queryKey = getQueryKey()
|
|
509
|
-
const cachedRawData = reactor.queryClient.getQueryData(
|
|
510
|
-
queryKey
|
|
511
|
-
) as TInfiniteData
|
|
512
|
-
|
|
513
|
-
if (cachedRawData === undefined) {
|
|
514
|
-
return undefined
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// Apply config.select to raw cache data
|
|
518
|
-
const selectedData = (
|
|
519
|
-
select ? select(cachedRawData) : cachedRawData
|
|
520
|
-
) as Selected
|
|
521
|
-
|
|
522
|
-
// Apply optional select parameter
|
|
523
|
-
if (selectFn) {
|
|
524
|
-
return selectFn(selectedData)
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
return selectedData
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
return {
|
|
531
|
-
fetch,
|
|
532
|
-
useInfiniteQuery: useInfiniteQueryHook,
|
|
533
|
-
invalidate,
|
|
534
|
-
getQueryKey,
|
|
535
|
-
getCacheData,
|
|
536
|
-
...queryCacheControls<TInfiniteData>(reactor, getQueryKey),
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
// ============================================================================
|
|
541
|
-
// Factory Function
|
|
542
|
-
// ============================================================================
|
|
543
|
-
|
|
544
|
-
export function createInfiniteQuery<
|
|
545
|
-
Service,
|
|
546
|
-
Transform extends TransformKey,
|
|
547
|
-
Method extends FunctionName<Service> = FunctionName<Service>,
|
|
548
|
-
TPageParam = unknown,
|
|
549
|
-
Selected = InfiniteData<
|
|
550
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
551
|
-
TPageParam
|
|
552
|
-
>,
|
|
553
|
-
>(
|
|
554
|
-
reactor: Reactor<Service, Transform>,
|
|
555
|
-
config: InfiniteQueryConfig<
|
|
556
|
-
NoInfer<Service>,
|
|
557
|
-
Method,
|
|
558
|
-
Transform,
|
|
559
|
-
TPageParam,
|
|
560
|
-
Selected
|
|
561
|
-
>
|
|
562
|
-
): InfiniteQueryResult<
|
|
563
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
564
|
-
TPageParam,
|
|
565
|
-
Selected,
|
|
566
|
-
InfiniteQueryError<Service, Method, Transform>
|
|
567
|
-
> {
|
|
568
|
-
return createInfiniteQueryImpl(
|
|
569
|
-
reactor,
|
|
570
|
-
config as InfiniteQueryConfig<
|
|
571
|
-
Service,
|
|
572
|
-
Method,
|
|
573
|
-
Transform,
|
|
574
|
-
TPageParam,
|
|
575
|
-
Selected
|
|
576
|
-
>
|
|
577
|
-
)
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
// ============================================================================
|
|
581
|
-
// Factory with Dynamic Args
|
|
582
|
-
// ============================================================================
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* Create an infinite query factory that accepts getArgs at call time.
|
|
586
|
-
* Useful when pagination logic varies by context.
|
|
587
|
-
*
|
|
588
|
-
* @template Service - The actor interface type
|
|
589
|
-
* @template Method - The method name on the actor
|
|
590
|
-
* @template Transform - The transformation key (identity, display, etc.)
|
|
591
|
-
* @template TPageParam - The page parameter type
|
|
592
|
-
* @template Selected - The type returned after select transformation
|
|
593
|
-
*
|
|
594
|
-
* @param reactor - The Reactor instance
|
|
595
|
-
* @param config - Infinite query configuration (without getArgs)
|
|
596
|
-
* @returns A function that accepts getArgs and returns an InfiniteQueryResult
|
|
597
|
-
*
|
|
598
|
-
* @example
|
|
599
|
-
* const getPostsQuery = createInfiniteQueryFactory(reactor, {
|
|
600
|
-
* functionName: "get_posts",
|
|
601
|
-
* initialPageParam: 0,
|
|
602
|
-
* getKeyArgs: (args) => {
|
|
603
|
-
* const [{ userId }] = args
|
|
604
|
-
* return [{ userId }]
|
|
605
|
-
* },
|
|
606
|
-
* getNextPageParam: (lastPage) => lastPage.nextCursor,
|
|
607
|
-
* })
|
|
608
|
-
*
|
|
609
|
-
* // Create query with specific args builder
|
|
610
|
-
* const userPostsQuery = getPostsQuery((cursor) => [{ userId, cursor, limit: 10 }])
|
|
611
|
-
* const { data, fetchNextPage } = userPostsQuery.useInfiniteQuery()
|
|
612
|
-
*
|
|
613
|
-
* // Every list this factory made, whatever its args and pages
|
|
614
|
-
* await getPostsQuery.invalidate()
|
|
615
|
-
*/
|
|
616
|
-
|
|
617
|
-
export function createInfiniteQueryFactory<
|
|
618
|
-
Service,
|
|
619
|
-
Transform extends TransformKey,
|
|
620
|
-
Method extends FunctionName<Service> = FunctionName<Service>,
|
|
621
|
-
TPageParam = unknown,
|
|
622
|
-
Selected = InfiniteData<
|
|
623
|
-
InfiniteQueryPageData<Service, Method, Transform>,
|
|
624
|
-
TPageParam
|
|
625
|
-
>,
|
|
626
|
-
>(
|
|
627
|
-
reactor: Reactor<Service, Transform>,
|
|
628
|
-
config: InfiniteQueryFactoryConfig<
|
|
629
|
-
NoInfer<Service>,
|
|
630
|
-
Method,
|
|
631
|
-
Transform,
|
|
632
|
-
TPageParam,
|
|
633
|
-
Selected
|
|
634
|
-
>
|
|
635
|
-
): InfiniteQueryFactoryFn<Service, Method, Transform, TPageParam, Selected> {
|
|
636
|
-
const factory = (
|
|
637
|
-
getArgs: (pageParam: TPageParam) => ReactorArgs<Service, Method, Transform>
|
|
638
|
-
) => {
|
|
639
|
-
// `getKeyArgs` and the args-derived key segment are applied by the impl,
|
|
640
|
-
// which now does it for every infinite query rather than only for factories.
|
|
641
|
-
return createInfiniteQueryImpl<
|
|
642
|
-
Service,
|
|
643
|
-
Method,
|
|
644
|
-
Transform,
|
|
645
|
-
TPageParam,
|
|
646
|
-
Selected
|
|
647
|
-
>(reactor, {
|
|
648
|
-
...(config as InfiniteQueryFactoryConfig<
|
|
649
|
-
Service,
|
|
650
|
-
Method,
|
|
651
|
-
Transform,
|
|
652
|
-
TPageParam,
|
|
653
|
-
Selected
|
|
654
|
-
>),
|
|
655
|
-
getArgs,
|
|
656
|
-
})
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// What every instance's key starts with: the method, the `callConfig`
|
|
660
|
-
// segments and the config `queryKey`. The args segment comes after them.
|
|
661
|
-
return withQueryFactoryMethods(factory, reactor, () =>
|
|
662
|
-
reactor.generateQueryKey(
|
|
663
|
-
{
|
|
664
|
-
functionName: config.functionName as Method,
|
|
665
|
-
queryKey: config.queryKey,
|
|
666
|
-
},
|
|
667
|
-
config.callConfig
|
|
668
|
-
)
|
|
669
|
-
)
|
|
670
|
-
}
|