@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.
Files changed (174) hide show
  1. package/README.md +237 -787
  2. package/dist/index.d.ts +260 -16
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +471 -23
  5. package/dist/index.js.map +1 -1
  6. package/llms.txt +82 -278
  7. package/package.json +11 -39
  8. package/src/index.tsx +612 -0
  9. package/dist/auth/auth-client-compat.d.ts +0 -122
  10. package/dist/auth/auth-client-compat.d.ts.map +0 -1
  11. package/dist/auth/auth-client-compat.js +0 -162
  12. package/dist/auth/auth-client-compat.js.map +0 -1
  13. package/dist/auth/authentication-manager.d.ts +0 -405
  14. package/dist/auth/authentication-manager.d.ts.map +0 -1
  15. package/dist/auth/authentication-manager.js +0 -1537
  16. package/dist/auth/authentication-manager.js.map +0 -1
  17. package/dist/auth/constants.d.ts +0 -24
  18. package/dist/auth/constants.d.ts.map +0 -1
  19. package/dist/auth/constants.js +0 -24
  20. package/dist/auth/constants.js.map +0 -1
  21. package/dist/auth/createIdentityAttributeHooks.d.ts +0 -14
  22. package/dist/auth/createIdentityAttributeHooks.d.ts.map +0 -1
  23. package/dist/auth/createIdentityAttributeHooks.js +0 -122
  24. package/dist/auth/createIdentityAttributeHooks.js.map +0 -1
  25. package/dist/auth/identity-attributes-manager.d.ts +0 -27
  26. package/dist/auth/identity-attributes-manager.d.ts.map +0 -1
  27. package/dist/auth/identity-attributes-manager.js +0 -191
  28. package/dist/auth/identity-attributes-manager.js.map +0 -1
  29. package/dist/auth/identity-attributes.d.ts +0 -19
  30. package/dist/auth/identity-attributes.d.ts.map +0 -1
  31. package/dist/auth/identity-attributes.js +0 -227
  32. package/dist/auth/identity-attributes.js.map +0 -1
  33. package/dist/auth/index.d.ts +0 -8
  34. package/dist/auth/index.d.ts.map +0 -1
  35. package/dist/auth/index.js +0 -8
  36. package/dist/auth/index.js.map +0 -1
  37. package/dist/auth/local-ii-probe.d.ts +0 -57
  38. package/dist/auth/local-ii-probe.d.ts.map +0 -1
  39. package/dist/auth/local-ii-probe.js +0 -121
  40. package/dist/auth/local-ii-probe.js.map +0 -1
  41. package/dist/auth/types.d.ts +0 -222
  42. package/dist/auth/types.d.ts.map +0 -1
  43. package/dist/auth/types.js +0 -2
  44. package/dist/auth/types.js.map +0 -1
  45. package/dist/createActorHooks.d.ts +0 -41
  46. package/dist/createActorHooks.d.ts.map +0 -1
  47. package/dist/createActorHooks.js +0 -17
  48. package/dist/createActorHooks.js.map +0 -1
  49. package/dist/createInfiniteQuery.d.ts +0 -185
  50. package/dist/createInfiniteQuery.d.ts.map +0 -1
  51. package/dist/createInfiniteQuery.js +0 -198
  52. package/dist/createInfiniteQuery.js.map +0 -1
  53. package/dist/createMutation.d.ts +0 -33
  54. package/dist/createMutation.d.ts.map +0 -1
  55. package/dist/createMutation.js +0 -199
  56. package/dist/createMutation.js.map +0 -1
  57. package/dist/createQuery.d.ts +0 -63
  58. package/dist/createQuery.d.ts.map +0 -1
  59. package/dist/createQuery.js +0 -204
  60. package/dist/createQuery.js.map +0 -1
  61. package/dist/createReactorProvider.d.ts +0 -158
  62. package/dist/createReactorProvider.d.ts.map +0 -1
  63. package/dist/createReactorProvider.js +0 -256
  64. package/dist/createReactorProvider.js.map +0 -1
  65. package/dist/createSuspenseInfiniteQuery.d.ts +0 -154
  66. package/dist/createSuspenseInfiniteQuery.d.ts.map +0 -1
  67. package/dist/createSuspenseInfiniteQuery.js +0 -209
  68. package/dist/createSuspenseInfiniteQuery.js.map +0 -1
  69. package/dist/createSuspenseQuery.d.ts +0 -46
  70. package/dist/createSuspenseQuery.d.ts.map +0 -1
  71. package/dist/createSuspenseQuery.js +0 -158
  72. package/dist/createSuspenseQuery.js.map +0 -1
  73. package/dist/defineDisplayReactor.d.ts +0 -43
  74. package/dist/defineDisplayReactor.d.ts.map +0 -1
  75. package/dist/defineDisplayReactor.js +0 -42
  76. package/dist/defineDisplayReactor.js.map +0 -1
  77. package/dist/defineReactor.d.ts +0 -99
  78. package/dist/defineReactor.d.ts.map +0 -1
  79. package/dist/defineReactor.js +0 -15
  80. package/dist/defineReactor.js.map +0 -1
  81. package/dist/defineReactorShared.d.ts +0 -84
  82. package/dist/defineReactorShared.d.ts.map +0 -1
  83. package/dist/defineReactorShared.js +0 -139
  84. package/dist/defineReactorShared.js.map +0 -1
  85. package/dist/hooks/createAuthHooks.d.ts +0 -50
  86. package/dist/hooks/createAuthHooks.d.ts.map +0 -1
  87. package/dist/hooks/createAuthHooks.js +0 -291
  88. package/dist/hooks/createAuthHooks.js.map +0 -1
  89. package/dist/hooks/index.d.ts +0 -21
  90. package/dist/hooks/index.d.ts.map +0 -1
  91. package/dist/hooks/index.js +0 -24
  92. package/dist/hooks/index.js.map +0 -1
  93. package/dist/hooks/useActorInfiniteQuery.d.ts +0 -67
  94. package/dist/hooks/useActorInfiniteQuery.d.ts.map +0 -1
  95. package/dist/hooks/useActorInfiniteQuery.js +0 -89
  96. package/dist/hooks/useActorInfiniteQuery.js.map +0 -1
  97. package/dist/hooks/useActorMethod.d.ts +0 -148
  98. package/dist/hooks/useActorMethod.d.ts.map +0 -1
  99. package/dist/hooks/useActorMethod.js +0 -394
  100. package/dist/hooks/useActorMethod.js.map +0 -1
  101. package/dist/hooks/useActorMutation.d.ts +0 -51
  102. package/dist/hooks/useActorMutation.d.ts.map +0 -1
  103. package/dist/hooks/useActorMutation.js +0 -70
  104. package/dist/hooks/useActorMutation.js.map +0 -1
  105. package/dist/hooks/useActorQuery.d.ts +0 -45
  106. package/dist/hooks/useActorQuery.d.ts.map +0 -1
  107. package/dist/hooks/useActorQuery.js +0 -67
  108. package/dist/hooks/useActorQuery.js.map +0 -1
  109. package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts +0 -51
  110. package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts.map +0 -1
  111. package/dist/hooks/useActorSuspenseInfiniteQuery.js +0 -76
  112. package/dist/hooks/useActorSuspenseInfiniteQuery.js.map +0 -1
  113. package/dist/hooks/useActorSuspenseQuery.d.ts +0 -32
  114. package/dist/hooks/useActorSuspenseQuery.d.ts.map +0 -1
  115. package/dist/hooks/useActorSuspenseQuery.js +0 -58
  116. package/dist/hooks/useActorSuspenseQuery.js.map +0 -1
  117. package/dist/ownedAuthentication.d.ts +0 -52
  118. package/dist/ownedAuthentication.d.ts.map +0 -1
  119. package/dist/ownedAuthentication.js +0 -49
  120. package/dist/ownedAuthentication.js.map +0 -1
  121. package/dist/server.d.ts +0 -21
  122. package/dist/server.d.ts.map +0 -1
  123. package/dist/server.js +0 -23
  124. package/dist/server.js.map +0 -1
  125. package/dist/testing.d.ts +0 -19
  126. package/dist/testing.d.ts.map +0 -1
  127. package/dist/testing.js +0 -19
  128. package/dist/testing.js.map +0 -1
  129. package/dist/types.d.ts +0 -671
  130. package/dist/types.d.ts.map +0 -1
  131. package/dist/types.js +0 -5
  132. package/dist/types.js.map +0 -1
  133. package/dist/utils.d.ts +0 -207
  134. package/dist/utils.d.ts.map +0 -1
  135. package/dist/utils.js +0 -405
  136. package/dist/utils.js.map +0 -1
  137. package/dist/validation.d.ts +0 -136
  138. package/dist/validation.d.ts.map +0 -1
  139. package/dist/validation.js +0 -144
  140. package/dist/validation.js.map +0 -1
  141. package/src/auth/auth-client-compat.ts +0 -273
  142. package/src/auth/authentication-manager.ts +0 -1682
  143. package/src/auth/constants.ts +0 -32
  144. package/src/auth/createIdentityAttributeHooks.ts +0 -169
  145. package/src/auth/identity-attributes-manager.ts +0 -226
  146. package/src/auth/identity-attributes.ts +0 -345
  147. package/src/auth/index.ts +0 -7
  148. package/src/auth/local-ii-probe.ts +0 -173
  149. package/src/auth/types.ts +0 -243
  150. package/src/createActorHooks.ts +0 -208
  151. package/src/createInfiniteQuery.ts +0 -670
  152. package/src/createMutation.ts +0 -324
  153. package/src/createQuery.ts +0 -369
  154. package/src/createReactorProvider.ts +0 -365
  155. package/src/createSuspenseInfiniteQuery.ts +0 -651
  156. package/src/createSuspenseQuery.ts +0 -304
  157. package/src/defineDisplayReactor.ts +0 -62
  158. package/src/defineReactor.ts +0 -142
  159. package/src/defineReactorShared.ts +0 -268
  160. package/src/hooks/createAuthHooks.ts +0 -371
  161. package/src/hooks/index.ts +0 -103
  162. package/src/hooks/useActorInfiniteQuery.ts +0 -278
  163. package/src/hooks/useActorMethod.ts +0 -710
  164. package/src/hooks/useActorMutation.ts +0 -205
  165. package/src/hooks/useActorQuery.ts +0 -157
  166. package/src/hooks/useActorSuspenseInfiniteQuery.ts +0 -248
  167. package/src/hooks/useActorSuspenseQuery.ts +0 -147
  168. package/src/index.ts +0 -31
  169. package/src/ownedAuthentication.ts +0 -81
  170. package/src/server.ts +0 -23
  171. package/src/testing.ts +0 -18
  172. package/src/types.ts +0 -948
  173. package/src/utils.ts +0 -505
  174. package/src/validation.ts +0 -226
