@ic-reactor/react 3.12.4 → 3.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +410 -44
  2. package/dist/auth/auth-client-compat.d.ts +122 -0
  3. package/dist/auth/auth-client-compat.d.ts.map +1 -0
  4. package/dist/auth/auth-client-compat.js +162 -0
  5. package/dist/auth/auth-client-compat.js.map +1 -0
  6. package/dist/auth/authentication-manager.d.ts +287 -5
  7. package/dist/auth/authentication-manager.d.ts.map +1 -1
  8. package/dist/auth/authentication-manager.js +920 -150
  9. package/dist/auth/authentication-manager.js.map +1 -1
  10. package/dist/auth/createIdentityAttributeHooks.d.ts.map +1 -1
  11. package/dist/auth/createIdentityAttributeHooks.js +36 -20
  12. package/dist/auth/createIdentityAttributeHooks.js.map +1 -1
  13. package/dist/auth/identity-attributes-manager.d.ts +2 -1
  14. package/dist/auth/identity-attributes-manager.d.ts.map +1 -1
  15. package/dist/auth/identity-attributes-manager.js +90 -6
  16. package/dist/auth/identity-attributes-manager.js.map +1 -1
  17. package/dist/auth/identity-attributes.d.ts.map +1 -1
  18. package/dist/auth/identity-attributes.js +57 -0
  19. package/dist/auth/identity-attributes.js.map +1 -1
  20. package/dist/auth/local-ii-probe.d.ts +12 -1
  21. package/dist/auth/local-ii-probe.d.ts.map +1 -1
  22. package/dist/auth/local-ii-probe.js +22 -3
  23. package/dist/auth/local-ii-probe.js.map +1 -1
  24. package/dist/auth/types.d.ts +48 -5
  25. package/dist/auth/types.d.ts.map +1 -1
  26. package/dist/createActorHooks.d.ts +9 -20
  27. package/dist/createActorHooks.d.ts.map +1 -1
  28. package/dist/createActorHooks.js.map +1 -1
  29. package/dist/createInfiniteQuery.d.ts +51 -10
  30. package/dist/createInfiniteQuery.d.ts.map +1 -1
  31. package/dist/createInfiniteQuery.js +39 -15
  32. package/dist/createInfiniteQuery.js.map +1 -1
  33. package/dist/createMutation.d.ts +4 -1
  34. package/dist/createMutation.d.ts.map +1 -1
  35. package/dist/createMutation.js +121 -84
  36. package/dist/createMutation.js.map +1 -1
  37. package/dist/createQuery.d.ts +35 -2
  38. package/dist/createQuery.d.ts.map +1 -1
  39. package/dist/createQuery.js +104 -17
  40. package/dist/createQuery.js.map +1 -1
  41. package/dist/createReactorProvider.d.ts +158 -0
  42. package/dist/createReactorProvider.d.ts.map +1 -0
  43. package/dist/createReactorProvider.js +256 -0
  44. package/dist/createReactorProvider.js.map +1 -0
  45. package/dist/createSuspenseInfiniteQuery.d.ts +16 -9
  46. package/dist/createSuspenseInfiniteQuery.d.ts.map +1 -1
  47. package/dist/createSuspenseInfiniteQuery.js +59 -27
  48. package/dist/createSuspenseInfiniteQuery.js.map +1 -1
  49. package/dist/createSuspenseQuery.d.ts +23 -2
  50. package/dist/createSuspenseQuery.d.ts.map +1 -1
  51. package/dist/createSuspenseQuery.js +68 -21
  52. package/dist/createSuspenseQuery.js.map +1 -1
  53. package/dist/defineDisplayReactor.d.ts +43 -0
  54. package/dist/defineDisplayReactor.d.ts.map +1 -0
  55. package/dist/defineDisplayReactor.js +42 -0
  56. package/dist/defineDisplayReactor.js.map +1 -0
  57. package/dist/defineReactor.d.ts +46 -72
  58. package/dist/defineReactor.d.ts.map +1 -1
  59. package/dist/defineReactor.js +11 -176
  60. package/dist/defineReactor.js.map +1 -1
  61. package/dist/defineReactorShared.d.ts +84 -0
  62. package/dist/defineReactorShared.d.ts.map +1 -0
  63. package/dist/defineReactorShared.js +139 -0
  64. package/dist/defineReactorShared.js.map +1 -0
  65. package/dist/hooks/createAuthHooks.d.ts +9 -2
  66. package/dist/hooks/createAuthHooks.d.ts.map +1 -1
  67. package/dist/hooks/createAuthHooks.js +184 -24
  68. package/dist/hooks/createAuthHooks.js.map +1 -1
  69. package/dist/hooks/useActorInfiniteQuery.d.ts +36 -8
  70. package/dist/hooks/useActorInfiniteQuery.d.ts.map +1 -1
  71. package/dist/hooks/useActorInfiniteQuery.js +54 -21
  72. package/dist/hooks/useActorInfiniteQuery.js.map +1 -1
  73. package/dist/hooks/useActorMethod.d.ts +37 -4
  74. package/dist/hooks/useActorMethod.d.ts.map +1 -1
  75. package/dist/hooks/useActorMethod.js +201 -57
  76. package/dist/hooks/useActorMethod.js.map +1 -1
  77. package/dist/hooks/useActorMutation.d.ts +15 -12
  78. package/dist/hooks/useActorMutation.d.ts.map +1 -1
  79. package/dist/hooks/useActorMutation.js +14 -13
  80. package/dist/hooks/useActorMutation.js.map +1 -1
  81. package/dist/hooks/useActorQuery.d.ts +17 -4
  82. package/dist/hooks/useActorQuery.d.ts.map +1 -1
  83. package/dist/hooks/useActorQuery.js +30 -9
  84. package/dist/hooks/useActorQuery.js.map +1 -1
  85. package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts +17 -5
  86. package/dist/hooks/useActorSuspenseInfiniteQuery.d.ts.map +1 -1
  87. package/dist/hooks/useActorSuspenseInfiniteQuery.js +37 -17
  88. package/dist/hooks/useActorSuspenseInfiniteQuery.js.map +1 -1
  89. package/dist/hooks/useActorSuspenseQuery.d.ts +2 -2
  90. package/dist/hooks/useActorSuspenseQuery.d.ts.map +1 -1
  91. package/dist/hooks/useActorSuspenseQuery.js +20 -9
  92. package/dist/hooks/useActorSuspenseQuery.js.map +1 -1
  93. package/dist/index.d.ts +4 -0
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +6 -0
  96. package/dist/index.js.map +1 -1
  97. package/dist/ownedAuthentication.d.ts +52 -0
  98. package/dist/ownedAuthentication.d.ts.map +1 -0
  99. package/dist/ownedAuthentication.js +49 -0
  100. package/dist/ownedAuthentication.js.map +1 -0
  101. package/dist/server.d.ts +21 -0
  102. package/dist/server.d.ts.map +1 -0
  103. package/dist/server.js +23 -0
  104. package/dist/server.js.map +1 -0
  105. package/dist/testing.d.ts +19 -0
  106. package/dist/testing.d.ts.map +1 -0
  107. package/dist/testing.js +19 -0
  108. package/dist/testing.js.map +1 -0
  109. package/dist/types.d.ts +428 -21
  110. package/dist/types.d.ts.map +1 -1
  111. package/dist/types.js +1 -1
  112. package/dist/utils.d.ts +159 -3
  113. package/dist/utils.d.ts.map +1 -1
  114. package/dist/utils.js +301 -1
  115. package/dist/utils.js.map +1 -1
  116. package/dist/validation.d.ts +12 -7
  117. package/dist/validation.d.ts.map +1 -1
  118. package/dist/validation.js +34 -15
  119. package/dist/validation.js.map +1 -1
  120. package/llms.txt +259 -33
  121. package/package.json +17 -5
  122. package/src/auth/auth-client-compat.ts +273 -0
  123. package/src/auth/authentication-manager.ts +918 -96
  124. package/src/auth/createIdentityAttributeHooks.ts +47 -21
  125. package/src/auth/identity-attributes-manager.ts +100 -5
  126. package/src/auth/identity-attributes.ts +75 -0
  127. package/src/auth/local-ii-probe.ts +29 -3
  128. package/src/auth/types.ts +49 -6
  129. package/src/createActorHooks.ts +50 -42
  130. package/src/createInfiniteQuery.ts +120 -28
  131. package/src/createMutation.ts +213 -132
  132. package/src/createQuery.ts +164 -32
  133. package/src/createReactorProvider.ts +365 -0
  134. package/src/createSuspenseInfiniteQuery.ts +93 -43
  135. package/src/createSuspenseQuery.ts +102 -32
  136. package/src/defineDisplayReactor.ts +62 -0
  137. package/src/defineReactor.ts +81 -263
  138. package/src/defineReactorShared.ts +268 -0
  139. package/src/hooks/createAuthHooks.ts +210 -28
  140. package/src/hooks/useActorInfiniteQuery.ts +156 -55
  141. package/src/hooks/useActorMethod.ts +295 -92
  142. package/src/hooks/useActorMutation.ts +42 -30
  143. package/src/hooks/useActorQuery.ts +43 -10
  144. package/src/hooks/useActorSuspenseInfiniteQuery.ts +110 -54
  145. package/src/hooks/useActorSuspenseQuery.ts +30 -15
  146. package/src/index.ts +8 -0
  147. package/src/ownedAuthentication.ts +81 -0
  148. package/src/server.ts +23 -0
  149. package/src/testing.ts +18 -0
  150. package/src/types.ts +492 -22
  151. package/src/utils.ts +387 -3
  152. package/src/validation.ts +43 -19
