@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
@@ -1,32 +0,0 @@
1
- export const IC_INTERNET_IDENTITY_PROVIDER = "https://id.ai/authorize"
2
-
3
- /**
4
- * `ic_env` key used to provide a fully resolved Internet Identity URL.
5
- */
6
- export const INTERNET_IDENTITY_PROVIDER_ENV_KEY = "INTERNET_IDENTITY_PROVIDER"
7
-
8
- /**
9
- * Well-known Internet Identity canister ID used when deploying II locally.
10
- */
11
- export const LOCAL_INTERNET_IDENTITY_CANISTER_ID = "rdmx6-jaaaa-aaaaa-aaadq-cai"
12
-
13
- /**
14
- * Builds the local Internet Identity provider URL for the given replica port.
15
- *
16
- * `authorizePath` selects the shape the installed build understands: modern
17
- * builds serve `/authorize` as a real asset, while pre-2026 ones serve the SPA
18
- * at `/` and drive the flow from a `#authorize` fragment. `AuthenticationManager`
19
- * probes the canister and passes the right one; the default keeps the previous
20
- * behaviour for direct callers.
21
- */
22
- export const localInternetIdentityProvider = (
23
- port: number,
24
- canisterId: string = LOCAL_INTERNET_IDENTITY_CANISTER_ID,
25
- authorizePath: "/authorize" | "/#authorize" = "/authorize"
26
- ) => `http://${canisterId}.localhost:${port}${authorizePath}`
27
-
28
- /**
29
- * Legacy default URL for local Internet Identity, using port `4943`.
30
- */
31
- export const LOCAL_INTERNET_IDENTITY_PROVIDER =
32
- localInternetIdentityProvider(4943)
@@ -1,169 +0,0 @@
1
- import { useCallback, useEffect, useRef, useState } from "react"
2
- import { Principal } from "@icp-sdk/core/principal"
3
- import type { IdentityAttributesManager } from "./identity-attributes-manager.js"
4
- import type {
5
- IdentityAttributeResult,
6
- RequestIdentityAttributesParameters,
7
- RequestOpenIdIdentityAttributesParameters,
8
- } from "./types.js"
9
-
10
- export interface UseIdentityAttributesReturn {
11
- requestAttributes: (
12
- params: RequestIdentityAttributesParameters
13
- ) => Promise<IdentityAttributeResult>
14
- requestOpenIdAttributes: (
15
- params: RequestOpenIdIdentityAttributesParameters
16
- ) => Promise<IdentityAttributeResult>
17
- attributes: IdentityAttributeResult | null
18
- isRequestingAttributes: boolean
19
- attributeError: Error | null
20
- clearAttributes: () => void
21
- }
22
-
23
- /** What `request()` reports as the principal of a signed-out session. */
24
- const ANONYMOUS_PRINCIPAL = Principal.anonymous().toText()
25
-
26
- export function createIdentityAttributeHooks(
27
- identityAttributes: IdentityAttributesManager
28
- ) {
29
- const useIdentityAttributes = (): UseIdentityAttributesReturn => {
30
- const [attributes, setAttributes] =
31
- useState<IdentityAttributeResult | null>(null)
32
- const [isRequestingAttributes, setIsRequestingAttributes] = useState(false)
33
- const [attributeError, setAttributeError] = useState<Error | null>(null)
34
-
35
- /** The principal the session is currently signed in as, if any. */
36
- const currentPrincipal = useCallback(() => {
37
- const { authState } = identityAttributes.authentication
38
- return authState.isAuthenticated
39
- ? authState.identity?.getPrincipal().toText()
40
- : undefined
41
- }, [])
42
-
43
- /**
44
- * A request started before a sign-out or an account switch resolves after
45
- * it, and publishing that result would put the previous user's decoded PII
46
- * back on screen with no further auth event to clear it again. So a result
47
- * is committed only when it is the current session's own: it carries the
48
- * principal signed in when it resolves or, while nobody is, the anonymous
49
- * principal that a `signIn: false` request made while signed out reports.
50
- *
51
- * With `signIn: true` the request itself signs the user in, so the
52
- * principal seen before the request (none, for a first sign-in; the old
53
- * account, for a switch made inside the provider window) is never the one
54
- * the result belongs to. Comparing against it left `attributes` null after
55
- * every successful first-time sign-in. Nor does "the same principal before
56
- * and after" mean the session never changed: the request's own sign-in is
57
- * published only when the whole request ends, so a user who signed in
58
- * through it and signed out before it ended is nobody on both sides. Their
59
- * name and email then went up on the signed-out screen.
60
- */
61
- const publishIfCurrent = useCallback(
62
- (result: IdentityAttributeResult) => {
63
- const session = currentPrincipal() ?? ANONYMOUS_PRINCIPAL
64
- if (result.principal !== session) return false
65
- setAttributes(result)
66
- return true
67
- },
68
- [currentPrincipal]
69
- )
70
-
71
- /**
72
- * The failure counterpart of `publishIfCurrent`. A request that signs in
73
- * can fail on its attribute side after its own sign-in went through, and
74
- * the manager keeps that sign-in before it reports the failure, so the
75
- * session is now the one this request opened and the failure is that
76
- * user's to see. A failure that lands after a sign-out is still dropped.
77
- */
78
- const publishErrorIfCurrent = useCallback(
79
- (requestedFor: string | undefined, signsIn: boolean, error: Error) => {
80
- const current = currentPrincipal()
81
- if (requestedFor !== current && !(signsIn && current !== undefined)) {
82
- return
83
- }
84
- setAttributeError(error)
85
- },
86
- [currentPrincipal]
87
- )
88
-
89
- const requestAttributes = useCallback(
90
- async (params: RequestIdentityAttributesParameters) => {
91
- setIsRequestingAttributes(true)
92
- setAttributeError(null)
93
- const requestedFor = currentPrincipal()
94
- try {
95
- const result = await identityAttributes.request(params)
96
- publishIfCurrent(result)
97
- return result
98
- } catch (error) {
99
- publishErrorIfCurrent(
100
- requestedFor,
101
- params.signIn !== false,
102
- error as Error
103
- )
104
- throw error
105
- } finally {
106
- setIsRequestingAttributes(false)
107
- }
108
- },
109
- []
110
- )
111
-
112
- const requestOpenIdAttributes = useCallback(
113
- async (params: RequestOpenIdIdentityAttributesParameters) => {
114
- setIsRequestingAttributes(true)
115
- setAttributeError(null)
116
- const requestedFor = currentPrincipal()
117
- try {
118
- const result = await identityAttributes.requestOpenId(params)
119
- publishIfCurrent(result)
120
- return result
121
- } catch (error) {
122
- publishErrorIfCurrent(
123
- requestedFor,
124
- params.signIn !== false,
125
- error as Error
126
- )
127
- throw error
128
- } finally {
129
- setIsRequestingAttributes(false)
130
- }
131
- },
132
- []
133
- )
134
-
135
- const clearAttributes = useCallback(() => {
136
- setAttributes(null)
137
- setAttributeError(null)
138
- }, [])
139
-
140
- // Decoded attributes are the signed-in user's personal data — a name, an
141
- // email. They used to survive a sign-out or a switch to another account,
142
- // so the next person to look at the screen saw the previous user's details.
143
- // Drop them whenever the principal behind them changes.
144
- const attributedPrincipal = useRef<string | undefined>(undefined)
145
- useEffect(() => {
146
- const { authentication } = identityAttributes
147
- attributedPrincipal.current ??= currentPrincipal()
148
-
149
- return authentication.subscribeAuthState(() => {
150
- const principal = currentPrincipal()
151
- if (principal === attributedPrincipal.current) return
152
- attributedPrincipal.current = principal
153
- setAttributes(null)
154
- setAttributeError(null)
155
- })
156
- }, [])
157
-
158
- return {
159
- requestAttributes,
160
- requestOpenIdAttributes,
161
- attributes,
162
- isRequestingAttributes,
163
- attributeError,
164
- clearAttributes,
165
- }
166
- }
167
-
168
- return { useIdentityAttributes }
169
- }
@@ -1,226 +0,0 @@
1
- import type { Identity } from "@icp-sdk/core/agent"
2
- import type {
3
- AuthClientLike,
4
- IdentityAttributeNonce,
5
- IdentityAttributeResult,
6
- RequestIdentityAttributesParameters,
7
- RequestOpenIdIdentityAttributesParameters,
8
- } from "./types.js"
9
-
10
- import { AuthenticationManager } from "./authentication-manager.js"
11
- import {
12
- decodeIdentityAttributeValues,
13
- identityAttributeKeys,
14
- normalizeSignedIdentityAttributes,
15
- } from "./identity-attributes.js"
16
-
17
- /**
18
- * Requests and decodes signed identity attributes for an authenticated
19
- * Internet Identity session.
20
- *
21
- * Await `authentication.prepareClient()` once during startup (the `useAuth`
22
- * hook already does) so that {@link request} can open the identity provider
23
- * window synchronously from a click handler.
24
- *
25
- * @example
26
- * ```ts
27
- * const attributes = new IdentityAttributesManager(authentication)
28
- * const result = await attributes.request({
29
- * keys: ["name"],
30
- * nonce: () => fetchNonceFromCanister(),
31
- * })
32
- * ```
33
- */
34
- export class IdentityAttributesManager {
35
- constructor(public readonly authentication: AuthenticationManager) {}
36
-
37
- public request = async ({
38
- keys,
39
- nonce,
40
- signIn = true,
41
- maxTimeToLive,
42
- maxTimeToIdle,
43
- targets,
44
- ...clientOptions
45
- }: RequestIdentityAttributesParameters): Promise<IdentityAttributeResult> => {
46
- // Nothing may be awaited before `requestAttributes` / `signIn` are invoked:
47
- // the ICRC-29 transport only opens the identity provider window while the
48
- // browser still considers us inside the user gesture. `getPreparedClient`
49
- // is synchronous whenever `prepareClient()` has run.
50
- const preparedClient = this.authentication.getPreparedClient(clientOptions)
51
- const authClient =
52
- preparedClient ?? (await this.authentication.ensureClient(clientOptions))
53
-
54
- if (!authClient) {
55
- throw new Error(
56
- "Authentication module is missing or failed to initialize. To request identity attributes, please install @icp-sdk/auth (v8 or v10), or provide a compatible authClient."
57
- )
58
- }
59
-
60
- this.authentication.setAuthenticating()
61
- // Replaced by anything else that changes auth state while this request
62
- // runs; see where the result is committed.
63
- const pendingState = this.authentication.authState
64
-
65
- let signInPromise: Promise<Identity> | undefined
66
- let committed = false
67
- try {
68
- // `signIn` first: it opens the transport channel synchronously, and the
69
- // attribute request then reuses that same channel and window.
70
- signInPromise = signIn
71
- ? this.authentication.signInOrRecoverIdentity({
72
- maxTimeToLive,
73
- maxTimeToIdle,
74
- targets,
75
- })
76
- : undefined
77
- const identityPromise =
78
- signInPromise ?? Promise.resolve(authClient.getIdentity())
79
- const requestPromise = authClient.requestAttributes({
80
- keys,
81
- nonce: toAuthClientNonce(nonce),
82
- })
83
-
84
- const [signedAttributes, identity] = await Promise.all([
85
- requestPromise,
86
- identityPromise,
87
- ])
88
-
89
- const finalIdentity = identity ?? (await authClient.getIdentity())
90
- // A v8 client can say it is authenticated for a delegation that lapsed
91
- // in this tab, or while it holds no session, once another tab has
92
- // signed in; see `AuthenticationManager.vouchesFor`.
93
- const isAuthenticated = this.authentication.vouchesFor(
94
- finalIdentity,
95
- await authClient.isAuthenticated()
96
- )
97
- committed = true
98
- // A sign-out, or another account's sign-in, can finish while the
99
- // attribute side is still pending: neither ends it. `finalIdentity` then
100
- // belongs to a session the client has left, and committing it put the
101
- // signed-out user's delegation back on the agent while the app showed
102
- // them signed out. So commit only what the client still holds and
103
- // vouches for, the rule `authenticate()` applies. Whatever moved the
104
- // client through the manager has published its own state.
105
- //
106
- // When nothing has published since this request began, the session
107
- // changed under the manager and this request is the first to find out.
108
- // A client that vouches for no session any more has lost it, as when
109
- // another tab signed out, while it still hands out the identity it held:
110
- // the manager signs out too, or it goes on reporting the user signed in
111
- // with their delegation on the agent. A client that still vouches for a
112
- // session gives no grounds to sign anyone out, so only the
113
- // `isAuthenticating` this request started is ended.
114
- if (await clientHolds(authClient, finalIdentity, isAuthenticated)) {
115
- await this.authentication.commitIdentity(finalIdentity, isAuthenticated)
116
- } else if (this.authentication.authState === pendingState) {
117
- if (isAuthenticated) {
118
- this.authentication.settleAuthenticating()
119
- } else {
120
- this.authentication.commitSignedOut()
121
- }
122
- }
123
-
124
- const normalizedSignedAttributes =
125
- normalizeSignedIdentityAttributes(signedAttributes)
126
-
127
- return {
128
- principal: finalIdentity.getPrincipal().toText(),
129
- requestedKeys: keys,
130
- signedAttributes: normalizedSignedAttributes,
131
- decodedAttributes: decodeIdentityAttributeValues(
132
- normalizedSignedAttributes.data,
133
- keys
134
- ),
135
- completedAt: new Date().toISOString(),
136
- }
137
- } catch (error) {
138
- // The sign-in and the attribute request share one provider window and
139
- // can end differently. When the attribute side failed (the app's nonce
140
- // call rejected, or the provider could not certify a key) but the user
141
- // went on to finish signing in, the client held a session nothing had
142
- // committed: the app showed the user signed out until a reload restored
143
- // it. So a sign-in this request started is waited for, and kept when the
144
- // client vouches for it, before the failure is reported.
145
- if (signInPromise && !committed) {
146
- await this.keepCompletedSignIn(signInPromise, authClient)
147
- }
148
- this.authentication.setAuthenticationError(error as Error)
149
- throw error
150
- }
151
- }
152
-
153
- private async keepCompletedSignIn(
154
- signInPromise: Promise<Identity>,
155
- authClient: AuthClientLike
156
- ) {
157
- const identity = await signInPromise.catch(() => undefined)
158
- if (!identity) return
159
- const isAuthenticated = await Promise.resolve()
160
- .then(() => authClient.isAuthenticated())
161
- .catch(() => false)
162
- if (!isAuthenticated) return
163
- // The session the client holds now must be the one this request opened.
164
- // Another login can switch the shared client to a different account while
165
- // the attribute side is still pending, and committing this identity then
166
- // would put back the account the user switched away from.
167
- const current = await Promise.resolve()
168
- .then(() => authClient.getIdentity())
169
- .catch(() => undefined)
170
- if (current?.getPrincipal().toText() !== identity.getPrincipal().toText()) {
171
- return
172
- }
173
- // The attribute failure is the one to report, so a failure here is not.
174
- await this.authentication
175
- .commitIdentity(identity, true)
176
- .catch(() => undefined)
177
- }
178
-
179
- public requestOpenId = ({
180
- keys,
181
- openIdProvider,
182
- ...rest
183
- }: RequestOpenIdIdentityAttributesParameters): Promise<IdentityAttributeResult> => {
184
- // Called (not awaited) synchronously so the user gesture is preserved.
185
- return this.request({
186
- ...rest,
187
- openIdProvider,
188
- keys: identityAttributeKeys({ openIdProvider, keys }),
189
- })
190
- }
191
- }
192
-
193
- /**
194
- * Whether `identity` is the session `authClient` holds now, and one it still
195
- * vouches for. The anonymous identity needs no vouching: it signs no one in.
196
- */
197
- async function clientHolds(
198
- authClient: AuthClientLike,
199
- identity: Identity,
200
- isAuthenticated: boolean
201
- ): Promise<boolean> {
202
- const held = await Promise.resolve()
203
- .then(() => authClient.getIdentity())
204
- .catch(() => undefined)
205
- const principal = identity.getPrincipal()
206
- if (held?.getPrincipal().toText() !== principal.toText()) return false
207
- return isAuthenticated || principal.isAnonymous()
208
- }
209
-
210
- /**
211
- * Adapts our nonce input to the `@icp-sdk/auth` nonce contract.
212
- *
213
- * v8 takes `() => Promise<Uint8Array>` — a thunk, so it can journal the value
214
- * and replay the same bytes through a redirect flow. The thunk form also opens
215
- * the transport channel synchronously, which is what preserves the user
216
- * gesture.
217
- *
218
- * Until 3.12.0 this probed `typeof authClient.memoize === "function"` to detect
219
- * v8 and fell back to a bare promise for v7. The peer range is now `^8.0.0`, so
220
- * the probe would only ever take one branch.
221
- */
222
- function toAuthClientNonce(
223
- nonce: IdentityAttributeNonce
224
- ): () => Promise<Uint8Array> {
225
- return () => Promise.resolve(typeof nonce === "function" ? nonce() : nonce)
226
- }