@oxyhq/services 27.1.3 → 29.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -661
- package/NOTICE +16 -0
- package/README.md +67 -2
- package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionModule.kt +178 -0
- package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionProvider.kt +99 -0
- package/android/src/main/java/so/oxy/devicesession/OxyDeviceSessionStore.kt +115 -0
- package/expo-module.config.json +1 -0
- package/lib/commonjs/index.js +78 -16
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/boot/runProviderColdBoot.js +7 -0
- package/lib/commonjs/ui/boot/runProviderColdBoot.js.map +1 -1
- package/lib/commonjs/ui/client.js +12 -7
- package/lib/commonjs/ui/client.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js +10 -27
- package/lib/commonjs/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAuthChooser.js +132 -44
- package/lib/commonjs/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +4 -2
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/SurfaceScreen.js +31 -3
- package/lib/commonjs/ui/components/SurfaceScreen.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js +209 -84
- package/lib/commonjs/ui/components/authChooser/AccountsMenuView.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/SignInEntryView.js +25 -7
- package/lib/commonjs/ui/components/authChooser/SignInEntryView.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/primitives.js +35 -22
- package/lib/commonjs/ui/components/authChooser/primitives.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/signInProgress.js +5 -0
- package/lib/commonjs/ui/components/authChooser/signInProgress.js.map +1 -1
- package/lib/commonjs/ui/components/authChooser/types.js +11 -0
- package/lib/commonjs/ui/components/authChooser/types.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +257 -306
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +27 -37
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/oxyContextHelpers.js +0 -29
- package/lib/commonjs/ui/context/oxyContextHelpers.js.map +1 -1
- package/lib/commonjs/ui/context/useOxyAccountGraph.js +6 -17
- package/lib/commonjs/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/commonjs/ui/hooks/accountDialogSnapshot.js +42 -0
- package/lib/commonjs/ui/hooks/accountDialogSnapshot.js.map +1 -0
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +0 -19
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/commonjs/ui/hooks/useDeviceSwitcher.js +57 -0
- package/lib/commonjs/ui/hooks/useDeviceSwitcher.js.map +1 -0
- package/lib/commonjs/ui/hooks/useI18n.js +22 -3
- package/lib/commonjs/ui/hooks/useI18n.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +46 -153
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/index.js +12 -7
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/navigation/routes.js +85 -73
- package/lib/commonjs/ui/navigation/routes.js.map +1 -1
- package/lib/commonjs/ui/navigation/surfaces.js +8 -7
- package/lib/commonjs/ui/navigation/surfaces.js.map +1 -1
- package/lib/commonjs/ui/runtime/createOxyRuntime.js +433 -0
- package/lib/commonjs/ui/runtime/createOxyRuntime.js.map +1 -0
- package/lib/commonjs/ui/runtime/index.js +63 -0
- package/lib/commonjs/ui/runtime/index.js.map +1 -0
- package/lib/commonjs/ui/runtime/runtimeContext.js +83 -0
- package/lib/commonjs/ui/runtime/runtimeContext.js.map +1 -0
- package/lib/commonjs/ui/runtime/types.js +6 -0
- package/lib/commonjs/ui/runtime/types.js.map +1 -0
- package/lib/commonjs/ui/runtime/useRuntimeSnapshot.js +57 -0
- package/lib/commonjs/ui/runtime/useRuntimeSnapshot.js.map +1 -0
- package/lib/commonjs/ui/screens/AccountMembersScreen.js +3 -4
- package/lib/commonjs/ui/screens/AccountMembersScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/CreateAccountScreen.js +3 -12
- package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js +6 -5
- package/lib/commonjs/ui/screens/trust/TrustCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js +4 -4
- package/lib/commonjs/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/trust/TrustRewardsScreen.js +1 -1
- package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js +4 -2
- package/lib/commonjs/ui/screens/trust/TrustRulesScreen.js.map +1 -1
- package/lib/commonjs/ui/server.js +1 -2
- package/lib/commonjs/ui/server.js.map +1 -1
- package/lib/commonjs/ui/session/authStore.js +45 -9
- package/lib/commonjs/ui/session/authStore.js.map +1 -1
- package/lib/commonjs/ui/session/sharedDeviceCredentialStore.js +306 -0
- package/lib/commonjs/ui/session/sharedDeviceCredentialStore.js.map +1 -0
- package/lib/commonjs/ui/stores/authStore.js +154 -55
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/stores/followTargetStore.js +27 -0
- package/lib/commonjs/ui/stores/followTargetStore.js.map +1 -1
- package/lib/commonjs/ui/utils/avatarUtils.js +2 -36
- package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
- package/lib/module/index.js +20 -9
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/boot/runProviderColdBoot.js +7 -0
- package/lib/module/ui/boot/runProviderColdBoot.js.map +1 -1
- package/lib/module/ui/client.js +1 -2
- package/lib/module/ui/client.js.map +1 -1
- package/lib/module/ui/components/OxyAccountDialogScreen.js +10 -27
- package/lib/module/ui/components/OxyAccountDialogScreen.js.map +1 -1
- package/lib/module/ui/components/OxyAuthChooser.js +134 -44
- package/lib/module/ui/components/OxyAuthChooser.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +5 -3
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/SurfaceScreen.js +33 -5
- package/lib/module/ui/components/SurfaceScreen.js.map +1 -1
- package/lib/module/ui/components/authChooser/AccountsMenuView.js +210 -85
- package/lib/module/ui/components/authChooser/AccountsMenuView.js.map +1 -1
- package/lib/module/ui/components/authChooser/SignInEntryView.js +25 -7
- package/lib/module/ui/components/authChooser/SignInEntryView.js.map +1 -1
- package/lib/module/ui/components/authChooser/primitives.js +35 -22
- package/lib/module/ui/components/authChooser/primitives.js.map +1 -1
- package/lib/module/ui/components/authChooser/signInProgress.js +5 -0
- package/lib/module/ui/components/authChooser/signInProgress.js.map +1 -1
- package/lib/module/ui/components/authChooser/types.js +11 -0
- package/lib/module/ui/components/authChooser/types.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +251 -303
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +27 -37
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/oxyContextHelpers.js +0 -28
- package/lib/module/ui/context/oxyContextHelpers.js.map +1 -1
- package/lib/module/ui/context/useOxyAccountGraph.js +6 -17
- package/lib/module/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/module/ui/hooks/accountDialogSnapshot.js +38 -0
- package/lib/module/ui/hooks/accountDialogSnapshot.js.map +1 -0
- package/lib/module/ui/hooks/mutations/useAccountMutations.js +0 -19
- package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/module/ui/hooks/useDeviceSwitcher.js +53 -0
- package/lib/module/ui/hooks/useDeviceSwitcher.js.map +1 -0
- package/lib/module/ui/hooks/useI18n.js +24 -4
- package/lib/module/ui/hooks/useI18n.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js +47 -155
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/index.js +1 -2
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/navigation/routes.js +84 -72
- package/lib/module/ui/navigation/routes.js.map +1 -1
- package/lib/module/ui/navigation/surfaces.js +6 -6
- package/lib/module/ui/navigation/surfaces.js.map +1 -1
- package/lib/module/ui/runtime/createOxyRuntime.js +430 -0
- package/lib/module/ui/runtime/createOxyRuntime.js.map +1 -0
- package/lib/module/ui/runtime/index.js +15 -0
- package/lib/module/ui/runtime/index.js.map +1 -0
- package/lib/module/ui/runtime/runtimeContext.js +75 -0
- package/lib/module/ui/runtime/runtimeContext.js.map +1 -0
- package/lib/module/ui/runtime/types.js +4 -0
- package/lib/module/ui/runtime/types.js.map +1 -0
- package/lib/module/ui/runtime/useRuntimeSnapshot.js +52 -0
- package/lib/module/ui/runtime/useRuntimeSnapshot.js.map +1 -0
- package/lib/module/ui/screens/AccountMembersScreen.js +4 -5
- package/lib/module/ui/screens/AccountMembersScreen.js.map +1 -1
- package/lib/module/ui/screens/CreateAccountScreen.js +4 -13
- package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustCenterScreen.js +6 -5
- package/lib/module/ui/screens/trust/TrustCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js +5 -5
- package/lib/module/ui/screens/trust/TrustLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/trust/TrustRewardsScreen.js +1 -1
- package/lib/module/ui/screens/trust/TrustRulesScreen.js +4 -2
- package/lib/module/ui/screens/trust/TrustRulesScreen.js.map +1 -1
- package/lib/module/ui/server.js +0 -1
- package/lib/module/ui/server.js.map +1 -1
- package/lib/module/ui/session/authStore.js +46 -11
- package/lib/module/ui/session/authStore.js.map +1 -1
- package/lib/module/ui/session/sharedDeviceCredentialStore.js +302 -0
- package/lib/module/ui/session/sharedDeviceCredentialStore.js.map +1 -0
- package/lib/module/ui/stores/authStore.js +154 -55
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/stores/followTargetStore.js +25 -0
- package/lib/module/ui/stores/followTargetStore.js.map +1 -1
- package/lib/module/ui/utils/avatarUtils.js +2 -35
- package/lib/module/ui/utils/avatarUtils.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +6 -4
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/client.d.ts +1 -2
- package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/SurfaceScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts +11 -4
- package/lib/typescript/commonjs/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts +3 -1
- package/lib/typescript/commonjs/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts +18 -6
- package/lib/typescript/commonjs/ui/components/authChooser/primitives.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/signInProgress.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts +33 -1
- package/lib/typescript/commonjs/ui/components/authChooser/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +35 -4
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +8 -12
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/oxyContextHelpers.d.ts +0 -2
- package/lib/typescript/commonjs/ui/context/oxyContextHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +9 -1
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts +1 -3
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts +15 -0
- package/lib/typescript/commonjs/ui/hooks/accountDialogSnapshot.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useDeviceSwitcher.d.ts +49 -0
- package/lib/typescript/commonjs/ui/hooks/useDeviceSwitcher.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/useI18n.d.ts +13 -0
- package/lib/typescript/commonjs/ui/hooks/useI18n.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts +23 -18
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts +1 -2
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts +15 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/surfaces.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/runtime/createOxyRuntime.d.ts +144 -0
- package/lib/typescript/commonjs/ui/runtime/createOxyRuntime.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/runtime/index.d.ts +16 -0
- package/lib/typescript/commonjs/ui/runtime/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/runtime/runtimeContext.d.ts +43 -0
- package/lib/typescript/commonjs/ui/runtime/runtimeContext.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/runtime/types.d.ts +89 -0
- package/lib/typescript/commonjs/ui/runtime/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/runtime/useRuntimeSnapshot.d.ts +23 -0
- package/lib/typescript/commonjs/ui/runtime/useRuntimeSnapshot.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/screens/AccountMembersScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/server.d.ts +0 -1
- package/lib/typescript/commonjs/ui/server.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/authStore.d.ts +60 -9
- package/lib/typescript/commonjs/ui/session/authStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/sharedDeviceCredentialStore.d.ts +32 -0
- package/lib/typescript/commonjs/ui/session/sharedDeviceCredentialStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/stores/authStore.d.ts +49 -5
- package/lib/typescript/commonjs/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/stores/followTargetStore.d.ts +8 -1
- package/lib/typescript/commonjs/ui/stores/followTargetStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/types/navigation.d.ts +26 -0
- package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts +2 -10
- package/lib/typescript/commonjs/ui/utils/avatarUtils.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +6 -4
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts.map +1 -1
- package/lib/typescript/module/ui/client.d.ts +1 -2
- package/lib/typescript/module/ui/client.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAccountDialogScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAuthChooser.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/SurfaceScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts +11 -4
- package/lib/typescript/module/ui/components/authChooser/AccountsMenuView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts +3 -1
- package/lib/typescript/module/ui/components/authChooser/SignInEntryView.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts +18 -6
- package/lib/typescript/module/ui/components/authChooser/primitives.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/signInProgress.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/authChooser/types.d.ts +33 -1
- package/lib/typescript/module/ui/components/authChooser/types.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts +35 -4
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +8 -12
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/oxyContextHelpers.d.ts +0 -2
- package/lib/typescript/module/ui/context/oxyContextHelpers.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +9 -1
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts +1 -3
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts +15 -0
- package/lib/typescript/module/ui/hooks/accountDialogSnapshot.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useDeviceSwitcher.d.ts +49 -0
- package/lib/typescript/module/ui/hooks/useDeviceSwitcher.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/useI18n.d.ts +13 -0
- package/lib/typescript/module/ui/hooks/useI18n.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +23 -18
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts +1 -2
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts +15 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/surfaces.d.ts.map +1 -1
- package/lib/typescript/module/ui/runtime/createOxyRuntime.d.ts +144 -0
- package/lib/typescript/module/ui/runtime/createOxyRuntime.d.ts.map +1 -0
- package/lib/typescript/module/ui/runtime/index.d.ts +16 -0
- package/lib/typescript/module/ui/runtime/index.d.ts.map +1 -0
- package/lib/typescript/module/ui/runtime/runtimeContext.d.ts +43 -0
- package/lib/typescript/module/ui/runtime/runtimeContext.d.ts.map +1 -0
- package/lib/typescript/module/ui/runtime/types.d.ts +89 -0
- package/lib/typescript/module/ui/runtime/types.d.ts.map +1 -0
- package/lib/typescript/module/ui/runtime/useRuntimeSnapshot.d.ts +23 -0
- package/lib/typescript/module/ui/runtime/useRuntimeSnapshot.d.ts.map +1 -0
- package/lib/typescript/module/ui/screens/AccountMembersScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustLeaderboardScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/trust/TrustRulesScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/server.d.ts +0 -1
- package/lib/typescript/module/ui/server.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/authStore.d.ts +60 -9
- package/lib/typescript/module/ui/session/authStore.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/sharedDeviceCredentialStore.d.ts +32 -0
- package/lib/typescript/module/ui/session/sharedDeviceCredentialStore.d.ts.map +1 -0
- package/lib/typescript/module/ui/stores/authStore.d.ts +49 -5
- package/lib/typescript/module/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/module/ui/stores/followTargetStore.d.ts +8 -1
- package/lib/typescript/module/ui/stores/followTargetStore.d.ts.map +1 -1
- package/lib/typescript/module/ui/types/navigation.d.ts +26 -0
- package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/avatarUtils.d.ts +2 -10
- package/lib/typescript/module/ui/utils/avatarUtils.d.ts.map +1 -1
- package/package.json +8 -8
- package/plugins/withSharedDeviceSessionProvider.js +102 -0
- package/plugins/withSharedDeviceSessionReader.js +57 -0
- package/src/__tests__/esmSourcePurity.test.ts +61 -0
- package/src/index.ts +36 -9
- package/src/ui/boot/runProviderColdBoot.ts +7 -0
- package/src/ui/client.ts +1 -2
- package/src/ui/components/OxyAccountDialogScreen.tsx +10 -29
- package/src/ui/components/OxyAuthChooser.tsx +149 -50
- package/src/ui/components/OxyProvider.tsx +7 -5
- package/src/ui/components/SurfaceScreen.tsx +28 -4
- package/src/ui/components/__tests__/followTargetButton.test.ts +39 -0
- package/src/ui/components/authChooser/AccountsMenuView.tsx +246 -96
- package/src/ui/components/authChooser/SignInEntryView.tsx +31 -8
- package/src/ui/components/authChooser/primitives.tsx +37 -23
- package/src/ui/components/authChooser/signInProgress.ts +4 -0
- package/src/ui/components/authChooser/types.ts +34 -1
- package/src/ui/context/OxyContext.tsx +269 -324
- package/src/ui/context/hooks/useAuthOperations.ts +32 -35
- package/src/ui/context/oxyContextHelpers.ts +0 -30
- package/src/ui/context/oxyContextTypes.ts +9 -1
- package/src/ui/context/useOxyAccountGraph.ts +5 -19
- package/src/ui/hooks/accountDialogSnapshot.ts +37 -0
- package/src/ui/hooks/mutations/useAccountMutations.ts +0 -19
- package/src/ui/hooks/queries/__tests__/userCache.test.ts +12 -1
- package/src/ui/hooks/useDeviceSwitcher.ts +110 -0
- package/src/ui/hooks/useI18n.ts +23 -3
- package/src/ui/hooks/useSessionManagement.ts +62 -211
- package/src/ui/index.ts +1 -2
- package/src/ui/navigation/routes.ts +85 -75
- package/src/ui/navigation/surfaces.ts +6 -9
- package/src/ui/runtime/createOxyRuntime.ts +623 -0
- package/src/ui/runtime/index.ts +34 -0
- package/src/ui/runtime/runtimeContext.tsx +111 -0
- package/src/ui/runtime/types.ts +110 -0
- package/src/ui/runtime/useRuntimeSnapshot.ts +52 -0
- package/src/ui/screens/AccountMembersScreen.tsx +6 -5
- package/src/ui/screens/CreateAccountScreen.tsx +3 -16
- package/src/ui/screens/trust/TrustCenterScreen.tsx +7 -7
- package/src/ui/screens/trust/TrustLeaderboardScreen.tsx +4 -5
- package/src/ui/screens/trust/TrustRewardsScreen.tsx +1 -1
- package/src/ui/screens/trust/TrustRulesScreen.tsx +3 -2
- package/src/ui/server.ts +0 -1
- package/src/ui/session/__tests__/authStore.test.ts +90 -0
- package/src/ui/session/__tests__/sharedDeviceCredentialStore.test.ts +289 -0
- package/src/ui/session/authStore.ts +78 -9
- package/src/ui/session/sharedDeviceCredentialStore.ts +318 -0
- package/src/ui/stores/authStore.ts +171 -43
- package/src/ui/stores/followTargetStore.ts +24 -1
- package/src/ui/types/navigation.ts +26 -0
- package/src/ui/utils/avatarUtils.ts +2 -37
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +0 -64
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +0 -1
- package/lib/commonjs/ui/screens/trust/trustTier.js +0 -23
- package/lib/commonjs/ui/screens/trust/trustTier.js.map +0 -1
- package/lib/commonjs/ui/stores/accountStore.js +0 -221
- package/lib/commonjs/ui/stores/accountStore.js.map +0 -1
- package/lib/module/ui/hooks/useSwitchableAccounts.js +0 -60
- package/lib/module/ui/hooks/useSwitchableAccounts.js.map +0 -1
- package/lib/module/ui/screens/trust/trustTier.js +0 -19
- package/lib/module/ui/screens/trust/trustTier.js.map +0 -1
- package/lib/module/ui/stores/accountStore.js +0 -213
- package/lib/module/ui/stores/accountStore.js.map +0 -1
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +0 -23
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts +0 -9
- package/lib/typescript/commonjs/ui/screens/trust/trustTier.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/stores/accountStore.d.ts +0 -27
- package/lib/typescript/commonjs/ui/stores/accountStore.d.ts.map +0 -1
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +0 -23
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +0 -1
- package/lib/typescript/module/ui/screens/trust/trustTier.d.ts +0 -9
- package/lib/typescript/module/ui/screens/trust/trustTier.d.ts.map +0 -1
- package/lib/typescript/module/ui/stores/accountStore.d.ts +0 -27
- package/lib/typescript/module/ui/stores/accountStore.d.ts.map +0 -1
- package/src/ui/hooks/useSwitchableAccounts.ts +0 -75
- package/src/ui/screens/trust/trustTier.ts +0 -20
- package/src/ui/stores/accountStore.ts +0 -264
|
@@ -13,8 +13,7 @@ import { isWebBrowser } from "../utils/isWebBrowser.js";
|
|
|
13
13
|
import { resolveDeliveryPlatform } from "../utils/deliveryPlatform.js";
|
|
14
14
|
import { runProviderColdBoot } from "../boot/runProviderColdBoot.js";
|
|
15
15
|
import { loadPersistedDeviceCredential } from "../utils/deviceCredential.js";
|
|
16
|
-
import {
|
|
17
|
-
import { useShallow } from 'zustand/react/shallow';
|
|
16
|
+
import { bindAuthStoreToRuntime } from "../stores/authStore.js";
|
|
18
17
|
import { useLanguageManagement } from "../hooks/useLanguageManagement.js";
|
|
19
18
|
import { useSessionManagement } from "../hooks/useSessionManagement.js";
|
|
20
19
|
import { useAuthOperations, clearPersistedAuthSafe } from "./hooks/useAuthOperations.js";
|
|
@@ -25,17 +24,35 @@ import { presentDetached, topRouteSurface } from "../navigation/surfaces.js";
|
|
|
25
24
|
import { useQueryClient, onlineManager } from '@tanstack/react-query';
|
|
26
25
|
import { clearQueryCache } from "../hooks/queryClient.js";
|
|
27
26
|
import { useAvatarPicker } from "../hooks/useAvatarPicker.js";
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
27
|
+
import { resetSessionScopedStores } from "../stores/resetSessionScopedStores.js";
|
|
28
|
+
import { ASSET_DOWNLOAD_URLS_QUERY_KEY } from "../hooks/useResolvedFileUrls.js";
|
|
29
|
+
import { createOxyRuntime, OxyRuntimeHandleProvider, useRuntimeSnapshot } from "../runtime/index.js";
|
|
30
|
+
import { createSessionClient, createIdentitySessionBinding, createPlatformAuthStateStore, IdentityBoundSessionError, useBackgroundSessionSync } from "../session/index.js";
|
|
31
|
+
import { DEFAULT_SESSION_VALIDITY_MS } from "./oxyContextHelpers.js";
|
|
32
|
+
// `useFollow` imports this module back, so the binding must only be READ inside
|
|
33
|
+
// the provider body — at render time, once every module has evaluated. It is
|
|
34
|
+
// never dereferenced at module scope here.
|
|
35
|
+
import { useFollow } from "../hooks/useFollow.js";
|
|
31
36
|
import { commitDeviceSetAndResolve } from "./commitSessionFlow.js";
|
|
32
37
|
import { runPasskeyLogin, runPasskeyRegister, runPasskeyAdd } from "./passkeyFlow.js";
|
|
33
38
|
import { isPasskeySupported, runRegistrationCeremony, runAuthenticationCeremony } from '../../webauthn/passkeyClient';
|
|
34
39
|
import { queryKeys } from "../hooks/queries/queryKeys.js";
|
|
35
40
|
import { useOxyAccountGraph } from "./useOxyAccountGraph.js";
|
|
36
41
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
37
|
-
const
|
|
38
|
-
|
|
42
|
+
const OxyRuntimeContext = /*#__PURE__*/createContext(null);
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The SDK's internal runtime provider — the session/account state machine that
|
|
46
|
+
* backs `useOxy()`.
|
|
47
|
+
*
|
|
48
|
+
* This is NOT the component consumers mount. The one public composition root is
|
|
49
|
+
* `OxyProvider` (`../components/OxyProvider`), which mounts this alongside the
|
|
50
|
+
* QueryClient, Bloom's dialog/surface/toast hosts, safe areas, the gesture root
|
|
51
|
+
* and the keyboard provider. Naming both of them `OxyProvider` (as this file
|
|
52
|
+
* used to) made every error message, stack frame and doc reference ambiguous —
|
|
53
|
+
* see ADR 0004.
|
|
54
|
+
*/
|
|
55
|
+
export const OxyRuntimeProvider = ({
|
|
39
56
|
children,
|
|
40
57
|
oxyServices: providedOxyServices,
|
|
41
58
|
baseURL,
|
|
@@ -47,6 +64,7 @@ export const OxyProvider = ({
|
|
|
47
64
|
sessionMode = 'account',
|
|
48
65
|
webAuthMode = 'popup',
|
|
49
66
|
backgroundSession = false,
|
|
67
|
+
deviceCredentialStorage = 'persistent',
|
|
50
68
|
onAuthStateChange,
|
|
51
69
|
onError
|
|
52
70
|
}) => {
|
|
@@ -63,17 +81,24 @@ export const OxyProvider = ({
|
|
|
63
81
|
authRedirectUri
|
|
64
82
|
});
|
|
65
83
|
} else {
|
|
66
|
-
throw new Error('Either oxyServices or baseURL must be provided to
|
|
84
|
+
throw new Error('Either oxyServices or baseURL must be provided to OxyProvider');
|
|
67
85
|
}
|
|
68
86
|
}
|
|
69
87
|
const oxyServices = oxyServicesRef.current;
|
|
70
88
|
|
|
71
|
-
// The device-first persisted auth-state store (per-origin
|
|
72
|
-
//
|
|
73
|
-
//
|
|
89
|
+
// The device-first persisted auth-state store (per-origin device credential on
|
|
90
|
+
// web; SecureStore session blob on native). Built ONCE per provider mount.
|
|
91
|
+
//
|
|
92
|
+
// `deviceCredentialStorage` is mount-time configuration for the same reason
|
|
93
|
+
// `sessionMode` is: it decides where the durable credential lives, and letting
|
|
94
|
+
// it change mid-flight would mean a session that started ephemeral could begin
|
|
95
|
+
// writing one.
|
|
74
96
|
const authStoreRef = useRef(null);
|
|
75
97
|
if (!authStoreRef.current) {
|
|
76
|
-
authStoreRef.current = createPlatformAuthStateStore(
|
|
98
|
+
authStoreRef.current = createPlatformAuthStateStore({
|
|
99
|
+
sessionMode,
|
|
100
|
+
storage: deviceCredentialStorage
|
|
101
|
+
});
|
|
77
102
|
}
|
|
78
103
|
const authStore = authStoreRef.current;
|
|
79
104
|
|
|
@@ -93,34 +118,92 @@ export const OxyProvider = ({
|
|
|
93
118
|
}
|
|
94
119
|
const identity = identityRef.current;
|
|
95
120
|
const isIdentityBound = identity !== null;
|
|
121
|
+
const logger = useCallback((message, err) => {
|
|
122
|
+
if (__DEV__) {
|
|
123
|
+
loggerUtil.warn(message, {
|
|
124
|
+
component: 'OxyContext'
|
|
125
|
+
}, err);
|
|
126
|
+
}
|
|
127
|
+
}, []);
|
|
128
|
+
|
|
129
|
+
// Server-authoritative device session client. Built ONCE per `oxyServices`
|
|
130
|
+
// instance. Device-scoped sockets connect with deviceId+deviceSecret when no
|
|
131
|
+
// bearer is planted yet, so cross-origin apps sync via `session_state`.
|
|
132
|
+
const sessionClientPairRef = useRef(null);
|
|
133
|
+
if (!sessionClientPairRef.current) {
|
|
134
|
+
sessionClientPairRef.current = createSessionClient(oxyServices, origin => {
|
|
135
|
+
// Erase the DURABLE device credential only on a `request`-origin verdict
|
|
136
|
+
// (a REST sign-out / revocation). A `push`-origin empty state is a socket
|
|
137
|
+
// broadcast that may be a transient reconnect artifact — clearing the
|
|
138
|
+
// credential on it would strand the user signed out with no way back, so
|
|
139
|
+
// we clear only the local UI session and keep the credential (a dead one
|
|
140
|
+
// re-mints to `no_active_session` and resolves signed-out on next boot).
|
|
141
|
+
if (origin === 'request') {
|
|
142
|
+
clearPersistedAuthSafe(authStore, logger);
|
|
143
|
+
}
|
|
144
|
+
void clearSessionStateRef.current().catch(clearError => {
|
|
145
|
+
logger('Failed to clear local state on remote sign-out', clearError);
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
// `null` for every account-mode provider — identical to omitting the
|
|
149
|
+
// option — and the pinned account id once an identity-bound provider has
|
|
150
|
+
// resolved its pin. Read through the ref so the resolver stays stable for
|
|
151
|
+
// the client's lifetime while still seeing later resolutions.
|
|
152
|
+
() => identityRef.current?.getPinnedAccountId() ?? null);
|
|
153
|
+
}
|
|
96
154
|
const {
|
|
97
|
-
|
|
98
|
-
|
|
155
|
+
client: sessionClient,
|
|
156
|
+
host: sessionClientHost
|
|
157
|
+
} = sessionClientPairRef.current;
|
|
158
|
+
|
|
159
|
+
// ── The runtime ──────────────────────────────────────────────────────────
|
|
160
|
+
// One owner for the session facts (ADR 0004), built ONCE and never rebuilt,
|
|
161
|
+
// so the context value below can hand out a reference that never changes.
|
|
162
|
+
//
|
|
163
|
+
// Its three callbacks reach forward through refs because the collaborators
|
|
164
|
+
// they need — the storage-backed teardown, the account-graph refresh — are
|
|
165
|
+
// hooks declared after it. Latching the runtime here rather than after them
|
|
166
|
+
// is deliberate: a runtime rebuilt mid-flight would drop its `SessionClient`
|
|
167
|
+
// subscription and every subscriber with it.
|
|
168
|
+
const clearSessionStateRef = useRef(() => Promise.resolve());
|
|
169
|
+
const saveSessionIdsRef = useRef(() => undefined);
|
|
170
|
+
const subjectChangeRef = useRef(() => undefined);
|
|
171
|
+
const reestablishRef = useRef(() => undefined);
|
|
172
|
+
const runtimeRef = useRef(null);
|
|
173
|
+
if (!runtimeRef.current) {
|
|
174
|
+
runtimeRef.current = createOxyRuntime({
|
|
175
|
+
oxyServices,
|
|
176
|
+
sessionClient,
|
|
177
|
+
sessionClientHost,
|
|
178
|
+
identity,
|
|
179
|
+
onSubjectChange: transition => subjectChangeRef.current(transition),
|
|
180
|
+
onDeviceEmpty: () => clearSessionStateRef.current(),
|
|
181
|
+
onSessionsProjected: sessionIds => saveSessionIdsRef.current(sessionIds),
|
|
182
|
+
onIdentityUnbound: (binding, revision) => reestablishRef.current(binding, revision),
|
|
183
|
+
logger
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
const runtime = runtimeRef.current;
|
|
187
|
+
const snapshot = useRuntimeSnapshot(runtime);
|
|
188
|
+
const {
|
|
189
|
+
account: user,
|
|
190
|
+
sessions,
|
|
191
|
+
activeSessionId,
|
|
99
192
|
isLoading,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
isAuthenticated: state.isAuthenticated,
|
|
107
|
-
isLoading: state.isLoading,
|
|
108
|
-
error: state.error,
|
|
109
|
-
loginSuccess: state.loginSuccess,
|
|
110
|
-
loginFailure: state.loginFailure,
|
|
111
|
-
logoutStore: state.logout
|
|
112
|
-
})));
|
|
113
|
-
const [tokenReady, setTokenReady] = useState(true);
|
|
114
|
-
const [hasAccessToken, setHasAccessToken] = useState(() => Boolean(oxyServices.getAccessToken()));
|
|
115
|
-
const [authResolved, setAuthResolved] = useState(false);
|
|
116
|
-
const authResolvedRef = useRef(false);
|
|
117
|
-
const userRef = useRef(user);
|
|
118
|
-
const isAuthenticatedRef = useRef(isAuthenticated);
|
|
119
|
-
userRef.current = user;
|
|
120
|
-
isAuthenticatedRef.current = isAuthenticated;
|
|
193
|
+
tokenReady,
|
|
194
|
+
hasAccessToken,
|
|
195
|
+
authResolved
|
|
196
|
+
} = snapshot;
|
|
197
|
+
const isAuthenticated = user !== null;
|
|
198
|
+
const error = snapshot.error?.message ?? null;
|
|
121
199
|
const [initialized, setInitialized] = useState(false);
|
|
122
200
|
const [accountDialogOpen, setAccountDialogOpen] = useState(false);
|
|
123
|
-
|
|
201
|
+
|
|
202
|
+
// Project the runtime onto `useAuthStore`, which a dozen out-of-band callers
|
|
203
|
+
// (mutation success handlers, cache helpers, the Commons app) still read the
|
|
204
|
+
// signed-in user through. It is a projection, not a second store.
|
|
205
|
+
useEffect(() => bindAuthStoreToRuntime(runtime), [runtime]);
|
|
206
|
+
useEffect(() => runtime.start(), [runtime]);
|
|
124
207
|
|
|
125
208
|
// Keep the shared `oxyClient` singleton's token store in lockstep with the
|
|
126
209
|
// session owned by THIS provider's instance (many apps build API clients
|
|
@@ -140,13 +223,6 @@ export const OxyProvider = ({
|
|
|
140
223
|
applyToSingleton(oxyServices.getAccessToken());
|
|
141
224
|
return oxyServices.onTokensChanged(applyToSingleton);
|
|
142
225
|
}, [oxyServices]);
|
|
143
|
-
const logger = useCallback((message, err) => {
|
|
144
|
-
if (__DEV__) {
|
|
145
|
-
loggerUtil.warn(message, {
|
|
146
|
-
component: 'OxyContext'
|
|
147
|
-
}, err);
|
|
148
|
-
}
|
|
149
|
-
}, []);
|
|
150
226
|
const storageKeys = useMemo(() => getStorageKeys(storageKeyPrefix), [storageKeyPrefix]);
|
|
151
227
|
const clientId = useMemo(() => {
|
|
152
228
|
const trimmed = clientIdProp?.trim();
|
|
@@ -180,6 +256,7 @@ export const OxyProvider = ({
|
|
|
180
256
|
storageReady.resolve(storageInstance);
|
|
181
257
|
if (mounted) {
|
|
182
258
|
setStorage(storageInstance);
|
|
259
|
+
runtime.setStorageReady(true);
|
|
183
260
|
}
|
|
184
261
|
}).catch(err => {
|
|
185
262
|
if (mounted) {
|
|
@@ -194,7 +271,7 @@ export const OxyProvider = ({
|
|
|
194
271
|
return () => {
|
|
195
272
|
mounted = false;
|
|
196
273
|
};
|
|
197
|
-
}, [logger, onError, storageReady]);
|
|
274
|
+
}, [logger, onError, runtime, storageReady]);
|
|
198
275
|
const {
|
|
199
276
|
currentLanguage,
|
|
200
277
|
languages: currentLanguages,
|
|
@@ -211,85 +288,36 @@ export const OxyProvider = ({
|
|
|
211
288
|
});
|
|
212
289
|
const queryClient = useQueryClient();
|
|
213
290
|
const {
|
|
214
|
-
|
|
215
|
-
activeSessionId,
|
|
216
|
-
setActiveSessionId,
|
|
217
|
-
updateSessions,
|
|
291
|
+
saveSessionIds,
|
|
218
292
|
switchSession,
|
|
219
293
|
clearSessionState,
|
|
220
294
|
saveActiveSessionId
|
|
221
295
|
} = useSessionManagement({
|
|
222
296
|
oxyServices,
|
|
297
|
+
runtime,
|
|
223
298
|
storage,
|
|
224
299
|
storageKeyPrefix,
|
|
225
|
-
loginSuccess,
|
|
226
|
-
logoutStore,
|
|
227
300
|
onAuthStateChange,
|
|
228
301
|
onError,
|
|
229
|
-
setAuthError: message =>
|
|
230
|
-
error: message
|
|
231
|
-
}),
|
|
302
|
+
setAuthError: message => runtime.setError(message),
|
|
232
303
|
logger,
|
|
233
|
-
setTokenReady,
|
|
234
304
|
queryClient
|
|
235
305
|
});
|
|
236
|
-
|
|
237
|
-
// Refs so callbacks below can invoke the latest session-management functions
|
|
238
|
-
// without widening dependency arrays.
|
|
239
|
-
const switchSessionRef = useRef(switchSession);
|
|
240
|
-
switchSessionRef.current = switchSession;
|
|
241
|
-
const clearSessionStateRef = useRef(clearSessionState);
|
|
242
306
|
clearSessionStateRef.current = clearSessionState;
|
|
243
|
-
|
|
244
|
-
setActiveSessionIdRef.current = setActiveSessionId;
|
|
245
|
-
const loginSuccessRef = useRef(loginSuccess);
|
|
246
|
-
loginSuccessRef.current = loginSuccess;
|
|
307
|
+
saveSessionIdsRef.current = saveSessionIds;
|
|
247
308
|
const onAuthStateChangeRef = useRef(onAuthStateChange);
|
|
248
309
|
onAuthStateChangeRef.current = onAuthStateChange;
|
|
249
310
|
|
|
250
|
-
// Flip the auth-resolution gate
|
|
251
|
-
//
|
|
311
|
+
// Flip the auth-resolution gate the moment a session commits or the boot
|
|
312
|
+
// concludes signed out. Idempotent + monotonic, enforced by the runtime.
|
|
252
313
|
const markAuthResolved = useCallback(() => {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
authResolvedRef.current = true;
|
|
257
|
-
setTokenReady(true);
|
|
258
|
-
setAuthResolved(true);
|
|
259
|
-
}, []);
|
|
314
|
+
runtime.markAuthResolved();
|
|
315
|
+
}, [runtime]);
|
|
260
316
|
const markAuthResolvedRef = useRef(markAuthResolved);
|
|
261
317
|
markAuthResolvedRef.current = markAuthResolved;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
// bearer is planted yet, so cross-origin apps sync via `session_state` after
|
|
266
|
-
// the one-shot join redirect.
|
|
267
|
-
const sessionClientPairRef = useRef(null);
|
|
268
|
-
if (!sessionClientPairRef.current) {
|
|
269
|
-
sessionClientPairRef.current = createSessionClient(oxyServices, origin => {
|
|
270
|
-
// Erase the DURABLE device credential only on a `request`-origin verdict
|
|
271
|
-
// (a REST sign-out / revocation). A `push`-origin empty state is a socket
|
|
272
|
-
// broadcast that may be a transient reconnect artifact — clearing the
|
|
273
|
-
// credential on it would strand the user signed out with no way back, so
|
|
274
|
-
// we clear only the local UI session and keep the credential (a dead one
|
|
275
|
-
// re-mints to `no_active_session` and resolves signed-out on next boot).
|
|
276
|
-
if (origin === 'request') {
|
|
277
|
-
clearPersistedAuthSafe(authStore, logger);
|
|
278
|
-
}
|
|
279
|
-
void clearSessionStateRef.current().catch(clearError => {
|
|
280
|
-
logger('Failed to clear local state on remote sign-out', clearError);
|
|
281
|
-
});
|
|
282
|
-
},
|
|
283
|
-
// `null` for every account-mode provider — identical to omitting the
|
|
284
|
-
// option — and the pinned account id once an identity-bound provider has
|
|
285
|
-
// resolved its pin. Read through the ref so the resolver stays stable for
|
|
286
|
-
// the client's lifetime while still seeing later resolutions.
|
|
287
|
-
() => identityRef.current?.getPinnedAccountId() ?? null);
|
|
288
|
-
}
|
|
289
|
-
const {
|
|
290
|
-
client: sessionClient,
|
|
291
|
-
host: sessionClientHost
|
|
292
|
-
} = sessionClientPairRef.current;
|
|
318
|
+
const setTokenReady = useCallback(ready => {
|
|
319
|
+
runtime.setTokenReady(ready);
|
|
320
|
+
}, [runtime]);
|
|
293
321
|
|
|
294
322
|
// Re-establishment lane for an identity-bound provider whose pin is missing or
|
|
295
323
|
// whose pinned account is no longer part of this device's session set (another
|
|
@@ -334,78 +362,22 @@ export const OxyProvider = ({
|
|
|
334
362
|
tracker.inFlight = false;
|
|
335
363
|
});
|
|
336
364
|
}, [oxyServices, authStore, sessionClient, logger]);
|
|
365
|
+
reestablishRef.current = reestablishIdentitySession;
|
|
337
366
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (state.accounts.length === 0) {
|
|
347
|
-
// Clear the LOCAL UI session on any applied empty state, but NEVER the
|
|
348
|
-
// durable device credential here: `syncFromClient` runs for socket-pushed
|
|
349
|
-
// (possibly transient) states too, and wiping the credential on one would
|
|
350
|
-
// strand the user signed out. The credential wipe is gated on a
|
|
351
|
-
// `request`-origin verdict in `onUnauthenticated` above.
|
|
352
|
-
sessionClientHost.setCurrentAccountId(null);
|
|
353
|
-
await clearSessionState();
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
// Last-write-wins guard: capture the revision this projection is for, then
|
|
357
|
-
// after the async profile fetch bail if a fresher state has landed.
|
|
358
|
-
const capturedRevision = state.revision;
|
|
359
|
-
// Resolve the pin BEFORE the profile fetch (memoised: one storage + keychain
|
|
360
|
-
// read per boot) so every projection below is bound on the FIRST pass over a
|
|
361
|
-
// freshly applied state. Deferring it would let a sibling app's switch render
|
|
362
|
-
// once as this client's user before the pin corrected it. `null` for every
|
|
363
|
-
// account-mode provider, where each projection falls back to the device's
|
|
364
|
-
// active account exactly as before.
|
|
365
|
-
const pinnedAccountId = identity ? await identity.ensurePinnedAccountId() : null;
|
|
366
|
-
const ids = accountIdsOf(state);
|
|
367
|
-
let users = [];
|
|
368
|
-
try {
|
|
369
|
-
users = ids.length > 0 ? await oxyServices.getUsersByIds(ids) : [];
|
|
370
|
-
} catch (fetchError) {
|
|
371
|
-
logger('Failed to resolve account profiles during syncFromClient', fetchError);
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
const latest = sessionClient.getState();
|
|
375
|
-
if (!latest || latest.revision !== capturedRevision) {
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
if (identity && (pinnedAccountId === null || activeSessionIdOf(latest, pinnedAccountId) === null)) {
|
|
379
|
-
// Either no verified pin, or the pinned account left this device's session
|
|
380
|
-
// set. Projecting anything here would mean projecting SOMEBODY ELSE's
|
|
381
|
-
// account, so leave the current projection untouched and re-derive the
|
|
382
|
-
// session from the local identity key instead.
|
|
383
|
-
reestablishIdentitySession(identity, latest.revision);
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
const usersById = new Map(users.map(resolvedUser => [resolvedUser.id, resolvedUser]));
|
|
387
|
-
updateSessions(deviceStateToClientSessions(latest, usersById, pinnedAccountId));
|
|
388
|
-
setActiveSessionId(activeSessionIdOf(latest, pinnedAccountId));
|
|
389
|
-
const activeUser = activeUserOf(latest, usersById, pinnedAccountId);
|
|
390
|
-
if (activeUser) {
|
|
391
|
-
loginSuccess(activeUser);
|
|
392
|
-
}
|
|
393
|
-
// The host's current account feeds the socket handshake and the bearer's
|
|
394
|
-
// token-account comparisons, so it tracks the PIN — never the account another
|
|
395
|
-
// app switched the device to.
|
|
396
|
-
sessionClientHost.setCurrentAccountId(pinnedAccountId ?? latest.activeAccountId);
|
|
397
|
-
}, [identity, oxyServices, reestablishIdentitySession, sessionClient, sessionClientHost, updateSessions, setActiveSessionId, loginSuccess, clearSessionState, logger]);
|
|
367
|
+
/**
|
|
368
|
+
* Project the server-authoritative device state onto the runtime.
|
|
369
|
+
*
|
|
370
|
+
* The projection itself lives in the runtime; this is the awaitable handle
|
|
371
|
+
* the commit/logout/reconnect paths already had. It is stable, because the
|
|
372
|
+
* runtime is.
|
|
373
|
+
*/
|
|
374
|
+
const syncFromClient = useCallback(() => runtime.reconcileFromClient(), [runtime]);
|
|
398
375
|
const syncFromClientRef = useRef(syncFromClient);
|
|
399
376
|
syncFromClientRef.current = syncFromClient;
|
|
400
377
|
const syncDeviceCredentialToHost = useCallback(async () => {
|
|
401
378
|
const cred = await loadPersistedDeviceCredential(authStore);
|
|
402
379
|
sessionClientHost.setDeviceCredential(cred);
|
|
403
380
|
}, [authStore, sessionClientHost]);
|
|
404
|
-
useEffect(() => {
|
|
405
|
-
return sessionClient.subscribe(() => {
|
|
406
|
-
void syncFromClient();
|
|
407
|
-
});
|
|
408
|
-
}, [sessionClient, syncFromClient]);
|
|
409
381
|
const {
|
|
410
382
|
signIn,
|
|
411
383
|
logout,
|
|
@@ -414,9 +386,7 @@ export const OxyProvider = ({
|
|
|
414
386
|
oxyServices,
|
|
415
387
|
store: authStore,
|
|
416
388
|
storage,
|
|
417
|
-
|
|
418
|
-
setActiveSessionId,
|
|
419
|
-
updateSessions,
|
|
389
|
+
runtime,
|
|
420
390
|
saveActiveSessionId,
|
|
421
391
|
clearSessionState,
|
|
422
392
|
switchSession,
|
|
@@ -424,10 +394,6 @@ export const OxyProvider = ({
|
|
|
424
394
|
syncFromClient,
|
|
425
395
|
onAuthStateChange,
|
|
426
396
|
onError,
|
|
427
|
-
loginSuccess,
|
|
428
|
-
loginFailure,
|
|
429
|
-
logoutStore,
|
|
430
|
-
setAuthState,
|
|
431
397
|
logger,
|
|
432
398
|
...(identity ? {
|
|
433
399
|
identityBinding: identity.binding,
|
|
@@ -456,7 +422,6 @@ export const OxyProvider = ({
|
|
|
456
422
|
// Explicit FULL wipe: also drop the persisted device credential so a reload
|
|
457
423
|
// finds nothing to restore.
|
|
458
424
|
await authStore.clear();
|
|
459
|
-
useAccountStore.getState().reset();
|
|
460
425
|
oxyServices.clearCache();
|
|
461
426
|
}, [queryClient, storage, clearSessionState, authStore, logger, oxyServices]);
|
|
462
427
|
const {
|
|
@@ -470,7 +435,6 @@ export const OxyProvider = ({
|
|
|
470
435
|
clearSessionState,
|
|
471
436
|
logger
|
|
472
437
|
});
|
|
473
|
-
const useFollowHook = loadUseFollowHook();
|
|
474
438
|
|
|
475
439
|
// Token-change side effects: an invalidated bearer (HttpService clears tokens
|
|
476
440
|
// on an unrecoverable 401 and emits `null`) must locally sign out an
|
|
@@ -481,16 +445,16 @@ export const OxyProvider = ({
|
|
|
481
445
|
const clearingInvalidTokenRef = useRef(false);
|
|
482
446
|
useEffect(() => {
|
|
483
447
|
const handleTokenChange = accessToken => {
|
|
484
|
-
setHasAccessToken(Boolean(accessToken));
|
|
448
|
+
runtime.setHasAccessToken(Boolean(accessToken));
|
|
485
449
|
if (accessToken) {
|
|
486
|
-
setTokenReady(true);
|
|
450
|
+
runtime.setTokenReady(true);
|
|
487
451
|
if (sessionClient.getState()?.accounts.length) {
|
|
488
452
|
void syncFromClientRef.current();
|
|
489
453
|
}
|
|
490
454
|
return;
|
|
491
455
|
}
|
|
492
|
-
if (
|
|
493
|
-
setTokenReady(false);
|
|
456
|
+
if (runtime.getSnapshot().account !== null) {
|
|
457
|
+
runtime.setTokenReady(false);
|
|
494
458
|
if (clearingInvalidTokenRef.current) {
|
|
495
459
|
return;
|
|
496
460
|
}
|
|
@@ -499,19 +463,19 @@ export const OxyProvider = ({
|
|
|
499
463
|
logger('Failed to clear invalidated auth session', clearError);
|
|
500
464
|
}).finally(() => {
|
|
501
465
|
clearingInvalidTokenRef.current = false;
|
|
502
|
-
if (
|
|
503
|
-
setTokenReady(true);
|
|
466
|
+
if (runtime.getSnapshot().authResolved) {
|
|
467
|
+
runtime.setTokenReady(true);
|
|
504
468
|
}
|
|
505
469
|
});
|
|
506
470
|
return;
|
|
507
471
|
}
|
|
508
|
-
if (
|
|
509
|
-
setTokenReady(true);
|
|
472
|
+
if (runtime.getSnapshot().authResolved) {
|
|
473
|
+
runtime.setTokenReady(true);
|
|
510
474
|
}
|
|
511
475
|
};
|
|
512
476
|
handleTokenChange(oxyServices.getAccessToken());
|
|
513
477
|
return oxyServices.onTokensChanged(handleTokenChange);
|
|
514
|
-
}, [logger, oxyServices, sessionClient]);
|
|
478
|
+
}, [logger, oxyServices, runtime, sessionClient]);
|
|
515
479
|
|
|
516
480
|
// Unified in-session refresh (SDK-owned; every RP inherits it). Installs the
|
|
517
481
|
// ONE core refresh handler (re-mint from the persisted zero-cookie device
|
|
@@ -574,20 +538,25 @@ export const OxyProvider = ({
|
|
|
574
538
|
}
|
|
575
539
|
|
|
576
540
|
// Fast local mirror so the UI updates before the server round-trip; the
|
|
577
|
-
// SessionClient projection below overwrites it with server truth.
|
|
541
|
+
// SessionClient projection below overwrites it with server truth. Batched
|
|
542
|
+
// so the mirror and the active id land in ONE transition — unbatched, a
|
|
543
|
+
// subscriber woken between them would see the new session list still
|
|
544
|
+
// pointing at the previous active id.
|
|
578
545
|
if (input.userId) {
|
|
579
546
|
const now = new Date();
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
547
|
+
runtime.batch(() => {
|
|
548
|
+
runtime.mergeSessions([{
|
|
549
|
+
sessionId: input.sessionId,
|
|
550
|
+
deviceId: input.deviceId ?? '',
|
|
551
|
+
expiresAt: input.expiresAt || new Date(now.getTime() + DEFAULT_SESSION_VALIDITY_MS).toISOString(),
|
|
552
|
+
lastActive: now.toISOString(),
|
|
553
|
+
userId: input.userId,
|
|
554
|
+
isCurrent: true
|
|
555
|
+
}], {
|
|
556
|
+
merge: true
|
|
557
|
+
});
|
|
558
|
+
runtime.setActiveSessionId(input.sessionId);
|
|
589
559
|
});
|
|
590
|
-
setActiveSessionId(input.sessionId);
|
|
591
560
|
}
|
|
592
561
|
|
|
593
562
|
// Register into the device set, hydrate the full user, and flip the
|
|
@@ -607,11 +576,11 @@ export const OxyProvider = ({
|
|
|
607
576
|
startSocket: () => sessionClient.start(),
|
|
608
577
|
syncFromClient,
|
|
609
578
|
getCurrentUser: () => oxyServices.getCurrentUser(),
|
|
610
|
-
loginSuccess,
|
|
579
|
+
loginSuccess: fullUser => runtime.setAccount(fullUser),
|
|
611
580
|
onAuthStateChange: onAuthStateChangeRef.current,
|
|
612
581
|
markAuthResolved: markAuthResolvedRef.current
|
|
613
582
|
});
|
|
614
|
-
}, [oxyServices, authStore,
|
|
583
|
+
}, [oxyServices, authStore, runtime, sessionClient, sessionClientHost, syncFromClient, logger]);
|
|
615
584
|
const commitSessionRef = useRef(commitSession);
|
|
616
585
|
commitSessionRef.current = commitSession;
|
|
617
586
|
|
|
@@ -634,27 +603,6 @@ export const OxyProvider = ({
|
|
|
634
603
|
});
|
|
635
604
|
}, [commitSession]);
|
|
636
605
|
|
|
637
|
-
// Commit a minted graph-SWITCH session through the same funnel as
|
|
638
|
-
// `handleWebSession`. Nothing extra to do IN-PLACE: the switch already
|
|
639
|
-
// propagates across tabs/apps via the server's `session_state` socket
|
|
640
|
-
// broadcast.
|
|
641
|
-
const commitSwitchedSession = useCallback(async session => {
|
|
642
|
-
if (!session?.user || !session?.sessionId || !session.accessToken) {
|
|
643
|
-
throw new Error('Session response did not include a usable session');
|
|
644
|
-
}
|
|
645
|
-
await commitSession({
|
|
646
|
-
sessionId: session.sessionId,
|
|
647
|
-
accessToken: session.accessToken,
|
|
648
|
-
deviceSecret: session.deviceSecret,
|
|
649
|
-
deviceId: session.deviceId,
|
|
650
|
-
expiresAt: session.expiresAt,
|
|
651
|
-
userId: session.user.id,
|
|
652
|
-
user: session.user
|
|
653
|
-
}, {
|
|
654
|
-
activate: true
|
|
655
|
-
});
|
|
656
|
-
}, [commitSession]);
|
|
657
|
-
|
|
658
606
|
// ── Web third-party OAuth sign-in ──────────────────────────────────────────
|
|
659
607
|
// The shared operation `OxySignInButton` (and any RP-owned button) delegates
|
|
660
608
|
// to, so no consumer ever writes popup listeners or a token exchange. The
|
|
@@ -674,13 +622,11 @@ export const OxyProvider = ({
|
|
|
674
622
|
// ── Unified account dialog ─────────────────────────────────────────────────
|
|
675
623
|
// The single account-chooser + sign-in surface. Built ONCE per provider mount
|
|
676
624
|
// and bound to the live `oxyServices` + `sessionClient` + this provider's
|
|
677
|
-
// commit
|
|
678
|
-
//
|
|
679
|
-
//
|
|
625
|
+
// sign-in commit funnel, threaded through a ref so the controller keeps a
|
|
626
|
+
// STABLE commit callback (rebuilding the controller on every commit-identity
|
|
627
|
+
// change would drop its subscription + state).
|
|
680
628
|
const handleWebSessionRef = useRef(handleWebSession);
|
|
681
629
|
handleWebSessionRef.current = handleWebSession;
|
|
682
|
-
const commitSwitchedSessionRef = useRef(commitSwitchedSession);
|
|
683
|
-
commitSwitchedSessionRef.current = commitSwitchedSession;
|
|
684
630
|
|
|
685
631
|
// The live AccountDialog surface (a stacked Bloom surface), while open — the
|
|
686
632
|
// SINGLE source of truth for "is the account dialog open". Held so
|
|
@@ -723,12 +669,10 @@ export const OxyProvider = ({
|
|
|
723
669
|
oxyServices,
|
|
724
670
|
sessionClient,
|
|
725
671
|
clientId,
|
|
726
|
-
locale: currentLanguage,
|
|
727
672
|
// Same statically-injected `io` as the SessionClient: gives the QR flow an
|
|
728
673
|
// instant `/auth-session` `auth_update` wake instead of a slow poll.
|
|
729
674
|
socketFactory: io,
|
|
730
675
|
commitSession: session => handleWebSessionRef.current(session),
|
|
731
|
-
commitSwitchedSession: session => commitSwitchedSessionRef.current(session),
|
|
732
676
|
onSignedIn: () => {
|
|
733
677
|
// Close the dialog: pop the morphed frame back to its host surface, or
|
|
734
678
|
// dismiss the detached surface (whose settle flips `accountDialogOpen`).
|
|
@@ -947,7 +891,7 @@ export const OxyProvider = ({
|
|
|
947
891
|
if (identity) {
|
|
948
892
|
await identity.refreshPinnedAccountId();
|
|
949
893
|
}
|
|
950
|
-
}, [oxyServices, authStore, clientIdProp, authRedirectUri, sessionMode, identity, syncDeviceCredentialToHost, sessionClient]);
|
|
894
|
+
}, [oxyServices, authStore, clientIdProp, authRedirectUri, sessionMode, identity, syncDeviceCredentialToHost, sessionClient, setTokenReady]);
|
|
951
895
|
useEffect(() => {
|
|
952
896
|
if (initialized) {
|
|
953
897
|
return;
|
|
@@ -1046,12 +990,12 @@ export const OxyProvider = ({
|
|
|
1046
990
|
}
|
|
1047
991
|
await sessionClient.switchAccount(targetAccountId);
|
|
1048
992
|
await syncFromClient();
|
|
1049
|
-
const activeUser =
|
|
993
|
+
const activeUser = runtime.getSnapshot().account;
|
|
1050
994
|
if (!activeUser) {
|
|
1051
995
|
throw new Error('Active account profile could not be resolved after switch');
|
|
1052
996
|
}
|
|
1053
997
|
return activeUser;
|
|
1054
|
-
}, [isIdentityBound, sessionClient, syncFromClient]);
|
|
998
|
+
}, [isIdentityBound, runtime, sessionClient, syncFromClient]);
|
|
1055
999
|
|
|
1056
1000
|
// Thin passthroughs to the platform-agnostic KeyManager. NOTE: both now THROW
|
|
1057
1001
|
// `IdentityUnavailableError` (from `@oxyhq/core`) when identity storage is
|
|
@@ -1087,10 +1031,44 @@ export const OxyProvider = ({
|
|
|
1087
1031
|
sessionClient,
|
|
1088
1032
|
syncFromClient,
|
|
1089
1033
|
commitSession,
|
|
1090
|
-
queryClient,
|
|
1091
1034
|
accountDialogControllerRef,
|
|
1092
1035
|
clearSessionStateRef
|
|
1093
1036
|
});
|
|
1037
|
+
|
|
1038
|
+
// The account-scoped cache reset, run by the runtime BETWEEN committing the
|
|
1039
|
+
// new subject's bearer and waking anybody (ADR 0002). It used to trail the two
|
|
1040
|
+
// branches of `switchToAccount`, which meant a switch pushed over the socket
|
|
1041
|
+
// by another app on this device got none of it: the follow stores, the scoped
|
|
1042
|
+
// media URLs and every warm query stayed on the previous subject until
|
|
1043
|
+
// something happened to refetch.
|
|
1044
|
+
//
|
|
1045
|
+
// An initial sign-in is deliberately exempt. There is nothing account-scoped
|
|
1046
|
+
// cached before the first account, so invalidating everything there would only
|
|
1047
|
+
// buy a refetch storm at first paint.
|
|
1048
|
+
const handleSubjectChange = useCallback(({
|
|
1049
|
+
previous,
|
|
1050
|
+
next
|
|
1051
|
+
}) => {
|
|
1052
|
+
if (previous === null) {
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
resetSessionScopedStores();
|
|
1056
|
+
if (next === null) {
|
|
1057
|
+
// A sign-out: `clearSessionState` owns the rest of the teardown, and
|
|
1058
|
+
// invalidating a cache we are about to clear would only refetch as the
|
|
1059
|
+
// bearer disappears.
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
// Scoped media tokens are per-viewer — drop any cached URLs immediately so
|
|
1063
|
+
// `keepPreviousData`-style placeholders cannot flash the prior account's
|
|
1064
|
+
// private thumbnails while the new bearer mint lands.
|
|
1065
|
+
queryClient.removeQueries({
|
|
1066
|
+
queryKey: [ASSET_DOWNLOAD_URLS_QUERY_KEY]
|
|
1067
|
+
});
|
|
1068
|
+
queryClient.invalidateQueries();
|
|
1069
|
+
void refreshAccounts();
|
|
1070
|
+
}, [queryClient, refreshAccounts]);
|
|
1071
|
+
subjectChangeRef.current = handleSubjectChange;
|
|
1094
1072
|
const canUsePrivateApi = authResolved && isAuthenticated && tokenReady && hasAccessToken;
|
|
1095
1073
|
const isPrivateApiPending = !authResolved || isAuthenticated && (!tokenReady || !hasAccessToken);
|
|
1096
1074
|
|
|
@@ -1116,7 +1094,7 @@ export const OxyProvider = ({
|
|
|
1116
1094
|
canUsePrivateApi,
|
|
1117
1095
|
isPrivateApiPending,
|
|
1118
1096
|
isAuthResolved: authResolved,
|
|
1119
|
-
isStorageReady:
|
|
1097
|
+
isStorageReady: snapshot.storageReady,
|
|
1120
1098
|
sessionMode: isIdentityBound ? 'identity' : 'account',
|
|
1121
1099
|
webAuthMode,
|
|
1122
1100
|
error,
|
|
@@ -1150,7 +1128,7 @@ export const OxyProvider = ({
|
|
|
1150
1128
|
clientId,
|
|
1151
1129
|
oxyServices,
|
|
1152
1130
|
sessionClient,
|
|
1153
|
-
useFollow
|
|
1131
|
+
useFollow,
|
|
1154
1132
|
showBottomSheet: showBottomSheetForContext,
|
|
1155
1133
|
openAvatarPicker,
|
|
1156
1134
|
accountDialogController,
|
|
@@ -1161,83 +1139,53 @@ export const OxyProvider = ({
|
|
|
1161
1139
|
switchToAccount,
|
|
1162
1140
|
refreshAccounts,
|
|
1163
1141
|
createAccount: createAccountFn
|
|
1164
|
-
}), [user, sessions, activeSessionId, isAuthenticated, isLoading, tokenReady, hasAccessToken, canUsePrivateApi, isPrivateApiPending, authResolved,
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1142
|
+
}), [user, sessions, activeSessionId, isAuthenticated, isLoading, tokenReady, hasAccessToken, canUsePrivateApi, isPrivateApiPending, authResolved, snapshot.storageReady, isIdentityBound, webAuthMode, error, currentLanguage, currentLanguages, currentLanguageMetadata, currentLanguageName, currentNativeLanguageName, hasIdentity, getPublicKey, signIn, signInWithPasskey, registerWithPasskey, addPasskey, removePasskey, revokeSuspiciousSignIn, handleWebSession, startWebOAuthSignInForContext, logout, logoutAll, switchSessionForContext, refreshSessionsForContext, setLanguage, getDeviceSessions, logoutAllDeviceSessions, updateDeviceName, clearSessionState, clearAllAccountData, storageKeyPrefix, clientId, oxyServices, sessionClient, showBottomSheetForContext, openAvatarPicker, accountDialogController, accountDialogOpen, openAccountDialog, closeAccountDialog, accounts, switchToAccount, refreshAccounts, createAccountFn]);
|
|
1143
|
+
|
|
1144
|
+
// Two contexts, deliberately. The inner one carries the wide compatibility
|
|
1145
|
+
// value every `useOxy()` consumer reads, rebuilt whenever any of its members
|
|
1146
|
+
// moves. The outer one carries the runtime reference, which never changes
|
|
1147
|
+
// identity — so `useActiveAccount()` and friends re-render on the fact they
|
|
1148
|
+
// selected and nothing else. Phase 8 retires the inner one.
|
|
1149
|
+
return /*#__PURE__*/_jsx(OxyRuntimeHandleProvider, {
|
|
1150
|
+
value: runtime,
|
|
1151
|
+
children: /*#__PURE__*/_jsx(OxyRuntimeContext.Provider, {
|
|
1152
|
+
value: contextValue,
|
|
1153
|
+
children: children
|
|
1154
|
+
})
|
|
1168
1155
|
});
|
|
1169
1156
|
};
|
|
1170
|
-
|
|
1157
|
+
const PROVIDER_MISSING_ERROR_MESSAGE = 'useOxy() was called outside <OxyProvider>. Mount <OxyProvider clientId="…"> above this component, ' + 'or use useOptionalOxy() if this component legitimately renders both inside and outside the provider.';
|
|
1158
|
+
export class OxyProviderMissingError extends Error {
|
|
1159
|
+
code = 'oxy_provider_missing';
|
|
1160
|
+
constructor() {
|
|
1161
|
+
super(PROVIDER_MISSING_ERROR_MESSAGE);
|
|
1162
|
+
this.name = 'OxyProviderMissingError';
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1171
1165
|
|
|
1172
1166
|
/**
|
|
1173
|
-
*
|
|
1174
|
-
*
|
|
1167
|
+
* The base runtime hook. THROWS when no `<OxyProvider>` is mounted.
|
|
1168
|
+
*
|
|
1169
|
+
* It used to return a fabricated forever-loading runtime — `isLoading: true`,
|
|
1170
|
+
* `isPrivateApiPending: true`, every method a rejecting no-op — which turned a
|
|
1171
|
+
* missing provider into a UI that spins forever with nothing in the console.
|
|
1172
|
+
* Failing here names the mistake at the exact component that made it (ADR 0004).
|
|
1173
|
+
*
|
|
1174
|
+
* A component that legitimately renders both inside and outside the provider
|
|
1175
|
+
* uses {@link useOptionalOxy} instead.
|
|
1175
1176
|
*/
|
|
1176
|
-
const PROVIDER_MISSING_ERROR_MESSAGE = 'OxyProvider is not mounted. Wrap your app in <OxyProvider> before calling useOxy() methods.';
|
|
1177
|
-
const rejectMissingProvider = () => Promise.reject(new Error(PROVIDER_MISSING_ERROR_MESSAGE));
|
|
1178
|
-
const LOADING_STATE_OXY_SERVICES = new OxyServices({
|
|
1179
|
-
baseURL: 'about:blank'
|
|
1180
|
-
});
|
|
1181
|
-
const LOADING_STATE = {
|
|
1182
|
-
user: null,
|
|
1183
|
-
sessions: [],
|
|
1184
|
-
activeSessionId: null,
|
|
1185
|
-
isAuthenticated: false,
|
|
1186
|
-
isLoading: true,
|
|
1187
|
-
isTokenReady: false,
|
|
1188
|
-
hasAccessToken: false,
|
|
1189
|
-
canUsePrivateApi: false,
|
|
1190
|
-
isPrivateApiPending: true,
|
|
1191
|
-
isAuthResolved: false,
|
|
1192
|
-
isStorageReady: false,
|
|
1193
|
-
sessionMode: 'account',
|
|
1194
|
-
webAuthMode: 'popup',
|
|
1195
|
-
error: null,
|
|
1196
|
-
currentLanguage: 'en-US',
|
|
1197
|
-
currentLanguages: [],
|
|
1198
|
-
currentLanguageMetadata: null,
|
|
1199
|
-
currentLanguageName: 'English (United States)',
|
|
1200
|
-
currentNativeLanguageName: 'English (United States)',
|
|
1201
|
-
hasIdentity: () => Promise.resolve(false),
|
|
1202
|
-
getPublicKey: () => Promise.resolve(null),
|
|
1203
|
-
signIn: () => rejectMissingProvider(),
|
|
1204
|
-
signInWithPasskey: () => rejectMissingProvider(),
|
|
1205
|
-
registerWithPasskey: () => rejectMissingProvider(),
|
|
1206
|
-
addPasskey: () => rejectMissingProvider(),
|
|
1207
|
-
removePasskey: () => rejectMissingProvider(),
|
|
1208
|
-
revokeSuspiciousSignIn: () => rejectMissingProvider(),
|
|
1209
|
-
handleWebSession: () => rejectMissingProvider(),
|
|
1210
|
-
startWebOAuthSignIn: () => rejectMissingProvider(),
|
|
1211
|
-
logout: () => rejectMissingProvider(),
|
|
1212
|
-
logoutAll: () => rejectMissingProvider(),
|
|
1213
|
-
switchSession: () => rejectMissingProvider(),
|
|
1214
|
-
removeSession: () => rejectMissingProvider(),
|
|
1215
|
-
refreshSessions: () => rejectMissingProvider(),
|
|
1216
|
-
setLanguage: () => rejectMissingProvider(),
|
|
1217
|
-
getDeviceSessions: () => Promise.resolve([]),
|
|
1218
|
-
logoutAllDeviceSessions: () => rejectMissingProvider(),
|
|
1219
|
-
updateDeviceName: () => rejectMissingProvider(),
|
|
1220
|
-
clearSessionState: () => rejectMissingProvider(),
|
|
1221
|
-
clearAllAccountData: () => rejectMissingProvider(),
|
|
1222
|
-
storageKeyPrefix: 'oxy_session',
|
|
1223
|
-
clientId: null,
|
|
1224
|
-
oxyServices: LOADING_STATE_OXY_SERVICES,
|
|
1225
|
-
sessionClient: null,
|
|
1226
|
-
openAvatarPicker: () => {},
|
|
1227
|
-
accountDialogController: null,
|
|
1228
|
-
isAccountDialogOpen: false,
|
|
1229
|
-
openAccountDialog: () => {},
|
|
1230
|
-
closeAccountDialog: () => {},
|
|
1231
|
-
accounts: [],
|
|
1232
|
-
switchToAccount: () => rejectMissingProvider(),
|
|
1233
|
-
refreshAccounts: () => rejectMissingProvider(),
|
|
1234
|
-
createAccount: () => rejectMissingProvider()
|
|
1235
|
-
};
|
|
1236
1177
|
export const useOxy = () => {
|
|
1237
|
-
const context = useContext(
|
|
1178
|
+
const context = useContext(OxyRuntimeContext);
|
|
1238
1179
|
if (!context) {
|
|
1239
|
-
|
|
1180
|
+
throw new OxyProviderMissingError();
|
|
1240
1181
|
}
|
|
1241
1182
|
return context;
|
|
1242
1183
|
};
|
|
1184
|
+
|
|
1185
|
+
/**
|
|
1186
|
+
* `useOxy()` for the rare component that renders both inside and outside the
|
|
1187
|
+
* provider — returns `null` instead of throwing. Callers must handle `null`;
|
|
1188
|
+
* there is no fabricated runtime to fall back on.
|
|
1189
|
+
*/
|
|
1190
|
+
export const useOptionalOxy = () => useContext(OxyRuntimeContext);
|
|
1243
1191
|
//# sourceMappingURL=OxyContext.js.map
|