package/dist/utils.d.ts CHANGED
@@ -1,15 +1,132 @@
1
1
  /**
2
- * Shared internal utilities for query and mutation factories.
2
+ * Shared internal utilities for the query and mutation hooks and factories.
3
3
  */
4
- import type { QueryKey } from "@tanstack/react-query";
5
- import type { ReactorQueryData } from "@ic-reactor/core";
4
+ import type { QueryClient, QueryKey } from "@tanstack/react-query";
5
+ import type { CallConfig } from "@icp-sdk/core/agent";
6
+ import type { ClientManager, Reactor, ReactorQueryData, TransformKey } from "@ic-reactor/core";
7
+ import type { InvalidationTarget, QueryCacheControls, QueryFactoryMethods } from "./types.js";
8
+ /**
9
+ * Keep `queryClient` mounted while the calling component is.
10
+ *
11
+ * `QueryClient.mount()` is what subscribes a client to TanStack's focus and
12
+ * online managers. Those subscriptions refetch stale queries on window focus
13
+ * and on reconnect, resume a fetch that started offline or a retry that paused
14
+ * while the tab was hidden, and resume mutations sent offline.
15
+ * `QueryClientProvider` normally calls it, but every hook here binds to its
16
+ * reactor's own client rather than the context one, and the setup guide calls
17
+ * the provider optional. Without one, nothing mounted the client: a query that
18
+ * started offline stayed `paused` after the connection came back, a mutation
19
+ * sent offline stayed pending, and `refetchOnWindowFocus` and
20
+ * `refetchOnReconnect` never fired.
21
+ *
22
+ * `mount()` and `unmount()` are reference-counted, so this composes with a
23
+ * provider mounting the same client and with any number of hooks. It runs in
24
+ * an effect, like the provider's, so a server render never subscribes.
25
+ *
26
+ * A reactor stand-in without a `queryClient` (a test double, say) makes the
27
+ * TanStack hooks fall back to the context client, which its provider mounts,
28
+ * so there is nothing to do for one.
29
+ */
30
+ export declare function useMountQueryClient(queryClient: QueryClient | undefined): void;
31
+ /**
32
+ * Keep `queryClient` mounted while a suspense hook waits on the promise it
33
+ * threw. Call it from a `catch` around the TanStack suspense hook, then
34
+ * rethrow. The `try` only lets the hook see the promise: it is rethrown
35
+ * untouched, so React discards the render as before and hook order is kept.
36
+ *
37
+ * A suspense hook throws its fetch promise before its component commits, so
38
+ * the effect in {@link useMountQueryClient} cannot run until that promise
39
+ * settles. A fetch that started offline, or whose retry is waiting for a hidden
40
+ * tab to come back, settles only once a mounted client hears the connection or
41
+ * the focus return. Without a provider nothing had mounted the client, so the
42
+ * Suspense fallback stayed up after reconnecting.
43
+ *
44
+ * The mount taken here is released when the promise settles, whether or not
45
+ * anything ever commits, so it stays balanced: each suspended render, a
46
+ * StrictMode double render or a retry included, takes and releases its own
47
+ * reference. Once the component commits, its effect holds the client like any
48
+ * other hook's. A tree discarded while suspended lets go once its fetch
49
+ * finishes, which it does on reconnect, as it would under a mounted provider.
50
+ * A server render never subscribes.
51
+ */
52
+ export declare function mountWhileSuspended(queryClient: QueryClient | undefined, thrown: unknown): void;
6
53
  /**
7
54
  * Internal query-key segment used to distinguish per-call factory args
8
55
  * from the base query key. Not part of the public API.
9
56
  */
