@oxyhq/services 13.3.0 → 14.0.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.
- package/lib/commonjs/index.js +11 -17
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/AccountMenu.js +103 -65
- package/lib/commonjs/ui/components/AccountMenu.js.map +1 -1
- package/lib/commonjs/ui/components/AccountSwitcher.js +84 -126
- package/lib/commonjs/ui/components/AccountSwitcher.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileMenu.js +140 -153
- package/lib/commonjs/ui/components/ProfileMenu.js.map +1 -1
- package/lib/commonjs/ui/components/SignInModal.js +4 -4
- package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +506 -466
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +59 -57
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/inSessionTokenRefresh.js +23 -42
- package/lib/commonjs/ui/context/inSessionTokenRefresh.js.map +1 -1
- package/lib/commonjs/ui/context/silentSessionRestore.js +12 -21
- package/lib/commonjs/ui/context/silentSessionRestore.js.map +1 -1
- package/lib/commonjs/ui/hooks/useAuth.js +4 -3
- package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
- package/lib/commonjs/ui/hooks/useOxyAuthSession.js +12 -7
- package/lib/commonjs/ui/hooks/useOxyAuthSession.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +17 -65
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +288 -0
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +1 -0
- package/lib/commonjs/ui/hooks/useWebSSO.js +12 -191
- package/lib/commonjs/ui/hooks/useWebSSO.js.map +1 -1
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +2 -2
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/commonjs/ui/session/createSessionClient.js +28 -0
- package/lib/commonjs/ui/session/createSessionClient.js.map +1 -0
- package/lib/commonjs/ui/session/index.js +52 -0
- package/lib/commonjs/ui/session/index.js.map +1 -0
- package/lib/commonjs/ui/session/projectSessionState.js +86 -0
- package/lib/commonjs/ui/session/projectSessionState.js.map +1 -0
- package/lib/commonjs/ui/session/sessionClientHost.js +30 -0
- package/lib/commonjs/ui/session/sessionClientHost.js.map +1 -0
- package/lib/commonjs/ui/session/tokenTransport.js +77 -0
- package/lib/commonjs/ui/session/tokenTransport.js.map +1 -0
- package/lib/commonjs/ui/utils/activeAuthuser.js +35 -79
- package/lib/commonjs/ui/utils/activeAuthuser.js.map +1 -1
- package/lib/commonjs/ui/utils/sessionHelpers.js +1 -51
- package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/commonjs/utils/deviceFlowSignIn.js +70 -15
- package/lib/commonjs/utils/deviceFlowSignIn.js.map +1 -1
- package/lib/module/index.js +5 -5
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/AccountMenu.js +103 -65
- package/lib/module/ui/components/AccountMenu.js.map +1 -1
- package/lib/module/ui/components/AccountSwitcher.js +85 -127
- package/lib/module/ui/components/AccountSwitcher.js.map +1 -1
- package/lib/module/ui/components/ProfileMenu.js +143 -156
- package/lib/module/ui/components/ProfileMenu.js.map +1 -1
- package/lib/module/ui/components/SignInModal.js +4 -4
- package/lib/module/ui/components/SignInModal.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +510 -470
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +61 -60
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/inSessionTokenRefresh.js +24 -43
- package/lib/module/ui/context/inSessionTokenRefresh.js.map +1 -1
- package/lib/module/ui/context/silentSessionRestore.js +12 -20
- package/lib/module/ui/context/silentSessionRestore.js.map +1 -1
- package/lib/module/ui/hooks/useAuth.js +4 -3
- package/lib/module/ui/hooks/useAuth.js.map +1 -1
- package/lib/module/ui/hooks/useOxyAuthSession.js +12 -7
- package/lib/module/ui/hooks/useOxyAuthSession.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js +18 -66
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/hooks/useSwitchableAccounts.js +283 -0
- package/lib/module/ui/hooks/useSwitchableAccounts.js.map +1 -0
- package/lib/module/ui/hooks/useWebSSO.js +13 -192
- package/lib/module/ui/hooks/useWebSSO.js.map +1 -1
- package/lib/module/ui/index.js +0 -1
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +2 -2
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/ui/session/createSessionClient.js +25 -0
- package/lib/module/ui/session/createSessionClient.js.map +1 -0
- package/lib/module/ui/session/index.js +17 -0
- package/lib/module/ui/session/index.js.map +1 -0
- package/lib/module/ui/session/projectSessionState.js +79 -0
- package/lib/module/ui/session/projectSessionState.js.map +1 -0
- package/lib/module/ui/session/sessionClientHost.js +26 -0
- package/lib/module/ui/session/sessionClientHost.js.map +1 -0
- package/lib/module/ui/session/tokenTransport.js +74 -0
- package/lib/module/ui/session/tokenTransport.js.map +1 -0
- package/lib/module/ui/utils/activeAuthuser.js +34 -76
- package/lib/module/ui/utils/activeAuthuser.js.map +1 -1
- package/lib/module/ui/utils/sessionHelpers.js +0 -49
- package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/module/utils/deviceFlowSignIn.js +71 -16
- package/lib/module/utils/deviceFlowSignIn.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -3
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +4 -2
- package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts +7 -8
- package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts +12 -9
- package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +16 -13
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +27 -3
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/inSessionTokenRefresh.d.ts +22 -17
- package/lib/typescript/commonjs/ui/context/inSessionTokenRefresh.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/silentSessionRestore.d.ts +12 -18
- package/lib/typescript/commonjs/ui/context/silentSessionRestore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +1 -0
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts +1 -1
- package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts +2 -2
- package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +162 -0
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts +13 -52
- package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts +15 -0
- package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/session/index.d.ts +15 -0
- package/lib/typescript/commonjs/ui/session/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/session/projectSessionState.d.ts +45 -0
- package/lib/typescript/commonjs/ui/session/projectSessionState.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/session/sessionClientHost.d.ts +14 -0
- package/lib/typescript/commonjs/ui/session/sessionClientHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts +24 -0
- package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts +21 -29
- package/lib/typescript/commonjs/ui/utils/activeAuthuser.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/sessionHelpers.d.ts +0 -19
- package/lib/typescript/commonjs/ui/utils/sessionHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts +51 -19
- package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -3
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/AccountMenu.d.ts +4 -2
- package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/AccountSwitcher.d.ts +7 -8
- package/lib/typescript/module/ui/components/AccountSwitcher.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ProfileMenu.d.ts +12 -9
- package/lib/typescript/module/ui/components/ProfileMenu.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts +16 -13
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +27 -3
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/inSessionTokenRefresh.d.ts +22 -17
- package/lib/typescript/module/ui/context/inSessionTokenRefresh.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/silentSessionRestore.d.ts +12 -18
- package/lib/typescript/module/ui/context/silentSessionRestore.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +1 -0
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useAuth.d.ts +1 -1
- package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts +2 -2
- package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +162 -0
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/useWebSSO.d.ts +13 -52
- package/lib/typescript/module/ui/hooks/useWebSSO.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/createSessionClient.d.ts +15 -0
- package/lib/typescript/module/ui/session/createSessionClient.d.ts.map +1 -0
- package/lib/typescript/module/ui/session/index.d.ts +15 -0
- package/lib/typescript/module/ui/session/index.d.ts.map +1 -0
- package/lib/typescript/module/ui/session/projectSessionState.d.ts +45 -0
- package/lib/typescript/module/ui/session/projectSessionState.d.ts.map +1 -0
- package/lib/typescript/module/ui/session/sessionClientHost.d.ts +14 -0
- package/lib/typescript/module/ui/session/sessionClientHost.d.ts.map +1 -0
- package/lib/typescript/module/ui/session/tokenTransport.d.ts +24 -0
- package/lib/typescript/module/ui/session/tokenTransport.d.ts.map +1 -0
- package/lib/typescript/module/ui/utils/activeAuthuser.d.ts +21 -29
- package/lib/typescript/module/ui/utils/activeAuthuser.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/sessionHelpers.d.ts +0 -19
- package/lib/typescript/module/ui/utils/sessionHelpers.d.ts.map +1 -1
- package/lib/typescript/module/utils/deviceFlowSignIn.d.ts +51 -19
- package/lib/typescript/module/utils/deviceFlowSignIn.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +9 -9
- package/src/ui/components/AccountMenu.tsx +117 -70
- package/src/ui/components/AccountSwitcher.tsx +88 -134
- package/src/ui/components/ProfileMenu.tsx +158 -162
- package/src/ui/components/SignInModal.tsx +5 -5
- package/src/ui/context/OxyContext.tsx +560 -475
- package/src/ui/context/hooks/useAuthOperations.ts +72 -63
- package/src/ui/context/inSessionTokenRefresh.ts +23 -42
- package/src/ui/context/silentSessionRestore.ts +12 -26
- package/src/ui/hooks/useAuth.ts +4 -3
- package/src/ui/hooks/useOxyAuthSession.ts +13 -8
- package/src/ui/hooks/useSessionManagement.ts +16 -87
- package/src/ui/hooks/useSwitchableAccounts.ts +397 -0
- package/src/ui/hooks/useWebSSO.ts +13 -227
- package/src/ui/index.ts +0 -1
- package/src/ui/screens/OxyAuthScreen.tsx +2 -2
- package/src/ui/session/__tests__/createSessionClient.test.ts +41 -0
- package/src/ui/session/__tests__/projectSessionState.test.ts +114 -0
- package/src/ui/session/__tests__/sessionClientHost.test.ts +43 -0
- package/src/ui/session/__tests__/tokenTransport.test.ts +142 -0
- package/src/ui/session/createSessionClient.ts +21 -0
- package/src/ui/session/index.ts +19 -0
- package/src/ui/session/projectSessionState.ts +85 -0
- package/src/ui/session/sessionClientHost.ts +27 -0
- package/src/ui/session/tokenTransport.ts +76 -0
- package/src/ui/utils/activeAuthuser.ts +34 -76
- package/src/ui/utils/sessionHelpers.ts +0 -66
- package/src/utils/__tests__/deviceFlowSignIn.test.ts +243 -34
- package/src/utils/deviceFlowSignIn.ts +98 -21
- package/lib/commonjs/ui/components/accountMenuRows.js +0 -33
- package/lib/commonjs/ui/components/accountMenuRows.js.map +0 -1
- package/lib/commonjs/ui/hooks/useDeviceAccounts.js +0 -280
- package/lib/commonjs/ui/hooks/useDeviceAccounts.js.map +0 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +0 -203
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +0 -1
- package/lib/commonjs/utils/silentGuardKey.js +0 -54
- package/lib/commonjs/utils/silentGuardKey.js.map +0 -1
- package/lib/module/ui/components/accountMenuRows.js +0 -29
- package/lib/module/ui/components/accountMenuRows.js.map +0 -1
- package/lib/module/ui/hooks/useDeviceAccounts.js +0 -276
- package/lib/module/ui/hooks/useDeviceAccounts.js.map +0 -1
- package/lib/module/ui/hooks/useSessionSocket.js +0 -199
- package/lib/module/ui/hooks/useSessionSocket.js.map +0 -1
- package/lib/module/utils/silentGuardKey.js +0 -49
- package/lib/module/utils/silentGuardKey.js.map +0 -1
- package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts +0 -34
- package/lib/typescript/commonjs/ui/components/accountMenuRows.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/hooks/useDeviceAccounts.d.ts +0 -133
- package/lib/typescript/commonjs/ui/hooks/useDeviceAccounts.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/hooks/useSessionSocket.d.ts +0 -14
- package/lib/typescript/commonjs/ui/hooks/useSessionSocket.d.ts.map +0 -1
- package/lib/typescript/commonjs/utils/silentGuardKey.d.ts +0 -31
- package/lib/typescript/commonjs/utils/silentGuardKey.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/accountMenuRows.d.ts +0 -34
- package/lib/typescript/module/ui/components/accountMenuRows.d.ts.map +0 -1
- package/lib/typescript/module/ui/hooks/useDeviceAccounts.d.ts +0 -133
- package/lib/typescript/module/ui/hooks/useDeviceAccounts.d.ts.map +0 -1
- package/lib/typescript/module/ui/hooks/useSessionSocket.d.ts +0 -14
- package/lib/typescript/module/ui/hooks/useSessionSocket.d.ts.map +0 -1
- package/lib/typescript/module/utils/silentGuardKey.d.ts +0 -31
- package/lib/typescript/module/utils/silentGuardKey.d.ts.map +0 -1
- package/src/ui/components/accountMenuRows.ts +0 -48
- package/src/ui/hooks/useDeviceAccounts.ts +0 -344
- package/src/ui/hooks/useSessionSocket.ts +0 -233
- package/src/ui/utils/__tests__/activeAuthuser.test.ts +0 -75
- package/src/utils/__tests__/silentGuardKey.test.ts +0 -82
- package/src/utils/silentGuardKey.ts +0 -46
|
@@ -2,25 +2,51 @@
|
|
|
2
2
|
* Shared, pure orchestration for completing the cross-app device-flow sign-in
|
|
3
3
|
* (the QR-code / "Open Oxy Auth" path used on native and web).
|
|
4
4
|
*
|
|
5
|
-
* THE BUG THIS FIXES (native): once another authenticated device
|
|
6
|
-
* pending AuthSession, the originating client is notified
|
|
7
|
-
* deep-link) with the authorized `sessionId`. Before any
|
|
8
|
-
* code can use it, the client MUST exchange the secret
|
|
9
|
-
* (held only by this client, generated for THIS flow)
|
|
10
|
-
* token via `claimSessionByToken` — the device-flow
|
|
11
|
-
* code-for-token exchange (RFC 8628 §3.4).
|
|
5
|
+
* THE FIRST BUG THIS FIXES (native): once another authenticated device
|
|
6
|
+
* approves the pending AuthSession, the originating client is notified
|
|
7
|
+
* (socket / poll / deep-link) with the authorized `sessionId`. Before any
|
|
8
|
+
* session-management code can use it, the client MUST exchange the secret
|
|
9
|
+
* 128-bit `sessionToken` (held only by this client, generated for THIS flow)
|
|
10
|
+
* for the first access token via `claimSessionByToken` — the device-flow
|
|
11
|
+
* equivalent of OAuth's code-for-token exchange (RFC 8628 §3.4).
|
|
12
|
+
*
|
|
13
|
+
* THE SECOND BUG THIS FIXES (session-sync cutover regression): the
|
|
14
|
+
* freshly-claimed session is NOT yet registered in the device's
|
|
15
|
+
* server-authoritative session set — nothing has run
|
|
16
|
+
* `sessionClient.addCurrentAccount()` for it — so it must NOT be committed
|
|
17
|
+
* through `switchSession`. That path is now an account-SWITCH between
|
|
18
|
+
* accounts already registered on this device (`OxyContext`'s
|
|
19
|
+
* `switchSessionForContext`), and throws `No device account found for
|
|
20
|
+
* session "..."` for anything else, surfacing as "Authorization successful
|
|
21
|
+
* but failed to complete sign in." Instead the claimed session must be
|
|
22
|
+
* committed through the SAME path a fresh password sign-in uses —
|
|
23
|
+
* `useOxy().handleWebSession` (`OxyContext`'s `handleWebSSOSession`) — which
|
|
24
|
+
* registers the account into the device set, persists it durably, and
|
|
25
|
+
* hydrates the full user profile.
|
|
12
26
|
*
|
|
13
27
|
* Skipping the claim leaves the SDK with NO bearer token: the session is
|
|
14
28
|
* authorized server-side but the app never becomes authenticated and the UI
|
|
15
|
-
* sits "Waiting for authorization..." forever. Consolidating the
|
|
16
|
-
* sequence here keeps native and web identical and
|
|
29
|
+
* sits "Waiting for authorization..." forever. Consolidating the
|
|
30
|
+
* claim->commit sequence here keeps native and web identical and
|
|
31
|
+
* unit-testable.
|
|
17
32
|
*/
|
|
18
33
|
|
|
19
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
KeyManager,
|
|
36
|
+
establishIdpSessionAfterClaim,
|
|
37
|
+
type EstablishAfterClaimDeps,
|
|
38
|
+
type MinimalUserData,
|
|
39
|
+
type SessionLoginResponse,
|
|
40
|
+
type SsoEstablishClient,
|
|
41
|
+
type User,
|
|
42
|
+
} from '@oxyhq/core';
|
|
20
43
|
|
|
21
44
|
interface DeviceFlowClaimResult {
|
|
22
45
|
accessToken?: string;
|
|
23
46
|
sessionId?: string;
|
|
47
|
+
deviceId?: string;
|
|
48
|
+
expiresAt?: string;
|
|
49
|
+
user?: User;
|
|
24
50
|
}
|
|
25
51
|
|
|
26
52
|
/**
|
|
@@ -28,8 +54,11 @@ interface DeviceFlowClaimResult {
|
|
|
28
54
|
* structural type (rather than importing the full client) so the helper is
|
|
29
55
|
* trivially unit-testable with a stub and never pulls the RN/Expo runtime into
|
|
30
56
|
* a test bundle.
|
|
57
|
+
*
|
|
58
|
+
* Extends {@link SsoEstablishClient} (`requestSsoEstablishUrl`) so the WEB
|
|
59
|
+
* post-claim durable-session hop can be driven off the same client.
|
|
31
60
|
*/
|
|
32
|
-
export interface DeviceFlowClient {
|
|
61
|
+
export interface DeviceFlowClient extends SsoEstablishClient {
|
|
33
62
|
/**
|
|
34
63
|
* Exchange the device-flow `sessionToken` for the first access + refresh
|
|
35
64
|
* token, planting them on the client. Single-use; replay is rejected by the
|
|
@@ -49,25 +78,37 @@ export interface CompleteDeviceFlowSignInOptions {
|
|
|
49
78
|
*/
|
|
50
79
|
sessionToken: string;
|
|
51
80
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
81
|
+
* `useOxy().handleWebSession` — commits the freshly-claimed session into
|
|
82
|
+
* context state through the SAME path a password sign-in uses:
|
|
83
|
+
* registers the account into the device's server-authoritative session set,
|
|
84
|
+
* persists it durably, and hydrates the full user profile. Runs AFTER the
|
|
85
|
+
* bearer is planted so its bearer-protected calls succeed.
|
|
55
86
|
*/
|
|
56
|
-
|
|
87
|
+
commitSession: (session: SessionLoginResponse) => Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Injectable web seams for the post-claim durable-session establish hop
|
|
90
|
+
* ({@link establishIdpSessionAfterClaim}). Omit in production — the defaults
|
|
91
|
+
* resolve to `window.*` (and no-op off-web / on native). Tests inject fakes to
|
|
92
|
+
* drive the web path deterministically.
|
|
93
|
+
*/
|
|
94
|
+
establishDeps?: EstablishAfterClaimDeps;
|
|
57
95
|
}
|
|
58
96
|
|
|
59
97
|
/**
|
|
60
98
|
* Complete a device-flow sign-in: claim the first access token with the secret
|
|
61
|
-
* `sessionToken` (planting the bearer), then
|
|
62
|
-
* `
|
|
99
|
+
* `sessionToken` (planting the bearer), then commit the resulting session via
|
|
100
|
+
* `commitSession` (registers it into the device's server-authoritative session
|
|
101
|
+
* set and hydrates the full user). Returns the authenticated user.
|
|
63
102
|
*
|
|
64
|
-
* Throws if
|
|
103
|
+
* Throws if the claim did not return a usable session, or if either the claim
|
|
104
|
+
* or the commit fails; callers surface a retry UI.
|
|
65
105
|
*/
|
|
66
106
|
export async function completeDeviceFlowSignIn({
|
|
67
107
|
oxyServices,
|
|
68
108
|
sessionId,
|
|
69
109
|
sessionToken,
|
|
70
|
-
|
|
110
|
+
commitSession,
|
|
111
|
+
establishDeps,
|
|
71
112
|
}: CompleteDeviceFlowSignInOptions): Promise<User> {
|
|
72
113
|
// 1) Plant the bearer + refresh tokens. The claim response is also persisted
|
|
73
114
|
// to native shared secure storage so a later cold boot has a bearer before
|
|
@@ -77,6 +118,42 @@ export async function completeDeviceFlowSignIn({
|
|
|
77
118
|
await KeyManager.storeSharedSession(claimed.sessionId || sessionId, claimed.accessToken);
|
|
78
119
|
}
|
|
79
120
|
|
|
80
|
-
|
|
81
|
-
|
|
121
|
+
if (!claimed?.accessToken || !claimed.user) {
|
|
122
|
+
throw new Error('Device-flow claim did not return a usable session');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// `SessionLoginResponse.user` is the minimal session-carried shape (avatar
|
|
126
|
+
// is `string | undefined`); the claim response returns the full `User`
|
|
127
|
+
// (avatar is `string | null | undefined`). Normalize rather than widening
|
|
128
|
+
// `SessionLoginResponse.user` to accept `null`.
|
|
129
|
+
const minimalUser: MinimalUserData = {
|
|
130
|
+
id: claimed.user.id,
|
|
131
|
+
username: claimed.user.username,
|
|
132
|
+
name: claimed.user.name,
|
|
133
|
+
avatar: claimed.user.avatar ?? undefined,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// 2) Bearer is now planted — commit the session through the same path a
|
|
137
|
+
// fresh sign-in uses so it is registered into the device's
|
|
138
|
+
// server-authoritative session set instead of an account switch.
|
|
139
|
+
await commitSession({
|
|
140
|
+
sessionId: claimed.sessionId || sessionId,
|
|
141
|
+
deviceId: claimed.deviceId ?? '',
|
|
142
|
+
expiresAt: claimed.expiresAt ?? '',
|
|
143
|
+
user: minimalUser,
|
|
144
|
+
accessToken: claimed.accessToken,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// 3) WEB durable-session hop (no-op on native). A device-flow claim plants
|
|
148
|
+
// ONLY in-memory tokens — no IdP `fedcm_session` cookie is ever planted, so
|
|
149
|
+
// a reload cannot re-mint a token and the session is lost. Now that the
|
|
150
|
+
// session is committed AND durably persisted (step 2), plant the per-apex
|
|
151
|
+
// IdP cookie via ONE top-level establish hop. Single attempt; total (never
|
|
152
|
+
// throws) — an establish failure leaves the committed session as-is. On web
|
|
153
|
+
// success it navigates away, so it is the LAST step: the browser tears the
|
|
154
|
+
// page down on the next tick, after `claimed.user` is returned to the
|
|
155
|
+
// caller's `onSignedIn`.
|
|
156
|
+
await establishIdpSessionAfterClaim(oxyServices, establishDeps ?? {});
|
|
157
|
+
|
|
158
|
+
return claimed.user;
|
|
82
159
|
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.buildAccountRows = buildAccountRows;
|
|
7
|
-
/**
|
|
8
|
-
* Pure builder for `AccountMenu` rows. Extracted so the multi-account display
|
|
9
|
-
* logic can be unit-tested without rendering React Native.
|
|
10
|
-
*
|
|
11
|
-
* Maps each {@link DeviceAccount} (sourced from `useDeviceAccounts()`, which
|
|
12
|
-
* hydrates EVERY account with real name/email/avatar/color from the shared
|
|
13
|
-
* apex `refresh-all` path or the local fallback) into an `AccountRow`.
|
|
14
|
-
*
|
|
15
|
-
* `secondary` is the account's real email when present; otherwise it falls
|
|
16
|
-
* back to the `@handle` line. A missing email is NEVER synthesized into a fake
|
|
17
|
-
* `username@oxy.so` — the device-account layer already resolved `email` to the
|
|
18
|
-
* real value or the `@handle` fallback.
|
|
19
|
-
*/
|
|
20
|
-
function buildAccountRows({
|
|
21
|
-
accounts
|
|
22
|
-
}) {
|
|
23
|
-
return accounts.map(account => ({
|
|
24
|
-
sessionId: account.sessionId,
|
|
25
|
-
authuser: account.authuser,
|
|
26
|
-
isActive: account.isCurrent,
|
|
27
|
-
displayName: account.displayName,
|
|
28
|
-
secondary: account.email,
|
|
29
|
-
avatarUri: account.avatarUrl,
|
|
30
|
-
user: account.user
|
|
31
|
-
}));
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=accountMenuRows.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["buildAccountRows","accounts","map","account","sessionId","authuser","isActive","isCurrent","displayName","secondary","email","avatarUri","avatarUrl","user"],"sourceRoot":"../../../../src","sources":["ui/components/accountMenuRows.ts"],"mappings":";;;;;;AAsBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASA,gBAAgBA,CAAC;EAC7BC;AACmB,CAAC,EAAgB;EACpC,OAAOA,QAAQ,CAACC,GAAG,CAAEC,OAAsB,KAAkB;IACzDC,SAAS,EAAED,OAAO,CAACC,SAAS;IAC5BC,QAAQ,EAAEF,OAAO,CAACE,QAAQ;IAC1BC,QAAQ,EAAEH,OAAO,CAACI,SAAS;IAC3BC,WAAW,EAAEL,OAAO,CAACK,WAAW;IAChCC,SAAS,EAAEN,OAAO,CAACO,KAAK;IACxBC,SAAS,EAAER,OAAO,CAACS,SAAS;IAC5BC,IAAI,EAAEV,OAAO,CAACU;EAClB,CAAC,CAAC,CAAC;AACP","ignoreList":[]}
|
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.markCurrentAccount = markCurrentAccount;
|
|
7
|
-
exports.useDeviceAccounts = useDeviceAccounts;
|
|
8
|
-
var _react = require("react");
|
|
9
|
-
var _reactQuery = require("@tanstack/react-query");
|
|
10
|
-
var _core = require("@oxyhq/core");
|
|
11
|
-
var _OxyContext = require("../context/OxyContext.js");
|
|
12
|
-
var _useI18n = require("./useI18n.js");
|
|
13
|
-
var _queryKeys = require("./queries/queryKeys.js");
|
|
14
|
-
/**
|
|
15
|
-
* The per-account user shape carried by a {@link DeviceAccount}. Either:
|
|
16
|
-
* - the minimal projection returned by `POST /auth/refresh-all`
|
|
17
|
-
* ({@link RefreshAllAccountUser}, the shared apex path), or
|
|
18
|
-
* - the SDK's canonical {@link User} document (the active row on the local
|
|
19
|
-
* fallback path, which already has the full user loaded in `useOxy()`).
|
|
20
|
-
*
|
|
21
|
-
* Both satisfy `getAccountDisplayName`'s `DisplayNameUserShape`, so display
|
|
22
|
-
* resolution is uniform across paths.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* One signed-in account on this device, fully hydrated for the account
|
|
27
|
-
* chooser. Unlike the old `AccountMenu` behaviour (which only carried the
|
|
28
|
-
* ACTIVE session's user), EVERY entry here carries real per-account
|
|
29
|
-
* `displayName` / `email` / `avatarUrl` / `color`.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Resolve which entries are the current account, robustly.
|
|
34
|
-
*
|
|
35
|
-
* Primary signal: `entry.sessionId === activeSessionId`. On the web shared-apex
|
|
36
|
-
* path, `refreshAllSessions()` returns SERVER-side session ids that may not
|
|
37
|
-
* equal the locally-stored `activeSessionId` (a different storage namespace /
|
|
38
|
-
* server perspective), so a pure `sessionId` match can flag NO row as current —
|
|
39
|
-
* the bug that surfaced as "Not signed in" even while authenticated.
|
|
40
|
-
*
|
|
41
|
-
* Fallbacks, applied only when the `sessionId` match found nothing AND the user
|
|
42
|
-
* is authenticated:
|
|
43
|
-
* 1. Match the live `user.id` against each entry's per-account user id.
|
|
44
|
-
* 2. If still nothing and there is exactly one account, mark that one current.
|
|
45
|
-
*
|
|
46
|
-
* At most ONE entry is ever marked current.
|
|
47
|
-
*
|
|
48
|
-
* Pure & side-effect free so it is unit-testable without rendering React.
|
|
49
|
-
*/
|
|
50
|
-
function markCurrentAccount(accounts, activeSessionId, liveUserId, isAuthenticated) {
|
|
51
|
-
const bySession = accounts.map(account => ({
|
|
52
|
-
...account,
|
|
53
|
-
isCurrent: Boolean(activeSessionId) && account.sessionId === activeSessionId
|
|
54
|
-
}));
|
|
55
|
-
if (bySession.some(account => account.isCurrent) || !isAuthenticated) {
|
|
56
|
-
return bySession;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// No row matched by session id: fall back to the live user's id, marking at
|
|
60
|
-
// most the FIRST matching entry current (never more than one).
|
|
61
|
-
if (liveUserId) {
|
|
62
|
-
let matched = false;
|
|
63
|
-
const byUser = bySession.map(account => {
|
|
64
|
-
if (!matched && account.user.id === liveUserId) {
|
|
65
|
-
matched = true;
|
|
66
|
-
return {
|
|
67
|
-
...account,
|
|
68
|
-
isCurrent: true
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return account;
|
|
72
|
-
});
|
|
73
|
-
if (matched) {
|
|
74
|
-
return byUser;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Authenticated, nothing matched, but there is exactly one account → it must
|
|
79
|
-
// be the current one (single-account shared-apex / cross-domain case).
|
|
80
|
-
if (bySession.length === 1) {
|
|
81
|
-
return [{
|
|
82
|
-
...bySession[0],
|
|
83
|
-
isCurrent: true
|
|
84
|
-
}];
|
|
85
|
-
}
|
|
86
|
-
return bySession;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Resolve every account signed in on this device for the unified account
|
|
91
|
-
* switcher, with real per-account name / email / avatar / color.
|
|
92
|
-
*
|
|
93
|
-
* ## Data sources (web vs native)
|
|
94
|
-
*
|
|
95
|
-
* - **Web on a `*.oxy.so` host** → `oxyServices.refreshAllSessions()` returns
|
|
96
|
-
* the full apex device-account list (identical to what `auth.oxy.so` sees,
|
|
97
|
-
* because the `Domain=oxy.so` refresh cookies reach `api.oxy.so`). Used
|
|
98
|
-
* directly — this is the `fromSharedApex: true` path.
|
|
99
|
-
* - **Cross-domain web (non-`oxy.so` apex)** OR **native (no browser cookies)**
|
|
100
|
-
* → `refreshAllSessions()` yields `{ accounts: [] }` (the apex cookies never
|
|
101
|
-
* reach the request: cross-domain by `Domain`, native by having no cookie
|
|
102
|
-
* jar at all; a 401 is also normalised to `{ accounts: [] }` inside the
|
|
103
|
-
* core mixin). In that case we FALL BACK to the SDK's local multi-account
|
|
104
|
-
* list from `useOxy()` (`sessions` + `activeSessionId` + the active `user`).
|
|
105
|
-
* This is the `fromSharedApex: false` path.
|
|
106
|
-
*
|
|
107
|
-
* The fallback decision is purely data-driven: **if `refreshAllSessions()`
|
|
108
|
-
* returns >0 accounts, use the shared path; otherwise fall back to local
|
|
109
|
-
* `useOxy()` sessions.** No host sniffing is needed — the cookie scoping does
|
|
110
|
-
* the discrimination for us, and the same code path works on native (where the
|
|
111
|
-
* fetch returns `{ accounts: [] }`).
|
|
112
|
-
*
|
|
113
|
-
* ## Why React Query (not a `useRef`/`useState` start-once like the auth app)
|
|
114
|
-
*
|
|
115
|
-
* The auth app's `use-device-accounts.ts` hand-rolls a `startedRef` because it
|
|
116
|
-
* has no React Query. The SDK does. `refreshAllSessions()` ROTATES single-use
|
|
117
|
-
* refresh cookies on every call, so it must run AT MOST ONCE per page load:
|
|
118
|
-
* we model that with `staleTime: Infinity` + `gcTime: Infinity` +
|
|
119
|
-
* `refetchOnWindowFocus/Reconnect/Mount: false` + `retry: false`. React Query
|
|
120
|
-
* dedupes concurrent mounts and caches the single result for the page's
|
|
121
|
-
* lifetime — the exact "run once" guarantee the auth app documents, but
|
|
122
|
-
* without the manual ref/state machinery.
|
|
123
|
-
*
|
|
124
|
-
* ## Validation note (intentionally NO zod re-parse)
|
|
125
|
-
*
|
|
126
|
-
* The auth app's hook calls `fetch` directly, so IT must `safeParse` the wire
|
|
127
|
-
* response with `@oxyhq/contracts`. This hook calls
|
|
128
|
-
* `oxyServices.refreshAllSessions()`, whose core mixin ALREADY validates and
|
|
129
|
-
* normalises the wire response (skips entries missing required fields,
|
|
130
|
-
* normalises `authuser` null→0, builds the `RefreshAllAccountUser` shape) — the
|
|
131
|
-
* mixin is the single source of truth. Re-validating the SDK's own already-typed
|
|
132
|
-
* output here would be redundant double-validation, so we do not re-parse.
|
|
133
|
-
*
|
|
134
|
-
* ## Error handling
|
|
135
|
-
*
|
|
136
|
-
* `refreshAllSessions()` already maps 401/404/abort to `{ accounts: [] }`
|
|
137
|
-
* internally. Any OTHER failure (network, 5xx) propagates as a thrown error and
|
|
138
|
-
* is surfaced by React Query (`query.isError`) — never swallowed. Callers that
|
|
139
|
-
* don't care can ignore it; the hook still returns the local fallback list so
|
|
140
|
-
* the chooser stays usable.
|
|
141
|
-
*/
|
|
142
|
-
function useDeviceAccounts() {
|
|
143
|
-
const {
|
|
144
|
-
oxyServices,
|
|
145
|
-
sessions,
|
|
146
|
-
activeSessionId,
|
|
147
|
-
user,
|
|
148
|
-
isAuthenticated
|
|
149
|
-
} = (0, _OxyContext.useOxy)();
|
|
150
|
-
const {
|
|
151
|
-
locale
|
|
152
|
-
} = (0, _useI18n.useI18n)();
|
|
153
|
-
|
|
154
|
-
// Stable, per-API-origin query key. `refreshAllSessions` resolves against
|
|
155
|
-
// the session base url derived from `getBaseURL()`, so keying on it scopes
|
|
156
|
-
// the cached result to the API the provider is pointed at.
|
|
157
|
-
const baseURL = oxyServices.getBaseURL();
|
|
158
|
-
const query = (0, _reactQuery.useQuery)({
|
|
159
|
-
queryKey: [..._queryKeys.queryKeys.accounts.all, 'deviceAccounts', baseURL],
|
|
160
|
-
queryFn: () => oxyServices.refreshAllSessions(),
|
|
161
|
-
// Only attempt the shared apex path while signed in. When logged out
|
|
162
|
-
// there is nothing to enumerate and the fallback (also empty) is used.
|
|
163
|
-
enabled: isAuthenticated,
|
|
164
|
-
// Single-use cookie rotation → run at most once per page load.
|
|
165
|
-
staleTime: Number.POSITIVE_INFINITY,
|
|
166
|
-
gcTime: Number.POSITIVE_INFINITY,
|
|
167
|
-
refetchOnWindowFocus: false,
|
|
168
|
-
refetchOnReconnect: false,
|
|
169
|
-
refetchOnMount: false,
|
|
170
|
-
retry: false
|
|
171
|
-
});
|
|
172
|
-
const sharedAccounts = query.data?.accounts ?? [];
|
|
173
|
-
const fromSharedApex = sharedAccounts.length > 0;
|
|
174
|
-
const accounts = (0, _react.useMemo)(() => {
|
|
175
|
-
const resolveAvatarUrl = avatar => avatar ? oxyServices.getFileDownloadUrl(avatar, 'thumb') : undefined;
|
|
176
|
-
|
|
177
|
-
// Build a single current-account row from the live `useOxy().user`. Used
|
|
178
|
-
// as a last-resort fallback when neither the shared-apex probe nor the
|
|
179
|
-
// local session store yielded a row but the user IS authenticated (e.g.
|
|
180
|
-
// a cross-domain host where the apex probe returned empty before the
|
|
181
|
-
// local session store hydrated). The signed-in user must ALWAYS be
|
|
182
|
-
// represented. Email is the REAL email or the `@handle` line — never a
|
|
183
|
-
// synthesized `username@oxy.so`.
|
|
184
|
-
const liveUserRow = () => {
|
|
185
|
-
if (!isAuthenticated || !user || !activeSessionId) {
|
|
186
|
-
return [];
|
|
187
|
-
}
|
|
188
|
-
const displayName = (0, _core.getAccountDisplayName)(user, locale);
|
|
189
|
-
const handle = (0, _core.getAccountFallbackHandle)(user);
|
|
190
|
-
const secondaryHandle = handle ? `@${handle}` : null;
|
|
191
|
-
return [{
|
|
192
|
-
sessionId: activeSessionId,
|
|
193
|
-
authuser: undefined,
|
|
194
|
-
isCurrent: true,
|
|
195
|
-
displayName,
|
|
196
|
-
email: user.email ?? secondaryHandle,
|
|
197
|
-
avatarUrl: resolveAvatarUrl(user.avatar),
|
|
198
|
-
color: user.color ?? null,
|
|
199
|
-
user
|
|
200
|
-
}];
|
|
201
|
-
};
|
|
202
|
-
let built;
|
|
203
|
-
if (fromSharedApex) {
|
|
204
|
-
// Shared apex path: every entry carries a real per-account user.
|
|
205
|
-
built = sharedAccounts.flatMap(entry => {
|
|
206
|
-
if (!entry.user) {
|
|
207
|
-
return [];
|
|
208
|
-
}
|
|
209
|
-
const accountUser = entry.user;
|
|
210
|
-
const displayName = (0, _core.getAccountDisplayName)(accountUser, locale);
|
|
211
|
-
const handle = (0, _core.getAccountFallbackHandle)(accountUser);
|
|
212
|
-
const email = entry.user.email ?? null;
|
|
213
|
-
const secondaryHandle = handle ? `@${handle}` : null;
|
|
214
|
-
return [{
|
|
215
|
-
sessionId: entry.sessionId,
|
|
216
|
-
authuser: entry.authuser,
|
|
217
|
-
// Provisional; finalised by `markCurrentAccount` below so the
|
|
218
|
-
// shared-apex path is robust to server/local session-id skew.
|
|
219
|
-
isCurrent: false,
|
|
220
|
-
displayName,
|
|
221
|
-
// Real email, or null (NEVER synthesized). The UI uses the
|
|
222
|
-
// `@handle` line only when email is genuinely absent.
|
|
223
|
-
email: email ?? secondaryHandle,
|
|
224
|
-
avatarUrl: resolveAvatarUrl(entry.user.avatar),
|
|
225
|
-
color: entry.user.color ?? null,
|
|
226
|
-
user: accountUser
|
|
227
|
-
}];
|
|
228
|
-
});
|
|
229
|
-
} else {
|
|
230
|
-
// Local fallback path: build from the SDK's multi-session store. The
|
|
231
|
-
// active session row gets the full loaded `user`; inactive fallback
|
|
232
|
-
// rows carry only what the `ClientSession` exposes (no synthesized
|
|
233
|
-
// identity — they show the active user's data only when active).
|
|
234
|
-
built = (sessions ?? []).flatMap(session => {
|
|
235
|
-
const isCurrent = session.sessionId === activeSessionId;
|
|
236
|
-
if (!isCurrent || !user) {
|
|
237
|
-
return [];
|
|
238
|
-
}
|
|
239
|
-
const accountUser = user;
|
|
240
|
-
const displayName = (0, _core.getAccountDisplayName)(accountUser, locale);
|
|
241
|
-
const handle = (0, _core.getAccountFallbackHandle)(accountUser);
|
|
242
|
-
const email = user.email ?? null;
|
|
243
|
-
const secondaryHandle = handle ? `@${handle}` : null;
|
|
244
|
-
return [{
|
|
245
|
-
sessionId: session.sessionId,
|
|
246
|
-
authuser: session.authuser,
|
|
247
|
-
isCurrent,
|
|
248
|
-
displayName,
|
|
249
|
-
email: email ?? secondaryHandle,
|
|
250
|
-
avatarUrl: resolveAvatarUrl(user.avatar),
|
|
251
|
-
color: user.color ?? null,
|
|
252
|
-
user: accountUser
|
|
253
|
-
}];
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Robust current-account detection: tolerate server/local session-id
|
|
258
|
-
// skew on the shared-apex path by falling back to the live user's id and
|
|
259
|
-
// the single-account heuristic.
|
|
260
|
-
const flagged = markCurrentAccount(built, activeSessionId, user?.id ?? null, isAuthenticated);
|
|
261
|
-
|
|
262
|
-
// The signed-in user must ALWAYS be represented. If detection produced
|
|
263
|
-
// an empty list yet the user is authenticated, synthesize a single
|
|
264
|
-
// current row from the live `useOxy().user`.
|
|
265
|
-
if (flagged.length === 0) {
|
|
266
|
-
return liveUserRow();
|
|
267
|
-
}
|
|
268
|
-
return flagged;
|
|
269
|
-
}, [fromSharedApex, sharedAccounts, sessions, activeSessionId, user, isAuthenticated, locale, oxyServices]);
|
|
270
|
-
return {
|
|
271
|
-
accounts,
|
|
272
|
-
// `isLoading` only reflects the shared probe while it's the relevant
|
|
273
|
-
// source. Once we know we're on the fallback (probe settled with 0
|
|
274
|
-
// accounts) the local list is synchronously available.
|
|
275
|
-
isLoading: isAuthenticated && query.isLoading,
|
|
276
|
-
currentSessionId: activeSessionId ?? null,
|
|
277
|
-
fromSharedApex
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
//# sourceMappingURL=useDeviceAccounts.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_reactQuery","_core","_OxyContext","_useI18n","_queryKeys","markCurrentAccount","accounts","activeSessionId","liveUserId","isAuthenticated","bySession","map","account","isCurrent","Boolean","sessionId","some","matched","byUser","user","id","length","useDeviceAccounts","oxyServices","sessions","useOxy","locale","useI18n","baseURL","getBaseURL","query","useQuery","queryKey","queryKeys","all","queryFn","refreshAllSessions","enabled","staleTime","Number","POSITIVE_INFINITY","gcTime","refetchOnWindowFocus","refetchOnReconnect","refetchOnMount","retry","sharedAccounts","data","fromSharedApex","useMemo","resolveAvatarUrl","avatar","getFileDownloadUrl","undefined","liveUserRow","displayName","getAccountDisplayName","handle","getAccountFallbackHandle","secondaryHandle","authuser","email","avatarUrl","color","built","flatMap","entry","accountUser","session","flagged","isLoading","currentSessionId"],"sourceRoot":"../../../../src","sources":["ui/hooks/useDeviceAccounts.ts"],"mappings":"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","ignoreList":[]}
|