@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
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import type { User, AccountNode, AccountRelationship, AccountKind, AccountMember } from '@oxyhq/core';
|
|
2
|
+
/**
|
|
3
|
+
* The per-account user shape carried by a {@link SwitchableAccount}. The SDK's
|
|
4
|
+
* canonical {@link User} document — either the freshest `useOxy().user` (the
|
|
5
|
+
* active row), a profile resolved via `oxyServices.getUsersByIds()` (every other
|
|
6
|
+
* device row), or the `account` document embedded in an account-graph node.
|
|
7
|
+
*/
|
|
8
|
+
export type SwitchableAccountUser = User;
|
|
9
|
+
/**
|
|
10
|
+
* One account the signed-in user can switch INTO, in the uniform switch model.
|
|
11
|
+
*
|
|
12
|
+
* A switchable account is either a device sign-in, an account-graph node (owned
|
|
13
|
+
* org / shared-with-you), or BOTH (an account that has been switched into
|
|
14
|
+
* becomes a device session while still being a graph node — the two are deduped
|
|
15
|
+
* into a single row). Every row carries a canonical `accountId` (the uniform
|
|
16
|
+
* switch key passed to `switchToAccount`); `sessionId` is present IFF the
|
|
17
|
+
* account is currently signed in on THIS device.
|
|
18
|
+
*/
|
|
19
|
+
export interface SwitchableAccount {
|
|
20
|
+
/**
|
|
21
|
+
* Canonical account id (the underlying `User._id`). The single key EVERY
|
|
22
|
+
* switch uses — `switchToAccount(accountId)`. Always present.
|
|
23
|
+
*/
|
|
24
|
+
accountId: string;
|
|
25
|
+
/**
|
|
26
|
+
* Device session id, present IFF this account is signed in on THIS device.
|
|
27
|
+
* Absent for a graph account not yet switched into. Used only for
|
|
28
|
+
* device-scoped actions (per-account sign-out via `removeSession`); switching
|
|
29
|
+
* ALWAYS goes through `switchToAccount(accountId)`.
|
|
30
|
+
*/
|
|
31
|
+
sessionId?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Device-local refresh-cookie slot index (0..N-1), when the underlying
|
|
34
|
+
* `ClientSession` carries one (web silent-switch). Absent on native and for
|
|
35
|
+
* graph-only rows.
|
|
36
|
+
*/
|
|
37
|
+
authuser?: number;
|
|
38
|
+
/** Whether this account is the currently-active one. */
|
|
39
|
+
isCurrent: boolean;
|
|
40
|
+
/** Whether this account is signed in on THIS device (has a `sessionId`). */
|
|
41
|
+
onDevice: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* The caller's relationship to this account when it appears in the account
|
|
44
|
+
* graph: `self` (the caller's own personal account), `owner` (an org/project/
|
|
45
|
+
* bot the caller owns), or `member` (shared with the caller). Absent for an
|
|
46
|
+
* independent device sign-in that is NOT in the active account's graph.
|
|
47
|
+
*/
|
|
48
|
+
relationship?: AccountRelationship;
|
|
49
|
+
/** Account classification (personal/organization/…). Cosmetic badge only. */
|
|
50
|
+
kind?: AccountKind;
|
|
51
|
+
/** Parent account id for 2-level tree grouping, or `null` for a root. */
|
|
52
|
+
parentAccountId?: string | null;
|
|
53
|
+
/**
|
|
54
|
+
* The caller's effective membership (role + permissions) in this account when
|
|
55
|
+
* it appears in the graph, or `null`/absent otherwise. Use `permissions` to
|
|
56
|
+
* gate per-account settings UI.
|
|
57
|
+
*/
|
|
58
|
+
callerMembership?: AccountMember | null;
|
|
59
|
+
/** Friendly display name (never blank — falls back to a handle/sentinel). */
|
|
60
|
+
displayName: string;
|
|
61
|
+
/**
|
|
62
|
+
* Real account email, or `null` when the account genuinely has none. NEVER a
|
|
63
|
+
* synthesized `username@oxy.so` — a missing email falls back to the `@handle`
|
|
64
|
+
* secondary line.
|
|
65
|
+
*/
|
|
66
|
+
email: string | null;
|
|
67
|
+
/** Resolved avatar thumbnail URL, or `undefined` when the account has no avatar. */
|
|
68
|
+
avatarUrl?: string;
|
|
69
|
+
/** Account's preferred Bloom color preset, or `null` when unset. */
|
|
70
|
+
color: string | null;
|
|
71
|
+
/** The underlying per-account user payload. */
|
|
72
|
+
user: SwitchableAccountUser;
|
|
73
|
+
}
|
|
74
|
+
export interface UseSwitchableAccountsResult {
|
|
75
|
+
/** Every switchable account (device sign-ins + linked graph accounts). */
|
|
76
|
+
accounts: SwitchableAccount[];
|
|
77
|
+
/** True until the per-device-account profile fetch settles. */
|
|
78
|
+
isLoading: boolean;
|
|
79
|
+
/** The currently-active session id (mirrors `useOxy().activeSessionId`). */
|
|
80
|
+
currentSessionId: string | null;
|
|
81
|
+
}
|
|
82
|
+
/** The minimal device-session shape {@link buildSwitchableAccounts} reads. */
|
|
83
|
+
export interface SwitchableSessionInput {
|
|
84
|
+
sessionId: string;
|
|
85
|
+
userId?: string;
|
|
86
|
+
authuser?: number;
|
|
87
|
+
}
|
|
88
|
+
export interface BuildSwitchableAccountsInput {
|
|
89
|
+
/** Device sessions projected from the server-authoritative `SessionClient`. */
|
|
90
|
+
sessions: SwitchableSessionInput[];
|
|
91
|
+
/** The currently-active session id. */
|
|
92
|
+
activeSessionId: string | null;
|
|
93
|
+
/** The freshest copy of the active account's user (`useOxy().user`). */
|
|
94
|
+
liveUser: User | null;
|
|
95
|
+
isAuthenticated: boolean;
|
|
96
|
+
/** The account graph under the active account (`useOxy().accounts`). */
|
|
97
|
+
graph: AccountNode[];
|
|
98
|
+
/** Per-device-account profiles resolved via `getUsersByIds()`, keyed by id. */
|
|
99
|
+
profilesById: Map<string, User>;
|
|
100
|
+
locale: string;
|
|
101
|
+
/** Resolves a file id to a thumbnail URL (bound to `getFileDownloadUrl`). */
|
|
102
|
+
resolveAvatarUrl: (avatar: string | null | undefined) => string | undefined;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Resolve which entries are the current account, robustly.
|
|
106
|
+
*
|
|
107
|
+
* Primary signal: `entry.sessionId === activeSessionId` — both are projected
|
|
108
|
+
* from the same `SessionClient` state, so this normally matches exactly.
|
|
109
|
+
* Fallbacks exist only to bridge the brief window between the two sequential
|
|
110
|
+
* `updateSessions` / `setActiveSessionId` calls in `OxyContext.syncFromClient`,
|
|
111
|
+
* applied only when the `sessionId` match found nothing AND the user is
|
|
112
|
+
* authenticated:
|
|
113
|
+
* 1. Match the live `user.id` against each entry's per-account user id.
|
|
114
|
+
* 2. If still nothing and there is exactly one account, mark that one current.
|
|
115
|
+
*
|
|
116
|
+
* At most ONE entry is ever marked current. Runs over DEVICE rows only (graph
|
|
117
|
+
* rows are never active — the active account is always a device session), so the
|
|
118
|
+
* single-account fallback counts device rows.
|
|
119
|
+
*
|
|
120
|
+
* Pure & side-effect free so it is unit-testable without rendering React.
|
|
121
|
+
*/
|
|
122
|
+
export declare function markCurrentAccount(accounts: SwitchableAccount[], activeSessionId: string | null | undefined, liveUserId: string | null | undefined, isAuthenticated: boolean): SwitchableAccount[];
|
|
123
|
+
/**
|
|
124
|
+
* Pure union of device sign-ins and account-graph nodes into the flat
|
|
125
|
+
* {@link SwitchableAccount}[] the switchers render. Extracted so the merge /
|
|
126
|
+
* dedup semantics are unit-testable without rendering React.
|
|
127
|
+
*
|
|
128
|
+
* Order: device rows first (in session order, current flagged), then graph-only
|
|
129
|
+
* rows (in graph order). An account present as BOTH a device session and a graph
|
|
130
|
+
* node is deduped into ONE device row enriched with the graph metadata
|
|
131
|
+
* (relationship / kind / parent / membership).
|
|
132
|
+
*/
|
|
133
|
+
export declare function buildSwitchableAccounts(input: BuildSwitchableAccountsInput): SwitchableAccount[];
|
|
134
|
+
/**
|
|
135
|
+
* Resolve every account the signed-in user can switch into — device sign-ins
|
|
136
|
+
* AND linked graph accounts (owned orgs + shared-with-you) — as one flat list
|
|
137
|
+
* with real per-account name / email / avatar / color, deduped by account id.
|
|
138
|
+
*
|
|
139
|
+
* ## Data sources
|
|
140
|
+
*
|
|
141
|
+
* - Device sign-ins: `useOxy().sessions` — a `ClientSession[]` projected by
|
|
142
|
+
* `OxyContext.syncFromClient` from the server-authoritative `SessionClient`.
|
|
143
|
+
* Each session carries only `sessionId` + `userId`, so this hook additionally
|
|
144
|
+
* fetches every device account's profile via `oxyServices.getUsersByIds()`.
|
|
145
|
+
* The ACTIVE row always uses `useOxy().user` directly (the freshest copy).
|
|
146
|
+
* - Linked accounts: `useOxy().accounts` — the `AccountNode[]` graph the context
|
|
147
|
+
* loads from `GET /accounts`. Each node already embeds its `account` `User`
|
|
148
|
+
* document, so graph-only rows need no extra fetch.
|
|
149
|
+
*
|
|
150
|
+
* An account present as BOTH a device session and a graph node is deduped into
|
|
151
|
+
* ONE row (see {@link buildSwitchableAccounts}). EVERY row switches the same
|
|
152
|
+
* way — through `useOxy().switchToAccount(row.accountId)`.
|
|
153
|
+
*
|
|
154
|
+
* ## Error handling
|
|
155
|
+
*
|
|
156
|
+
* `getUsersByIds()` resolves to `[]` on a failed chunk (logged internally)
|
|
157
|
+
* rather than throwing. Device accounts whose profile could not be resolved are
|
|
158
|
+
* omitted until a subsequent fetch succeeds (except the active one, which never
|
|
159
|
+
* depends on this fetch); graph accounts are unaffected.
|
|
160
|
+
*/
|
|
161
|
+
export declare function useSwitchableAccounts(): UseSwitchableAccountsResult;
|
|
162
|
+
//# sourceMappingURL=useSwitchableAccounts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSwitchableAccounts.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useSwitchableAccounts.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACR,IAAI,EACJ,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,aAAa,EAChB,MAAM,aAAa,CAAC;AAKrB;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEzC;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAC9B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,SAAS,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,6EAA6E;IAC7E,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACxC,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,+CAA+C;IAC/C,IAAI,EAAE,qBAAqB,CAAC;CAC/B;AAED,MAAM,WAAW,2BAA2B;IACxC,0EAA0E;IAC1E,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,8EAA8E;AAC9E,MAAM,WAAW,sBAAsB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,4BAA4B;IACzC,+EAA+E;IAC/E,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,uCAAuC;IACvC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,wEAAwE;IACxE,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,+EAA+E;IAC/E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;CAC/E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAC9B,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC1C,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACrC,eAAe,EAAE,OAAO,GACzB,iBAAiB,EAAE,CAiCrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,EAAE,CAoHhG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,qBAAqB,IAAI,2BAA2B,CA2DnE"}
|
|
@@ -1,58 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API
|
|
2
|
+
* Platform detection helper for the web auth/session-sync surfaces.
|
|
3
|
+
*
|
|
4
|
+
* This module previously hosted a FedCM-based `useWebSSO` hook (Federated
|
|
5
|
+
* Credential Management — Chrome-only). It was removed: FedCM is no longer
|
|
6
|
+
* used anywhere in the client sign-in/cold-boot path (see `CrossDomainAuth`'s
|
|
7
|
+
* doc comment in `@oxyhq/core` for the production sign-in loop that motivated
|
|
8
|
+
* the removal). Cross-domain silent SSO is owned entirely by the
|
|
9
|
+
* `silent-iframe` cold-boot step (per-apex `/auth/silent`) plus the terminal
|
|
10
|
+
* `/sso` bounce in `OxyContext`.
|
|
11
|
+
*
|
|
12
|
+
* `isWebBrowser` is kept here (rather than moved) so every existing consumer
|
|
13
|
+
* import path stays valid.
|
|
16
14
|
*/
|
|
17
|
-
import type { OxyServices } from '@oxyhq/core';
|
|
18
|
-
import type { SessionLoginResponse } from '@oxyhq/core';
|
|
19
|
-
interface UseWebSSOOptions {
|
|
20
|
-
oxyServices: OxyServices;
|
|
21
|
-
onSessionFound: (session: SessionLoginResponse) => Promise<void>;
|
|
22
|
-
onSSOUnavailable?: () => void;
|
|
23
|
-
onError?: (error: Error) => void;
|
|
24
|
-
enabled?: boolean;
|
|
25
|
-
}
|
|
26
|
-
interface UseWebSSOResult {
|
|
27
|
-
/** Manually trigger SSO check */
|
|
28
|
-
checkSSO: () => Promise<SessionLoginResponse | null>;
|
|
29
|
-
/** Trigger interactive FedCM sign-in (shows browser UI) */
|
|
30
|
-
signInWithFedCM: () => Promise<SessionLoginResponse | null>;
|
|
31
|
-
/** Whether SSO check is in progress */
|
|
32
|
-
isChecking: boolean;
|
|
33
|
-
/** Whether FedCM is supported in this browser */
|
|
34
|
-
isFedCMSupported: boolean;
|
|
35
|
-
}
|
|
36
15
|
/**
|
|
37
16
|
* Check if we're running in a web browser environment (not React Native)
|
|
38
17
|
*/
|
|
39
|
-
declare function isWebBrowser(): boolean;
|
|
40
|
-
/**
|
|
41
|
-
* Hook for automatic cross-domain web SSO
|
|
42
|
-
*
|
|
43
|
-
* Uses FedCM (Federated Credential Management) - the modern browser-native
|
|
44
|
-
* identity federation API. This is the same technology that powers
|
|
45
|
-
* Google's cross-domain SSO (YouTube, Gmail, Maps, etc.).
|
|
46
|
-
*
|
|
47
|
-
* Key benefits:
|
|
48
|
-
* - Works across different TLDs (alia.onl ↔ mention.earth ↔ homiio.com)
|
|
49
|
-
* - No third-party cookies required
|
|
50
|
-
* - Privacy-preserving (browser mediates identity, IdP can't track)
|
|
51
|
-
* - Automatic silent sign-in after initial authentication
|
|
52
|
-
*
|
|
53
|
-
* For browsers without FedCM (Firefox, older browsers), automatic SSO
|
|
54
|
-
* is not possible. Users will see a sign-in button instead.
|
|
55
|
-
*/
|
|
56
|
-
export declare function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onError, enabled, }: UseWebSSOOptions): UseWebSSOResult;
|
|
57
|
-
export { isWebBrowser };
|
|
18
|
+
export declare function isWebBrowser(): boolean;
|
|
58
19
|
//# sourceMappingURL=useWebSSO.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWebSSO.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useWebSSO.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"useWebSSO.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useWebSSO.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAItC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { OxyServices } from '@oxyhq/core';
|
|
2
|
+
import { SessionClient } from '@oxyhq/core';
|
|
3
|
+
import { createSessionClientHost } from './sessionClientHost';
|
|
4
|
+
/**
|
|
5
|
+
* Wires a `SessionClient` for `@oxyhq/services`: builds the `SessionClientHost`
|
|
6
|
+
* adapter (Task 1) and the platform `TokenTransport` (Task 3) over the given
|
|
7
|
+
* `OxyServices` instance, and returns both the client and the host — the host
|
|
8
|
+
* is returned (not just the client) so `OxyContext` (Fase 3-B) can call
|
|
9
|
+
* `host.setCurrentAccountId(...)` as the active account changes.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createSessionClient(oxyServices: OxyServices): {
|
|
12
|
+
client: SessionClient;
|
|
13
|
+
host: ReturnType<typeof createSessionClientHost>;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=createSessionClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSessionClient.d.ts","sourceRoot":"","sources":["../../../../../src/ui/session/createSessionClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAG9D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG;IAC7D,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;CAClD,CAKA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-sync integration layer (Fase 3-A) — intra-package use only.
|
|
3
|
+
*
|
|
4
|
+
* These modules let `@oxyhq/services` drive the platform-agnostic
|
|
5
|
+
* `SessionClient` (in `@oxyhq/core`): a thin host adapter over `OxyServices`,
|
|
6
|
+
* pure `DeviceSessionState → services` projection helpers, a platform token
|
|
7
|
+
* transport, and the factory that wires them together. Nothing here is
|
|
8
|
+
* re-exported from the package root — `OxyContext` consumes it directly in
|
|
9
|
+
* Fase 3-B.
|
|
10
|
+
*/
|
|
11
|
+
export { createSessionClient } from './createSessionClient';
|
|
12
|
+
export { createSessionClientHost } from './sessionClientHost';
|
|
13
|
+
export { createTokenTransport } from './tokenTransport';
|
|
14
|
+
export { accountIdsOf, activeSessionIdOf, activeUserOf, deviceStateToClientSessions, } from './projectSessionState';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/ui/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { DeviceSessionState } from '@oxyhq/contracts';
|
|
2
|
+
import type { ClientSession, User } from '@oxyhq/core';
|
|
3
|
+
/**
|
|
4
|
+
* Pure projection helpers: `DeviceSessionState` (the device-scoped
|
|
5
|
+
* multi-account session-sync state produced by `@oxyhq/core`'s
|
|
6
|
+
* `SessionClient`) -> the shapes `OxyContext` renders today
|
|
7
|
+
* (`ClientSession[]`, an active session id, an active `User`).
|
|
8
|
+
*
|
|
9
|
+
* No I/O. The caller fetches profiles via
|
|
10
|
+
* `oxyServices.getUsersByIds(accountIdsOf(state))` and builds `usersById`
|
|
11
|
+
* from the result before calling `deviceStateToClientSessions` /
|
|
12
|
+
* `activeUserOf`.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Maps every `SessionAccount` in `state.accounts` to a `ClientSession`.
|
|
16
|
+
*
|
|
17
|
+
* `DeviceSessionState` carries no per-account `expiresAt` / `lastActive` —
|
|
18
|
+
* both are set to `state.updatedAt` (converted to an ISO-8601 string; the
|
|
19
|
+
* wire value is an epoch-ms number) as a provisional value. Fase 3-B
|
|
20
|
+
* rewrites `ClientSession` to make `expiresAt`/`lastActive` optional (they
|
|
21
|
+
* are not derivable from `DeviceSessionState`).
|
|
22
|
+
*
|
|
23
|
+
* `usersById` is accepted for signature symmetry with `activeUserOf` even
|
|
24
|
+
* though `ClientSession` only stores `userId` — a session is still
|
|
25
|
+
* projected for an account whose id is absent from `usersById` (no
|
|
26
|
+
* placeholder user is fabricated).
|
|
27
|
+
*/
|
|
28
|
+
export declare function deviceStateToClientSessions(state: DeviceSessionState, usersById: Map<string, User>): ClientSession[];
|
|
29
|
+
/**
|
|
30
|
+
* The active account's `sessionId`, or `null` when there is no state or no
|
|
31
|
+
* active account is set.
|
|
32
|
+
*/
|
|
33
|
+
export declare function activeSessionIdOf(state: DeviceSessionState | null): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* The active account's `User`, resolved from `usersById`. `null` when there
|
|
36
|
+
* is no state, no active account is set, or the active account id is absent
|
|
37
|
+
* from `usersById`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function activeUserOf(state: DeviceSessionState | null, usersById: Map<string, User>): User | null;
|
|
40
|
+
/**
|
|
41
|
+
* All account ids in `state`, suitable for an `oxyServices.getUsersByIds(...)`
|
|
42
|
+
* fetch. `[]` for `null` state.
|
|
43
|
+
*/
|
|
44
|
+
export declare function accountIdsOf(state: DeviceSessionState | null): string[];
|
|
45
|
+
//# sourceMappingURL=projectSessionState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectSessionState.d.ts","sourceRoot":"","sources":["../../../../../src/ui/session/projectSessionState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEvD;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,kBAAkB,EACzB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAC3B,aAAa,EAAE,CAajB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAOjF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,kBAAkB,GAAG,IAAI,EAChC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAC3B,IAAI,GAAG,IAAI,CAKb;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,GAAG,MAAM,EAAE,CAKvE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { OxyServices, SessionClientHost } from '@oxyhq/core';
|
|
2
|
+
/**
|
|
3
|
+
* Thin `SessionClientHost` adapter over an `OxyServices` instance.
|
|
4
|
+
*
|
|
5
|
+
* `SessionClient` (in `@oxyhq/core`) is host-agnostic: it only needs a REST +
|
|
6
|
+
* token surface. `OxyServices` already exposes all of that except
|
|
7
|
+
* `getCurrentAccountId`, which has no direct equivalent — the adapter holds a
|
|
8
|
+
* mutable ref set by the caller (`OxyContext`, in Fase 3-B) via
|
|
9
|
+
* `setCurrentAccountId`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createSessionClientHost(oxyServices: OxyServices): SessionClientHost & {
|
|
12
|
+
setCurrentAccountId(id: string | null): void;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=sessionClientHost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionClientHost.d.ts","sourceRoot":"","sources":["../../../../../src/ui/session/sessionClientHost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAElE;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,WAAW,GACvB,iBAAiB,GAAG;IAAE,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;CAAE,CAatE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { OxyServices, TokenTransport } from '@oxyhq/core';
|
|
2
|
+
/**
|
|
3
|
+
* Platform `TokenTransport` for `SessionClient`: mints an access token when
|
|
4
|
+
* none is currently held, reusing the SAME primitives `OxyContext`'s cold
|
|
5
|
+
* boot already relies on (never re-implemented here):
|
|
6
|
+
*
|
|
7
|
+
* - web: `oxyServices.silentSignIn()` (per-apex `/auth/silent` iframe).
|
|
8
|
+
* - native: `oxyServices.signInWithSharedIdentity()` (app-group keychain).
|
|
9
|
+
*
|
|
10
|
+
* Both primitives plant the token internally on success (the "Sign-In Token
|
|
11
|
+
* Planting" rule) — `ensureActiveToken` never calls `setTokens` itself.
|
|
12
|
+
*
|
|
13
|
+
* `ensureActiveToken` treats a PRESENT token as sufficient in this phase; it
|
|
14
|
+
* does not decode/match the token's subject against `state.activeAccountId`
|
|
15
|
+
* (that refinement is Fase 3-B). Account switching itself is server-driven
|
|
16
|
+
* via the `activeToken` carried in the sync envelope — this transport is
|
|
17
|
+
* only the fallback used when the envelope carried no token.
|
|
18
|
+
*
|
|
19
|
+
* A failed mint is logged and swallowed: it must never throw out of
|
|
20
|
+
* `ensureActiveToken`, since that would crash the caller (the SessionClient
|
|
21
|
+
* socket handler in Fase 3-B).
|
|
22
|
+
*/
|
|
23
|
+
export declare function createTokenTransport(oxyServices: OxyServices): TokenTransport;
|
|
24
|
+
//# sourceMappingURL=tokenTransport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenTransport.d.ts","sourceRoot":"","sources":["../../../../../src/ui/session/tokenTransport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI/D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,GAAG,cAAc,CAiD7E"}
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Web-only
|
|
2
|
+
* Web-only helpers around the retired `oxy_rt_${authuser}` multi-slot
|
|
3
|
+
* refresh-cookie scheme, PLUS the (unrelated, still load-bearing) deliberate
|
|
4
|
+
* sign-out / SSO-bounce gates.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* It
|
|
14
|
-
*
|
|
6
|
+
* NOTE (session-sync cutover, Task 5): the device account SET is now
|
|
7
|
+
* server-authoritative via `SessionClient` (`@oxyhq/core`) — nothing in
|
|
8
|
+
* `@oxyhq/services` writes the persisted active-`authuser`-slot key anymore
|
|
9
|
+
* (`writeActiveAuthuser`/`clearActiveAuthuser` were deleted; their only
|
|
10
|
+
* callers were the deleted `establishDeviceRefreshSlot` sign-in registration
|
|
11
|
+
* and the deleted `switchToAccount`/`switchSession` slot bookkeeping).
|
|
12
|
+
* {@link readActiveAuthuser} is KEPT purely as an OPTIONAL restore hint:
|
|
13
|
+
* `OxyContext`'s `restoreStoredSession` cold-boot step reads it only to
|
|
14
|
+
* backfill `clientSession.authuser` for the active session when a legacy value
|
|
15
|
+
* happens to be present. It NO LONGER gates whether restore is attempted — the
|
|
16
|
+
* old guard that also required this marker made every web reload with a lapsed
|
|
17
|
+
* local bearer bail before any network validation (P0), and was replaced by a
|
|
18
|
+
* "bail only when there is nothing to restore" guard plus a valid-session
|
|
19
|
+
* election. Since nothing writes the key anymore, the backfill is dormant on
|
|
20
|
+
* fresh installs; it stays for legacy installs and costs nothing.
|
|
15
21
|
*
|
|
16
22
|
* Native (React Native) has no equivalent of these device-local cookies
|
|
17
23
|
* and uses bearer-protected session ids directly, so these helpers no-op
|
|
18
24
|
* outside the browser.
|
|
19
25
|
*/
|
|
20
|
-
declare const ACTIVE_AUTHUSER_KEY = "oxy_active_authuser";
|
|
21
26
|
/**
|
|
22
27
|
* Read the persisted active `authuser` slot index.
|
|
23
28
|
*
|
|
@@ -26,30 +31,18 @@ declare const ACTIVE_AUTHUSER_KEY = "oxy_active_authuser";
|
|
|
26
31
|
* fall back to deterministic selection (lowest authuser).
|
|
27
32
|
*/
|
|
28
33
|
export declare function readActiveAuthuser(): number | null;
|
|
29
|
-
/**
|
|
30
|
-
* Persist the active `authuser` slot index. No-ops on native and on any
|
|
31
|
-
* storage failure (e.g. Safari private mode). Callers MUST NOT depend on
|
|
32
|
-
* this succeeding — it is best-effort UX persistence, not authoritative.
|
|
33
|
-
*/
|
|
34
|
-
export declare function writeActiveAuthuser(authuser: number): void;
|
|
35
|
-
/**
|
|
36
|
-
* Clear the persisted active `authuser` slot index. Called on full sign-out
|
|
37
|
-
* (logoutAll) so that the next cold boot doesn't try to resurrect a
|
|
38
|
-
* cleared slot.
|
|
39
|
-
*/
|
|
40
|
-
export declare function clearActiveAuthuser(): void;
|
|
41
34
|
/**
|
|
42
35
|
* Mark this origin as DELIBERATELY signed out (durable `localStorage`, via the
|
|
43
36
|
* core {@link ssoSignedOutKey}). Called ONLY on EXPLICIT full sign-out so that
|
|
44
37
|
* the next cold boot does NOT silently re-mint a session from a still-live IdP
|
|
45
|
-
* session (
|
|
38
|
+
* session (the per-apex `/auth/silent` iframe cold-boot step). Cleared by any
|
|
46
39
|
* deliberate sign-in (see {@link clearSignedOut}). No-ops on native / storage
|
|
47
40
|
* failure (best-effort).
|
|
48
41
|
*/
|
|
49
42
|
export declare function markSignedOut(): void;
|
|
50
43
|
/**
|
|
51
44
|
* Clear the durable deliberately-signed-out flag. Called on ANY deliberate
|
|
52
|
-
* sign-in (password,
|
|
45
|
+
* sign-in (password, account switch, device claim) so a real sign-in
|
|
53
46
|
* fully re-enables automatic silent restore — there is no "stuck signed out"
|
|
54
47
|
* state. No-ops on native / storage failure.
|
|
55
48
|
*/
|
|
@@ -59,7 +52,7 @@ export declare function clearSignedOut(): void;
|
|
|
59
52
|
* the user deliberately signed out. Reads the durable flag through the core
|
|
60
53
|
* {@link silentRestoreSuppressed} predicate. Returns `false` off-web and on any
|
|
61
54
|
* storage failure (fail safe toward normal restore). Used to gate the
|
|
62
|
-
* `
|
|
55
|
+
* `silent-iframe` cold-boot step.
|
|
63
56
|
*/
|
|
64
57
|
export declare function isSilentRestoreSuppressed(): boolean;
|
|
65
58
|
/**
|
|
@@ -71,5 +64,4 @@ export declare function isSilentRestoreSuppressed(): boolean;
|
|
|
71
64
|
* No-ops on native and on any storage failure (best-effort).
|
|
72
65
|
*/
|
|
73
66
|
export declare function clearSsoBounceState(): void;
|
|
74
|
-
export { ACTIVE_AUTHUSER_KEY };
|
|
75
67
|
//# sourceMappingURL=activeAuthuser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activeAuthuser.d.ts","sourceRoot":"","sources":["../../../../../src/ui/utils/activeAuthuser.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"activeAuthuser.d.ts","sourceRoot":"","sources":["../../../../../src/ui/utils/activeAuthuser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AA2BH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAalD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAOpC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAOrC;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAMnD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAa1C"}
|
|
@@ -26,17 +26,6 @@ export interface FetchSessionsWithFallbackOptions {
|
|
|
26
26
|
fallbackUserId?: string;
|
|
27
27
|
logger?: (message: string, error?: unknown) => void;
|
|
28
28
|
}
|
|
29
|
-
export interface ValidateSessionBatchOptions {
|
|
30
|
-
useHeaderValidation?: boolean;
|
|
31
|
-
maxConcurrency?: number;
|
|
32
|
-
}
|
|
33
|
-
export interface SessionValidationResult {
|
|
34
|
-
sessionId: string;
|
|
35
|
-
valid: boolean;
|
|
36
|
-
user?: unknown;
|
|
37
|
-
raw?: unknown;
|
|
38
|
-
error?: unknown;
|
|
39
|
-
}
|
|
40
29
|
/**
|
|
41
30
|
* Normalize backend session payloads into `ClientSession` objects.
|
|
42
31
|
*
|
|
@@ -55,13 +44,5 @@ export declare const mapSessionsToClient: (sessions: DeviceSession[], fallbackDe
|
|
|
55
44
|
* @param options - Optional fallback options
|
|
56
45
|
*/
|
|
57
46
|
export declare const fetchSessionsWithFallback: (oxyServices: OxyServicesAny, sessionId: string, { fallbackDeviceId, fallbackUserId, logger, }?: FetchSessionsWithFallbackOptions) => Promise<ClientSession[]>;
|
|
58
|
-
/**
|
|
59
|
-
* Validate multiple sessions concurrently with configurable concurrency.
|
|
60
|
-
*
|
|
61
|
-
* @param oxyServices - Oxy service instance
|
|
62
|
-
* @param sessionIds - Session identifiers to validate
|
|
63
|
-
* @param options - Validation options
|
|
64
|
-
*/
|
|
65
|
-
export declare const validateSessionBatch: (oxyServices: OxyServicesAny, sessionIds: string[], { useHeaderValidation, maxConcurrency }?: ValidateSessionBatchOptions) => Promise<SessionValidationResult[]>;
|
|
66
47
|
export {};
|
|
67
48
|
//# sourceMappingURL=sessionHelpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionHelpers.d.ts","sourceRoot":"","sources":["../../../../../src/ui/utils/sessionHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE;YAAE,QAAQ,IAAI,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AAEH,KAAK,cAAc,GAAG,GAAG,CAAC;AAE1B,MAAM,WAAW,gCAAgC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD;AAED
|
|
1
|
+
{"version":3,"file":"sessionHelpers.d.ts","sourceRoot":"","sources":["../../../../../src/ui/utils/sessionHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE;YAAE,QAAQ,IAAI,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AAEH,KAAK,cAAc,GAAG,GAAG,CAAC;AAE1B,MAAM,WAAW,gCAAgC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACrD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,aAAa,EAAE,EACzB,mBAAmB,MAAM,EACzB,iBAAiB,MAAM,KACtB,aAAa,EAgBf,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,GACpC,aAAa,cAAc,EAC3B,WAAW,MAAM,EACjB,gDAIG,gCAAqC,KACvC,OAAO,CAAC,aAAa,EAAE,CAYzB,CAAC"}
|
|
@@ -2,31 +2,52 @@
|
|
|
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
|
-
import { type User } from '@oxyhq/core';
|
|
33
|
+
import { type EstablishAfterClaimDeps, type SessionLoginResponse, type SsoEstablishClient, type User } from '@oxyhq/core';
|
|
19
34
|
interface DeviceFlowClaimResult {
|
|
20
35
|
accessToken?: string;
|
|
21
36
|
sessionId?: string;
|
|
37
|
+
deviceId?: string;
|
|
38
|
+
expiresAt?: string;
|
|
39
|
+
user?: User;
|
|
22
40
|
}
|
|
23
41
|
/**
|
|
24
42
|
* The minimal `OxyServices` surface this orchestration needs. Kept as a
|
|
25
43
|
* structural type (rather than importing the full client) so the helper is
|
|
26
44
|
* trivially unit-testable with a stub and never pulls the RN/Expo runtime into
|
|
27
45
|
* a test bundle.
|
|
46
|
+
*
|
|
47
|
+
* Extends {@link SsoEstablishClient} (`requestSsoEstablishUrl`) so the WEB
|
|
48
|
+
* post-claim durable-session hop can be driven off the same client.
|
|
28
49
|
*/
|
|
29
|
-
export interface DeviceFlowClient {
|
|
50
|
+
export interface DeviceFlowClient extends SsoEstablishClient {
|
|
30
51
|
/**
|
|
31
52
|
* Exchange the device-flow `sessionToken` for the first access + refresh
|
|
32
53
|
* token, planting them on the client. Single-use; replay is rejected by the
|
|
@@ -45,19 +66,30 @@ export interface CompleteDeviceFlowSignInOptions {
|
|
|
45
66
|
*/
|
|
46
67
|
sessionToken: string;
|
|
47
68
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
69
|
+
* `useOxy().handleWebSession` — commits the freshly-claimed session into
|
|
70
|
+
* context state through the SAME path a password sign-in uses:
|
|
71
|
+
* registers the account into the device's server-authoritative session set,
|
|
72
|
+
* persists it durably, and hydrates the full user profile. Runs AFTER the
|
|
73
|
+
* bearer is planted so its bearer-protected calls succeed.
|
|
74
|
+
*/
|
|
75
|
+
commitSession: (session: SessionLoginResponse) => Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Injectable web seams for the post-claim durable-session establish hop
|
|
78
|
+
* ({@link establishIdpSessionAfterClaim}). Omit in production — the defaults
|
|
79
|
+
* resolve to `window.*` (and no-op off-web / on native). Tests inject fakes to
|
|
80
|
+
* drive the web path deterministically.
|
|
51
81
|
*/
|
|
52
|
-
|
|
82
|
+
establishDeps?: EstablishAfterClaimDeps;
|
|
53
83
|
}
|
|
54
84
|
/**
|
|
55
85
|
* Complete a device-flow sign-in: claim the first access token with the secret
|
|
56
|
-
* `sessionToken` (planting the bearer), then
|
|
57
|
-
* `
|
|
86
|
+
* `sessionToken` (planting the bearer), then commit the resulting session via
|
|
87
|
+
* `commitSession` (registers it into the device's server-authoritative session
|
|
88
|
+
* set and hydrates the full user). Returns the authenticated user.
|
|
58
89
|
*
|
|
59
|
-
* Throws if
|
|
90
|
+
* Throws if the claim did not return a usable session, or if either the claim
|
|
91
|
+
* or the commit fails; callers surface a retry UI.
|
|
60
92
|
*/
|
|
61
|
-
export declare function completeDeviceFlowSignIn({ oxyServices, sessionId, sessionToken,
|
|
93
|
+
export declare function completeDeviceFlowSignIn({ oxyServices, sessionId, sessionToken, commitSession, establishDeps, }: CompleteDeviceFlowSignInOptions): Promise<User>;
|
|
62
94
|
export {};
|
|
63
95
|
//# sourceMappingURL=deviceFlowSignIn.d.ts.map
|