10
57
  export declare const FACTORY_KEY_ARGS_QUERY_KEY = "__ic_reactor_factory_key_args";
58
+ /**
59
+ * Internal query-key segment that ends the key of a query waiting on
60
+ * `skipToken`. Not part of the public API.
61
+ */
62
+ export declare const SKIPPED_QUERY_KEY = "__ic_reactor_skipped";
63
+ /**
64
+ * The key of a query whose args are `skipToken`: `prefix`, the method's key
65
+ * that every key its args give extends, and then a segment no call's key has.
66
+ *
67
+ * It used to be the bare prefix, which is also the key of a query of the same
68
+ * method made without args, as a method with no parameters is called. The
69
+ * skipped query then showed that query's data though its own args were not
70
+ * known. And TanStack Query refetches an entry with the options of whichever
71
+ * of its observers rendered last, so an invalidation, including the sweep a
72
+ * sign-in or sign-out runs, could find `skipToken` in place of the query
73
+ * function: the refetch failed with "Missing queryFn" and the other query
74
+ * kept the previous caller's answer.
75
+ *
76
+ * `kind` keeps a waiting list apart from a waiting query of the same method,
77
+ * since TanStack Query does not share an entry between `useQuery` and
78
+ * `useInfiniteQuery`.
79
+ */
80
+ export declare function skippedQueryKey(prefix: QueryKey, kind: "query" | "infinite"): QueryKey;
81
+ /**
82
+ * The call config an infinite query's function fetches with: the caller's,
83
+ * aimed at the canister its query key names unless the caller named one.
84
+ *
85
+ * The key is built from the reactor's canister when the query is set up, but
86
+ * the query function reached `callMethod`, which reads `reactor.canisterId`
87
+ * again whenever it runs. After a `setCanisterId`, a retry or a refetch by an
88
+ * observer that had not re-rendered then fetched the new canister's pages and
89
+ * cached them under the old canister's key. `generateQueryKey` always roots a
90
+ * key at the canister it resolved, so the key says where its pages come from.
91
+ * `Reactor.getQueryOptions` pins its query function the same way.
92
+ */
93
+ export declare function callConfigForKey(queryKey: QueryKey, callConfig: CallConfig | undefined): CallConfig | undefined;
11
94
  /** Convert a direct reactor result into a value TanStack Query can cache. */
