@oxyhq/services 28.0.0 → 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/NOTICE +10 -9
- package/README.md +65 -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 +60 -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/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/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/utils/avatarUtils.js +2 -36
- package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
- package/lib/module/index.js +16 -8
- 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/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/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/utils/avatarUtils.js +2 -35
- package/lib/module/ui/utils/avatarUtils.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +5 -3
- 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/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/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/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 +5 -3
- 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/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/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/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 +6 -7
- package/plugins/withSharedDeviceSessionProvider.js +102 -0
- package/plugins/withSharedDeviceSessionReader.js +57 -0
- package/src/__tests__/esmSourcePurity.test.ts +61 -0
- package/src/index.ts +31 -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/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/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/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/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/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/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/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/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/stores/accountStore.ts +0 -264
|
@@ -42,8 +42,7 @@ import { isWebBrowser } from '../utils/isWebBrowser';
|
|
|
42
42
|
import { resolveDeliveryPlatform } from '../utils/deliveryPlatform';
|
|
43
43
|
import { runProviderColdBoot } from '../boot/runProviderColdBoot';
|
|
44
44
|
import { loadPersistedDeviceCredential } from '../utils/deviceCredential';
|
|
45
|
-
import {
|
|
46
|
-
import { useShallow } from 'zustand/react/shallow';
|
|
45
|
+
import { bindAuthStoreToRuntime } from '../stores/authStore';
|
|
47
46
|
import { useLanguageManagement } from '../hooks/useLanguageManagement';
|
|
48
47
|
import { useSessionManagement } from '../hooks/useSessionManagement';
|
|
49
48
|
import { useAuthOperations, clearPersistedAuthSafe } from './hooks/useAuthOperations';
|
|
@@ -60,7 +59,15 @@ import {
|
|
|
60
59
|
import { useQueryClient, onlineManager } from '@tanstack/react-query';
|
|
61
60
|
import { clearQueryCache } from '../hooks/queryClient';
|
|
62
61
|
import { useAvatarPicker } from '../hooks/useAvatarPicker';
|
|
63
|
-
import {
|
|
62
|
+
import { resetSessionScopedStores } from '../stores/resetSessionScopedStores';
|
|
63
|
+
import { ASSET_DOWNLOAD_URLS_QUERY_KEY } from '../hooks/useResolvedFileUrls';
|
|
64
|
+
import {
|
|
65
|
+
createOxyRuntime,
|
|
66
|
+
OxyRuntimeHandleProvider,
|
|
67
|
+
useRuntimeSnapshot,
|
|
68
|
+
type OxyRuntime,
|
|
69
|
+
type SubjectTransition,
|
|
70
|
+
} from '../runtime';
|
|
64
71
|
import {
|
|
65
72
|
createSessionClient,
|
|
66
73
|
createIdentitySessionBinding,
|
|
@@ -75,10 +82,14 @@ import {
|
|
|
75
82
|
} from '../session';
|
|
76
83
|
import type {
|
|
77
84
|
OxyContextState,
|
|
78
|
-
|
|
85
|
+
OxyRuntimeProviderProps,
|
|
79
86
|
CommitInput,
|
|
80
87
|
} from './oxyContextTypes';
|
|
81
|
-
import { DEFAULT_SESSION_VALIDITY_MS
|
|
88
|
+
import { DEFAULT_SESSION_VALIDITY_MS } from './oxyContextHelpers';
|
|
89
|
+
// `useFollow` imports this module back, so the binding must only be READ inside
|
|
90
|
+
// the provider body — at render time, once every module has evaluated. It is
|
|
91
|
+
// never dereferenced at module scope here.
|
|
92
|
+
import { useFollow } from '../hooks/useFollow';
|
|
82
93
|
import { commitDeviceSetAndResolve } from './commitSessionFlow';
|
|
83
94
|
import { runPasskeyLogin, runPasskeyRegister, runPasskeyAdd } from './passkeyFlow';
|
|
84
95
|
import {
|
|
@@ -89,11 +100,22 @@ import {
|
|
|
89
100
|
import { queryKeys } from '../hooks/queries/queryKeys';
|
|
90
101
|
import { useOxyAccountGraph } from './useOxyAccountGraph';
|
|
91
102
|
|
|
92
|
-
export type { OxyContextState,
|
|
103
|
+
export type { OxyContextState, OxyRuntimeProviderProps } from './oxyContextTypes';
|
|
93
104
|
|
|
94
|
-
const
|
|
105
|
+
const OxyRuntimeContext = createContext<OxyContextState | null>(null);
|
|
95
106
|
|
|
96
|
-
|
|
107
|
+
/**
|
|
108
|
+
* The SDK's internal runtime provider — the session/account state machine that
|
|
109
|
+
* backs `useOxy()`.
|
|
110
|
+
*
|
|
111
|
+
* This is NOT the component consumers mount. The one public composition root is
|
|
112
|
+
* `OxyProvider` (`../components/OxyProvider`), which mounts this alongside the
|
|
113
|
+
* QueryClient, Bloom's dialog/surface/toast hosts, safe areas, the gesture root
|
|
114
|
+
* and the keyboard provider. Naming both of them `OxyProvider` (as this file
|
|
115
|
+
* used to) made every error message, stack frame and doc reference ambiguous —
|
|
116
|
+
* see ADR 0004.
|
|
117
|
+
*/
|
|
118
|
+
export const OxyRuntimeProvider: React.FC<OxyRuntimeProviderProps> = ({
|
|
97
119
|
children,
|
|
98
120
|
oxyServices: providedOxyServices,
|
|
99
121
|
baseURL,
|
|
@@ -105,6 +127,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
105
127
|
sessionMode = 'account',
|
|
106
128
|
webAuthMode = 'popup',
|
|
107
129
|
backgroundSession = false,
|
|
130
|
+
deviceCredentialStorage = 'persistent',
|
|
108
131
|
onAuthStateChange,
|
|
109
132
|
onError,
|
|
110
133
|
}) => {
|
|
@@ -117,17 +140,24 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
117
140
|
// link builder at the central auth host; there is no cold-boot redirect.
|
|
118
141
|
oxyServicesRef.current = new OxyServices({ baseURL, authWebUrl, authRedirectUri });
|
|
119
142
|
} else {
|
|
120
|
-
throw new Error('Either oxyServices or baseURL must be provided to
|
|
143
|
+
throw new Error('Either oxyServices or baseURL must be provided to OxyProvider');
|
|
121
144
|
}
|
|
122
145
|
}
|
|
123
146
|
const oxyServices = oxyServicesRef.current;
|
|
124
147
|
|
|
125
|
-
// The device-first persisted auth-state store (per-origin
|
|
126
|
-
//
|
|
127
|
-
//
|
|
148
|
+
// The device-first persisted auth-state store (per-origin device credential on
|
|
149
|
+
// web; SecureStore session blob on native). Built ONCE per provider mount.
|
|
150
|
+
//
|
|
151
|
+
// `deviceCredentialStorage` is mount-time configuration for the same reason
|
|
152
|
+
// `sessionMode` is: it decides where the durable credential lives, and letting
|
|
153
|
+
// it change mid-flight would mean a session that started ephemeral could begin
|
|
154
|
+
// writing one.
|
|
128
155
|
const authStoreRef = useRef<AuthStateStore | null>(null);
|
|
129
156
|
if (!authStoreRef.current) {
|
|
130
|
-
authStoreRef.current = createPlatformAuthStateStore(
|
|
157
|
+
authStoreRef.current = createPlatformAuthStateStore({
|
|
158
|
+
sessionMode,
|
|
159
|
+
storage: deviceCredentialStorage,
|
|
160
|
+
});
|
|
131
161
|
}
|
|
132
162
|
const authStore = authStoreRef.current;
|
|
133
163
|
|
|
@@ -148,37 +178,96 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
148
178
|
const identity = identityRef.current;
|
|
149
179
|
const isIdentityBound = identity !== null;
|
|
150
180
|
|
|
181
|
+
const logger = useCallback((message: string, err?: unknown) => {
|
|
182
|
+
if (__DEV__) {
|
|
183
|
+
loggerUtil.warn(message, { component: 'OxyContext' }, err);
|
|
184
|
+
}
|
|
185
|
+
}, []);
|
|
186
|
+
|
|
187
|
+
// Server-authoritative device session client. Built ONCE per `oxyServices`
|
|
188
|
+
// instance. Device-scoped sockets connect with deviceId+deviceSecret when no
|
|
189
|
+
// bearer is planted yet, so cross-origin apps sync via `session_state`.
|
|
190
|
+
const sessionClientPairRef = useRef<ReturnType<typeof createSessionClient> | null>(null);
|
|
191
|
+
if (!sessionClientPairRef.current) {
|
|
192
|
+
sessionClientPairRef.current = createSessionClient(
|
|
193
|
+
oxyServices,
|
|
194
|
+
(origin) => {
|
|
195
|
+
// Erase the DURABLE device credential only on a `request`-origin verdict
|
|
196
|
+
// (a REST sign-out / revocation). A `push`-origin empty state is a socket
|
|
197
|
+
// broadcast that may be a transient reconnect artifact — clearing the
|
|
198
|
+
// credential on it would strand the user signed out with no way back, so
|
|
199
|
+
// we clear only the local UI session and keep the credential (a dead one
|
|
200
|
+
// re-mints to `no_active_session` and resolves signed-out on next boot).
|
|
201
|
+
if (origin === 'request') {
|
|
202
|
+
clearPersistedAuthSafe(authStore, logger);
|
|
203
|
+
}
|
|
204
|
+
void clearSessionStateRef.current().catch((clearError) => {
|
|
205
|
+
logger('Failed to clear local state on remote sign-out', clearError);
|
|
206
|
+
});
|
|
207
|
+
},
|
|
208
|
+
// `null` for every account-mode provider — identical to omitting the
|
|
209
|
+
// option — and the pinned account id once an identity-bound provider has
|
|
210
|
+
// resolved its pin. Read through the ref so the resolver stays stable for
|
|
211
|
+
// the client's lifetime while still seeing later resolutions.
|
|
212
|
+
() => identityRef.current?.getPinnedAccountId() ?? null,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
const { client: sessionClient, host: sessionClientHost } = sessionClientPairRef.current;
|
|
216
|
+
|
|
217
|
+
// ── The runtime ──────────────────────────────────────────────────────────
|
|
218
|
+
// One owner for the session facts (ADR 0004), built ONCE and never rebuilt,
|
|
219
|
+
// so the context value below can hand out a reference that never changes.
|
|
220
|
+
//
|
|
221
|
+
// Its three callbacks reach forward through refs because the collaborators
|
|
222
|
+
// they need — the storage-backed teardown, the account-graph refresh — are
|
|
223
|
+
// hooks declared after it. Latching the runtime here rather than after them
|
|
224
|
+
// is deliberate: a runtime rebuilt mid-flight would drop its `SessionClient`
|
|
225
|
+
// subscription and every subscriber with it.
|
|
226
|
+
const clearSessionStateRef = useRef<() => Promise<void>>(() => Promise.resolve());
|
|
227
|
+
const saveSessionIdsRef = useRef<(sessionIds: string[]) => void>(() => undefined);
|
|
228
|
+
const subjectChangeRef = useRef<(transition: SubjectTransition) => void>(() => undefined);
|
|
229
|
+
const reestablishRef = useRef<(binding: IdentitySessionBinding, revision: number) => void>(
|
|
230
|
+
() => undefined,
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
const runtimeRef = useRef<OxyRuntime | null>(null);
|
|
234
|
+
if (!runtimeRef.current) {
|
|
235
|
+
runtimeRef.current = createOxyRuntime({
|
|
236
|
+
oxyServices,
|
|
237
|
+
sessionClient,
|
|
238
|
+
sessionClientHost,
|
|
239
|
+
identity,
|
|
240
|
+
onSubjectChange: (transition) => subjectChangeRef.current(transition),
|
|
241
|
+
onDeviceEmpty: () => clearSessionStateRef.current(),
|
|
242
|
+
onSessionsProjected: (sessionIds) => saveSessionIdsRef.current(sessionIds),
|
|
243
|
+
onIdentityUnbound: (binding, revision) => reestablishRef.current(binding, revision),
|
|
244
|
+
logger,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
const runtime = runtimeRef.current;
|
|
248
|
+
|
|
249
|
+
const snapshot = useRuntimeSnapshot(runtime);
|
|
151
250
|
const {
|
|
152
|
-
user,
|
|
153
|
-
|
|
251
|
+
account: user,
|
|
252
|
+
sessions,
|
|
253
|
+
activeSessionId,
|
|
154
254
|
isLoading,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
user: state.user,
|
|
162
|
-
isAuthenticated: state.isAuthenticated,
|
|
163
|
-
isLoading: state.isLoading,
|
|
164
|
-
error: state.error,
|
|
165
|
-
loginSuccess: state.loginSuccess,
|
|
166
|
-
loginFailure: state.loginFailure,
|
|
167
|
-
logoutStore: state.logout,
|
|
168
|
-
})),
|
|
169
|
-
);
|
|
255
|
+
tokenReady,
|
|
256
|
+
hasAccessToken,
|
|
257
|
+
authResolved,
|
|
258
|
+
} = snapshot;
|
|
259
|
+
const isAuthenticated = user !== null;
|
|
260
|
+
const error = snapshot.error?.message ?? null;
|
|
170
261
|
|
|
171
|
-
const [tokenReady, setTokenReady] = useState(true);
|
|
172
|
-
const [hasAccessToken, setHasAccessToken] = useState(() => Boolean(oxyServices.getAccessToken()));
|
|
173
|
-
const [authResolved, setAuthResolved] = useState(false);
|
|
174
|
-
const authResolvedRef = useRef(false);
|
|
175
|
-
const userRef = useRef<User | null>(user);
|
|
176
|
-
const isAuthenticatedRef = useRef(isAuthenticated);
|
|
177
|
-
userRef.current = user;
|
|
178
|
-
isAuthenticatedRef.current = isAuthenticated;
|
|
179
262
|
const [initialized, setInitialized] = useState(false);
|
|
180
263
|
const [accountDialogOpen, setAccountDialogOpen] = useState(false);
|
|
181
|
-
|
|
264
|
+
|
|
265
|
+
// Project the runtime onto `useAuthStore`, which a dozen out-of-band callers
|
|
266
|
+
// (mutation success handlers, cache helpers, the Commons app) still read the
|
|
267
|
+
// signed-in user through. It is a projection, not a second store.
|
|
268
|
+
useEffect(() => bindAuthStoreToRuntime(runtime), [runtime]);
|
|
269
|
+
|
|
270
|
+
useEffect(() => runtime.start(), [runtime]);
|
|
182
271
|
|
|
183
272
|
// Keep the shared `oxyClient` singleton's token store in lockstep with the
|
|
184
273
|
// session owned by THIS provider's instance (many apps build API clients
|
|
@@ -199,12 +288,6 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
199
288
|
return oxyServices.onTokensChanged(applyToSingleton);
|
|
200
289
|
}, [oxyServices]);
|
|
201
290
|
|
|
202
|
-
const logger = useCallback((message: string, err?: unknown) => {
|
|
203
|
-
if (__DEV__) {
|
|
204
|
-
loggerUtil.warn(message, { component: 'OxyContext' }, err);
|
|
205
|
-
}
|
|
206
|
-
}, []);
|
|
207
|
-
|
|
208
291
|
const storageKeys = useMemo(() => getStorageKeys(storageKeyPrefix), [storageKeyPrefix]);
|
|
209
292
|
|
|
210
293
|
const clientId = useMemo(() => {
|
|
@@ -238,6 +321,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
238
321
|
storageReady.resolve(storageInstance);
|
|
239
322
|
if (mounted) {
|
|
240
323
|
setStorage(storageInstance);
|
|
324
|
+
runtime.setStorageReady(true);
|
|
241
325
|
}
|
|
242
326
|
})
|
|
243
327
|
.catch((err) => {
|
|
@@ -249,7 +333,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
249
333
|
return () => {
|
|
250
334
|
mounted = false;
|
|
251
335
|
};
|
|
252
|
-
}, [logger, onError, storageReady]);
|
|
336
|
+
}, [logger, onError, runtime, storageReady]);
|
|
253
337
|
|
|
254
338
|
const {
|
|
255
339
|
currentLanguage,
|
|
@@ -269,83 +353,42 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
269
353
|
const queryClient = useQueryClient();
|
|
270
354
|
|
|
271
355
|
const {
|
|
272
|
-
|
|
273
|
-
activeSessionId,
|
|
274
|
-
setActiveSessionId,
|
|
275
|
-
updateSessions,
|
|
356
|
+
saveSessionIds,
|
|
276
357
|
switchSession,
|
|
277
358
|
clearSessionState,
|
|
278
359
|
saveActiveSessionId,
|
|
279
360
|
} = useSessionManagement({
|
|
280
361
|
oxyServices,
|
|
362
|
+
runtime,
|
|
281
363
|
storage,
|
|
282
364
|
storageKeyPrefix,
|
|
283
|
-
loginSuccess,
|
|
284
|
-
logoutStore,
|
|
285
365
|
onAuthStateChange,
|
|
286
366
|
onError,
|
|
287
|
-
setAuthError: (message) =>
|
|
367
|
+
setAuthError: (message) => runtime.setError(message),
|
|
288
368
|
logger,
|
|
289
|
-
setTokenReady,
|
|
290
369
|
queryClient,
|
|
291
370
|
});
|
|
292
371
|
|
|
293
|
-
// Refs so callbacks below can invoke the latest session-management functions
|
|
294
|
-
// without widening dependency arrays.
|
|
295
|
-
const switchSessionRef = useRef(switchSession);
|
|
296
|
-
switchSessionRef.current = switchSession;
|
|
297
|
-
const clearSessionStateRef = useRef(clearSessionState);
|
|
298
372
|
clearSessionStateRef.current = clearSessionState;
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const loginSuccessRef = useRef(loginSuccess);
|
|
302
|
-
loginSuccessRef.current = loginSuccess;
|
|
373
|
+
saveSessionIdsRef.current = saveSessionIds;
|
|
374
|
+
|
|
303
375
|
const onAuthStateChangeRef = useRef(onAuthStateChange);
|
|
304
376
|
onAuthStateChangeRef.current = onAuthStateChange;
|
|
305
377
|
|
|
306
|
-
// Flip the auth-resolution gate
|
|
307
|
-
//
|
|
378
|
+
// Flip the auth-resolution gate the moment a session commits or the boot
|
|
379
|
+
// concludes signed out. Idempotent + monotonic, enforced by the runtime.
|
|
308
380
|
const markAuthResolved = useCallback(() => {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
authResolvedRef.current = true;
|
|
313
|
-
setTokenReady(true);
|
|
314
|
-
setAuthResolved(true);
|
|
315
|
-
}, []);
|
|
381
|
+
runtime.markAuthResolved();
|
|
382
|
+
}, [runtime]);
|
|
316
383
|
const markAuthResolvedRef = useRef(markAuthResolved);
|
|
317
384
|
markAuthResolvedRef.current = markAuthResolved;
|
|
318
385
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
sessionClientPairRef.current = createSessionClient(
|
|
326
|
-
oxyServices,
|
|
327
|
-
(origin) => {
|
|
328
|
-
// Erase the DURABLE device credential only on a `request`-origin verdict
|
|
329
|
-
// (a REST sign-out / revocation). A `push`-origin empty state is a socket
|
|
330
|
-
// broadcast that may be a transient reconnect artifact — clearing the
|
|
331
|
-
// credential on it would strand the user signed out with no way back, so
|
|
332
|
-
// we clear only the local UI session and keep the credential (a dead one
|
|
333
|
-
// re-mints to `no_active_session` and resolves signed-out on next boot).
|
|
334
|
-
if (origin === 'request') {
|
|
335
|
-
clearPersistedAuthSafe(authStore, logger);
|
|
336
|
-
}
|
|
337
|
-
void clearSessionStateRef.current().catch((clearError) => {
|
|
338
|
-
logger('Failed to clear local state on remote sign-out', clearError);
|
|
339
|
-
});
|
|
340
|
-
},
|
|
341
|
-
// `null` for every account-mode provider — identical to omitting the
|
|
342
|
-
// option — and the pinned account id once an identity-bound provider has
|
|
343
|
-
// resolved its pin. Read through the ref so the resolver stays stable for
|
|
344
|
-
// the client's lifetime while still seeing later resolutions.
|
|
345
|
-
() => identityRef.current?.getPinnedAccountId() ?? null,
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
const { client: sessionClient, host: sessionClientHost } = sessionClientPairRef.current;
|
|
386
|
+
const setTokenReady = useCallback(
|
|
387
|
+
(ready: boolean) => {
|
|
388
|
+
runtime.setTokenReady(ready);
|
|
389
|
+
},
|
|
390
|
+
[runtime],
|
|
391
|
+
);
|
|
349
392
|
|
|
350
393
|
// Re-establishment lane for an identity-bound provider whose pin is missing or
|
|
351
394
|
// whose pinned account is no longer part of this device's session set (another
|
|
@@ -396,78 +439,16 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
396
439
|
},
|
|
397
440
|
[oxyServices, authStore, sessionClient, logger],
|
|
398
441
|
);
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
// Clear the LOCAL UI session on any applied empty state, but NEVER the
|
|
410
|
-
// durable device credential here: `syncFromClient` runs for socket-pushed
|
|
411
|
-
// (possibly transient) states too, and wiping the credential on one would
|
|
412
|
-
// strand the user signed out. The credential wipe is gated on a
|
|
413
|
-
// `request`-origin verdict in `onUnauthenticated` above.
|
|
414
|
-
sessionClientHost.setCurrentAccountId(null);
|
|
415
|
-
await clearSessionState();
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
// Last-write-wins guard: capture the revision this projection is for, then
|
|
419
|
-
// after the async profile fetch bail if a fresher state has landed.
|
|
420
|
-
const capturedRevision = state.revision;
|
|
421
|
-
// Resolve the pin BEFORE the profile fetch (memoised: one storage + keychain
|
|
422
|
-
// read per boot) so every projection below is bound on the FIRST pass over a
|
|
423
|
-
// freshly applied state. Deferring it would let a sibling app's switch render
|
|
424
|
-
// once as this client's user before the pin corrected it. `null` for every
|
|
425
|
-
// account-mode provider, where each projection falls back to the device's
|
|
426
|
-
// active account exactly as before.
|
|
427
|
-
const pinnedAccountId = identity ? await identity.ensurePinnedAccountId() : null;
|
|
428
|
-
const ids = accountIdsOf(state);
|
|
429
|
-
let users: User[] = [];
|
|
430
|
-
try {
|
|
431
|
-
users = ids.length > 0 ? await oxyServices.getUsersByIds(ids) : [];
|
|
432
|
-
} catch (fetchError) {
|
|
433
|
-
logger('Failed to resolve account profiles during syncFromClient', fetchError);
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
const latest = sessionClient.getState();
|
|
437
|
-
if (!latest || latest.revision !== capturedRevision) {
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
if (identity && (pinnedAccountId === null || activeSessionIdOf(latest, pinnedAccountId) === null)) {
|
|
441
|
-
// Either no verified pin, or the pinned account left this device's session
|
|
442
|
-
// set. Projecting anything here would mean projecting SOMEBODY ELSE's
|
|
443
|
-
// account, so leave the current projection untouched and re-derive the
|
|
444
|
-
// session from the local identity key instead.
|
|
445
|
-
reestablishIdentitySession(identity, latest.revision);
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
const usersById = new Map(users.map((resolvedUser) => [resolvedUser.id, resolvedUser]));
|
|
449
|
-
updateSessions(deviceStateToClientSessions(latest, usersById, pinnedAccountId));
|
|
450
|
-
setActiveSessionId(activeSessionIdOf(latest, pinnedAccountId));
|
|
451
|
-
const activeUser = activeUserOf(latest, usersById, pinnedAccountId);
|
|
452
|
-
if (activeUser) {
|
|
453
|
-
loginSuccess(activeUser);
|
|
454
|
-
}
|
|
455
|
-
// The host's current account feeds the socket handshake and the bearer's
|
|
456
|
-
// token-account comparisons, so it tracks the PIN — never the account another
|
|
457
|
-
// app switched the device to.
|
|
458
|
-
sessionClientHost.setCurrentAccountId(pinnedAccountId ?? latest.activeAccountId);
|
|
459
|
-
}, [
|
|
460
|
-
identity,
|
|
461
|
-
oxyServices,
|
|
462
|
-
reestablishIdentitySession,
|
|
463
|
-
sessionClient,
|
|
464
|
-
sessionClientHost,
|
|
465
|
-
updateSessions,
|
|
466
|
-
setActiveSessionId,
|
|
467
|
-
loginSuccess,
|
|
468
|
-
clearSessionState,
|
|
469
|
-
logger,
|
|
470
|
-
]);
|
|
442
|
+
reestablishRef.current = reestablishIdentitySession;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Project the server-authoritative device state onto the runtime.
|
|
446
|
+
*
|
|
447
|
+
* The projection itself lives in the runtime; this is the awaitable handle
|
|
448
|
+
* the commit/logout/reconnect paths already had. It is stable, because the
|
|
449
|
+
* runtime is.
|
|
450
|
+
*/
|
|
451
|
+
const syncFromClient = useCallback((): Promise<void> => runtime.reconcileFromClient(), [runtime]);
|
|
471
452
|
const syncFromClientRef = useRef(syncFromClient);
|
|
472
453
|
syncFromClientRef.current = syncFromClient;
|
|
473
454
|
|
|
@@ -476,19 +457,11 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
476
457
|
sessionClientHost.setDeviceCredential(cred);
|
|
477
458
|
}, [authStore, sessionClientHost]);
|
|
478
459
|
|
|
479
|
-
useEffect(() => {
|
|
480
|
-
return sessionClient.subscribe(() => {
|
|
481
|
-
void syncFromClient();
|
|
482
|
-
});
|
|
483
|
-
}, [sessionClient, syncFromClient]);
|
|
484
|
-
|
|
485
460
|
const { signIn, logout, logoutAll } = useAuthOperations({
|
|
486
461
|
oxyServices,
|
|
487
462
|
store: authStore,
|
|
488
463
|
storage,
|
|
489
|
-
|
|
490
|
-
setActiveSessionId,
|
|
491
|
-
updateSessions,
|
|
464
|
+
runtime,
|
|
492
465
|
saveActiveSessionId,
|
|
493
466
|
clearSessionState,
|
|
494
467
|
switchSession,
|
|
@@ -496,10 +469,6 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
496
469
|
syncFromClient,
|
|
497
470
|
onAuthStateChange,
|
|
498
471
|
onError,
|
|
499
|
-
loginSuccess,
|
|
500
|
-
loginFailure,
|
|
501
|
-
logoutStore,
|
|
502
|
-
setAuthState,
|
|
503
472
|
logger,
|
|
504
473
|
...(identity
|
|
505
474
|
? {
|
|
@@ -531,7 +500,6 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
531
500
|
// Explicit FULL wipe: also drop the persisted device credential so a reload
|
|
532
501
|
// finds nothing to restore.
|
|
533
502
|
await authStore.clear();
|
|
534
|
-
useAccountStore.getState().reset();
|
|
535
503
|
oxyServices.clearCache();
|
|
536
504
|
}, [queryClient, storage, clearSessionState, authStore, logger, oxyServices]);
|
|
537
505
|
|
|
@@ -543,7 +511,6 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
543
511
|
logger,
|
|
544
512
|
});
|
|
545
513
|
|
|
546
|
-
const useFollowHook = loadUseFollowHook();
|
|
547
514
|
|
|
548
515
|
// Token-change side effects: an invalidated bearer (HttpService clears tokens
|
|
549
516
|
// on an unrecoverable 401 and emits `null`) must locally sign out an
|
|
@@ -554,16 +521,16 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
554
521
|
const clearingInvalidTokenRef = useRef(false);
|
|
555
522
|
useEffect(() => {
|
|
556
523
|
const handleTokenChange = (accessToken: string | null) => {
|
|
557
|
-
setHasAccessToken(Boolean(accessToken));
|
|
524
|
+
runtime.setHasAccessToken(Boolean(accessToken));
|
|
558
525
|
if (accessToken) {
|
|
559
|
-
setTokenReady(true);
|
|
526
|
+
runtime.setTokenReady(true);
|
|
560
527
|
if (sessionClient.getState()?.accounts.length) {
|
|
561
528
|
void syncFromClientRef.current();
|
|
562
529
|
}
|
|
563
530
|
return;
|
|
564
531
|
}
|
|
565
|
-
if (
|
|
566
|
-
setTokenReady(false);
|
|
532
|
+
if (runtime.getSnapshot().account !== null) {
|
|
533
|
+
runtime.setTokenReady(false);
|
|
567
534
|
if (clearingInvalidTokenRef.current) {
|
|
568
535
|
return;
|
|
569
536
|
}
|
|
@@ -574,19 +541,19 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
574
541
|
})
|
|
575
542
|
.finally(() => {
|
|
576
543
|
clearingInvalidTokenRef.current = false;
|
|
577
|
-
if (
|
|
578
|
-
setTokenReady(true);
|
|
544
|
+
if (runtime.getSnapshot().authResolved) {
|
|
545
|
+
runtime.setTokenReady(true);
|
|
579
546
|
}
|
|
580
547
|
});
|
|
581
548
|
return;
|
|
582
549
|
}
|
|
583
|
-
if (
|
|
584
|
-
setTokenReady(true);
|
|
550
|
+
if (runtime.getSnapshot().authResolved) {
|
|
551
|
+
runtime.setTokenReady(true);
|
|
585
552
|
}
|
|
586
553
|
};
|
|
587
554
|
handleTokenChange(oxyServices.getAccessToken());
|
|
588
555
|
return oxyServices.onTokensChanged(handleTokenChange);
|
|
589
|
-
}, [logger, oxyServices, sessionClient]);
|
|
556
|
+
}, [logger, oxyServices, runtime, sessionClient]);
|
|
590
557
|
|
|
591
558
|
// Unified in-session refresh (SDK-owned; every RP inherits it). Installs the
|
|
592
559
|
// ONE core refresh handler (re-mint from the persisted zero-cookie device
|
|
@@ -644,23 +611,28 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
644
611
|
}
|
|
645
612
|
|
|
646
613
|
// Fast local mirror so the UI updates before the server round-trip; the
|
|
647
|
-
// SessionClient projection below overwrites it with server truth.
|
|
614
|
+
// SessionClient projection below overwrites it with server truth. Batched
|
|
615
|
+
// so the mirror and the active id land in ONE transition — unbatched, a
|
|
616
|
+
// subscriber woken between them would see the new session list still
|
|
617
|
+
// pointing at the previous active id.
|
|
648
618
|
if (input.userId) {
|
|
649
619
|
const now = new Date();
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
620
|
+
runtime.batch(() => {
|
|
621
|
+
runtime.mergeSessions(
|
|
622
|
+
[
|
|
623
|
+
{
|
|
624
|
+
sessionId: input.sessionId,
|
|
625
|
+
deviceId: input.deviceId ?? '',
|
|
626
|
+
expiresAt: input.expiresAt || new Date(now.getTime() + DEFAULT_SESSION_VALIDITY_MS).toISOString(),
|
|
627
|
+
lastActive: now.toISOString(),
|
|
628
|
+
userId: input.userId,
|
|
629
|
+
isCurrent: true,
|
|
630
|
+
},
|
|
631
|
+
],
|
|
632
|
+
{ merge: true },
|
|
633
|
+
);
|
|
634
|
+
runtime.setActiveSessionId(input.sessionId);
|
|
635
|
+
});
|
|
664
636
|
}
|
|
665
637
|
|
|
666
638
|
// Register into the device set, hydrate the full user, and flip the
|
|
@@ -680,12 +652,12 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
680
652
|
startSocket: () => sessionClient.start(),
|
|
681
653
|
syncFromClient,
|
|
682
654
|
getCurrentUser: () => oxyServices.getCurrentUser(),
|
|
683
|
-
loginSuccess,
|
|
655
|
+
loginSuccess: (fullUser) => runtime.setAccount(fullUser),
|
|
684
656
|
onAuthStateChange: onAuthStateChangeRef.current,
|
|
685
657
|
markAuthResolved: markAuthResolvedRef.current,
|
|
686
658
|
});
|
|
687
659
|
},
|
|
688
|
-
[oxyServices, authStore,
|
|
660
|
+
[oxyServices, authStore, runtime, sessionClient, sessionClientHost, syncFromClient, logger],
|
|
689
661
|
);
|
|
690
662
|
const commitSessionRef = useRef(commitSession);
|
|
691
663
|
commitSessionRef.current = commitSession;
|
|
@@ -713,31 +685,6 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
713
685
|
[commitSession],
|
|
714
686
|
);
|
|
715
687
|
|
|
716
|
-
// Commit a minted graph-SWITCH session through the same funnel as
|
|
717
|
-
// `handleWebSession`. Nothing extra to do IN-PLACE: the switch already
|
|
718
|
-
// propagates across tabs/apps via the server's `session_state` socket
|
|
719
|
-
// broadcast.
|
|
720
|
-
const commitSwitchedSession = useCallback(
|
|
721
|
-
async (session: SessionLoginResponse): Promise<void> => {
|
|
722
|
-
if (!session?.user || !session?.sessionId || !session.accessToken) {
|
|
723
|
-
throw new Error('Session response did not include a usable session');
|
|
724
|
-
}
|
|
725
|
-
await commitSession(
|
|
726
|
-
{
|
|
727
|
-
sessionId: session.sessionId,
|
|
728
|
-
accessToken: session.accessToken,
|
|
729
|
-
deviceSecret: session.deviceSecret,
|
|
730
|
-
deviceId: session.deviceId,
|
|
731
|
-
expiresAt: session.expiresAt,
|
|
732
|
-
userId: session.user.id,
|
|
733
|
-
user: session.user,
|
|
734
|
-
},
|
|
735
|
-
{ activate: true },
|
|
736
|
-
);
|
|
737
|
-
},
|
|
738
|
-
[commitSession],
|
|
739
|
-
);
|
|
740
|
-
|
|
741
688
|
// ── Web third-party OAuth sign-in ──────────────────────────────────────────
|
|
742
689
|
// The shared operation `OxySignInButton` (and any RP-owned button) delegates
|
|
743
690
|
// to, so no consumer ever writes popup listeners or a token exchange. The
|
|
@@ -762,13 +709,11 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
762
709
|
// ── Unified account dialog ─────────────────────────────────────────────────
|
|
763
710
|
// The single account-chooser + sign-in surface. Built ONCE per provider mount
|
|
764
711
|
// and bound to the live `oxyServices` + `sessionClient` + this provider's
|
|
765
|
-
// commit
|
|
766
|
-
//
|
|
767
|
-
//
|
|
712
|
+
// sign-in commit funnel, threaded through a ref so the controller keeps a
|
|
713
|
+
// STABLE commit callback (rebuilding the controller on every commit-identity
|
|
714
|
+
// change would drop its subscription + state).
|
|
768
715
|
const handleWebSessionRef = useRef(handleWebSession);
|
|
769
716
|
handleWebSessionRef.current = handleWebSession;
|
|
770
|
-
const commitSwitchedSessionRef = useRef(commitSwitchedSession);
|
|
771
|
-
commitSwitchedSessionRef.current = commitSwitchedSession;
|
|
772
717
|
|
|
773
718
|
// The live AccountDialog surface (a stacked Bloom surface), while open — the
|
|
774
719
|
// SINGLE source of truth for "is the account dialog open". Held so
|
|
@@ -811,12 +756,10 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
811
756
|
oxyServices,
|
|
812
757
|
sessionClient,
|
|
813
758
|
clientId,
|
|
814
|
-
locale: currentLanguage,
|
|
815
759
|
// Same statically-injected `io` as the SessionClient: gives the QR flow an
|
|
816
760
|
// instant `/auth-session` `auth_update` wake instead of a slow poll.
|
|
817
761
|
socketFactory: io,
|
|
818
762
|
commitSession: (session) => handleWebSessionRef.current(session),
|
|
819
|
-
commitSwitchedSession: (session) => commitSwitchedSessionRef.current(session),
|
|
820
763
|
onSignedIn: () => {
|
|
821
764
|
// Close the dialog: pop the morphed frame back to its host surface, or
|
|
822
765
|
// dismiss the detached surface (whose settle flips `accountDialogOpen`).
|
|
@@ -1044,6 +987,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
1044
987
|
identity,
|
|
1045
988
|
syncDeviceCredentialToHost,
|
|
1046
989
|
sessionClient,
|
|
990
|
+
setTokenReady,
|
|
1047
991
|
]);
|
|
1048
992
|
|
|
1049
993
|
useEffect(() => {
|
|
@@ -1147,13 +1091,13 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
1147
1091
|
}
|
|
1148
1092
|
await sessionClient.switchAccount(targetAccountId);
|
|
1149
1093
|
await syncFromClient();
|
|
1150
|
-
const activeUser =
|
|
1094
|
+
const activeUser = runtime.getSnapshot().account;
|
|
1151
1095
|
if (!activeUser) {
|
|
1152
1096
|
throw new Error('Active account profile could not be resolved after switch');
|
|
1153
1097
|
}
|
|
1154
1098
|
return activeUser;
|
|
1155
1099
|
},
|
|
1156
|
-
[isIdentityBound, sessionClient, syncFromClient],
|
|
1100
|
+
[isIdentityBound, runtime, sessionClient, syncFromClient],
|
|
1157
1101
|
);
|
|
1158
1102
|
|
|
1159
1103
|
// Thin passthroughs to the platform-agnostic KeyManager. NOTE: both now THROW
|
|
@@ -1189,11 +1133,43 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
1189
1133
|
sessionClient,
|
|
1190
1134
|
syncFromClient,
|
|
1191
1135
|
commitSession,
|
|
1192
|
-
queryClient,
|
|
1193
1136
|
accountDialogControllerRef,
|
|
1194
1137
|
clearSessionStateRef,
|
|
1195
1138
|
});
|
|
1196
1139
|
|
|
1140
|
+
// The account-scoped cache reset, run by the runtime BETWEEN committing the
|
|
1141
|
+
// new subject's bearer and waking anybody (ADR 0002). It used to trail the two
|
|
1142
|
+
// branches of `switchToAccount`, which meant a switch pushed over the socket
|
|
1143
|
+
// by another app on this device got none of it: the follow stores, the scoped
|
|
1144
|
+
// media URLs and every warm query stayed on the previous subject until
|
|
1145
|
+
// something happened to refetch.
|
|
1146
|
+
//
|
|
1147
|
+
// An initial sign-in is deliberately exempt. There is nothing account-scoped
|
|
1148
|
+
// cached before the first account, so invalidating everything there would only
|
|
1149
|
+
// buy a refetch storm at first paint.
|
|
1150
|
+
const handleSubjectChange = useCallback(
|
|
1151
|
+
({ previous, next }: SubjectTransition): void => {
|
|
1152
|
+
if (previous === null) {
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
resetSessionScopedStores();
|
|
1156
|
+
if (next === null) {
|
|
1157
|
+
// A sign-out: `clearSessionState` owns the rest of the teardown, and
|
|
1158
|
+
// invalidating a cache we are about to clear would only refetch as the
|
|
1159
|
+
// bearer disappears.
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
// Scoped media tokens are per-viewer — drop any cached URLs immediately so
|
|
1163
|
+
// `keepPreviousData`-style placeholders cannot flash the prior account's
|
|
1164
|
+
// private thumbnails while the new bearer mint lands.
|
|
1165
|
+
queryClient.removeQueries({ queryKey: [ASSET_DOWNLOAD_URLS_QUERY_KEY] });
|
|
1166
|
+
queryClient.invalidateQueries();
|
|
1167
|
+
void refreshAccounts();
|
|
1168
|
+
},
|
|
1169
|
+
[queryClient, refreshAccounts],
|
|
1170
|
+
);
|
|
1171
|
+
subjectChangeRef.current = handleSubjectChange;
|
|
1172
|
+
|
|
1197
1173
|
const canUsePrivateApi = authResolved && isAuthenticated && tokenReady && hasAccessToken;
|
|
1198
1174
|
const isPrivateApiPending = !authResolved || (isAuthenticated && (!tokenReady || !hasAccessToken));
|
|
1199
1175
|
|
|
@@ -1221,7 +1197,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
1221
1197
|
canUsePrivateApi,
|
|
1222
1198
|
isPrivateApiPending,
|
|
1223
1199
|
isAuthResolved: authResolved,
|
|
1224
|
-
isStorageReady:
|
|
1200
|
+
isStorageReady: snapshot.storageReady,
|
|
1225
1201
|
sessionMode: isIdentityBound ? 'identity' : 'account',
|
|
1226
1202
|
webAuthMode,
|
|
1227
1203
|
error,
|
|
@@ -1255,7 +1231,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
1255
1231
|
clientId,
|
|
1256
1232
|
oxyServices,
|
|
1257
1233
|
sessionClient,
|
|
1258
|
-
useFollow
|
|
1234
|
+
useFollow,
|
|
1259
1235
|
showBottomSheet: showBottomSheetForContext,
|
|
1260
1236
|
openAvatarPicker,
|
|
1261
1237
|
accountDialogController,
|
|
@@ -1278,7 +1254,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
1278
1254
|
canUsePrivateApi,
|
|
1279
1255
|
isPrivateApiPending,
|
|
1280
1256
|
authResolved,
|
|
1281
|
-
|
|
1257
|
+
snapshot.storageReady,
|
|
1282
1258
|
isIdentityBound,
|
|
1283
1259
|
webAuthMode,
|
|
1284
1260
|
error,
|
|
@@ -1311,7 +1287,6 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
1311
1287
|
clientId,
|
|
1312
1288
|
oxyServices,
|
|
1313
1289
|
sessionClient,
|
|
1314
|
-
useFollowHook,
|
|
1315
1290
|
showBottomSheetForContext,
|
|
1316
1291
|
openAvatarPicker,
|
|
1317
1292
|
accountDialogController,
|
|
@@ -1325,83 +1300,53 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
1325
1300
|
],
|
|
1326
1301
|
);
|
|
1327
1302
|
|
|
1328
|
-
|
|
1303
|
+
// Two contexts, deliberately. The inner one carries the wide compatibility
|
|
1304
|
+
// value every `useOxy()` consumer reads, rebuilt whenever any of its members
|
|
1305
|
+
// moves. The outer one carries the runtime reference, which never changes
|
|
1306
|
+
// identity — so `useActiveAccount()` and friends re-render on the fact they
|
|
1307
|
+
// selected and nothing else. Phase 8 retires the inner one.
|
|
1308
|
+
return (
|
|
1309
|
+
<OxyRuntimeHandleProvider value={runtime}>
|
|
1310
|
+
<OxyRuntimeContext.Provider value={contextValue}>{children}</OxyRuntimeContext.Provider>
|
|
1311
|
+
</OxyRuntimeHandleProvider>
|
|
1312
|
+
);
|
|
1329
1313
|
};
|
|
1330
1314
|
|
|
1331
|
-
|
|
1315
|
+
const PROVIDER_MISSING_ERROR_MESSAGE =
|
|
1316
|
+
'useOxy() was called outside <OxyProvider>. Mount <OxyProvider clientId="…"> above this component, ' +
|
|
1317
|
+
'or use useOptionalOxy() if this component legitimately renders both inside and outside the provider.';
|
|
1318
|
+
|
|
1319
|
+
export class OxyProviderMissingError extends Error {
|
|
1320
|
+
readonly code = 'oxy_provider_missing';
|
|
1321
|
+
|
|
1322
|
+
constructor() {
|
|
1323
|
+
super(PROVIDER_MISSING_ERROR_MESSAGE);
|
|
1324
|
+
this.name = 'OxyProviderMissingError';
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1332
1327
|
|
|
1333
1328
|
/**
|
|
1334
|
-
*
|
|
1335
|
-
*
|
|
1329
|
+
* The base runtime hook. THROWS when no `<OxyProvider>` is mounted.
|
|
1330
|
+
*
|
|
1331
|
+
* It used to return a fabricated forever-loading runtime — `isLoading: true`,
|
|
1332
|
+
* `isPrivateApiPending: true`, every method a rejecting no-op — which turned a
|
|
1333
|
+
* missing provider into a UI that spins forever with nothing in the console.
|
|
1334
|
+
* Failing here names the mistake at the exact component that made it (ADR 0004).
|
|
1335
|
+
*
|
|
1336
|
+
* A component that legitimately renders both inside and outside the provider
|
|
1337
|
+
* uses {@link useOptionalOxy} instead.
|
|
1336
1338
|
*/
|
|
1337
|
-
const PROVIDER_MISSING_ERROR_MESSAGE =
|
|
1338
|
-
'OxyProvider is not mounted. Wrap your app in <OxyProvider> before calling useOxy() methods.';
|
|
1339
|
-
|
|
1340
|
-
const rejectMissingProvider = <T,>(): Promise<T> =>
|
|
1341
|
-
Promise.reject(new Error(PROVIDER_MISSING_ERROR_MESSAGE));
|
|
1342
|
-
|
|
1343
|
-
const LOADING_STATE_OXY_SERVICES = new OxyServices({ baseURL: 'about:blank' });
|
|
1344
|
-
|
|
1345
|
-
const LOADING_STATE: OxyContextState = {
|
|
1346
|
-
user: null,
|
|
1347
|
-
sessions: [],
|
|
1348
|
-
activeSessionId: null,
|
|
1349
|
-
isAuthenticated: false,
|
|
1350
|
-
isLoading: true,
|
|
1351
|
-
isTokenReady: false,
|
|
1352
|
-
hasAccessToken: false,
|
|
1353
|
-
canUsePrivateApi: false,
|
|
1354
|
-
isPrivateApiPending: true,
|
|
1355
|
-
isAuthResolved: false,
|
|
1356
|
-
isStorageReady: false,
|
|
1357
|
-
sessionMode: 'account',
|
|
1358
|
-
webAuthMode: 'popup',
|
|
1359
|
-
error: null,
|
|
1360
|
-
currentLanguage: 'en-US',
|
|
1361
|
-
currentLanguages: [],
|
|
1362
|
-
currentLanguageMetadata: null,
|
|
1363
|
-
currentLanguageName: 'English (United States)',
|
|
1364
|
-
currentNativeLanguageName: 'English (United States)',
|
|
1365
|
-
hasIdentity: () => Promise.resolve(false),
|
|
1366
|
-
getPublicKey: () => Promise.resolve(null),
|
|
1367
|
-
signIn: () => rejectMissingProvider<User>(),
|
|
1368
|
-
signInWithPasskey: () => rejectMissingProvider<void>(),
|
|
1369
|
-
registerWithPasskey: () => rejectMissingProvider<void>(),
|
|
1370
|
-
addPasskey: () => rejectMissingProvider<void>(),
|
|
1371
|
-
removePasskey: () => rejectMissingProvider<void>(),
|
|
1372
|
-
revokeSuspiciousSignIn: () => rejectMissingProvider<void>(),
|
|
1373
|
-
handleWebSession: () => rejectMissingProvider<void>(),
|
|
1374
|
-
startWebOAuthSignIn: () => rejectMissingProvider<WebOAuthSignInResult>(),
|
|
1375
|
-
logout: () => rejectMissingProvider<void>(),
|
|
1376
|
-
logoutAll: () => rejectMissingProvider<void>(),
|
|
1377
|
-
switchSession: () => rejectMissingProvider<User>(),
|
|
1378
|
-
removeSession: () => rejectMissingProvider<void>(),
|
|
1379
|
-
refreshSessions: () => rejectMissingProvider<void>(),
|
|
1380
|
-
setLanguage: () => rejectMissingProvider<void>(),
|
|
1381
|
-
getDeviceSessions: () => Promise.resolve([]),
|
|
1382
|
-
logoutAllDeviceSessions: () => rejectMissingProvider<void>(),
|
|
1383
|
-
updateDeviceName: () => rejectMissingProvider<void>(),
|
|
1384
|
-
clearSessionState: () => rejectMissingProvider<void>(),
|
|
1385
|
-
clearAllAccountData: () => rejectMissingProvider<void>(),
|
|
1386
|
-
storageKeyPrefix: 'oxy_session',
|
|
1387
|
-
clientId: null,
|
|
1388
|
-
oxyServices: LOADING_STATE_OXY_SERVICES,
|
|
1389
|
-
sessionClient: null,
|
|
1390
|
-
openAvatarPicker: () => {},
|
|
1391
|
-
accountDialogController: null,
|
|
1392
|
-
isAccountDialogOpen: false,
|
|
1393
|
-
openAccountDialog: () => {},
|
|
1394
|
-
closeAccountDialog: () => {},
|
|
1395
|
-
accounts: [],
|
|
1396
|
-
switchToAccount: () => rejectMissingProvider<void>(),
|
|
1397
|
-
refreshAccounts: () => rejectMissingProvider<void>(),
|
|
1398
|
-
createAccount: () => rejectMissingProvider<import('@oxyhq/core').AccountNode>(),
|
|
1399
|
-
};
|
|
1400
|
-
|
|
1401
1339
|
export const useOxy = (): OxyContextState => {
|
|
1402
|
-
const context = useContext(
|
|
1340
|
+
const context = useContext(OxyRuntimeContext);
|
|
1403
1341
|
if (!context) {
|
|
1404
|
-
|
|
1342
|
+
throw new OxyProviderMissingError();
|
|
1405
1343
|
}
|
|
1406
1344
|
return context;
|
|
1407
1345
|
};
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* `useOxy()` for the rare component that renders both inside and outside the
|
|
1349
|
+
* provider — returns `null` instead of throwing. Callers must handle `null`;
|
|
1350
|
+
* there is no fabricated runtime to fall back on.
|
|
1351
|
+
*/
|
|
1352
|
+
export const useOptionalOxy = (): OxyContextState | null => useContext(OxyRuntimeContext);
|