package/dist/types.d.ts DELETED
@@ -1,671 +0,0 @@
1
- /**
2
- * Shared type definitions for query factories (createQuery, createSuspenseQuery, etc.)
3
- */
4
- import type { FunctionName, ReactorReturnOk, ReactorQueryData, ReactorReturnErr, ReactorArgs, BaseActor, TransformKey, TransformReturnRegistry, ErrResult, ActorMethodReturnType } from "@ic-reactor/core";
5
- import { CanisterError } from "@ic-reactor/core";
6
- import { CallConfig } from "@icp-sdk/core/agent";
7
- import { QueryKey, QueryObserverOptions, UseQueryOptions, UseQueryResult, UseSuspenseQueryOptions, UseSuspenseQueryResult, UseMutationOptions, UseMutationResult, SkipToken } from "@tanstack/react-query";
8
- export type NoInfer<T> = [T][T extends any ? 0 : never];
9
- /** The raw data type returned by the query function (before select) */
10
- export type QueryFnData<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid"> = ReactorQueryData<ReactorReturnOk<Service, Method, Transform>>;
11
- /** The error type for queries */
12
- export type QueryError<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid"> = ReactorReturnErr<Service, Method, Transform>;
13
- /**
14
- * Base configuration for query wrappers (shared between regular and suspense).
15
- *
16
- * @template Service - The actor interface type
17
- * @template Method - The method name on the actor
18
- * @template Transform - The transformation key (identity, display, etc.)
19
- * @template Selected - The type returned after select transformation
20
- */
21
- export interface BaseQueryConfig<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", Selected = QueryFnData<Service, Method, Transform>> extends Omit<QueryObserverOptions<QueryFnData<Service, Method, Transform>, ReactorReturnErr<Service, Method, Transform>, Selected, QueryFnData<Service, Method, Transform>, QueryKey>, "queryFn" | "queryKey"> {
22
- /** The method to call on the canister */
23
- functionName: Method;
24
- /** Arguments to pass to the method (if any) */
25
- args?: ReactorArgs<Service, Method, Transform>;
26
- /**
27
- * Call configuration for the method, as `Reactor.callMethod` takes it: a
28
- * `canisterId` sends the query to another canister of the same interface,
29
- * an `agent` sends it through another agent, `effectiveCanisterId` routes
30
- * it. The query key carries what it sets, as the hooks' keys do, so the
31
- * answer is cached apart from the reactor's own canister and agent, and
32
- * `getQueryKey()`, `invalidate()` and the other cache controls act on that
33
- * entry.
34
- *
35
- * @example
36
- * ```typescript
37
- * // The same ledger interface, another token's canister
38
- * const ckbtcSymbol = createQuery(ledger, {
39
- * functionName: "icrc1_symbol",
40
- * callConfig: { canisterId: "mxzaz-hqaaa-aaaar-qaada-cai" },
41
- * })
42
- * ```
43
- */
44
- callConfig?: CallConfig;
45
- /** The query key to use for this query */
46
- queryKey?: QueryKey;
47
- /**
48
- * How long data stays fresh before refetching, in milliseconds.
49
- *
50
- * `createQuery`, `createSuspenseQuery` and their factories default to 5
51
- * minutes. The bound `useActorQuery` and `useActorSuspenseQuery` hooks (from
52
- * `createActorHooks` or `defineReactor`) set no default and leave it to
53
- * TanStack Query, which reads the QueryClient's
54
- * `defaultOptions.queries.staleTime`. With that unset too, `useActorQuery`
55
- * uses 0 and `useActorSuspenseQuery` uses 1 second, TanStack Query's
56
- * fallback for suspense queries.
57
- */
58
- staleTime?: number;
59
- /** Transform the raw result before returning */
60
- select?: (data: QueryFnData<Service, Method, Transform>) => Selected;
61
- }
62
- /**
63
- * Configuration for createQuery (regular useQuery).
64
- * Alias for BaseQueryConfig for clarity.
65
- */
66
- export type QueryConfig<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", Selected = QueryFnData<Service, Method, Transform>> = BaseQueryConfig<Service, Method, Transform, Selected>;
67
- /**
68
- * Configuration for the non-suspense query hook of `createActorHooks` and
69
- * `defineReactor` (`useActorQuery`): a {@link QueryConfig} whose `args` may
70
- * also be TanStack Query's `skipToken`, for a query whose arguments are not
71
- * known yet.
72
- *
73
- * A skipped query does not fetch. It has an entry of its own under its
74
- * method's key (at the canister and agent `callConfig` names), which no
75
- * call's key shares, so it shows no data until the arguments arrive, not
76
- * even that of a call made without arguments. Once `args` holds arguments,
77
- * the query is keyed and fetched as usual. Its `refetch()` has nothing to
78
- * run: TanStack Query answers it with a "Missing queryFn" error, so offer a
79
- * refresh only once the arguments exist.
80
- *
81
- * The suspense hooks do not take `skipToken`: TanStack Query has no way to
82
- * suspend on a query that cannot run.
83
- *
84
- * @example
85
- * ```typescript
86
- * import { skipToken } from "@ic-reactor/react"
87
- *
88
- * function Balance({ owner }: { owner?: string }) {
89
- * // No `!`, no placeholder account, no `enabled`
90
- * const { data } = useActorQuery({
91
- * functionName: "icrc1_balance_of",
92
- * args: owner ? [{ owner }] : skipToken,
93
- * })
94
- * }
95
- * ```
96
- */
97
- export interface SkippableQueryConfig<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", Selected = QueryFnData<Service, Method, Transform>> extends Omit<QueryConfig<Service, Method, Transform, Selected>, "args"> {
98
- /**
99
- * Arguments to pass to the method, or `skipToken` while they are not
100
- * known: the query then waits without fetching.
101
- */
102
- args?: ReactorArgs<Service, Method, Transform> | SkipToken;
103
- }
104
- /**
105
- * Configuration for createSuspenseQuery (useSuspenseQuery).
106
- * Alias for BaseQueryConfig for clarity.
107
- */
108
- export type SuspenseQueryConfig<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", Selected = QueryFnData<Service, Method, Transform>> = BaseQueryConfig<Service, Method, Transform, Selected>;
109
- /**
110
- * Configuration for createQueryFactory (args are provided at call time).
111
- */
112
- export type QueryFactoryConfig<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", Selected = QueryFnData<Service, Method, Transform>> = Omit<QueryConfig<Service, Method, Transform, Selected>, "args">;
113
- /**
114
- * Configuration for createSuspenseQueryFactory (args are provided at call time).
115
- */
116
- export type SuspenseQueryFactoryConfig<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", Selected = QueryFnData<Service, Method, Transform>> = Omit<SuspenseQueryConfig<Service, Method, Transform, Selected>, "args">;
117
- /**
118
- * useQuery hook with chained select support.
119
- * - Without select: returns TSelected (from config.select)
120
- * - With select: chains on top and returns TFinal
121
- *
122
- * Accepts all useQuery options from React Query documentation.
123
- * Select is special: it chains on top of config.select.
124
- */
125
- export interface UseQueryWithSelect<TQueryFnData, TSelected = TQueryFnData, TError = Error> {
126
- (options?: Omit<UseQueryOptions<TQueryFnData, TError, TSelected>, "queryKey" | "queryFn"> & {
127
- select?: undefined;
128
- }): UseQueryResult<TSelected, TError>;
129
- <TFinal = TSelected>(options: Omit<UseQueryOptions<TQueryFnData, TError, TFinal>, "queryKey" | "queryFn" | "select"> & {
130
- select: (data: TSelected) => TFinal;
131
- }): UseQueryResult<TFinal, TError>;
132
- }
133
- /**
134
- * useSuspenseQuery hook with chained select support.
135
- * - Without select: returns TSelected (from config.select)
136
- * - With select: chains on top and returns TFinal
137
- *
138
- * Accepts all useSuspenseQuery options from React Query documentation.
139
- * Select is special: it chains on top of config.select.
140
- * Data is always defined (never undefined).
141
- * Does NOT support `enabled` option.
142
- */
143
- export interface UseSuspenseQueryWithSelect<TQueryFnData, TSelected = TQueryFnData, TError = Error> {
144
- (options?: Omit<UseSuspenseQueryOptions<TQueryFnData, TError, TSelected>, "queryKey" | "queryFn"> & {
145
- select?: undefined;
146
- }): UseSuspenseQueryResult<TSelected, TError>;
147
- <TFinal = TSelected>(options: Omit<UseSuspenseQueryOptions<TQueryFnData, TError, TFinal>, "queryKey" | "queryFn" | "select"> & {
148
- select: (data: TSelected) => TFinal;
149
- }): UseSuspenseQueryResult<TFinal, TError>;
150
- }
151
- /**
152
- * What `optimisticUpdate()` resolves with: the way back to the value the
153
- * cache held before the update.
154
- *
155
- * @example
156
- * ```typescript
157
- * const update = await postQuery.optimisticUpdate((post) => ({
158
- * ...post,
159
- * likes: post.likes + 1n,
160
- * }))
161
- * // The call failed: show the post as it was
162
- * update.rollback()
163
- * ```
164
- */
165
- export interface OptimisticRollback {
166
- /**
167
- * Write back the value the cache held before the update, with the time it
168
- * was fetched, so it is as fresh or as stale as it was. A value that was
169
- * invalidated is invalidated again, so a mounted query refetches it, as
170
- * the refetch the update cancelled would have.
171
- *
172
- * It does nothing when the update wrote nothing, or when another principal
173
- * has signed in or out since: the value was the previous principal's, and
174
- * the sign-in has already removed or refetched it. It restores that value
175
- * even if a fetch or another update has written since; invalidate the
176
- * query afterwards when the canister's current value matters.
177
- */
178
- rollback: () => void;
179
- }
180
- /**
181
- * The operations every query object has on its own cache entry, on the
182
- * reactor's QueryClient. They act on that one entry: other args of the same
183
- * method, and other queries under the same key prefix, are left alone.
184
- *
185
- * @template TQueryFnData - The raw (pre-`select`) data the entry holds
186
- */
187
- export interface QueryCacheControls<TQueryFnData> {
188
- /**
189
- * Cancel this query's fetch in flight, if there is one. The entry keeps
190
- * the value it held before that fetch started, and a later refetch runs as
191
- * usual.
192
- *
193
- * @example
194
- * ```typescript
195
- * // Before writing to the cache, so an older answer cannot land on top
196
- * await postQuery.cancel()
197
- * postQuery.setData(draft)
198
- * ```
199
- */
200
- cancel: () => Promise<void>;
201
- /**
202
- * Reset this query's entry to its initial state, as TanStack Query's
203
- * `resetQueries` does: its data is cleared, or goes back to `initialData`
204
- * when one was given. A mounted hook then fetches it again, and a suspense
205
- * hook suspends until it has. It resolves once that fetch settles.
206
- *
207
- * @example
208
- * ```typescript
209
- * // A reload button that shows the Suspense fallback again
210
- * <button onClick={() => void statsQuery.reset()}>Reload</button>
211
- * ```
212
- */
213
- reset: () => Promise<void>;
214
- /**
215
- * Replace this query's cached value for the duration of a mutation, and
216
- * get back a rollback for when it fails.
217
- *
218
- * It cancels the query's fetch in flight, so an answer from before the
219
- * mutation cannot overwrite the new value, then writes what `updater`
220
- * returns for the cached value. `updater` gets and returns the raw,
221
- * pre-`select` data. When nothing is cached yet it is not called, nothing
222
- * is cancelled or written, and `rollback()` does nothing: there is no
223
- * value on screen to update, and the query's own fetch will bring one. The
224
- * same goes when another principal signs in or out while it cancels, since
225
- * the cached value is then the previous principal's.
226
- *
227
- * The fetch it cancels may be a refetch an invalidation or a sign-in
228
- * started, so refetch the query once the mutation settles, with
229
- * `invalidate()` in `onSettled` or the query in `invalidateQueries`.
230
- *
231
- * Return it from `onMutate`, so the rollback reaches `onError`.
232
- *
233
- * @param updater - The new value, from the cached one. Do not mutate the
234
- * cached value in place; return a new one.
235
- *
236
- * @example
237
- * ```typescript
238
- * const getPost = createQueryFactory(backend, { functionName: "getPost" })
239
- * const likePost = createMutation(backend, { functionName: "likePost" })
240
- *
241
- * const { mutate } = likePost.useMutation({
242
- * onMutate: ([postId]) =>
243
- * getPost([postId]).optimisticUpdate((post) => ({
244
- * ...post,
245
- * likes: post.likes + 1n,
246
- * })),
247
- * onError: (_error, _args, update) => update?.rollback(),
248
- * // Refetch either way: a call that failed in transit may still have run
249
- * onSettled: (_data, _error, [postId]) => getPost([postId]).invalidate(),
250
- * })
251
- * ```
252
- */
253
- optimisticUpdate: (updater: (old: TQueryFnData) => TQueryFnData) => Promise<OptimisticRollback>;
254
- }
255
- /**
256
- * Base result interface shared between createQuery and createSuspenseQuery.
257
- *
258
- * @template TQueryFnData - The raw data type
259
- * @template TSelected - The type after select transformation
260
- * @template TError - The error type
261
- */
262
- export interface BaseQueryResult<TQueryFnData, TSelected = TQueryFnData, _TError = Error> extends QueryCacheControls<TQueryFnData> {
263
- /** Fetch data in loader (uses ensureQueryData for cache-first) */
264
- fetch: () => Promise<TSelected>;
265
- /**
266
- * Eagerly prefetch data into the cache without blocking.
267
- * Useful for preloading data before navigating to a route.
268
- *
269
- * Unlike `fetch()`, this returns a void promise so it can be fire-and-forget.
270
- * It never rejects: after a failed fetch the cached data is left as it was.
271
- *
272
- * A sign-in or sign-out while it is in flight cancels the fetch, so the
273
- * previous principal's answer is never cached, and it runs again for the
274
- * principal signed in, as `fetch()` does. When that run succeeds, the cache
275
- * holds that principal's answer by the time the promise resolves.
276
- *
277
- * @example
278
- * // In a route hover handler
279
- * button.addEventListener("mouseenter", () => userQuery.prefetch())
280
- */
281
- prefetch: () => Promise<void>;
282
- /** Invalidate the cache (refetches if query is active) */
283
- invalidate: () => Promise<void>;
284
- /** Get query key (for advanced React Query usage) */
285
- getQueryKey: () => QueryKey;
286
- /**
287
- * Read data directly from cache without fetching.
288
- * Returns undefined if data is not in cache.
289
- *
290
- * @template TFinal - Type returned after optional select transformation
291
- * @param select - Optional select function to transform cached data further
292
- * @returns Cached data with select applied, or undefined if not in cache
293
- *
294
- * @example
295
- * // Just get the cached data
296
- * const user = userQuery.getCacheData()
297
- *
298
- * // With additional select transformation
299
- * const name = userQuery.getCacheData((user) => user.name)
300
- */
301
- getCacheData: {
302
- (): TSelected | undefined;
303
- <TFinal>(select: (data: TSelected) => TFinal): TFinal | undefined;
304
- };
305
- /**
306
- * Write raw data directly into the cache (useful for optimistic updates).
307
- * Accepts a new value or an updater function that receives the current cached raw data.
308
- *
309
- * Note: The value is stored as raw (pre-select) data. Any active `select`
310
- * transformations are automatically re-applied by React Query on the next render.
311
- *
312
- * @example
313
- * // Optimistic update before a mutation
314
- * userQuery.setData({ id: "1", name: "Alice" })
315
- *
316
- * // Functional update
317
- * counterQuery.setData((prev) => (prev ?? 0) + 1)
318
- */
319
- setData: (updater: TQueryFnData | ((old: TQueryFnData | undefined) => TQueryFnData | undefined)) => TQueryFnData | undefined;
320
- }
321
- /**
322
- * Result from createQuery
323
- *
324
- * Includes useQuery hook that:
325
- * - Supports `enabled` option for conditional fetching
326
- * - Data may be `undefined` during loading
327
- * - Uses regular `useQuery` with manual loading state handling
328
- *
329
- * @template TQueryFnData - The raw data type
330
- * @template TSelected - The type after select transformation
331
- * @template TError - The error type
332
- */
333
- export interface QueryResult<TQueryFnData, TSelected = TQueryFnData, TError = Error> extends BaseQueryResult<TQueryFnData, TSelected, TError> {
334
- /** React hook for components - supports chained select and enabled option */
335
- useQuery: UseQueryWithSelect<TQueryFnData, TSelected, TError>;
336
- }
337
- /**
338
- * Result from createSuspenseQuery
339
- *
340
- * Includes useSuspenseQuery hook that:
341
- * - Requires wrapping in <Suspense> boundary
342
- * - Data is always defined (no undefined checks)
343
- * - Does NOT support `enabled` option
344
- *
345
- * @template TQueryFnData - The raw data type
346
- * @template TSelected - The type after select transformation
347
- * @template TError - The error type
348
- */
349
- export interface SuspenseQueryResult<TQueryFnData, TSelected = TQueryFnData, TError = Error> extends BaseQueryResult<TQueryFnData, TSelected, TError> {
350
- /** React hook for components - data is always defined (wrap in Suspense) */
351
- useSuspenseQuery: UseSuspenseQueryWithSelect<TQueryFnData, TSelected, TError>;
352
- }
353
- /**
354
- * The members every args-late query factory function carries
355
- * (`createQueryFactory`, `createSuspenseQueryFactory`,
356
- * `createInfiniteQueryFactory`, `createSuspenseInfiniteQueryFactory`).
357
- *
358
- * A factory makes one query per set of args, so there was no key to name all
359
- * of them: invalidating a list after a mutation meant keeping the args of each
360
- * instance around. These address every query the factory returns at once.
361
- */
362
- export interface QueryFactoryMethods {
363
- /**
364
- * The key prefix every query of this factory shares, whatever its args: the
365
- * canister (the config's `callConfig.canisterId`, else the reactor's) and
366
- * the method, plus the reactor's transform segment and any agent or
367
- * effective-target segment the config's `callConfig` adds, and for an
368
- * infinite factory its config `queryKey`. TanStack Query matches keys by
369
- * prefix, so the prefix covers every args instance and every infinite page
370
- * set. Queries of the same method made elsewhere share it too.
371
- *
372
- * @example
373
- * ```typescript
374
- * const getBalance = createQueryFactory(ledger, {
375
- * functionName: "icrc1_balance_of",
376
- * })
377
- *
378
- * // Every cached balance, whatever the account
379
- * ledger.queryClient.getQueriesData({ queryKey: getBalance.getQueryKey() })
380
- * ```
381
- */
382
- getQueryKey: () => QueryKey;
383
- /**
384
- * Invalidate every query of this factory, whatever its args, on the
385
- * reactor's QueryClient. It resolves once the active ones have refetched; a
386
- * refetch that fails does not reject it.
387
- *
388
- * @example
389
- * ```typescript
390
- * // After a transfer, refresh every balance on screen
391
- * await getBalance.invalidate()
392
- * ```
393
- */
394
- invalidate: () => Promise<void>;
395
- }
396
- /**
397
- * The function `createQueryFactory` and `createSuspenseQueryFactory` return:
398
- * called with args it returns the query object for them, the same object for
399
- * the same args, and it also carries {@link QueryFactoryMethods}.
400
- *
401
- * @template TArgs - The method's arguments
402
- * @template TQuery - The query object it returns
403
- *
404
- * @example
405
- * ```typescript
406
- * const getPost = createQueryFactory(backend, { functionName: "get_post" })
407
- *
408
- * // One post's query object
409
- * const { data } = getPost([postId]).useQuery()
410
- *
411
- * // Every post's, whatever its args
412
- * await getPost.invalidate()
413
- * ```
414
- */
415
- export interface QueryFactoryFn<TArgs, TQuery> extends QueryFactoryMethods {
416
- (args: TArgs): TQuery;
417
- }
418
- /**
419
- * What a query factory returns for `skipToken`: the query's `useQuery` hook
420
- * alone, which renders a query that waits without fetching.
421
- *
422
- * The imperative members are left out because there is no call to make or
423
- * entry to read until the args are known: narrow to the args first to reach
424
- * `fetch()`, `invalidate()` or the cache controls.
425
- *
426
- * @template TQuery - The query object the factory returns for args
427
- *
428
- * @example
429
- * ```typescript
430
- * const getBalance = createQueryFactory(ledger, {
431
- * functionName: "icrc1_balance_of",
432
- * })
433
- *
434
- * // A SkippedQuery: only useQuery(), which does not fetch
435
- * const { data } = getBalance(skipToken).useQuery()
436
- * ```
437
- */
438
- export type SkippedQuery<TQuery extends {
439
- useQuery: unknown;
440
- }> = Pick<TQuery, "useQuery">;
441
- /**
442
- * The function `createQueryFactory` returns: a {@link QueryFactoryFn} that
443
- * also takes TanStack Query's `skipToken` in place of args, for a component
444
- * whose args are not known yet. For `skipToken` it returns a
445
- * {@link SkippedQuery}, whose `useQuery()` waits without fetching, in an
446
- * entry of its own under the factory's `getQueryKey()` prefix. Given
447
- * `args ? [args] : skipToken`, it returns either, and `useQuery()` can be
448
- * called on the result directly.
449
- *
450
- * `createSuspenseQueryFactory` returns a plain {@link QueryFactoryFn}: a
451
- * suspense query cannot wait on `skipToken`.
452
- *
453
- * @template TArgs - The method's arguments
454
- * @template TQuery - The query object it returns for args
455
- *
456
- * @example
457
- * ```typescript
458
- * const getBalance = createQueryFactory(ledger, {
459
- * functionName: "icrc1_balance_of",
460
- * })
461
- *
462
- * function Balance({ owner }: { owner?: string }) {
463
- * const { data } = getBalance(owner ? [{ owner }] : skipToken).useQuery()
464
- * }
465
- * ```
466
- */
467
- export interface SkippableQueryFactoryFn<TArgs, TQuery extends {
468
- useQuery: unknown;
469
- }> extends QueryFactoryMethods {
470
- (args: TArgs): TQuery;
471
- (args: SkipToken): SkippedQuery<TQuery>;
472
- (args: TArgs | SkipToken): TQuery | SkippedQuery<TQuery>;
473
- (args: TArgs): TQuery;
474
- }
475
- /**
476
- * Anything that knows the key of its queries: a query object from
477
- * `createQuery`, `createSuspenseQuery`, `createInfiniteQuery` or
478
- * `createSuspenseInfiniteQuery` (factory instances included), or a query
479
- * factory function, whose key covers every query it returns.
480
- *
481
- * @example
482
- * ```typescript
483
- * const postsQuery = createQuery(backend, { functionName: "get_posts" })
484
- * const getPost = createQueryFactory(backend, { functionName: "get_post" })
485
- *
486
- * // Both are key sources, so both go straight into invalidateQueries
487
- * createMutation(backend, {
488
- * functionName: "create_post",
489
- * invalidateQueries: [postsQuery, getPost],
490
- * })
491
- * ```
492
- */
493
- export interface QueryKeySource {
494
- /** The key, or key prefix, of the queries it names. */
495
- getQueryKey: () => QueryKey;
496
- /**
497
- * Invalidate those queries on the QueryClient they are cached in.
498
- * `invalidateQueries` calls it when it is there, so a query of another
499
- * reactor with a QueryClient of its own is invalidated in that client. The
500
- * key goes to the mutation's reactor's QueryClient otherwise.
501
- */
502
- invalidate?: () => Promise<void>;
503
- }
504
- /**
505
- * A method of the mutation's own reactor, and optionally one set of its
506
- * arguments: the same shape `Reactor.invalidateQueries` takes. Its key is
507
- * built by the reactor's `generateQueryKey` when the mutation succeeds, so it
508
- * follows a `setCanisterId` and carries the reactor's transform segment. It
509
- * is rooted at the canister the mutation was sent to: the reactor's, or the
510
- * one the mutation's `callConfig.canisterId` names.
511
- *
512
- * Without `args` it names every query of the method, whatever its args,
513
- * infinite queries included. With `args` it names the queries made with those
514
- * args by `createQuery`, a query factory or the hooks, and `args: []` names a
515
- * method without parameters as no `args` does. An infinite query keys its
516
- * page set by its first page's args in another form, which `args` does not
517
- * match, and a query of another canister than the mutation's is keyed apart:
518
- * name either by its query object or key instead.
519
- *
520
- * @example
521
- * ```typescript
522
- * invalidateQueries: [
523
- * { functionName: "get_posts" },
524
- * { functionName: "get_post", args: [postId] },
525
- * ]
526
- * ```
527
- */
528
- export type QueryDescriptor<Service = BaseActor, Transform extends TransformKey = "candid"> = {
529
- [Method in FunctionName<Service>]: {
530
- /** The method whose queries to name */
531
- functionName: Method;
532
- /** The arguments of the one query to name; omit for every query of the method */
533
- args?: ReactorArgs<Service, Method, Transform>;
534
- };
535
- }[FunctionName<Service>];
536
- /**
537
- * One entry of `invalidateQueries`: which queries a successful mutation
538
- * invalidates.
539
- *
540
- * - a query key, as `generateQueryKey` or `getQueryKey()` builds it;
541
- * - a query object or query factory ({@link QueryKeySource});
542
- * - a method of the mutation's own reactor, with or without args
543
- * ({@link QueryDescriptor});
544
- * - `undefined`, which is skipped, so `[maybeQuery]` and
545
- * `[maybeQuery?.getQueryKey()]` are safe when the query is absent.
546
- *
547
- * TanStack Query matches each key by prefix.
548
- *
549
- * @example
550
- * ```typescript
551
- * createMutation(backend, {
552
- * functionName: "create_post",
553
- * invalidateQueries: [
554
- * postsQuery, // a query object
555
- * getPost, // a query factory: every post, whatever its args
556
- * { functionName: "get_posts_count" }, // a method of this reactor
557
- * ],
558
- * })
559
- * ```
560
- */
561
- export type InvalidationTarget<Service = BaseActor, Transform extends TransformKey = "candid"> = QueryKey | QueryKeySource | QueryDescriptor<Service, Transform> | undefined;
562
- /**
563
- * Configuration for createMutation and useActorMutation.
564
- *
565
- * @template TOnMutateResult - The value `onMutate` returns, which `onSuccess`,
566
- * `onError` and `onSettled` receive. TypeScript infers it from `onMutate`.
567
- */
568
- export interface MutationConfig<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", TOnMutateResult = unknown> extends Omit<UseMutationOptions<ReactorReturnOk<Service, Method, Transform>, ReactorReturnErr<Service, Method, Transform>, ReactorArgs<Service, Method, Transform>, TOnMutateResult>, "mutationFn"> {
569
- /** The method to call on the canister */
570
- functionName: Method;
571
- /** Call configuration for the actor method */
572
- callConfig?: CallConfig;
573
- /**
574
- * Queries to invalidate upon successful mutation, before `onSuccess` runs.
575
- * The mutation stays pending until the invalidated queries in use have
576
- * refetched, so `onSuccess` reads the refetched data.
577
- *
578
- * Each entry is a query key, a query object or query factory, or a
579
- * `{ functionName, args? }` method of this mutation's reactor; see
580
- * {@link InvalidationTarget}. `undefined` entries are skipped, so
581
- * `[maybeQuery]` is safe when the optional query object is absent.
582
- *
583
- * @example
584
- * ```typescript
585
- * invalidateQueries: [getPosts, { functionName: "get_posts_count" }]
586
- * ```
587
- */
588
- invalidateQueries?: InvalidationTarget<Service, Transform>[];
589
- /**
590
- * Callback for canister-level business logic errors.
591
- * Called when the canister returns a Result { Err: E } variant.
592
- *
593
- * This is separate from `onError` which handles all errors including
594
- * network failures, agent errors, etc.
595
- *
596
- * @param error - The CanisterError containing the typed error value
597
- * @param variables - The arguments passed to the mutation
598
- *
599
- * @example
600
- * ```typescript
601
- * createMutation(reactor, {
602
- * functionName: "transfer",
603
- * onCanisterError: (error, variables) => {
604
- * // error.err contains the typed Err value
605
- * // error.code contains the variant key (e.g., "InsufficientFunds")
606
- * console.error(`Transfer failed: ${error.code}`, error.err)
607
- * },
608
- * })
609
- * ```
610
- */
611
- onCanisterError?: (error: CanisterError<TransformReturnRegistry<ErrResult<ActorMethodReturnType<Service[Method]>>, Service>[Transform]>, variables: ReactorArgs<Service, Method, Transform>) => void;
612
- }
613
- /**
614
- * Configuration for createMutationFactory.
615
- */
616
- export type MutationFactoryConfig<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", TOnMutateResult = unknown> = Omit<MutationConfig<Service, Method, Transform, TOnMutateResult>, "onSuccess">;
617
- /**
618
- * Options for useMutation hook.
619
- * Extends React Query's UseMutationOptions with invalidateQueries support.
620
- *
621
- * @template TOnMutateResult - The value `onMutate` returns, which `onSuccess`,
622
- * `onError` and `onSettled` receive. TypeScript infers it from `onMutate`.
623
- */
624
- export interface MutationHookOptions<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid", TOnMutateResult = unknown> extends Omit<UseMutationOptions<ReactorReturnOk<Service, Method, Transform>, ReactorReturnErr<Service, Method, Transform>, ReactorArgs<Service, Method, Transform>, TOnMutateResult>, "mutationFn"> {
625
- /**
626
- * Queries to invalidate upon successful mutation, after the factory's own
627
- * `invalidateQueries` and before `onSuccess`. Takes the same entries:
628
- * a query key, a query object or query factory, or a
629
- * `{ functionName, args? }` method of the mutation's reactor; see
630
- * {@link InvalidationTarget}.
631
- *
632
- * @example
633
- * const balanceQuery = getIcpBalance([account])
634
- * useMutation({
635
- * invalidateQueries: [balanceQuery],
636
- * })
637
- */
638
- invalidateQueries?: InvalidationTarget<Service, Transform>[];
639
- /**
640
- * Callback for canister-level business logic errors.
641
- * Called when the canister returns a Result { Err: E } variant.
642
- *
643
- * @param error - The CanisterError containing the typed error value
644
- * @param variables - The arguments passed to the mutation
645
- */
646
- onCanisterError?: (error: CanisterError<TransformReturnRegistry<ErrResult<ActorMethodReturnType<Service[Method]>>, Service>[Transform]>, variables: ReactorArgs<Service, Method, Transform>) => void;
647
- }
648
- /**
649
- * Result from createMutation.
650
- */
651
- export interface MutationResult<Service = BaseActor, Method extends FunctionName<Service> = FunctionName<Service>, Transform extends TransformKey = "candid"> {
652
- /**
653
- * React hook for the mutation.
654
- * Accepts options to override/extend the factory config.
655
- *
656
- * @example
657
- * // With invalidateQueries to auto-update balance after transfer
658
- * const { mutate } = icpTransferMutation.useMutation({
659
- * invalidateQueries: [userBalanceQuery], // Auto-invalidate after success!
660
- * })
661
- */
662
- useMutation: <TOnMutateResult = unknown>(options?: MutationHookOptions<Service, Method, Transform, TOnMutateResult>) => UseMutationResult<ReactorReturnOk<Service, Method, Transform>, ReactorReturnErr<Service, Method, Transform>, ReactorArgs<Service, Method, Transform>, TOnMutateResult>;
663
- /**
664
- * Execute the update call outside React. It runs in the QueryClient's
665
- * MutationCache with the factory's options and callbacks, as `useMutation()`
666
- * does without hook options. It resolves with the method's result and
667
- * rejects with the call's error.
668
- */
669
- execute: (args: ReactorArgs<Service, Method, Transform>) => Promise<ReactorReturnOk<Service, Method, Transform>>;
670
- }
671
- //# sourceMappingURL=types.d.ts.map