12
95
  export declare const normalizeQueryData: <T>(value: T) => ReactorQueryData<T>;
96
+ /** Config options that decide how a query's function runs. */
97
+ declare const FETCH_OPTION_KEYS: readonly ["networkMode", "retry", "retryDelay", "meta"];
98
+ type FetchOptionKey = (typeof FETCH_OPTION_KEYS)[number];
99
+ /**
100
+ * The part of a factory config that `fetch()` and `prefetch()` pass on.
101
+ *
102
+ * A factory's hook hands its whole config to TanStack Query, but the
103
+ * imperative path used to pass only the key and query function. So a config's
104
+ * `networkMode: "always"` let the hook fetch while `fetch()` stayed paused
105
+ * offline, its `retry` retried in the hook and not in a loader, and its `meta`
106
+ * never reached the QueryCache callbacks for a `fetch()` failure. These four
107
+ * say how the query function runs, so they now apply to both paths.
108
+ *
109
+ * Options that decide what the cache keeps (`gcTime`, `initialData`) or how an
110
+ * observer renders (`select`, `placeholderData`, `enabled`, …) stay with the
111
+ * hook. Unset options are left out rather than passed as `undefined`, which
112
+ * would override the QueryClient's own defaults.
113
+ */
114
+ export declare function pickFetchOptions<Config extends object>(config: Config): Partial<Pick<Config, Extract<keyof Config, FetchOptionKey>>>;
115
+ /**
116
+ * The `retry` entry of a query's options: the query's own `retry` when it sets
117
+ * one, otherwise the reactor's default for its method, and no entry when
118
+ * neither is set, so the QueryClient's defaults apply.
119
+ *
120
+ * The default is `Reactor.getQueryRetry`'s: `undefined` for a query method,
121
+ * and for an update method a retry of only the failures that prove the
122
+ * canister never ran the call, since each attempt runs the update again.
123
+ * Spread this after the caller's options. An update method's default then also
124
+ * replaces a `retry: undefined` spread in from them, which would otherwise
125
+ * select TanStack Query's own three retries.
126
+ */
127
+ export declare function retryOption<TRetry, TDefault>(ownRetry: TRetry | undefined, defaultRetry: TDefault | undefined): {
128
+ retry?: TRetry | TDefault;
129
+ };
13
130
  /**
14
131
  * Merge a base query key, optional per-call query key, and optional key-args
15
132
  * into a single query key array.
@@ -48,4 +165,43 @@ export declare function createBoundedCache<V>(limit?: number): {
48
165
  set(key: string, value: V): void;
49
166
  readonly size: number;
50
167
  };
168
+ /**
169
+ * Invalidate every entry of a mutation's `invalidateQueries` in parallel, on
170
+ * behalf of `reactor`, the mutation's own. It resolves once every active
171
+ * query they matched has refetched; a refetch that fails does not reject it,
172
+ * so it cannot turn an update that already ran into a failure.
173
+ *
174
+ * An entry is a query key, a query object or query factory (anything with a
175
+ * `getQueryKey()`), or a `{ functionName, args? }` descriptor, which is keyed
176
+ * by `reactor.generateQueryKey` at the canister the mutation was sent to:
177
+ * the one its `callConfig.canisterId` names, else the reactor's. `undefined`
178
+ * entries are skipped.
179
+ */
180
+ export declare function invalidateTargets<Service, Transform extends TransformKey>(reactor: Reactor<Service, Transform>, targets: readonly InvalidationTarget<Service, Transform>[] | undefined, callConfig?: CallConfig): Promise<void>;
181
+ /**
182
+ * Give an args-late query factory function its {@link QueryFactoryMethods}.
183
+ *
184
+ * `getQueryKey` builds the prefix every query of the factory shares, and is
185
+ * called each time so that it follows a `setCanisterId`.
186
+ */
187
+ export declare function withQueryFactoryMethods<Factory extends object>(factory: Factory, reactor: {
188
+ readonly queryClient: QueryClient;
189
+ }, getQueryKey: () => QueryKey): Factory & QueryFactoryMethods;
190
+ /** What {@link queryCacheControls} reads from a reactor. */
191
+ interface CacheOwner {
192
+ readonly queryClient: QueryClient;
193
+ readonly clientManager: Pick<ClientManager, "identity">;
194
+ }
195
+ /**
196
+ * The {@link QueryCacheControls} of a query object: `cancel`, `reset` and
197
+ * `optimisticUpdate` on its own entry of the reactor's QueryClient.
198
+ *
199
+ * They match the key exactly. A query object's key is also the prefix of
200
+ * other entries (a query without args prefixes every args instance of its
201
+ * method), and cancelling or resetting those would reach queries this object
202
+ * does not own. `getQueryKey` is called each time, so the controls follow a
203
+ * `setCanisterId`.
204
+ */
205
+ export declare function queryCacheControls<TQueryFnData>(reactor: CacheOwner, getQueryKey: () => QueryKey): QueryCacheControls<TQueryFnData>;
206
+ export {};
51
207
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAGxD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,kCAAkC,CAAA;AAEzE,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,gBAAgB,CAAC,CAAC,CACN,CAAA;AAE7D;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,CAAC,EAAE,QAAQ,EACvB,YAAY,CAAC,EAAE,QAAQ,EACvB,OAAO,CAAC,EAAE,OAAO,GAChB,QAAQ,GAAG,SAAS,CAgBtB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EACrE,YAAY,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,SAAS,CAAC,GAAG,SAAS,EACtD,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,KAAK,MAAM,CAAC,GAAG,SAAS,GACpD,CAAC,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,GAAG,MAAM,CAAC,GAAG,SAAS,CAStD;AAaD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,GAAE,MAA4B;aAI5D,MAAM,GAAG,CAAC,GAAG,SAAS;aAQtB,MAAM,SAAS,CAAC,GAAG,IAAI;mBAQpB,MAAM;EAIrB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/dist/utils.js CHANGED
@@ -1,14 +1,166 @@
1
1
  /**
2
- * Shared internal utilities for query and mutation factories.
2
+ * Shared internal utilities for the query and mutation hooks and factories.
3
3
  */
