@ic-reactor/react 3.13.0 → 4.0.0-beta.1

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 +234 -787
  2. package/dist/index.d.ts +259 -16
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +470 -23
  5. package/dist/index.js.map +1 -1
  6. package/llms.txt +80 -278
  7. package/package.json +11 -39
  8. package/src/index.tsx +611 -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
@@ -1,304 +0,0 @@
1
- /**
2
- * Suspense Query Factory - Generic wrapper for React Suspense-based canister data
3
- *
4
- * Creates unified fetch/hook/invalidate functions for any canister method.
5
- * Works with any Reactor instance.
6
- *
7
- * Uses `useSuspenseQuery` which:
8
- * - Requires wrapping in <Suspense> boundary
9
- * - Data is always defined (no undefined checks)
10
- * - Does NOT support `enabled` option
11
- *
12
- * @example
13
- * const userQuery = createSuspenseQuery(todoManager, {
14
- * functionName: "get_user",
15
- * select: (result) => result.user,
16
- * })
17
- *
18
- * // In component (wrap in Suspense)
19
- * const { data: user } = userQuery.useSuspenseQuery() // data is never undefined!
20
- */
21
-
22
- import type {
23
- Reactor,
24
- FunctionName,
25
- ReactorArgs,
26
- TransformKey,
27
- } from "@ic-reactor/core"
28
- import { useMemo } from "react"
29
- import { useSuspenseQuery } from "@tanstack/react-query"
30
- import type {
31
- QueryFnData,
32
- QueryError,
33
- SuspenseQueryConfig,
34
- UseSuspenseQueryWithSelect,
35
- SuspenseQueryResult,
36
- SuspenseQueryFactoryConfig,
37
- QueryFactoryFn,
38
- NoInfer,
39
- } from "./types.js"
40
- import {
41
- buildChainedSelect,
42
- createBoundedCache,
43
- mountWhileSuspended,
44
- pickFetchOptions,
45
- queryCacheControls,
46
- retryOption,
47
- useMountQueryClient,
48
- withQueryFactoryMethods,
49
- } from "./utils.js"
50
-
51
- // ============================================================================
52
- // Internal Implementation
53
- // ============================================================================
54
-
55
- const createSuspenseQueryImpl = <
56
- Service,
57
- Method extends FunctionName<Service> = FunctionName<Service>,
58
- Transform extends TransformKey = "candid",
59
- Selected = QueryFnData<Service, Method, Transform>,
60
- >(
61
- reactor: Reactor<Service, Transform>,
62
- config: SuspenseQueryConfig<Service, Method, Transform, Selected>
63
- ): SuspenseQueryResult<
64
- QueryFnData<Service, Method, Transform>,
65
- Selected,
66
- QueryError<Service, Method, Transform>
67
- > => {
68
- type TData = QueryFnData<Service, Method, Transform>
69
- type TError = QueryError<Service, Method, Transform>
70
-
71
- const {
72
- functionName,
73
- args,
74
- callConfig,
75
- staleTime = 5 * 60 * 1000,
76
- select,
77
- queryKey: customQueryKey,
78
- ...rest
79
- } = config
80
-
81
- // `callConfig` goes wherever the hooks send it: to the call and into the
82
- // key, so a query of another canister or agent has an entry of its own.
83
- const params = { functionName, args, queryKey: customQueryKey, callConfig }
84
-
85
- const getQueryKey = () => reactor.generateQueryKey(params, callConfig)
86
-
87
- const applySelect = (raw: TData): Selected =>
88
- select ? select(raw) : (raw as unknown as Selected)
89
-
90
- // How the query function runs, shared with the hook; see pickFetchOptions.
91
- const fetchOptions = pickFetchOptions(rest)
92
-
93
- /** Cache-first fetch for use in loaders / route preloading. */
94
- const fetch = async (): Promise<Selected> => {
95
- // Through the reactor rather than straight to the QueryClient: overriding
96
- // `fetchQuery` in a Reactor subclass is a documented way to add logic to
97
- // every factory fetch.
98
- const result = await reactor.fetchQuery(params, fetchOptions)
99
- return applySelect(result)
100
- }
101
-
102
- /** Fire-and-forget prefetch — warms the cache without blocking. */
103
- const prefetch = (): Promise<void> => {
104
- const baseOptions = reactor.getQueryOptions(params)
105
- // Runs again when a sign-in or sign-out cancels it, and never rejects;
106
- // see `prefetch` in createQuery.
107
- return reactor.clientManager
108
- .fetchAcrossIdentitySwitch(() =>
109
- reactor.queryClient.prefetchQuery({
110
- ...fetchOptions,
111
- // An update method's default `retry`; see `Reactor.getQueryRetry`.
112
- ...retryOption(fetchOptions.retry, baseOptions.retry),
113
- queryKey: baseOptions.queryKey,
114
- queryFn: baseOptions.queryFn,
115
- staleTime,
116
- })
117
- )
118
- .catch(() => undefined)
119
- }
120
-
121
- const useSuspenseQueryHook: UseSuspenseQueryWithSelect<
122
- TData,
123
- Selected,
124
- TError
125
- > = (options: any): any => {
126
- useMountQueryClient(reactor.queryClient)
127
- const baseOptions = reactor.getQueryOptions(params)
128
- // Memoized so the observer's select-result cache can hit; see
129
- // buildChainedSelect. `select` comes from the factory config and is stable.
130
- const chainedSelect = useMemo(
131
- () => buildChainedSelect(select, options?.select),
132
- [options?.select]
133
- )
134
- try {
135
- return useSuspenseQuery(
136
- {
137
- queryKey: baseOptions.queryKey,
138
- staleTime,
139
- ...rest,
140
- ...options,
141
- queryFn: baseOptions.queryFn,
142
- select: chainedSelect,
143
- // The hook's `retry`, else the config's, else an update method's
144
- // default; see `Reactor.getQueryRetry`.
145
- ...retryOption(options?.retry ?? rest.retry, baseOptions.retry),
146
- },
147
- reactor.queryClient
148
- )
149
- } catch (thrown) {
150
- mountWhileSuspended(reactor.queryClient, thrown)
151
- throw thrown
152
- }
153
- }
154
-
155
- const invalidate = async (): Promise<void> => {
156
- await reactor.queryClient.invalidateQueries({ queryKey: getQueryKey() })
157
- }
158
-
159
- const getCacheData: SuspenseQueryResult<
160
- TData,
161
- Selected,
162
- TError
163
- >["getCacheData"] = (selectFn?: (data: Selected) => unknown): any => {
164
- const raw = reactor.getQueryData(params, callConfig)
165
- if (raw === undefined) return undefined
166
- const selected = applySelect(raw)
167
- return selectFn ? selectFn(selected) : selected
168
- }
169
-
170
- const setData: SuspenseQueryResult<TData, Selected, TError>["setData"] = (
171
- updater
172
- ) => {
173
- return reactor.queryClient.setQueryData(getQueryKey(), updater as any) as
174
- TData | undefined
175
- }
176
-
177
- return {
178
- fetch,
179
- prefetch,
180
- useSuspenseQuery: useSuspenseQueryHook,
181
- invalidate,
182
- getQueryKey,
183
- getCacheData,
184
- setData,
185
- ...queryCacheControls<TData>(reactor, getQueryKey),
186
- }
187
- }
188
-
189
- // ============================================================================
190
- // Public Factory Function
191
- // ============================================================================
192
-
193
- export function createSuspenseQuery<
194
- Service,
195
- Transform extends TransformKey,
196
- Method extends FunctionName<Service> = FunctionName<Service>,
197
- Selected = QueryFnData<Service, Method, Transform>,
198
- >(
199
- reactor: Reactor<Service, Transform>,
200
- config: SuspenseQueryConfig<NoInfer<Service>, Method, Transform, Selected>
201
- ): SuspenseQueryResult<
202
- QueryFnData<Service, Method, Transform>,
203
- Selected,
204
- QueryError<Service, Method, Transform>
205
- > {
206
- return createSuspenseQueryImpl(
207
- reactor,
208
- config as SuspenseQueryConfig<Service, Method, Transform, Selected>
209
- )
210
- }
211
-
212
- // ============================================================================
213
- // Convenience: Create suspense query with dynamic args
214
- // ============================================================================
215
-
216
- /**
217
- * Create a suspense query factory: a function that takes the method's args
218
- * and returns the suspense query object for them, the same object for the
219
- * same args.
220
- *
221
- * The function also has `getQueryKey()`, the key prefix every query it
222
- * returns shares, and `invalidate()`, which invalidates all of them whatever
223
- * their args. Pass the function itself to a mutation's `invalidateQueries` to
224
- * refresh every instance after the mutation.
225
- *
226
- * @example
227
- * const getBalance = createSuspenseQueryFactory(ledger, {
228
- * functionName: "icrc1_balance_of",
229
- * })
230
- *
231
- * // In a component under <Suspense>
232
- * const { data } = getBalance([{ owner, subaccount: [] }]).useSuspenseQuery()
233
- *
234
- * // Refetch every account's balance
235
- * await getBalance.invalidate()
236
- */
237
- export function createSuspenseQueryFactory<
238
- Service,
239
- Transform extends TransformKey,
240
- Method extends FunctionName<Service> = FunctionName<Service>,
241
- Selected = QueryFnData<Service, Method, Transform>,
242
- >(
243
- reactor: Reactor<Service, Transform>,
244
- config: SuspenseQueryFactoryConfig<
245
- NoInfer<Service>,
246
- Method,
247
- Transform,
248
- Selected
249
- >
250
- ): QueryFactoryFn<
251
- ReactorArgs<Service, Method, Transform>,
252
- SuspenseQueryResult<
253
- QueryFnData<Service, Method, Transform>,
254
- Selected,
255
- QueryError<Service, Method, Transform>
256
- >
257
- > {
258
- const cache =
259
- createBoundedCache<
260
- SuspenseQueryResult<
261
- QueryFnData<Service, Method, Transform>,
262
- Selected,
263
- QueryError<Service, Method, Transform>
264
- >
265
- >()
266
-
267
- const factory = (args: ReactorArgs<Service, Method, Transform>) => {
268
- const key = reactor.generateQueryKey(
269
- { functionName: config.functionName as Method, args },
270
- config.callConfig
271
- )
272
- const cacheKey = JSON.stringify(key)
273
-
274
- const existing = cache.get(cacheKey)
275
- if (existing) return existing
276
-
277
- const result = createSuspenseQueryImpl<
278
- Service,
279
- Method,
280
- Transform,
281
- Selected
282
- >(reactor, {
283
- ...(config as SuspenseQueryFactoryConfig<
284
- Service,
285
- Method,
286
- Transform,
287
- Selected
288
- >),
289
- args,
290
- })
291
- cache.set(cacheKey, result)
292
- return result
293
- }
294
-
295
- // The method's own prefix, at the canister and agent the config's
296
- // `callConfig` names. A config `queryKey` follows the args segment in every
297
- // instance's key, so it cannot narrow the prefix.
298
- return withQueryFactoryMethods(factory, reactor, () =>
299
- reactor.generateQueryKey(
300
- { functionName: config.functionName as Method },
301
- config.callConfig
302
- )
303
- )
304
- }
@@ -1,62 +0,0 @@
1
- import { DisplayReactor } from "@ic-reactor/core"
2
- import type { BaseActor, DisplayReactorParameters } from "@ic-reactor/core"
3
- import { defineReactorWith } from "./defineReactorShared.js"
4
- import type {
5
- DefineReactorSharedParameters,
6
- DefineReactorResult,
7
- } from "./defineReactorShared.js"
8
-
9
- /** Options for {@link defineDisplayReactor}: `defineReactor`'s, plus validators. */
10
- export interface DefineDisplayReactorOptions<
11
- Service,
12
- > extends DefineReactorSharedParameters {
13
- /** Optional initial argument validators (receive display types). */
14
- validators?: DisplayReactorParameters<Service>["validators"]
15
- }
16
-
17
- /**
18
- * One-call bootstrap for a {@link DisplayReactor} and its React hooks: the
19
- * display counterpart of `defineReactor`, taking the same options.
20
- *
21
- * A DisplayReactor takes and returns UI-friendly values — text for
22
- * `Principal`, `nat`, `int` and 64-bit integers, hex for blobs — which suits
23
- * forms and components. Its codecs are built on zod, so this adds zod to the
24
- * bundle. `defineReactor`, which builds a plain `Reactor` with raw Candid
25
- * values, does not need zod, but until its deprecated `display` flag is removed
26
- * at the next major it bundles zod anyway; `createActorHooks(new Reactor(...))`
27
- * is the setup without it.
28
- *
29
- * Replaces `defineReactor({ display: true })`, which is deprecated.
30
- *
31
- * @example
32
- * ```typescript
33
- * import { defineDisplayReactor } from "@ic-reactor/react"
34
- * import { idlFactory, type _SERVICE } from "./declarations/backend"
35
- *
36
- * export const { reactor, useActorQuery, useActorMutation, useAuth } =
37
- * defineDisplayReactor<_SERVICE>({
38
- * name: "backend",
39
- * idlFactory,
40
- * canisterId: "rrkah-fqaaa-aaaaa-aaaaq-cai",
41
- * })
42
- *
43
- * function Balance() {
44
- * // `nat` arrives as text, ready to render.
45
- * const { data } = useActorQuery({ functionName: "get_balance" })
46
- * return <span>{data}</span>
47
- * }
48
- * ```
49
- */
50
- export function defineDisplayReactor<Service = BaseActor>(
51
- params: DefineDisplayReactorOptions<Service>
52
- ): DefineReactorResult<Service, "display", DisplayReactor<Service>> {
53
- return defineReactorWith<Service, "display", DisplayReactor<Service>>(
54
- "defineDisplayReactor",
55
- params,
56
- (config) =>
57
- new DisplayReactor<Service>({
58
- ...config,
59
- validators: params.validators,
60
- })
61
- )
62
- }
@@ -1,142 +0,0 @@
1
- // DisplayReactor is only for the deprecated `display: true` path. It is what
2
- // puts DisplayReactor and zod in every bundle that uses defineReactor; drop it
3
- // with that path.
4
- import { DisplayReactor, Reactor } from "@ic-reactor/core"
5
- import type { BaseActor } from "@ic-reactor/core"
6
- import { defineReactorWith } from "./defineReactorShared.js"
7
- import type {
8
- DefineReactorSharedParameters,
9
- DefineReactorResult,
10
- } from "./defineReactorShared.js"
11
- import type { DefineDisplayReactorOptions } from "./defineDisplayReactor.js"
12
-
13
- export type {
14
- DefineReactorSharedParameters,
15
- DefineReactorResult,
16
- } from "./defineReactorShared.js"
17
-
18
- /** Parameters for a standard (raw Candid types) reactor. */
19
- export interface DefineReactorParameters extends DefineReactorSharedParameters {
20
- display?: false
21
- }
22
-
23
- /**
24
- * Parameters for `defineReactor({ display: true })`.
25
- *
26
- * @deprecated Call `defineDisplayReactor` with the same options, without
27
- * `display`: see {@link DefineDisplayReactorOptions}.
28
- */
29
- export interface DefineDisplayReactorParameters<
30
- Service,
31
- > extends DefineDisplayReactorOptions<Service> {
32
- /**
33
- * @deprecated Use `defineDisplayReactor(...)` instead of
34
- * `defineReactor({ display: true, ... })`. The flag keeps working until the
35
- * next major, but it makes every bundle that calls `defineReactor` carry
36
- * `DisplayReactor` and zod, even when it never sets the flag.
37
- */
38
- display: true
39
- }
40
-
41
- /**
42
- * The `display: true` form: builds a DisplayReactor and its hooks.
43
- *
44
- * @deprecated `defineReactor({ display: true })` is deprecated: pass the same
45
- * options, without `display`, to `defineDisplayReactor(...)`. Only this form
46
- * is; `defineReactor` without `display` builds a plain `Reactor` and is not
47
- * deprecated. The flag keeps working until the next major, but it makes every
48
- * bundle that calls `defineReactor` carry `DisplayReactor` and zod, even when
49
- * it never sets the flag.
50
- */
51
- export function defineReactor<Service = BaseActor>(
52
- params: DefineDisplayReactorParameters<Service>
53
- ): DefineReactorResult<Service, "display", DisplayReactor<Service>>
54
-
55
- /**
56
- * One-call bootstrap for a canister reactor + its React hooks.
57
- *
58
- * Collapses the four manual steps (QueryClient → ClientManager → Reactor →
59
- * createActorHooks) into a single call. It builds a `Reactor`, which takes and
60
- * returns raw Candid values; `defineDisplayReactor` takes the same options and
61
- * builds a `DisplayReactor` for UI-friendly ones.
62
- * Use this when one-call bootstrap is enough. If you need reusable
63
- * method-specific operations outside React, compose with query/mutation
64
- * factories after setup.
65
- *
66
- * @example
67
- * ```typescript
68
- * import { defineReactor } from "@ic-reactor/react"
69
- * import { idlFactory, type _SERVICE } from "./declarations/backend"
70
- *
71
- * const { reactor, useActorQuery, useActorMutation } = defineReactor<_SERVICE>({
72
- * name: "backend",
73
- * idlFactory,
74
- * canisterId: "rrkah-fqaaa-aaaaa-aaaaq-cai",
75
- * })
76
- *
77
- * function Profile() {
78
- * const { data } = useActorQuery({ functionName: "get_profile" })
79
- * return <div>{data?.name}</div>
80
- * }
81
- * ```
82
- *
83
- * @example Reuse an existing ClientManager (multiple canisters share one agent)
84
- * ```typescript
85
- * const ledger = defineReactor<_LEDGER>({
86
- * name: "ledger",
87
- * idlFactory: ledgerIdl,
88
- * canisterId: "ryjl3-tyaaa-aaaaa-aaaba-cai",
89
- * })
90
- * const index = defineReactor<_INDEX>({
91
- * name: "index",
92
- * idlFactory: indexIdl,
93
- * canisterId: "qhbym-qaaaa-aaaaa-aaafq-cai",
94
- * clientManager: ledger.clientManager,
95
- * authentication: ledger.authentication, // one Internet Identity session
96
- * })
97
- * ```
98
- *
99
- * @example Internet Identity is wired up out of the box
100
- * ```typescript
101
- * const { useAuth, useIdentityAttributes } = defineReactor<_SERVICE>({
102
- * name: "backend",
103
- * idlFactory,
104
- * canisterId: "rrkah-fqaaa-aaaaa-aaaaq-cai",
105
- * // Needed when the app is served from more than one origin.
106
- * auth: { derivationOrigin: "https://app.example.com" },
107
- * })
108
- *
109
- * function LoginButton() {
110
- * const { login, logout, isAuthenticated, principal } = useAuth()
111
- * return isAuthenticated
112
- * ? <button onClick={() => logout()}>{principal?.toText()}</button>
113
- * : <button onClick={() => login()}>Sign in</button>
114
- * }
115
- * ```
116
- */
117
- export function defineReactor<Service = BaseActor>(
118
- params: DefineReactorParameters
119
- ): DefineReactorResult<Service, "candid", Reactor<Service, "candid">>
120
-
121
- export function defineReactor<Service = BaseActor>(
122
- params: DefineReactorParameters | DefineDisplayReactorParameters<Service>
123
- ):
124
- | DefineReactorResult<Service, "display", DisplayReactor<Service>>
125
- | DefineReactorResult<Service, "candid", Reactor<Service, "candid">> {
126
- if (params.display) {
127
- // What defineDisplayReactor builds, but under this function's name, so an
128
- // error names the call the app actually made.
129
- const { validators } = params
130
- return defineReactorWith<Service, "display", DisplayReactor<Service>>(
131
- "defineReactor",
132
- params,
133
- (config) => new DisplayReactor<Service>({ ...config, validators })
134
- )
135
- }
136
-
137
- return defineReactorWith<Service, "candid", Reactor<Service, "candid">>(
138
- "defineReactor",
139
- params,
140
- (config) => new Reactor<Service>(config)
141
- )
142
- }