@oxyhq/services 13.3.0 → 14.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/index.js +11 -16
- 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/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 -4
- 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/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/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/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 -8
- 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/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
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useEffect, useRef } from 'react';
|
|
4
|
-
import io from 'socket.io-client';
|
|
5
|
-
import { toast } from '@oxyhq/bloom';
|
|
6
|
-
import { logger } from '@oxyhq/core';
|
|
7
|
-
import { createDebugLogger } from '@oxyhq/core';
|
|
8
|
-
const debug = createDebugLogger('SessionSocket');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Server-emitted event types on the `session_update` channel.
|
|
12
|
-
*
|
|
13
|
-
* `session_removed`, `device_removed`, `sessions_removed` are the ONLY
|
|
14
|
-
* events that may sign the user out. Anything else (e.g. `session_created`
|
|
15
|
-
* fired right after a successful sign-in) MUST NOT trigger sign-out — see
|
|
16
|
-
* the comment on the `default` branch below.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
export function useSessionSocket({
|
|
20
|
-
userId,
|
|
21
|
-
activeSessionId,
|
|
22
|
-
currentDeviceId,
|
|
23
|
-
refreshSessions,
|
|
24
|
-
clearSessionState,
|
|
25
|
-
baseURL,
|
|
26
|
-
getAccessToken,
|
|
27
|
-
onRemoteSignOut,
|
|
28
|
-
onSessionRemoved
|
|
29
|
-
}) {
|
|
30
|
-
const socketRef = useRef(null);
|
|
31
|
-
|
|
32
|
-
// Store callbacks in refs to avoid reconnecting when they change
|
|
33
|
-
const refreshSessionsRef = useRef(refreshSessions);
|
|
34
|
-
const clearSessionStateRef = useRef(clearSessionState);
|
|
35
|
-
const onRemoteSignOutRef = useRef(onRemoteSignOut);
|
|
36
|
-
const onSessionRemovedRef = useRef(onSessionRemoved);
|
|
37
|
-
const activeSessionIdRef = useRef(activeSessionId);
|
|
38
|
-
const currentDeviceIdRef = useRef(currentDeviceId);
|
|
39
|
-
const getAccessTokenRef = useRef(getAccessToken);
|
|
40
|
-
|
|
41
|
-
// Update refs when callbacks change
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
refreshSessionsRef.current = refreshSessions;
|
|
44
|
-
clearSessionStateRef.current = clearSessionState;
|
|
45
|
-
onRemoteSignOutRef.current = onRemoteSignOut;
|
|
46
|
-
onSessionRemovedRef.current = onSessionRemoved;
|
|
47
|
-
activeSessionIdRef.current = activeSessionId;
|
|
48
|
-
currentDeviceIdRef.current = currentDeviceId;
|
|
49
|
-
getAccessTokenRef.current = getAccessToken;
|
|
50
|
-
}, [refreshSessions, clearSessionState, onRemoteSignOut, onSessionRemoved, activeSessionId, currentDeviceId, getAccessToken]);
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
if (!userId || !baseURL) {
|
|
53
|
-
// Clean up if userId or baseURL becomes invalid
|
|
54
|
-
if (socketRef.current) {
|
|
55
|
-
socketRef.current.disconnect();
|
|
56
|
-
socketRef.current = null;
|
|
57
|
-
}
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Disconnect previous socket if switching users
|
|
62
|
-
if (socketRef.current) {
|
|
63
|
-
socketRef.current.disconnect();
|
|
64
|
-
socketRef.current = null;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Connect with auth token; use callback so reconnections get a fresh token
|
|
68
|
-
socketRef.current = io(baseURL, {
|
|
69
|
-
transports: ['websocket'],
|
|
70
|
-
auth: cb => {
|
|
71
|
-
const token = getAccessTokenRef.current();
|
|
72
|
-
cb({
|
|
73
|
-
token: token ?? ''
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
const socket = socketRef.current;
|
|
78
|
-
|
|
79
|
-
// Server auto-joins the user to `user:<userId>` room on connection
|
|
80
|
-
const handleConnect = () => {
|
|
81
|
-
debug.log('Socket connected:', socket.id);
|
|
82
|
-
};
|
|
83
|
-
const refreshSessionsSafe = () => {
|
|
84
|
-
refreshSessionsRef.current().catch(error => {
|
|
85
|
-
// Refresh errors shouldn't break the socket handler. They happen
|
|
86
|
-
// routinely when sessions are removed mid-fetch — log and move on.
|
|
87
|
-
if (__DEV__) {
|
|
88
|
-
logger.debug('Failed to refresh sessions after session_update', {
|
|
89
|
-
component: 'useSessionSocket'
|
|
90
|
-
}, error);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
const triggerLocalSignOut = async (toastMessage, errorContext) => {
|
|
95
|
-
if (onRemoteSignOutRef.current) {
|
|
96
|
-
onRemoteSignOutRef.current();
|
|
97
|
-
} else {
|
|
98
|
-
toast.info(toastMessage);
|
|
99
|
-
}
|
|
100
|
-
// Clear local state since the server has already removed the session.
|
|
101
|
-
// Await so storage cleanup completes before any subsequent navigation.
|
|
102
|
-
try {
|
|
103
|
-
await clearSessionStateRef.current();
|
|
104
|
-
} catch (error) {
|
|
105
|
-
if (__DEV__) {
|
|
106
|
-
logger.error(`Failed to clear session state after ${errorContext}`, error instanceof Error ? error : new Error(String(error)), {
|
|
107
|
-
component: 'useSessionSocket'
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
const handleSessionUpdate = async data => {
|
|
113
|
-
debug.log('Received session_update:', data);
|
|
114
|
-
const currentActiveSessionId = activeSessionIdRef.current;
|
|
115
|
-
const currentDeviceIdValue = currentDeviceIdRef.current;
|
|
116
|
-
|
|
117
|
-
// Strict whitelist. Every event type that may sign the user out must
|
|
118
|
-
// appear in the switch. Anything unknown falls through to `default`,
|
|
119
|
-
// which is intentionally a no-op for session lifecycle — it only logs
|
|
120
|
-
// in dev. This guards against future server-side event additions
|
|
121
|
-
// accidentally triggering sign-out.
|
|
122
|
-
switch (data.type) {
|
|
123
|
-
case 'session_removed':
|
|
124
|
-
{
|
|
125
|
-
if (data.sessionId && onSessionRemovedRef.current) {
|
|
126
|
-
onSessionRemovedRef.current(data.sessionId);
|
|
127
|
-
}
|
|
128
|
-
if (data.sessionId && data.sessionId === currentActiveSessionId) {
|
|
129
|
-
await triggerLocalSignOut('You have been signed out remotely.', 'session_removed');
|
|
130
|
-
} else {
|
|
131
|
-
refreshSessionsSafe();
|
|
132
|
-
}
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
case 'device_removed':
|
|
136
|
-
{
|
|
137
|
-
if (data.sessionIds && onSessionRemovedRef.current) {
|
|
138
|
-
for (const sessionId of data.sessionIds) {
|
|
139
|
-
onSessionRemovedRef.current(sessionId);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
if (data.deviceId && currentDeviceIdValue && data.deviceId === currentDeviceIdValue) {
|
|
143
|
-
await triggerLocalSignOut('This device has been removed. You have been signed out.', 'device_removed');
|
|
144
|
-
} else {
|
|
145
|
-
refreshSessionsSafe();
|
|
146
|
-
}
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
case 'sessions_removed':
|
|
150
|
-
{
|
|
151
|
-
if (data.sessionIds && onSessionRemovedRef.current) {
|
|
152
|
-
for (const sessionId of data.sessionIds) {
|
|
153
|
-
onSessionRemovedRef.current(sessionId);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (data.sessionIds && currentActiveSessionId && data.sessionIds.includes(currentActiveSessionId)) {
|
|
157
|
-
await triggerLocalSignOut('You have been signed out remotely.', 'sessions_removed');
|
|
158
|
-
} else {
|
|
159
|
-
refreshSessionsSafe();
|
|
160
|
-
}
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
case 'session_created':
|
|
164
|
-
case 'session_update':
|
|
165
|
-
{
|
|
166
|
-
// Lifecycle event for the current user. Just resync the sessions
|
|
167
|
-
// list — never sign out. A prior implementation compared
|
|
168
|
-
// `data.sessionId === currentActiveSessionId` and signed the user
|
|
169
|
-
// out if true, which was catastrophic: a
|
|
170
|
-
// `session_created` event fired immediately after a successful
|
|
171
|
-
// sign-in carries the user's NEW (now-active) session id, which
|
|
172
|
-
// matched and triggered an instant remote sign-out toast on every
|
|
173
|
-
// login. Whitelist explicitly; never fall through.
|
|
174
|
-
refreshSessionsSafe();
|
|
175
|
-
break;
|
|
176
|
-
}
|
|
177
|
-
default:
|
|
178
|
-
{
|
|
179
|
-
if (__DEV__) {
|
|
180
|
-
logger.warn('Unknown session socket event type', {
|
|
181
|
-
component: 'useSessionSocket',
|
|
182
|
-
type: data.type
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
socket.on('connect', handleConnect);
|
|
190
|
-
socket.on('session_update', handleSessionUpdate);
|
|
191
|
-
return () => {
|
|
192
|
-
socket.off('connect', handleConnect);
|
|
193
|
-
socket.off('session_update', handleSessionUpdate);
|
|
194
|
-
socket.disconnect();
|
|
195
|
-
socketRef.current = null;
|
|
196
|
-
};
|
|
197
|
-
}, [userId, baseURL]); // Only depend on userId and baseURL - callbacks are in refs
|
|
198
|
-
}
|
|
199
|
-
//# sourceMappingURL=useSessionSocket.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["useEffect","useRef","io","toast","logger","createDebugLogger","debug","useSessionSocket","userId","activeSessionId","currentDeviceId","refreshSessions","clearSessionState","baseURL","getAccessToken","onRemoteSignOut","onSessionRemoved","socketRef","refreshSessionsRef","clearSessionStateRef","onRemoteSignOutRef","onSessionRemovedRef","activeSessionIdRef","currentDeviceIdRef","getAccessTokenRef","current","disconnect","transports","auth","cb","token","socket","handleConnect","log","id","refreshSessionsSafe","catch","error","__DEV__","component","triggerLocalSignOut","toastMessage","errorContext","info","Error","String","handleSessionUpdate","data","currentActiveSessionId","currentDeviceIdValue","type","sessionId","sessionIds","deviceId","includes","warn","on","off"],"sourceRoot":"../../../../src","sources":["ui/hooks/useSessionSocket.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shared, pure helpers for building the `origin|baseURL` signature used as the
|
|
5
|
-
* module-level run-once guard key for cold-boot silent-SSO probes
|
|
6
|
-
* (`silentColdBootKey` in `OxyContext`, `ssoSignature` in `useWebSSO`).
|
|
7
|
-
*
|
|
8
|
-
* NATIVE SAFETY (the bug this fixes): React Native aliases a global `window`
|
|
9
|
-
* (it points at the JS global object), so `typeof window !== 'undefined'` is
|
|
10
|
-
* `true` on native — but `window.location` is `undefined`. Reading
|
|
11
|
-
* `window.location.origin` after only a `typeof window` check therefore throws
|
|
12
|
-
* `TypeError: Cannot read property 'origin' of undefined` on native. Because
|
|
13
|
-
* the key is built UNCONDITIONALLY at the top of the cold-boot path (before its
|
|
14
|
-
* try/catch), that throw escaped session restore entirely and broke
|
|
15
|
-
* cross-session restore on native. Both prior copies of the guard had the same
|
|
16
|
-
* insufficient `typeof window` check and were prone to drift, so the read is
|
|
17
|
-
* consolidated here behind a guard that also verifies `window.location`.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Read `window.location.origin` safely on every platform.
|
|
22
|
-
*
|
|
23
|
-
* Returns the browser origin on web, and the sentinel `'no-origin'` anywhere
|
|
24
|
-
* `window.location` is absent (React Native, SSR/Node). Never throws.
|
|
25
|
-
*/
|
|
26
|
-
export function safeWindowOrigin() {
|
|
27
|
-
if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {
|
|
28
|
-
return window.location.origin;
|
|
29
|
-
}
|
|
30
|
-
return 'no-origin';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Build the stable `origin|baseURL` signature for the silent-SSO run-once
|
|
35
|
-
* guard. Two providers pointed at the same API from the same origin share one
|
|
36
|
-
* attempt. `getBaseURL` is invoked defensively (it may be absent or throw on a
|
|
37
|
-
* partially-initialised client); any failure degrades to an empty baseURL.
|
|
38
|
-
*/
|
|
39
|
-
export function buildSilentGuardKey(getBaseURL) {
|
|
40
|
-
const origin = safeWindowOrigin();
|
|
41
|
-
let baseURL = '';
|
|
42
|
-
try {
|
|
43
|
-
baseURL = getBaseURL?.() ?? '';
|
|
44
|
-
} catch {
|
|
45
|
-
baseURL = '';
|
|
46
|
-
}
|
|
47
|
-
return `${origin}|${baseURL}`;
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=silentGuardKey.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["safeWindowOrigin","window","location","origin","buildSilentGuardKey","getBaseURL","baseURL"],"sourceRoot":"../../../src","sources":["utils/silentGuardKey.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,gBAAgBA,CAAA,EAAW;EACzC,IAAI,OAAOC,MAAM,KAAK,WAAW,IAAI,OAAOA,MAAM,CAACC,QAAQ,KAAK,WAAW,EAAE;IAC3E,OAAOD,MAAM,CAACC,QAAQ,CAACC,MAAM;EAC/B;EACA,OAAO,WAAW;AACpB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,mBAAmBA,CAACC,UAAqC,EAAU;EACjF,MAAMF,MAAM,GAAGH,gBAAgB,CAAC,CAAC;EACjC,IAAIM,OAAO,GAAG,EAAE;EAChB,IAAI;IACFA,OAAO,GAAGD,UAAU,GAAG,CAAC,IAAI,EAAE;EAChC,CAAC,CAAC,MAAM;IACNC,OAAO,GAAG,EAAE;EACd;EACA,OAAO,GAAGH,MAAM,IAAIG,OAAO,EAAE;AAC/B","ignoreList":[]}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { DeviceAccount, DeviceAccountUser } from '../hooks/useDeviceAccounts';
|
|
2
|
-
export interface AccountRow {
|
|
3
|
-
sessionId: string;
|
|
4
|
-
/** Device-local refresh-cookie slot index (web silent-switch). */
|
|
5
|
-
authuser?: number;
|
|
6
|
-
isActive: boolean;
|
|
7
|
-
displayName: string;
|
|
8
|
-
secondary: string | null;
|
|
9
|
-
avatarUri?: string;
|
|
10
|
-
user: DeviceAccountUser | null;
|
|
11
|
-
}
|
|
12
|
-
export interface BuildAccountRowsInput {
|
|
13
|
-
/**
|
|
14
|
-
* Per-device account entries from {@link useDeviceAccounts}. Each entry
|
|
15
|
-
* already carries real per-account `displayName` / `email` / `avatarUrl` /
|
|
16
|
-
* `color`, so EVERY row (not just the active one) renders full identity.
|
|
17
|
-
*/
|
|
18
|
-
accounts: DeviceAccount[];
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Pure builder for `AccountMenu` rows. Extracted so the multi-account display
|
|
22
|
-
* logic can be unit-tested without rendering React Native.
|
|
23
|
-
*
|
|
24
|
-
* Maps each {@link DeviceAccount} (sourced from `useDeviceAccounts()`, which
|
|
25
|
-
* hydrates EVERY account with real name/email/avatar/color from the shared
|
|
26
|
-
* apex `refresh-all` path or the local fallback) into an `AccountRow`.
|
|
27
|
-
*
|
|
28
|
-
* `secondary` is the account's real email when present; otherwise it falls
|
|
29
|
-
* back to the `@handle` line. A missing email is NEVER synthesized into a fake
|
|
30
|
-
* `username@oxy.so` — the device-account layer already resolved `email` to the
|
|
31
|
-
* real value or the `@handle` fallback.
|
|
32
|
-
*/
|
|
33
|
-
export declare function buildAccountRows({ accounts, }: BuildAccountRowsInput): AccountRow[];
|
|
34
|
-
//# sourceMappingURL=accountMenuRows.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accountMenuRows.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/accountMenuRows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEnF,MAAM,WAAW,UAAU;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,EAC7B,QAAQ,GACX,EAAE,qBAAqB,GAAG,UAAU,EAAE,CAUtC"}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import type { RefreshAllAccountUser, User } from '@oxyhq/core';
|
|
2
|
-
/**
|
|
3
|
-
* The per-account user shape carried by a {@link DeviceAccount}. Either:
|
|
4
|
-
* - the minimal projection returned by `POST /auth/refresh-all`
|
|
5
|
-
* ({@link RefreshAllAccountUser}, the shared apex path), or
|
|
6
|
-
* - the SDK's canonical {@link User} document (the active row on the local
|
|
7
|
-
* fallback path, which already has the full user loaded in `useOxy()`).
|
|
8
|
-
*
|
|
9
|
-
* Both satisfy `getAccountDisplayName`'s `DisplayNameUserShape`, so display
|
|
10
|
-
* resolution is uniform across paths.
|
|
11
|
-
*/
|
|
12
|
-
export type DeviceAccountUser = RefreshAllAccountUser | User;
|
|
13
|
-
/**
|
|
14
|
-
* One signed-in account on this device, fully hydrated for the account
|
|
15
|
-
* chooser. Unlike the old `AccountMenu` behaviour (which only carried the
|
|
16
|
-
* ACTIVE session's user), EVERY entry here carries real per-account
|
|
17
|
-
* `displayName` / `email` / `avatarUrl` / `color`.
|
|
18
|
-
*/
|
|
19
|
-
export interface DeviceAccount {
|
|
20
|
-
/** Session id used to switch to this account on native. */
|
|
21
|
-
sessionId: string;
|
|
22
|
-
/**
|
|
23
|
-
* Device-local refresh-cookie slot index (0..N-1), present only on the
|
|
24
|
-
* shared apex path. Web silent-switch (`refreshTokenViaCookie({ authuser }`)
|
|
25
|
-
* keys off this; absent on the local fallback and on native.
|
|
26
|
-
*/
|
|
27
|
-
authuser?: number;
|
|
28
|
-
/** Whether this account is the currently-active session. */
|
|
29
|
-
isCurrent: boolean;
|
|
30
|
-
/** Friendly display name (never blank — falls back to a handle/sentinel). */
|
|
31
|
-
displayName: string;
|
|
32
|
-
/**
|
|
33
|
-
* Real account email, or `null` when the account genuinely has none.
|
|
34
|
-
* NEVER a synthesized `username@oxy.so` — a missing email stays `null` and
|
|
35
|
-
* the UI falls back to the `@handle` secondary line.
|
|
36
|
-
*/
|
|
37
|
-
email: string | null;
|
|
38
|
-
/** Resolved avatar thumbnail URL, or `undefined` when the account has no avatar. */
|
|
39
|
-
avatarUrl?: string;
|
|
40
|
-
/** Account's preferred Bloom color preset, or `null` when unset. */
|
|
41
|
-
color: string | null;
|
|
42
|
-
/** The underlying per-account user payload (shared projection or full User). */
|
|
43
|
-
user: DeviceAccountUser;
|
|
44
|
-
}
|
|
45
|
-
export interface UseDeviceAccountsResult {
|
|
46
|
-
/** Every account signed in on this device, current one(s) flagged `isCurrent`. */
|
|
47
|
-
accounts: DeviceAccount[];
|
|
48
|
-
/** True until the first detection settles. */
|
|
49
|
-
isLoading: boolean;
|
|
50
|
-
/** The currently-active session id (mirrors `useOxy().activeSessionId`). */
|
|
51
|
-
currentSessionId: string | null;
|
|
52
|
-
/**
|
|
53
|
-
* `true` when the list came from the shared apex path
|
|
54
|
-
* (`refreshAllSessions()` returned >0 accounts — the cross-domain SSO cookie
|
|
55
|
-
* set on `*.oxy.so`). `false` when it came from the local `useOxy()`
|
|
56
|
-
* fallback (native, or cross-domain web where the apex cookie is absent).
|
|
57
|
-
*/
|
|
58
|
-
fromSharedApex: boolean;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Resolve which entries are the current account, robustly.
|
|
62
|
-
*
|
|
63
|
-
* Primary signal: `entry.sessionId === activeSessionId`. On the web shared-apex
|
|
64
|
-
* path, `refreshAllSessions()` returns SERVER-side session ids that may not
|
|
65
|
-
* equal the locally-stored `activeSessionId` (a different storage namespace /
|
|
66
|
-
* server perspective), so a pure `sessionId` match can flag NO row as current —
|
|
67
|
-
* the bug that surfaced as "Not signed in" even while authenticated.
|
|
68
|
-
*
|
|
69
|
-
* Fallbacks, applied only when the `sessionId` match found nothing AND the user
|
|
70
|
-
* is authenticated:
|
|
71
|
-
* 1. Match the live `user.id` against each entry's per-account user id.
|
|
72
|
-
* 2. If still nothing and there is exactly one account, mark that one current.
|
|
73
|
-
*
|
|
74
|
-
* At most ONE entry is ever marked current.
|
|
75
|
-
*
|
|
76
|
-
* Pure & side-effect free so it is unit-testable without rendering React.
|
|
77
|
-
*/
|
|
78
|
-
export declare function markCurrentAccount(accounts: DeviceAccount[], activeSessionId: string | null | undefined, liveUserId: string | null | undefined, isAuthenticated: boolean): DeviceAccount[];
|
|
79
|
-
/**
|
|
80
|
-
* Resolve every account signed in on this device for the unified account
|
|
81
|
-
* switcher, with real per-account name / email / avatar / color.
|
|
82
|
-
*
|
|
83
|
-
* ## Data sources (web vs native)
|
|
84
|
-
*
|
|
85
|
-
* - **Web on a `*.oxy.so` host** → `oxyServices.refreshAllSessions()` returns
|
|
86
|
-
* the full apex device-account list (identical to what `auth.oxy.so` sees,
|
|
87
|
-
* because the `Domain=oxy.so` refresh cookies reach `api.oxy.so`). Used
|
|
88
|
-
* directly — this is the `fromSharedApex: true` path.
|
|
89
|
-
* - **Cross-domain web (non-`oxy.so` apex)** OR **native (no browser cookies)**
|
|
90
|
-
* → `refreshAllSessions()` yields `{ accounts: [] }` (the apex cookies never
|
|
91
|
-
* reach the request: cross-domain by `Domain`, native by having no cookie
|
|
92
|
-
* jar at all; a 401 is also normalised to `{ accounts: [] }` inside the
|
|
93
|
-
* core mixin). In that case we FALL BACK to the SDK's local multi-account
|
|
94
|
-
* list from `useOxy()` (`sessions` + `activeSessionId` + the active `user`).
|
|
95
|
-
* This is the `fromSharedApex: false` path.
|
|
96
|
-
*
|
|
97
|
-
* The fallback decision is purely data-driven: **if `refreshAllSessions()`
|
|
98
|
-
* returns >0 accounts, use the shared path; otherwise fall back to local
|
|
99
|
-
* `useOxy()` sessions.** No host sniffing is needed — the cookie scoping does
|
|
100
|
-
* the discrimination for us, and the same code path works on native (where the
|
|
101
|
-
* fetch returns `{ accounts: [] }`).
|
|
102
|
-
*
|
|
103
|
-
* ## Why React Query (not a `useRef`/`useState` start-once like the auth app)
|
|
104
|
-
*
|
|
105
|
-
* The auth app's `use-device-accounts.ts` hand-rolls a `startedRef` because it
|
|
106
|
-
* has no React Query. The SDK does. `refreshAllSessions()` ROTATES single-use
|
|
107
|
-
* refresh cookies on every call, so it must run AT MOST ONCE per page load:
|
|
108
|
-
* we model that with `staleTime: Infinity` + `gcTime: Infinity` +
|
|
109
|
-
* `refetchOnWindowFocus/Reconnect/Mount: false` + `retry: false`. React Query
|
|
110
|
-
* dedupes concurrent mounts and caches the single result for the page's
|
|
111
|
-
* lifetime — the exact "run once" guarantee the auth app documents, but
|
|
112
|
-
* without the manual ref/state machinery.
|
|
113
|
-
*
|
|
114
|
-
* ## Validation note (intentionally NO zod re-parse)
|
|
115
|
-
*
|
|
116
|
-
* The auth app's hook calls `fetch` directly, so IT must `safeParse` the wire
|
|
117
|
-
* response with `@oxyhq/contracts`. This hook calls
|
|
118
|
-
* `oxyServices.refreshAllSessions()`, whose core mixin ALREADY validates and
|
|
119
|
-
* normalises the wire response (skips entries missing required fields,
|
|
120
|
-
* normalises `authuser` null→0, builds the `RefreshAllAccountUser` shape) — the
|
|
121
|
-
* mixin is the single source of truth. Re-validating the SDK's own already-typed
|
|
122
|
-
* output here would be redundant double-validation, so we do not re-parse.
|
|
123
|
-
*
|
|
124
|
-
* ## Error handling
|
|
125
|
-
*
|
|
126
|
-
* `refreshAllSessions()` already maps 401/404/abort to `{ accounts: [] }`
|
|
127
|
-
* internally. Any OTHER failure (network, 5xx) propagates as a thrown error and
|
|
128
|
-
* is surfaced by React Query (`query.isError`) — never swallowed. Callers that
|
|
129
|
-
* don't care can ignore it; the hook still returns the local fallback list so
|
|
130
|
-
* the chooser stays usable.
|
|
131
|
-
*/
|
|
132
|
-
export declare function useDeviceAccounts(): UseDeviceAccountsResult;
|
|
133
|
-
//# sourceMappingURL=useDeviceAccounts.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useDeviceAccounts.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useDeviceAccounts.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACR,qBAAqB,EACrB,IAAI,EAEP,MAAM,aAAa,CAAC;AAKrB;;;;;;;;;GASG;AACH,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,GAAG,IAAI,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC1B,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gFAAgF;IAChF,IAAI,EAAE,iBAAiB,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACpC,kFAAkF;IAClF,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,8CAA8C;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAC9B,QAAQ,EAAE,aAAa,EAAE,EACzB,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC1C,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACrC,eAAe,EAAE,OAAO,GACzB,aAAa,EAAE,CAiCjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAgB,iBAAiB,IAAI,uBAAuB,CA4J3D"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
interface UseSessionSocketProps {
|
|
2
|
-
userId: string | null | undefined;
|
|
3
|
-
activeSessionId: string | null | undefined;
|
|
4
|
-
currentDeviceId: string | null | undefined;
|
|
5
|
-
refreshSessions: () => Promise<void>;
|
|
6
|
-
clearSessionState: () => Promise<void>;
|
|
7
|
-
baseURL: string;
|
|
8
|
-
getAccessToken: () => string | null;
|
|
9
|
-
onRemoteSignOut?: () => void;
|
|
10
|
-
onSessionRemoved?: (sessionId: string) => void;
|
|
11
|
-
}
|
|
12
|
-
export declare function useSessionSocket({ userId, activeSessionId, currentDeviceId, refreshSessions, clearSessionState, baseURL, getAccessToken, onRemoteSignOut, onSessionRemoved, }: UseSessionSocketProps): void;
|
|
13
|
-
export {};
|
|
14
|
-
//# sourceMappingURL=useSessionSocket.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSessionSocket.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useSessionSocket.ts"],"names":[],"mappings":"AA8BA,UAAU,qBAAqB;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAChD;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,eAAe,EACf,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,eAAe,EACf,gBAAgB,GACjB,EAAE,qBAAqB,QAoLvB"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared, pure helpers for building the `origin|baseURL` signature used as the
|
|
3
|
-
* module-level run-once guard key for cold-boot silent-SSO probes
|
|
4
|
-
* (`silentColdBootKey` in `OxyContext`, `ssoSignature` in `useWebSSO`).
|
|
5
|
-
*
|
|
6
|
-
* NATIVE SAFETY (the bug this fixes): React Native aliases a global `window`
|
|
7
|
-
* (it points at the JS global object), so `typeof window !== 'undefined'` is
|
|
8
|
-
* `true` on native — but `window.location` is `undefined`. Reading
|
|
9
|
-
* `window.location.origin` after only a `typeof window` check therefore throws
|
|
10
|
-
* `TypeError: Cannot read property 'origin' of undefined` on native. Because
|
|
11
|
-
* the key is built UNCONDITIONALLY at the top of the cold-boot path (before its
|
|
12
|
-
* try/catch), that throw escaped session restore entirely and broke
|
|
13
|
-
* cross-session restore on native. Both prior copies of the guard had the same
|
|
14
|
-
* insufficient `typeof window` check and were prone to drift, so the read is
|
|
15
|
-
* consolidated here behind a guard that also verifies `window.location`.
|
|
16
|
-
*/
|
|
17
|
-
/**
|
|
18
|
-
* Read `window.location.origin` safely on every platform.
|
|
19
|
-
*
|
|
20
|
-
* Returns the browser origin on web, and the sentinel `'no-origin'` anywhere
|
|
21
|
-
* `window.location` is absent (React Native, SSR/Node). Never throws.
|
|
22
|
-
*/
|
|
23
|
-
export declare function safeWindowOrigin(): string;
|
|
24
|
-
/**
|
|
25
|
-
* Build the stable `origin|baseURL` signature for the silent-SSO run-once
|
|
26
|
-
* guard. Two providers pointed at the same API from the same origin share one
|
|
27
|
-
* attempt. `getBaseURL` is invoked defensively (it may be absent or throw on a
|
|
28
|
-
* partially-initialised client); any failure degrades to an empty baseURL.
|
|
29
|
-
*/
|
|
30
|
-
export declare function buildSilentGuardKey(getBaseURL?: () => string | undefined): string;
|
|
31
|
-
//# sourceMappingURL=silentGuardKey.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"silentGuardKey.d.ts","sourceRoot":"","sources":["../../../../src/utils/silentGuardKey.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,GAAG,MAAM,CASjF"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { DeviceAccount, DeviceAccountUser } from '../hooks/useDeviceAccounts.js';
|
|
2
|
-
export interface AccountRow {
|
|
3
|
-
sessionId: string;
|
|
4
|
-
/** Device-local refresh-cookie slot index (web silent-switch). */
|
|
5
|
-
authuser?: number;
|
|
6
|
-
isActive: boolean;
|
|
7
|
-
displayName: string;
|
|
8
|
-
secondary: string | null;
|
|
9
|
-
avatarUri?: string;
|
|
10
|
-
user: DeviceAccountUser | null;
|
|
11
|
-
}
|
|
12
|
-
export interface BuildAccountRowsInput {
|
|
13
|
-
/**
|
|
14
|
-
* Per-device account entries from {@link useDeviceAccounts}. Each entry
|
|
15
|
-
* already carries real per-account `displayName` / `email` / `avatarUrl` /
|
|
16
|
-
* `color`, so EVERY row (not just the active one) renders full identity.
|
|
17
|
-
*/
|
|
18
|
-
accounts: DeviceAccount[];
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Pure builder for `AccountMenu` rows. Extracted so the multi-account display
|
|
22
|
-
* logic can be unit-tested without rendering React Native.
|
|
23
|
-
*
|
|
24
|
-
* Maps each {@link DeviceAccount} (sourced from `useDeviceAccounts()`, which
|
|
25
|
-
* hydrates EVERY account with real name/email/avatar/color from the shared
|
|
26
|
-
* apex `refresh-all` path or the local fallback) into an `AccountRow`.
|
|
27
|
-
*
|
|
28
|
-
* `secondary` is the account's real email when present; otherwise it falls
|
|
29
|
-
* back to the `@handle` line. A missing email is NEVER synthesized into a fake
|
|
30
|
-
* `username@oxy.so` — the device-account layer already resolved `email` to the
|
|
31
|
-
* real value or the `@handle` fallback.
|
|
32
|
-
*/
|
|
33
|
-
export declare function buildAccountRows({ accounts, }: BuildAccountRowsInput): AccountRow[];
|
|
34
|
-
//# sourceMappingURL=accountMenuRows.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"accountMenuRows.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/accountMenuRows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,+BAA4B,CAAC;AAEnF,MAAM,WAAW,UAAU;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,EAC7B,QAAQ,GACX,EAAE,qBAAqB,GAAG,UAAU,EAAE,CAUtC"}
|