4
+ import { useEffect } from "react";
4
5
  import { generateKey } from "@ic-reactor/core";
6
+ /**
7
+ * Keep `queryClient` mounted while the calling component is.
8
+ *
9
+ * `QueryClient.mount()` is what subscribes a client to TanStack's focus and
10
+ * online managers. Those subscriptions refetch stale queries on window focus
11
+ * and on reconnect, resume a fetch that started offline or a retry that paused
12
+ * while the tab was hidden, and resume mutations sent offline.
13
+ * `QueryClientProvider` normally calls it, but every hook here binds to its
14
+ * reactor's own client rather than the context one, and the setup guide calls
15
+ * the provider optional. Without one, nothing mounted the client: a query that
16
+ * started offline stayed `paused` after the connection came back, a mutation
17
+ * sent offline stayed pending, and `refetchOnWindowFocus` and
18
+ * `refetchOnReconnect` never fired.
19
+ *
20
+ * `mount()` and `unmount()` are reference-counted, so this composes with a
21
+ * provider mounting the same client and with any number of hooks. It runs in
22
+ * an effect, like the provider's, so a server render never subscribes.
23
+ *
24
+ * A reactor stand-in without a `queryClient` (a test double, say) makes the
25
+ * TanStack hooks fall back to the context client, which its provider mounts,
26
+ * so there is nothing to do for one.
27
+ */
28
+ export function useMountQueryClient(queryClient) {
29
+ useEffect(() => {
30
+ if (!queryClient)
31
+ return;
32
+ queryClient.mount();
33
+ return () => queryClient.unmount();
34
+ }, [queryClient]);
35
+ }
36
+ const isThenable = (value) => typeof value?.then === "function";
37
+ /**
38
+ * Keep `queryClient` mounted while a suspense hook waits on the promise it
39
+ * threw. Call it from a `catch` around the TanStack suspense hook, then
40
+ * rethrow. The `try` only lets the hook see the promise: it is rethrown
41
+ * untouched, so React discards the render as before and hook order is kept.
42
+ *
43
+ * A suspense hook throws its fetch promise before its component commits, so
44
+ * the effect in {@link useMountQueryClient} cannot run until that promise
45
+ * settles. A fetch that started offline, or whose retry is waiting for a hidden
46
+ * tab to come back, settles only once a mounted client hears the connection or
47
+ * the focus return. Without a provider nothing had mounted the client, so the
48
+ * Suspense fallback stayed up after reconnecting.
49
+ *
50
+ * The mount taken here is released when the promise settles, whether or not
51
+ * anything ever commits, so it stays balanced: each suspended render, a
52
+ * StrictMode double render or a retry included, takes and releases its own
53
+ * reference. Once the component commits, its effect holds the client like any
54
+ * other hook's. A tree discarded while suspended lets go once its fetch
55
+ * finishes, which it does on reconnect, as it would under a mounted provider.
56
+ * A server render never subscribes.
57
+ */
58
+ export function mountWhileSuspended(queryClient, thrown) {
59
+ if (!queryClient || typeof window === "undefined" || !isThenable(thrown)) {
60
+ return;
61
+ }
62
+ queryClient.mount();
63
+ const release = () => queryClient.unmount();
64
+ void thrown.then(release, release);
65
+ }
5
66
  /**
6
67
  * Internal query-key segment used to distinguish per-call factory args
7
68
  * from the base query key. Not part of the public API.
8
69
  */
9
70
  export const FACTORY_KEY_ARGS_QUERY_KEY = "__ic_reactor_factory_key_args";
71
+ /**
72
+ * Internal query-key segment that ends the key of a query waiting on
73
+ * `skipToken`. Not part of the public API.
74
+ */
75
+ export const SKIPPED_QUERY_KEY = "__ic_reactor_skipped";
76
+ /**
77
+ * The key of a query whose args are `skipToken`: `prefix`, the method's key
78
+ * that every key its args give extends, and then a segment no call's key has.
79
+ *
80
+ * It used to be the bare prefix, which is also the key of a query of the same
81
+ * method made without args, as a method with no parameters is called. The
82
+ * skipped query then showed that query's data though its own args were not
83
+ * known. And TanStack Query refetches an entry with the options of whichever
84
+ * of its observers rendered last, so an invalidation, including the sweep a
85
+ * sign-in or sign-out runs, could find `skipToken` in place of the query
86
+ * function: the refetch failed with "Missing queryFn" and the other query
87
+ * kept the previous caller's answer.
88
+ *
89
+ * `kind` keeps a waiting list apart from a waiting query of the same method,
90
+ * since TanStack Query does not share an entry between `useQuery` and
91
+ * `useInfiniteQuery`.
92
+ */
93
+ export function skippedQueryKey(prefix, kind) {
94
+ return [...prefix, { [SKIPPED_QUERY_KEY]: kind }];
95
+ }
96
+ /**
97
+ * The call config an infinite query's function fetches with: the caller's,
98
+ * aimed at the canister its query key names unless the caller named one.
99
+ *
100
+ * The key is built from the reactor's canister when the query is set up, but
101
+ * the query function reached `callMethod`, which reads `reactor.canisterId`
102
+ * again whenever it runs. After a `setCanisterId`, a retry or a refetch by an
103
+ * observer that had not re-rendered then fetched the new canister's pages and
104
+ * cached them under the old canister's key. `generateQueryKey` always roots a
105
+ * key at the canister it resolved, so the key says where its pages come from.
106
+ * `Reactor.getQueryOptions` pins its query function the same way.
107
+ */
108
+ export function callConfigForKey(queryKey, callConfig) {
109
+ const keyedCanister = queryKey[0];
110
+ if (callConfig?.canisterId || typeof keyedCanister !== "string") {
111
+ return callConfig;
112
+ }
113
+ return { ...callConfig, canisterId: keyedCanister };
114
+ }
10
115
  /** Convert a direct reactor result into a value TanStack Query can cache. */
11
116
  export const normalizeQueryData = (value) => (value === undefined ? null : value);
117
+ /** Config options that decide how a query's function runs. */
118
+ const FETCH_OPTION_KEYS = [
119
+ "networkMode",
120
+ "retry",
121
+ "retryDelay",
122
+ "meta",
123
+ ];
124
+ /**
125
+ * The part of a factory config that `fetch()` and `prefetch()` pass on.
126
+ *
127
+ * A factory's hook hands its whole config to TanStack Query, but the
128
+ * imperative path used to pass only the key and query function. So a config's
129
+ * `networkMode: "always"` let the hook fetch while `fetch()` stayed paused
130
+ * offline, its `retry` retried in the hook and not in a loader, and its `meta`
131
+ * never reached the QueryCache callbacks for a `fetch()` failure. These four
132
+ * say how the query function runs, so they now apply to both paths.
133
+ *
134
+ * Options that decide what the cache keeps (`gcTime`, `initialData`) or how an
135
+ * observer renders (`select`, `placeholderData`, `enabled`, …) stay with the
136
+ * hook. Unset options are left out rather than passed as `undefined`, which
137
+ * would override the QueryClient's own defaults.
138
+ */
139
+ export function pickFetchOptions(config) {
140
+ const picked = {};
141
+ for (const key of FETCH_OPTION_KEYS) {
142
+ const value = config[key];
143
+ if (value !== undefined)
144
+ picked[key] = value;
145
+ }
146
+ return picked;
147
+ }
148
+ /**
149
+ * The `retry` entry of a query's options: the query's own `retry` when it sets
150
+ * one, otherwise the reactor's default for its method, and no entry when
151
+ * neither is set, so the QueryClient's defaults apply.
152
+ *
153
+ * The default is `Reactor.getQueryRetry`'s: `undefined` for a query method,
154
+ * and for an update method a retry of only the failures that prove the
155
+ * canister never ran the call, since each attempt runs the update again.
156
+ * Spread this after the caller's options. An update method's default then also
157
+ * replaces a `retry: undefined` spread in from them, which would otherwise
158
+ * select TanStack Query's own three retries.
159
+ */
160
+ export function retryOption(ownRetry, defaultRetry) {
161
+ const retry = ownRetry ?? defaultRetry;
162
+ return retry === undefined ? {} : { retry };
163
+ }
12
164
  /**
13
165
  * Merge a base query key, optional per-call query key, and optional key-args
14
166
  * into a single query key array.
@@ -102,4 +254,152 @@ export function createBoundedCache(limit = FACTORY_CACHE_LIMIT) {
102
254
  },
103
255
  };
104
256
  }
257
+ const isQueryKeySource = (value) => typeof value.getQueryKey === "function";
258
+ /**
259
+ * Invalidate one `invalidateQueries` entry; see {@link invalidateTargets}.
260
+ */
261
+ function invalidateTarget(reactor, target, canisterId) {
262
+ // React Query reads `{ queryKey: undefined }` as "match everything", so an
263
+ // absent entry would invalidate every query in the client, the app's
264
+ // unrelated non-canister ones included. `null` only comes from untyped code
265
+ // and would do the same.
266
+ if (target == null)
267
+ return Promise.resolve();
268
+ if (Array.isArray(target)) {
269
+ return reactor.queryClient.invalidateQueries({ queryKey: target });
270
+ }
271
+ if (isQueryKeySource(target)) {
272
+ // A query object or factory invalidates on its own reactor's client, which
273
+ // is not this reactor's when each reactor has a QueryClient of its own.
274
+ return target.invalidate
275
+ ? target.invalidate()
276
+ : reactor.queryClient.invalidateQueries({
277
+ queryKey: target.getQueryKey(),
278
+ });
279
+ }
280
+ // A `{ functionName, args? }` descriptor. Its key is built now rather than
281
+ // when the mutation was set up, so it follows a `setCanisterId`.
282
+ const { functionName, args } = target;
283
+ // `args: []`, all that a method without parameters takes, names the same
284
+ // queries as no args. Keyed as given, it adds an args segment that a query
285
+ // made without args lacks, and would match none of those.
286
+ const hasArgs = args?.length;
287
+ return reactor.queryClient.invalidateQueries({
288
+ // At the canister the mutation was sent to, whose queries it changed.
289
+ // Only the canister is taken from its `callConfig`: an agent or effective
290
+ // target segment would narrow the prefix to the queries sent the same
291
+ // way, while the canister's state changed for every caller.
292
+ queryKey: reactor.generateQueryKey({ functionName, args: hasArgs ? args : undefined }, canisterId ? { canisterId } : undefined),
293
+ });
294
+ }
295
+ /**
296
+ * Invalidate every entry of a mutation's `invalidateQueries` in parallel, on
297
+ * behalf of `reactor`, the mutation's own. It resolves once every active
298
+ * query they matched has refetched; a refetch that fails does not reject it,
299
+ * so it cannot turn an update that already ran into a failure.
300
+ *
301
+ * An entry is a query key, a query object or query factory (anything with a
302
+ * `getQueryKey()`), or a `{ functionName, args? }` descriptor, which is keyed
303
+ * by `reactor.generateQueryKey` at the canister the mutation was sent to:
304
+ * the one its `callConfig.canisterId` names, else the reactor's. `undefined`
305
+ * entries are skipped.
306
+ */
307
+ export async function invalidateTargets(reactor, targets, callConfig) {
308
+ if (!targets || targets.length === 0)
309
+ return;
310
+ await Promise.all(targets.map((target) => invalidateTarget(reactor, target, callConfig?.canisterId)));
311
+ }
312
+ /**
313
+ * Give an args-late query factory function its {@link QueryFactoryMethods}.
314
+ *
315
+ * `getQueryKey` builds the prefix every query of the factory shares, and is
316
+ * called each time so that it follows a `setCanisterId`.
317
+ */
318
+ export function withQueryFactoryMethods(factory, reactor, getQueryKey) {
319
+ const methods = {
320
+ getQueryKey,
321
+ invalidate: () => reactor.queryClient.invalidateQueries({ queryKey: getQueryKey() }),
322
+ };
323
+ return Object.assign(factory, methods);
324
+ }
325
+ /** The rollback of an optimistic update that wrote nothing. */
326
+ const NOTHING_TO_ROLL_BACK = { rollback: () => { } };
327
+ /**
328
+ * The principal whose answers the reactor's cache holds: the one installed on
329
+ * the manager's agent, `undefined` before one is.
330
+ *
331
+ * Query keys carry no principal. `ClientManager.updateAgent` sweeps the cache
332
+ * instead when another principal signs in, removing inactive entries and
333
+ * refetching active ones, so a value read from the cache is this principal's
334
+ * only while it stays installed.
335
+ */
336
+ const cachedPrincipal = (reactor) => reactor.clientManager.identity?.getPrincipal().toText();
337
+ /**
338
+ * The {@link QueryCacheControls} of a query object: `cancel`, `reset` and
339
+ * `optimisticUpdate` on its own entry of the reactor's QueryClient.
340
+ *
341
+ * They match the key exactly. A query object's key is also the prefix of
342
+ * other entries (a query without args prefixes every args instance of its
343
+ * method), and cancelling or resetting those would reach queries this object
344
+ * does not own. `getQueryKey` is called each time, so the controls follow a
345
+ * `setCanisterId`.
346
+ */
347
+ export function queryCacheControls(reactor, getQueryKey) {
348
+ return {
349
+ cancel: () => reactor.queryClient.cancelQueries({
350
+ queryKey: getQueryKey(),
351
+ exact: true,
352
+ }),
353
+ reset: () => reactor.queryClient.resetQueries({
354
+ queryKey: getQueryKey(),
355
+ exact: true,
356
+ }),
357
+ optimisticUpdate: async (updater) => {
358
+ const { queryClient } = reactor;
359
+ const queryKey = getQueryKey();
360
+ // Nothing cached means nothing on screen to update. Cancelling the
361
+ // entry's first fetch would also leave it pending with no data.
362
+ if (queryClient.getQueryData(queryKey) === undefined) {
363
+ return NOTHING_TO_ROLL_BACK;
364
+ }
365
+ const principal = cachedPrincipal(reactor);
366
+ // A fetch in flight would otherwise land after the write below with the
367
+ // canister's answer from before the mutation. Cancelling reverts the
368
+ // entry to what it held before that fetch, so it is read afterwards.
369
+ await queryClient.cancelQueries({ queryKey, exact: true });
370
+ // A sign-in or sign-out while that ran left the previous principal's
371
+ // value in the entry until the sweep's refetch lands. An update built
372
+ // on it would show that value to the principal signed in now.
373
+ if (cachedPrincipal(reactor) !== principal)
374
+ return NOTHING_TO_ROLL_BACK;
375
+ const snapshot = queryClient.getQueryState(queryKey);
376
+ if (snapshot?.data === undefined)
377
+ return NOTHING_TO_ROLL_BACK;
378
+ const { data: previous, dataUpdatedAt, isInvalidated } = snapshot;
379
+ queryClient.setQueryData(queryKey, updater(previous));
380
+ return {
381
+ rollback: () => {
382
+ // After a switch to another principal, `previous` is the previous
383
+ // principal's value, which the sweep has removed or is refetching.
384
+ // Written back, it would be served to the one signed in now.
385
+ if (cachedPrincipal(reactor) !== principal)
386
+ return;
387
+ // With its own timestamp: written back as new, a value from before
388
+ // the mutation would look freshly fetched and skip the refetches
389
+ // its age calls for.
390
+ queryClient.setQueryData(queryKey, previous, {
391
+ updatedAt: dataUpdatedAt,
392
+ });
393
+ // The write clears the invalidated mark too, and the fetch the
394
+ // update cancelled was often the refetch an invalidation started.
395
+ // Marked again, the value reads as outdated as it was, and a
396
+ // mounted query refetches it.
397
+ if (isInvalidated) {
398
+ void queryClient.invalidateQueries({ queryKey, exact: true });
399
+ }
400
+ },
401
+ };
402
+ },
403
+ };
404
+ }
105
405
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
@@ -29,7 +29,9 @@ export interface MapValidationErrorsOptions {
29
29
  }
30
30
  /**
31
31
  * Maps validation error issues to a simple field -> message object.
32
- * Returns the first error message for each field path.
32
+ * Returns the first error message for each field path, or every message with
33
+ * `{ multiple: true }`. Issues about the whole argument (an empty path) are
34
+ * filed under `""`.
33
35
  *
34
36
  * @example
35
37
  * ```tsx
@@ -49,16 +51,18 @@ export interface MapValidationErrorsOptions {
49
51
  * })
50
52
  * ```
51
53
  */
52
- export declare function mapValidationErrors(error: ValidationError): FieldErrors;
54
+ export declare function mapValidationErrors(error: ValidationError, options?: {
55
+ multiple?: false;
56
+ }): FieldErrors;
53
57
  export declare function mapValidationErrors(error: ValidationError, options: {
54
58
  multiple: true;
55
59
  }): FieldErrorsMultiple;
56
- export declare function mapValidationErrors(error: ValidationError, options: {
57
- multiple: false;
58
- }): FieldErrors;
60
+ export declare function mapValidationErrors(error: ValidationError, options?: MapValidationErrorsOptions): FieldErrors | FieldErrorsMultiple;
59
61
  /**
60
62
  * Gets error message for a specific field from a ValidationError.
61
- * Returns undefined if no error exists for that field.
63
+ * Returns undefined if no error exists for that field. Pass `""` for issues
64
+ * about the whole argument (an empty path), the key `mapValidationErrors`
65
+ * files them under.
62
66
  *
63
67
  * @example
64
68
  * ```tsx
@@ -71,7 +75,8 @@ export declare function mapValidationErrors(error: ValidationError, options: {
71
75
  export declare function getFieldError(error: ValidationError, fieldName: string): string | undefined;
72
76
  /**
73
77
  * Gets all error messages for a specific field from a ValidationError.
74
- * Returns empty array if no errors exist for that field.
78
+ * Returns empty array if no errors exist for that field. Pass `""` for issues
79
+ * about the whole argument (an empty path).
75
80
  *
76
81
  * @example
77
82
  * ```tsx
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,CAAA;AAC7C,YAAY,EAAE,eAAe,EAAE,CAAA;AAE/B;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEhD;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AAE1D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,WAAW,CAAA;AACxE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,GAC1B,mBAAmB,CAAA;AACtB,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAA;CAAE,GAC3B,WAAW,CAAA;AA2Bd;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAGpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,MAAM,GAChB,MAAM,EAAE,CAIV;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAK1E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,EAC7C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GACpC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CASxB"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,CAAA;AAC7C,YAAY,EAAE,eAAe,EAAE,CAAA;AAE/B;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAEhD;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;AAE1D;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAWD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAC7B,WAAW,CAAA;AACd,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,GAC1B,mBAAmB,CAAA;AACtB,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,OAAO,CAAC,EAAE,0BAA0B,GACnC,WAAW,GAAG,mBAAmB,CAAA;AAkCpC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAGpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,MAAM,GAChB,MAAM,EAAE,CAIV;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAK1E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,EAC7C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GACpC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CASxB"}