@oxyhq/services 5.13.0 → 5.13.2
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/README.md +71 -0
- package/lib/commonjs/core/HttpClient.js +238 -0
- package/lib/commonjs/core/HttpClient.js.map +1 -0
- package/lib/commonjs/core/OxyServices.js +530 -332
- package/lib/commonjs/core/OxyServices.js.map +1 -1
- package/lib/commonjs/core/RequestManager.js +199 -0
- package/lib/commonjs/core/RequestManager.js.map +1 -0
- package/lib/commonjs/core/index.js +38 -1
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/i18n/index.js +37 -1
- package/lib/commonjs/i18n/index.js.map +1 -1
- package/lib/commonjs/i18n/locales/ar-SA.json +128 -0
- package/lib/commonjs/i18n/locales/ca-ES.json +128 -0
- package/lib/commonjs/i18n/locales/de-DE.json +128 -0
- package/lib/commonjs/i18n/locales/en-US.json +85 -12
- package/lib/commonjs/i18n/locales/es-ES.json +58 -6
- package/lib/commonjs/i18n/locales/fr-FR.json +128 -0
- package/lib/commonjs/i18n/locales/it-IT.json +128 -0
- package/lib/commonjs/i18n/locales/ja-JP.json +127 -0
- package/lib/commonjs/i18n/locales/ko-KR.json +128 -0
- package/lib/commonjs/i18n/locales/pt-PT.json +128 -0
- package/lib/commonjs/i18n/locales/zh-CN.json +128 -0
- package/lib/commonjs/index.js +36 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/Avatar.js +94 -27
- package/lib/commonjs/ui/components/Avatar.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +1 -0
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/FontLoader.js +22 -42
- package/lib/commonjs/ui/components/FontLoader.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +5 -8
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/StepBasedScreen.js +64 -44
- package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +14 -35
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/commonjs/ui/components/internal/PinInput.js +2 -2
- package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
- package/lib/commonjs/ui/components/internal/TextField.js +13 -8
- package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +443 -371
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +80 -22
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/index.js +4 -1
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +32 -2
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +101 -59
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +3 -2
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +75 -117
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +43 -50
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +14 -16
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +188 -142
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +10 -10
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +2 -4
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +45 -25
- package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js +88 -53
- package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +79 -58
- package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +61 -52
- package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +218 -39
- package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignInTotpStep.js +77 -50
- package/lib/commonjs/ui/screens/steps/SignInTotpStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +424 -71
- package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +55 -30
- package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +64 -46
- package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +84 -146
- package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +113 -34
- package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
- package/lib/commonjs/ui/stores/accountStore.js +237 -0
- package/lib/commonjs/ui/stores/accountStore.js.map +1 -0
- package/lib/commonjs/ui/stores/authStore.js +17 -20
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/styles/authStyles.js +16 -8
- package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
- package/lib/commonjs/ui/styles/index.js +11 -0
- package/lib/commonjs/ui/styles/index.js.map +1 -1
- package/lib/commonjs/ui/styles/spacing.js +51 -0
- package/lib/commonjs/ui/styles/spacing.js.map +1 -0
- package/lib/commonjs/utils/asyncUtils.js +9 -22
- package/lib/commonjs/utils/asyncUtils.js.map +1 -1
- package/lib/commonjs/utils/cache.js +259 -0
- package/lib/commonjs/utils/cache.js.map +1 -0
- package/lib/commonjs/utils/index.js +99 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/utils/languageUtils.js +159 -0
- package/lib/commonjs/utils/languageUtils.js.map +1 -0
- package/lib/commonjs/utils/requestUtils.js +217 -0
- package/lib/commonjs/utils/requestUtils.js.map +1 -0
- package/lib/commonjs/utils/sessionUtils.js +191 -0
- package/lib/commonjs/utils/sessionUtils.js.map +1 -0
- package/lib/commonjs/utils/validationUtils.js +1 -1
- package/lib/module/core/HttpClient.js +232 -0
- package/lib/module/core/HttpClient.js.map +1 -0
- package/lib/module/core/OxyServices.js +528 -326
- package/lib/module/core/OxyServices.js.map +1 -1
- package/lib/module/core/RequestManager.js +194 -0
- package/lib/module/core/RequestManager.js.map +1 -0
- package/lib/module/core/index.js +2 -0
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/i18n/index.js +37 -1
- package/lib/module/i18n/index.js.map +1 -1
- package/lib/module/i18n/locales/ar-SA.json +128 -0
- package/lib/module/i18n/locales/ca-ES.json +128 -0
- package/lib/module/i18n/locales/de-DE.json +128 -0
- package/lib/module/i18n/locales/en-US.json +85 -12
- package/lib/module/i18n/locales/es-ES.json +58 -6
- package/lib/module/i18n/locales/fr-FR.json +128 -0
- package/lib/module/i18n/locales/it-IT.json +128 -0
- package/lib/module/i18n/locales/ja-JP.json +127 -0
- package/lib/module/i18n/locales/ko-KR.json +128 -0
- package/lib/module/i18n/locales/pt-PT.json +128 -0
- package/lib/module/i18n/locales/zh-CN.json +128 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/Avatar.js +94 -27
- package/lib/module/ui/components/Avatar.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +1 -0
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/FontLoader.js +23 -43
- package/lib/module/ui/components/FontLoader.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +6 -8
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/StepBasedScreen.js +65 -45
- package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
- package/lib/module/ui/components/internal/GroupedPillButtons.js +14 -35
- package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/module/ui/components/internal/PinInput.js +2 -2
- package/lib/module/ui/components/internal/PinInput.js.map +1 -1
- package/lib/module/ui/components/internal/TextField.js +13 -8
- package/lib/module/ui/components/internal/TextField.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +442 -370
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +80 -22
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/index.js +4 -2
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +33 -2
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +102 -60
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +3 -2
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +73 -117
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +44 -51
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +14 -16
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js +187 -143
- package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInPasswordStep.js +10 -10
- package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInUsernameStep.js +2 -4
- package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverRequestStep.js +45 -25
- package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js +89 -54
- package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverSuccessStep.js +80 -59
- package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverVerifyStep.js +62 -53
- package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignInPasswordStep.js +219 -40
- package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignInTotpStep.js +78 -51
- package/lib/module/ui/screens/steps/SignInTotpStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignInUsernameStep.js +426 -73
- package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpIdentityStep.js +55 -30
- package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpSecurityStep.js +65 -47
- package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpSummaryStep.js +84 -146
- package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +114 -35
- package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
- package/lib/module/ui/stores/accountStore.js +229 -0
- package/lib/module/ui/stores/accountStore.js.map +1 -0
- package/lib/module/ui/stores/authStore.js +17 -20
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/styles/authStyles.js +16 -8
- package/lib/module/ui/styles/authStyles.js.map +1 -1
- package/lib/module/ui/styles/index.js +1 -0
- package/lib/module/ui/styles/index.js.map +1 -1
- package/lib/module/ui/styles/spacing.js +48 -0
- package/lib/module/ui/styles/spacing.js.map +1 -0
- package/lib/module/utils/asyncUtils.js +10 -22
- package/lib/module/utils/asyncUtils.js.map +1 -1
- package/lib/module/utils/cache.js +250 -0
- package/lib/module/utils/cache.js.map +1 -0
- package/lib/module/utils/index.js +7 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/languageUtils.js +151 -0
- package/lib/module/utils/languageUtils.js.map +1 -0
- package/lib/module/utils/requestUtils.js +210 -0
- package/lib/module/utils/requestUtils.js.map +1 -0
- package/lib/module/utils/sessionUtils.js +180 -0
- package/lib/module/utils/sessionUtils.js.map +1 -0
- package/lib/module/utils/validationUtils.js +1 -1
- package/lib/typescript/core/HttpClient.d.ts +64 -0
- package/lib/typescript/core/HttpClient.d.ts.map +1 -0
- package/lib/typescript/core/OxyServices.d.ts +86 -73
- package/lib/typescript/core/OxyServices.d.ts.map +1 -1
- package/lib/typescript/core/RequestManager.d.ts +67 -0
- package/lib/typescript/core/RequestManager.d.ts.map +1 -0
- package/lib/typescript/core/index.d.ts +2 -0
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/i18n/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +15 -0
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/models/session.d.ts +1 -0
- package/lib/typescript/models/session.d.ts.map +1 -1
- package/lib/typescript/ui/components/Avatar.d.ts +6 -7
- package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
- package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/ui/components/FontLoader.d.ts +3 -3
- package/lib/typescript/ui/components/FontLoader.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts +2 -2
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +5 -0
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/index.d.ts +2 -2
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts +3 -3
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +2 -0
- package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -1
- package/lib/typescript/ui/stores/accountStore.d.ts +34 -0
- package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -0
- package/lib/typescript/ui/stores/authStore.d.ts +7 -3
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/styles/authStyles.d.ts +19 -2
- package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
- package/lib/typescript/ui/styles/index.d.ts +1 -0
- package/lib/typescript/ui/styles/index.d.ts.map +1 -1
- package/lib/typescript/ui/styles/spacing.d.ts +43 -0
- package/lib/typescript/ui/styles/spacing.d.ts.map +1 -0
- package/lib/typescript/utils/asyncUtils.d.ts +2 -0
- package/lib/typescript/utils/asyncUtils.d.ts.map +1 -1
- package/lib/typescript/utils/cache.d.ts +128 -0
- package/lib/typescript/utils/cache.d.ts.map +1 -0
- package/lib/typescript/utils/index.d.ts +4 -0
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/lib/typescript/utils/languageUtils.d.ts +38 -0
- package/lib/typescript/utils/languageUtils.d.ts.map +1 -0
- package/lib/typescript/utils/requestUtils.d.ts +122 -0
- package/lib/typescript/utils/requestUtils.d.ts.map +1 -0
- package/lib/typescript/utils/sessionUtils.d.ts +55 -0
- package/lib/typescript/utils/sessionUtils.d.ts.map +1 -0
- package/lib/typescript/utils/validationUtils.d.ts +1 -1
- package/package.json +1 -1
- package/src/core/HttpClient.ts +277 -0
- package/src/core/OxyServices.ts +461 -352
- package/src/core/RequestManager.ts +240 -0
- package/src/core/index.ts +10 -0
- package/src/i18n/index.ts +36 -0
- package/src/i18n/locales/ar-SA.json +128 -0
- package/src/i18n/locales/ca-ES.json +128 -0
- package/src/i18n/locales/de-DE.json +128 -0
- package/src/i18n/locales/en-US.json +85 -12
- package/src/i18n/locales/es-ES.json +58 -6
- package/src/i18n/locales/fr-FR.json +128 -0
- package/src/i18n/locales/it-IT.json +128 -0
- package/src/i18n/locales/ja-JP.json +127 -0
- package/src/i18n/locales/ko-KR.json +128 -0
- package/src/i18n/locales/pt-PT.json +128 -0
- package/src/i18n/locales/zh-CN.json +128 -0
- package/src/index.ts +10 -0
- package/src/models/interfaces.ts +19 -0
- package/src/models/session.ts +1 -1
- package/src/ui/components/Avatar.tsx +151 -35
- package/src/ui/components/FollowButton.tsx +1 -0
- package/src/ui/components/FontLoader.tsx +17 -37
- package/src/ui/components/OxyProvider.tsx +14 -13
- package/src/ui/components/StepBasedScreen.tsx +66 -43
- package/src/ui/components/internal/GroupedPillButtons.tsx +15 -31
- package/src/ui/components/internal/PinInput.tsx +2 -2
- package/src/ui/components/internal/TextField.tsx +7 -6
- package/src/ui/context/OxyContext.tsx +441 -326
- package/src/ui/hooks/useSessionSocket.ts +72 -18
- package/src/ui/index.ts +4 -1
- package/src/ui/screens/AccountSettingsScreen.tsx +34 -2
- package/src/ui/screens/AccountSwitcherScreen.tsx +102 -68
- package/src/ui/screens/FileManagementScreen.tsx +16 -16
- package/src/ui/screens/LanguageSelectorScreen.tsx +86 -143
- package/src/ui/screens/SignInScreen.tsx +59 -43
- package/src/ui/screens/SignUpScreen.tsx +14 -15
- package/src/ui/screens/WelcomeNewUserScreen.tsx +153 -105
- package/src/ui/screens/internal/SignInPasswordStep.tsx +4 -6
- package/src/ui/screens/internal/SignInUsernameStep.tsx +1 -1
- package/src/ui/screens/steps/RecoverRequestStep.tsx +34 -24
- package/src/ui/screens/steps/RecoverResetPasswordStep.tsx +65 -36
- package/src/ui/screens/steps/RecoverSuccessStep.tsx +71 -47
- package/src/ui/screens/steps/RecoverVerifyStep.tsx +60 -50
- package/src/ui/screens/steps/SignInPasswordStep.tsx +190 -32
- package/src/ui/screens/steps/SignInTotpStep.tsx +68 -34
- package/src/ui/screens/steps/SignInUsernameStep.tsx +446 -63
- package/src/ui/screens/steps/SignUpIdentityStep.tsx +49 -35
- package/src/ui/screens/steps/SignUpSecurityStep.tsx +56 -39
- package/src/ui/screens/steps/SignUpSummaryStep.tsx +99 -89
- package/src/ui/screens/steps/SignUpWelcomeStep.tsx +88 -20
- package/src/ui/stores/accountStore.ts +285 -0
- package/src/ui/stores/authStore.ts +16 -19
- package/src/ui/styles/authStyles.ts +16 -8
- package/src/ui/styles/index.ts +1 -0
- package/src/ui/styles/spacing.ts +46 -0
- package/src/utils/asyncUtils.ts +10 -24
- package/src/utils/cache.ts +264 -0
- package/src/utils/index.ts +19 -0
- package/src/utils/languageUtils.ts +174 -0
- package/src/utils/requestUtils.ts +234 -0
- package/src/utils/sessionUtils.ts +206 -0
- package/src/utils/validationUtils.ts +1 -1
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
*
|
|
59
59
|
* See method JSDoc for more details and options.
|
|
60
60
|
*/
|
|
61
|
-
import axios from 'axios';
|
|
62
61
|
import { jwtDecode } from 'jwt-decode';
|
|
62
|
+
import { normalizeLanguageCode, getLanguageMetadata, getLanguageName, getNativeLanguageName } from '../utils/languageUtils';
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* OxyConfig - Configuration for OxyServices
|
|
@@ -69,6 +69,8 @@ import { jwtDecode } from 'jwt-decode';
|
|
|
69
69
|
|
|
70
70
|
import { handleHttpError } from '../utils/errorUtils';
|
|
71
71
|
import { buildSearchParams, buildPaginationParams } from '../utils/apiUtils';
|
|
72
|
+
import { HttpClient } from './HttpClient';
|
|
73
|
+
import { RequestManager } from './RequestManager';
|
|
72
74
|
/**
|
|
73
75
|
* Custom error types for better error handling
|
|
74
76
|
*/
|
|
@@ -91,42 +93,12 @@ export class OxyAuthenticationTimeoutError extends OxyAuthenticationError {
|
|
|
91
93
|
* OxyServices - Unified client library for interacting with the Oxy API
|
|
92
94
|
*
|
|
93
95
|
* This class provides all API functionality in one simple, easy-to-use interface.
|
|
94
|
-
*
|
|
96
|
+
* Architecture:
|
|
97
|
+
* - HttpClient: Handles HTTP communication and authentication
|
|
98
|
+
* - RequestManager: Handles caching, deduplication, queuing, and retry
|
|
99
|
+
* - OxyServices: Provides high-level API methods
|
|
95
100
|
*/
|
|
96
|
-
// Centralized token store
|
|
97
|
-
class TokenStore {
|
|
98
|
-
accessToken = null;
|
|
99
|
-
refreshToken = null;
|
|
100
|
-
constructor() {}
|
|
101
|
-
static getInstance() {
|
|
102
|
-
if (!TokenStore.instance) {
|
|
103
|
-
TokenStore.instance = new TokenStore();
|
|
104
|
-
}
|
|
105
|
-
return TokenStore.instance;
|
|
106
|
-
}
|
|
107
|
-
setTokens(accessToken, refreshToken = '') {
|
|
108
|
-
this.accessToken = accessToken;
|
|
109
|
-
this.refreshToken = refreshToken;
|
|
110
|
-
}
|
|
111
|
-
getAccessToken() {
|
|
112
|
-
return this.accessToken;
|
|
113
|
-
}
|
|
114
|
-
getRefreshToken() {
|
|
115
|
-
return this.refreshToken;
|
|
116
|
-
}
|
|
117
|
-
clearTokens() {
|
|
118
|
-
this.accessToken = null;
|
|
119
|
-
this.refreshToken = null;
|
|
120
|
-
}
|
|
121
|
-
hasAccessToken() {
|
|
122
|
-
return !!this.accessToken;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
101
|
export class OxyServices {
|
|
126
|
-
/**
|
|
127
|
-
* Creates a new instance of the OxyServices client
|
|
128
|
-
* @param config - Configuration for the client
|
|
129
|
-
*/
|
|
130
102
|
/**
|
|
131
103
|
* Creates a new instance of the OxyServices client
|
|
132
104
|
* @param config - Configuration for the client
|
|
@@ -134,89 +106,27 @@ export class OxyServices {
|
|
|
134
106
|
* config.cloudURL: Oxy Cloud URL (e.g., https://cloud.oxy.so)
|
|
135
107
|
*/
|
|
136
108
|
constructor(config) {
|
|
137
|
-
this.
|
|
138
|
-
baseURL: config.baseURL,
|
|
139
|
-
timeout: 5000 // 5 second timeout
|
|
140
|
-
});
|
|
109
|
+
this.config = config;
|
|
141
110
|
this.cloudURL = config.cloudURL || OXY_CLOUD_URL;
|
|
142
|
-
|
|
143
|
-
|
|
111
|
+
|
|
112
|
+
// Initialize HTTP client (handles authentication and interceptors)
|
|
113
|
+
this.httpClient = new HttpClient(config);
|
|
114
|
+
|
|
115
|
+
// Initialize request manager (handles caching, deduplication, queuing, retry)
|
|
116
|
+
this.requestManager = new RequestManager(this.httpClient, config);
|
|
144
117
|
}
|
|
145
118
|
|
|
146
119
|
// Test-only utility to reset global tokens between jest tests
|
|
147
120
|
static __resetTokensForTests() {
|
|
148
|
-
|
|
149
|
-
TokenStore.getInstance().clearTokens();
|
|
150
|
-
} catch {}
|
|
121
|
+
HttpClient.__resetTokensForTests();
|
|
151
122
|
}
|
|
152
123
|
|
|
153
124
|
/**
|
|
154
|
-
*
|
|
125
|
+
* Make a request with all performance optimizations
|
|
126
|
+
* This is the main method for all API calls - ensures authentication and performance features
|
|
155
127
|
*/
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.client.interceptors.request.use(async req => {
|
|
159
|
-
console.log('🔍 Interceptor - URL:', req.url);
|
|
160
|
-
console.log('🔍 Interceptor - Has token:', this.tokenStore.hasAccessToken());
|
|
161
|
-
const accessToken = this.tokenStore.getAccessToken();
|
|
162
|
-
if (!accessToken) {
|
|
163
|
-
console.log('❌ Interceptor - No token available');
|
|
164
|
-
return req;
|
|
165
|
-
}
|
|
166
|
-
try {
|
|
167
|
-
console.log('✅ Interceptor - Adding Authorization header');
|
|
168
|
-
const decoded = jwtDecode(accessToken);
|
|
169
|
-
const currentTime = Math.floor(Date.now() / 1000);
|
|
170
|
-
|
|
171
|
-
// If token expires in less than 60 seconds, refresh it
|
|
172
|
-
if (decoded.exp && decoded.exp - currentTime < 60) {
|
|
173
|
-
// For session-based tokens, get a new token from the session
|
|
174
|
-
if (decoded.sessionId) {
|
|
175
|
-
try {
|
|
176
|
-
// Create a new axios instance to avoid interceptor recursion
|
|
177
|
-
const refreshClient = axios.create({
|
|
178
|
-
baseURL: this.client.defaults.baseURL,
|
|
179
|
-
timeout: this.client.defaults.timeout
|
|
180
|
-
});
|
|
181
|
-
const res = await refreshClient.get(`/api/session/token/${decoded.sessionId}`);
|
|
182
|
-
this.tokenStore.setTokens(res.data.accessToken);
|
|
183
|
-
req.headers.Authorization = `Bearer ${res.data.accessToken}`;
|
|
184
|
-
console.log('✅ Interceptor - Token refreshed and Authorization header set');
|
|
185
|
-
} catch (refreshError) {
|
|
186
|
-
// If refresh fails, use current token anyway
|
|
187
|
-
req.headers.Authorization = `Bearer ${accessToken}`;
|
|
188
|
-
console.log('❌ Interceptor - Token refresh failed, using current token');
|
|
189
|
-
}
|
|
190
|
-
} else {
|
|
191
|
-
// No session ID, use current token
|
|
192
|
-
req.headers.Authorization = `Bearer ${accessToken}`;
|
|
193
|
-
console.log('✅ Interceptor - No session ID, using current token');
|
|
194
|
-
}
|
|
195
|
-
} else {
|
|
196
|
-
// Add authorization header with current token
|
|
197
|
-
req.headers.Authorization = `Bearer ${accessToken}`;
|
|
198
|
-
console.log('✅ Interceptor - Authorization header set with current token');
|
|
199
|
-
}
|
|
200
|
-
} catch (error) {
|
|
201
|
-
console.log('❌ Interceptor - Error processing token:', error);
|
|
202
|
-
// Even if there's an error, still try to use the token
|
|
203
|
-
req.headers.Authorization = `Bearer ${accessToken}`;
|
|
204
|
-
console.log('⚠️ Interceptor - Using token despite error');
|
|
205
|
-
}
|
|
206
|
-
return req;
|
|
207
|
-
}, error => {
|
|
208
|
-
console.log('❌ Interceptor - Request error:', error);
|
|
209
|
-
return Promise.reject(error);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// Response interceptor for handling auth errors
|
|
213
|
-
this.client.interceptors.response.use(response => response, error => {
|
|
214
|
-
if (error.response?.status === 401) {
|
|
215
|
-
console.log('❌ Response interceptor - 401 Unauthorized, clearing tokens');
|
|
216
|
-
this.clearTokens();
|
|
217
|
-
}
|
|
218
|
-
return Promise.reject(error);
|
|
219
|
-
});
|
|
128
|
+
async makeRequest(method, url, data, options = {}) {
|
|
129
|
+
return this.requestManager.request(method, url, data, options);
|
|
220
130
|
}
|
|
221
131
|
|
|
222
132
|
// ============================================================================
|
|
@@ -227,7 +137,35 @@ export class OxyServices {
|
|
|
227
137
|
* Get the configured Oxy API base URL
|
|
228
138
|
*/
|
|
229
139
|
getBaseURL() {
|
|
230
|
-
return this.
|
|
140
|
+
return this.httpClient.getBaseURL();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get performance metrics
|
|
145
|
+
*/
|
|
146
|
+
getMetrics() {
|
|
147
|
+
return this.requestManager.getMetrics();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Clear request cache
|
|
152
|
+
*/
|
|
153
|
+
clearCache() {
|
|
154
|
+
this.requestManager.clearCache();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Clear specific cache entry
|
|
159
|
+
*/
|
|
160
|
+
clearCacheEntry(key) {
|
|
161
|
+
this.requestManager.clearCacheEntry(key);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get cache statistics
|
|
166
|
+
*/
|
|
167
|
+
getCacheStats() {
|
|
168
|
+
return this.requestManager.getCacheStats();
|
|
231
169
|
}
|
|
232
170
|
|
|
233
171
|
/**
|
|
@@ -241,21 +179,21 @@ export class OxyServices {
|
|
|
241
179
|
* Set authentication tokens
|
|
242
180
|
*/
|
|
243
181
|
setTokens(accessToken, refreshToken = '') {
|
|
244
|
-
this.
|
|
182
|
+
this.httpClient.setTokens(accessToken, refreshToken);
|
|
245
183
|
}
|
|
246
184
|
|
|
247
185
|
/**
|
|
248
186
|
* Clear stored authentication tokens
|
|
249
187
|
*/
|
|
250
188
|
clearTokens() {
|
|
251
|
-
this.
|
|
189
|
+
this.httpClient.clearTokens();
|
|
252
190
|
}
|
|
253
191
|
|
|
254
192
|
/**
|
|
255
193
|
* Get the current user ID from the access token
|
|
256
194
|
*/
|
|
257
195
|
getCurrentUserId() {
|
|
258
|
-
const accessToken = this.
|
|
196
|
+
const accessToken = this.httpClient.getAccessToken();
|
|
259
197
|
if (!accessToken) {
|
|
260
198
|
return null;
|
|
261
199
|
}
|
|
@@ -271,21 +209,21 @@ export class OxyServices {
|
|
|
271
209
|
* Check if the client has a valid access token
|
|
272
210
|
*/
|
|
273
211
|
hasAccessToken() {
|
|
274
|
-
return this.
|
|
212
|
+
return this.httpClient.hasAccessToken();
|
|
275
213
|
}
|
|
276
214
|
|
|
277
215
|
/**
|
|
278
216
|
* Check if the client has a valid access token (public method)
|
|
279
217
|
*/
|
|
280
218
|
hasValidToken() {
|
|
281
|
-
return this.
|
|
219
|
+
return this.httpClient.hasAccessToken();
|
|
282
220
|
}
|
|
283
221
|
|
|
284
222
|
/**
|
|
285
223
|
* Get the raw access token (for constructing anchor URLs when needed)
|
|
286
224
|
*/
|
|
287
225
|
getAccessToken() {
|
|
288
|
-
return this.
|
|
226
|
+
return this.httpClient.getAccessToken();
|
|
289
227
|
}
|
|
290
228
|
|
|
291
229
|
/**
|
|
@@ -304,7 +242,7 @@ export class OxyServices {
|
|
|
304
242
|
const checkInterval = 100; // Check every 100ms
|
|
305
243
|
|
|
306
244
|
while (Date.now() - startTime < timeoutMs) {
|
|
307
|
-
if (this.
|
|
245
|
+
if (this.httpClient.hasAccessToken()) {
|
|
308
246
|
return true;
|
|
309
247
|
}
|
|
310
248
|
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
@@ -325,15 +263,13 @@ export class OxyServices {
|
|
|
325
263
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
326
264
|
try {
|
|
327
265
|
// First attempt: check if we have a token
|
|
328
|
-
if (!this.
|
|
266
|
+
if (!this.httpClient.hasAccessToken()) {
|
|
329
267
|
if (attempt === 0) {
|
|
330
268
|
// On first attempt, wait briefly for authentication to complete
|
|
331
|
-
console.log(`🔄 ${operationName} - Waiting for authentication...`);
|
|
332
269
|
const authReady = await this.waitForAuthentication(authTimeoutMs);
|
|
333
270
|
if (!authReady) {
|
|
334
271
|
throw new OxyAuthenticationTimeoutError(operationName, authTimeoutMs);
|
|
335
272
|
}
|
|
336
|
-
console.log(`✅ ${operationName} - Authentication ready, proceeding...`);
|
|
337
273
|
} else {
|
|
338
274
|
// On retry attempts, fail immediately if no token
|
|
339
275
|
throw new OxyAuthenticationError(`Authentication required: ${operationName} requires a valid access token.`, 'AUTH_REQUIRED');
|
|
@@ -346,7 +282,6 @@ export class OxyServices {
|
|
|
346
282
|
const isLastAttempt = attempt === maxRetries;
|
|
347
283
|
const isAuthError = error?.response?.status === 401 || error?.code === 'MISSING_TOKEN' || error?.message?.includes('Authentication') || error instanceof OxyAuthenticationError;
|
|
348
284
|
if (isAuthError && !isLastAttempt && !(error instanceof OxyAuthenticationTimeoutError)) {
|
|
349
|
-
console.log(`🔄 ${operationName} - Auth error on attempt ${attempt + 1}, retrying in ${retryDelay}ms...`);
|
|
350
285
|
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
351
286
|
continue;
|
|
352
287
|
}
|
|
@@ -371,20 +306,16 @@ export class OxyServices {
|
|
|
371
306
|
return false;
|
|
372
307
|
}
|
|
373
308
|
try {
|
|
374
|
-
const res = await this.
|
|
375
|
-
|
|
309
|
+
const res = await this.makeRequest('GET', '/api/auth/validate', undefined, {
|
|
310
|
+
cache: false,
|
|
311
|
+
retry: false
|
|
312
|
+
});
|
|
313
|
+
return res.valid === true;
|
|
376
314
|
} catch (error) {
|
|
377
315
|
return false;
|
|
378
316
|
}
|
|
379
317
|
}
|
|
380
318
|
|
|
381
|
-
/**
|
|
382
|
-
* Get the HTTP client instance (public for external use)
|
|
383
|
-
*/
|
|
384
|
-
getClient() {
|
|
385
|
-
return this.client;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
319
|
/**
|
|
389
320
|
* Centralized error handling
|
|
390
321
|
*/
|
|
@@ -402,8 +333,9 @@ export class OxyServices {
|
|
|
402
333
|
*/
|
|
403
334
|
async healthCheck() {
|
|
404
335
|
try {
|
|
405
|
-
|
|
406
|
-
|
|
336
|
+
return await this.makeRequest('GET', '/health', undefined, {
|
|
337
|
+
cache: false
|
|
338
|
+
});
|
|
407
339
|
} catch (error) {
|
|
408
340
|
throw this.handleError(error);
|
|
409
341
|
}
|
|
@@ -418,15 +350,17 @@ export class OxyServices {
|
|
|
418
350
|
*/
|
|
419
351
|
async signUp(username, email, password) {
|
|
420
352
|
try {
|
|
421
|
-
const res = await this.
|
|
353
|
+
const res = await this.makeRequest('POST', '/api/auth/signup', {
|
|
422
354
|
username,
|
|
423
355
|
email,
|
|
424
356
|
password
|
|
357
|
+
}, {
|
|
358
|
+
cache: false
|
|
425
359
|
});
|
|
426
|
-
if (!res ||
|
|
360
|
+
if (!res || typeof res === 'object' && Object.keys(res).length === 0) {
|
|
427
361
|
throw new OxyAuthenticationError('Sign up failed', 'SIGNUP_FAILED', 400);
|
|
428
362
|
}
|
|
429
|
-
return res
|
|
363
|
+
return res;
|
|
430
364
|
} catch (error) {
|
|
431
365
|
throw this.handleError(error);
|
|
432
366
|
}
|
|
@@ -437,10 +371,11 @@ export class OxyServices {
|
|
|
437
371
|
*/
|
|
438
372
|
async requestRecovery(identifier) {
|
|
439
373
|
try {
|
|
440
|
-
|
|
374
|
+
return await this.makeRequest('POST', '/api/auth/recover/request', {
|
|
441
375
|
identifier
|
|
376
|
+
}, {
|
|
377
|
+
cache: false
|
|
442
378
|
});
|
|
443
|
-
return res.data;
|
|
444
379
|
} catch (error) {
|
|
445
380
|
throw this.handleError(error);
|
|
446
381
|
}
|
|
@@ -451,11 +386,12 @@ export class OxyServices {
|
|
|
451
386
|
*/
|
|
452
387
|
async verifyRecoveryCode(identifier, code) {
|
|
453
388
|
try {
|
|
454
|
-
|
|
389
|
+
return await this.makeRequest('POST', '/api/auth/recover/verify', {
|
|
455
390
|
identifier,
|
|
456
391
|
code
|
|
392
|
+
}, {
|
|
393
|
+
cache: false
|
|
457
394
|
});
|
|
458
|
-
return res.data;
|
|
459
395
|
} catch (error) {
|
|
460
396
|
throw this.handleError(error);
|
|
461
397
|
}
|
|
@@ -466,12 +402,13 @@ export class OxyServices {
|
|
|
466
402
|
*/
|
|
467
403
|
async resetPassword(identifier, code, newPassword) {
|
|
468
404
|
try {
|
|
469
|
-
|
|
405
|
+
return await this.makeRequest('POST', '/api/auth/recover/reset', {
|
|
470
406
|
identifier,
|
|
471
407
|
code,
|
|
472
408
|
newPassword
|
|
409
|
+
}, {
|
|
410
|
+
cache: false
|
|
473
411
|
});
|
|
474
|
-
return res.data;
|
|
475
412
|
} catch (error) {
|
|
476
413
|
throw this.handleError(error);
|
|
477
414
|
}
|
|
@@ -482,36 +419,39 @@ export class OxyServices {
|
|
|
482
419
|
*/
|
|
483
420
|
async resetPasswordWithTotp(identifier, code, newPassword) {
|
|
484
421
|
try {
|
|
485
|
-
|
|
422
|
+
return await this.makeRequest('POST', '/api/auth/recover/totp/reset', {
|
|
486
423
|
identifier,
|
|
487
424
|
code,
|
|
488
425
|
newPassword
|
|
426
|
+
}, {
|
|
427
|
+
cache: false
|
|
489
428
|
});
|
|
490
|
-
return res.data;
|
|
491
429
|
} catch (error) {
|
|
492
430
|
throw this.handleError(error);
|
|
493
431
|
}
|
|
494
432
|
}
|
|
495
433
|
async resetPasswordWithBackupCode(identifier, backupCode, newPassword) {
|
|
496
434
|
try {
|
|
497
|
-
|
|
435
|
+
return await this.makeRequest('POST', '/api/auth/recover/backup/reset', {
|
|
498
436
|
identifier,
|
|
499
437
|
backupCode,
|
|
500
438
|
newPassword
|
|
439
|
+
}, {
|
|
440
|
+
cache: false
|
|
501
441
|
});
|
|
502
|
-
return res.data;
|
|
503
442
|
} catch (error) {
|
|
504
443
|
throw this.handleError(error);
|
|
505
444
|
}
|
|
506
445
|
}
|
|
507
446
|
async resetPasswordWithRecoveryKey(identifier, recoveryKey, newPassword) {
|
|
508
447
|
try {
|
|
509
|
-
|
|
448
|
+
return await this.makeRequest('POST', '/api/auth/recover/recovery-key/reset', {
|
|
510
449
|
identifier,
|
|
511
450
|
recoveryKey,
|
|
512
451
|
newPassword
|
|
452
|
+
}, {
|
|
453
|
+
cache: false
|
|
513
454
|
});
|
|
514
|
-
return res.data;
|
|
515
455
|
} catch (error) {
|
|
516
456
|
throw this.handleError(error);
|
|
517
457
|
}
|
|
@@ -522,13 +462,14 @@ export class OxyServices {
|
|
|
522
462
|
*/
|
|
523
463
|
async signIn(username, password, deviceName, deviceFingerprint) {
|
|
524
464
|
try {
|
|
525
|
-
|
|
465
|
+
return await this.makeRequest('POST', '/api/auth/login', {
|
|
526
466
|
username,
|
|
527
467
|
password,
|
|
528
468
|
deviceName,
|
|
529
469
|
deviceFingerprint
|
|
470
|
+
}, {
|
|
471
|
+
cache: false
|
|
530
472
|
});
|
|
531
|
-
return res.data;
|
|
532
473
|
} catch (error) {
|
|
533
474
|
throw this.handleError(error);
|
|
534
475
|
}
|
|
@@ -539,11 +480,12 @@ export class OxyServices {
|
|
|
539
480
|
*/
|
|
540
481
|
async verifyTotpLogin(mfaToken, code) {
|
|
541
482
|
try {
|
|
542
|
-
|
|
483
|
+
return await this.makeRequest('POST', '/api/auth/totp/verify-login', {
|
|
543
484
|
mfaToken,
|
|
544
485
|
code
|
|
486
|
+
}, {
|
|
487
|
+
cache: false
|
|
545
488
|
});
|
|
546
|
-
return res.data;
|
|
547
489
|
} catch (error) {
|
|
548
490
|
throw this.handleError(error);
|
|
549
491
|
}
|
|
@@ -554,8 +496,35 @@ export class OxyServices {
|
|
|
554
496
|
*/
|
|
555
497
|
async getUserBySession(sessionId) {
|
|
556
498
|
try {
|
|
557
|
-
|
|
558
|
-
|
|
499
|
+
return await this.makeRequest('GET', `/api/session/user/${sessionId}`, undefined, {
|
|
500
|
+
cache: true,
|
|
501
|
+
cacheTTL: 2 * 60 * 1000 // 2 minutes cache for user data
|
|
502
|
+
});
|
|
503
|
+
} catch (error) {
|
|
504
|
+
throw this.handleError(error);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Batch get multiple user profiles by session IDs (optimized for account switching)
|
|
510
|
+
* Returns array of { sessionId, user } objects
|
|
511
|
+
*/
|
|
512
|
+
async getUsersBySessions(sessionIds) {
|
|
513
|
+
try {
|
|
514
|
+
if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
|
|
515
|
+
return [];
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Deduplicate and sort sessionIds for consistent cache keys
|
|
519
|
+
const uniqueSessionIds = Array.from(new Set(sessionIds)).sort();
|
|
520
|
+
return await this.makeRequest('POST', '/api/session/users/batch', {
|
|
521
|
+
sessionIds: uniqueSessionIds
|
|
522
|
+
}, {
|
|
523
|
+
cache: true,
|
|
524
|
+
cacheTTL: 2 * 60 * 1000,
|
|
525
|
+
// 2 minutes cache
|
|
526
|
+
deduplicate: true // Important for batch requests
|
|
527
|
+
});
|
|
559
528
|
} catch (error) {
|
|
560
529
|
throw this.handleError(error);
|
|
561
530
|
}
|
|
@@ -566,19 +535,15 @@ export class OxyServices {
|
|
|
566
535
|
*/
|
|
567
536
|
async getTokenBySession(sessionId) {
|
|
568
537
|
try {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
} = res.data;
|
|
574
|
-
console.log('🔑 getTokenBySession - Token received:', !!accessToken);
|
|
538
|
+
const res = await this.makeRequest('GET', `/api/session/token/${sessionId}`, undefined, {
|
|
539
|
+
cache: false,
|
|
540
|
+
retry: false
|
|
541
|
+
});
|
|
575
542
|
|
|
576
543
|
// Set the token in the centralized token store
|
|
577
|
-
this.setTokens(accessToken);
|
|
578
|
-
|
|
579
|
-
return res.data;
|
|
544
|
+
this.setTokens(res.accessToken);
|
|
545
|
+
return res;
|
|
580
546
|
} catch (error) {
|
|
581
|
-
console.log('❌ getTokenBySession - Error:', error);
|
|
582
547
|
throw this.handleError(error);
|
|
583
548
|
}
|
|
584
549
|
}
|
|
@@ -588,8 +553,9 @@ export class OxyServices {
|
|
|
588
553
|
*/
|
|
589
554
|
async getSessionsBySessionId(sessionId) {
|
|
590
555
|
try {
|
|
591
|
-
|
|
592
|
-
|
|
556
|
+
return await this.makeRequest('GET', `/api/session/sessions/${sessionId}`, undefined, {
|
|
557
|
+
cache: false
|
|
558
|
+
});
|
|
593
559
|
} catch (error) {
|
|
594
560
|
throw this.handleError(error);
|
|
595
561
|
}
|
|
@@ -601,7 +567,9 @@ export class OxyServices {
|
|
|
601
567
|
async logoutSession(sessionId, targetSessionId) {
|
|
602
568
|
try {
|
|
603
569
|
const url = targetSessionId ? `/api/session/logout/${sessionId}/${targetSessionId}` : `/api/session/logout/${sessionId}`;
|
|
604
|
-
await this.
|
|
570
|
+
await this.makeRequest('POST', url, undefined, {
|
|
571
|
+
cache: false
|
|
572
|
+
});
|
|
605
573
|
} catch (error) {
|
|
606
574
|
throw this.handleError(error);
|
|
607
575
|
}
|
|
@@ -612,7 +580,9 @@ export class OxyServices {
|
|
|
612
580
|
*/
|
|
613
581
|
async logoutAllSessions(sessionId) {
|
|
614
582
|
try {
|
|
615
|
-
await this.
|
|
583
|
+
await this.makeRequest('POST', `/api/session/logout-all/${sessionId}`, undefined, {
|
|
584
|
+
cache: false
|
|
585
|
+
});
|
|
616
586
|
} catch (error) {
|
|
617
587
|
throw this.handleError(error);
|
|
618
588
|
}
|
|
@@ -630,9 +600,13 @@ export class OxyServices {
|
|
|
630
600
|
if (options.useHeaderValidation) {
|
|
631
601
|
params.append('useHeaderValidation', 'true');
|
|
632
602
|
}
|
|
633
|
-
const url = `/api/session/validate/${sessionId}
|
|
634
|
-
const
|
|
635
|
-
|
|
603
|
+
const url = `/api/session/validate/${sessionId}`;
|
|
604
|
+
const urlParams = {};
|
|
605
|
+
if (options.deviceFingerprint) urlParams.deviceFingerprint = options.deviceFingerprint;
|
|
606
|
+
if (options.useHeaderValidation) urlParams.useHeaderValidation = 'true';
|
|
607
|
+
return await this.makeRequest('GET', url, urlParams, {
|
|
608
|
+
cache: false
|
|
609
|
+
});
|
|
636
610
|
} catch (error) {
|
|
637
611
|
throw this.handleError(error);
|
|
638
612
|
}
|
|
@@ -643,8 +617,9 @@ export class OxyServices {
|
|
|
643
617
|
*/
|
|
644
618
|
async checkUsernameAvailability(username) {
|
|
645
619
|
try {
|
|
646
|
-
|
|
647
|
-
|
|
620
|
+
return await this.makeRequest('GET', `/api/auth/check-username/${username}`, undefined, {
|
|
621
|
+
cache: false
|
|
622
|
+
});
|
|
648
623
|
} catch (error) {
|
|
649
624
|
throw this.handleError(error);
|
|
650
625
|
}
|
|
@@ -655,8 +630,9 @@ export class OxyServices {
|
|
|
655
630
|
*/
|
|
656
631
|
async checkEmailAvailability(email) {
|
|
657
632
|
try {
|
|
658
|
-
|
|
659
|
-
|
|
633
|
+
return await this.makeRequest('GET', `/api/auth/check-email/${email}`, undefined, {
|
|
634
|
+
cache: false
|
|
635
|
+
});
|
|
660
636
|
} catch (error) {
|
|
661
637
|
throw this.handleError(error);
|
|
662
638
|
}
|
|
@@ -671,8 +647,10 @@ export class OxyServices {
|
|
|
671
647
|
*/
|
|
672
648
|
async getProfileByUsername(username) {
|
|
673
649
|
try {
|
|
674
|
-
|
|
675
|
-
|
|
650
|
+
return await this.makeRequest('GET', `/api/profiles/username/${username}`, undefined, {
|
|
651
|
+
cache: true,
|
|
652
|
+
cacheTTL: 5 * 60 * 1000 // 5 minutes cache for profiles
|
|
653
|
+
});
|
|
676
654
|
} catch (error) {
|
|
677
655
|
throw this.handleError(error);
|
|
678
656
|
}
|
|
@@ -684,44 +662,36 @@ export class OxyServices {
|
|
|
684
662
|
|
|
685
663
|
async startTotpEnrollment(sessionId) {
|
|
686
664
|
try {
|
|
687
|
-
|
|
665
|
+
// Note: x-session-id header is handled by HttpClient interceptors if needed
|
|
666
|
+
return await this.makeRequest('POST', '/api/auth/totp/enroll/start', {
|
|
688
667
|
sessionId
|
|
689
668
|
}, {
|
|
690
|
-
|
|
691
|
-
'x-session-id': sessionId
|
|
692
|
-
}
|
|
669
|
+
cache: false
|
|
693
670
|
});
|
|
694
|
-
return res.data;
|
|
695
671
|
} catch (error) {
|
|
696
672
|
throw this.handleError(error);
|
|
697
673
|
}
|
|
698
674
|
}
|
|
699
675
|
async verifyTotpEnrollment(sessionId, code) {
|
|
700
676
|
try {
|
|
701
|
-
|
|
677
|
+
return await this.makeRequest('POST', '/api/auth/totp/enroll/verify', {
|
|
702
678
|
sessionId,
|
|
703
679
|
code
|
|
704
680
|
}, {
|
|
705
|
-
|
|
706
|
-
'x-session-id': sessionId
|
|
707
|
-
}
|
|
681
|
+
cache: false
|
|
708
682
|
});
|
|
709
|
-
return res.data;
|
|
710
683
|
} catch (error) {
|
|
711
684
|
throw this.handleError(error);
|
|
712
685
|
}
|
|
713
686
|
}
|
|
714
687
|
async disableTotp(sessionId, code) {
|
|
715
688
|
try {
|
|
716
|
-
|
|
689
|
+
return await this.makeRequest('POST', '/api/auth/totp/disable', {
|
|
717
690
|
sessionId,
|
|
718
691
|
code
|
|
719
692
|
}, {
|
|
720
|
-
|
|
721
|
-
'x-session-id': sessionId
|
|
722
|
-
}
|
|
693
|
+
cache: false
|
|
723
694
|
});
|
|
724
|
-
return res.data;
|
|
725
695
|
} catch (error) {
|
|
726
696
|
throw this.handleError(error);
|
|
727
697
|
}
|
|
@@ -737,8 +707,14 @@ export class OxyServices {
|
|
|
737
707
|
...pagination
|
|
738
708
|
};
|
|
739
709
|
const searchParams = buildSearchParams(params);
|
|
740
|
-
const
|
|
741
|
-
|
|
710
|
+
const paramsObj = {};
|
|
711
|
+
searchParams.forEach((value, key) => {
|
|
712
|
+
paramsObj[key] = value;
|
|
713
|
+
});
|
|
714
|
+
return await this.makeRequest('GET', '/api/profiles/search', paramsObj, {
|
|
715
|
+
cache: true,
|
|
716
|
+
cacheTTL: 2 * 60 * 1000 // 2 minutes cache
|
|
717
|
+
});
|
|
742
718
|
} catch (error) {
|
|
743
719
|
throw this.handleError(error);
|
|
744
720
|
}
|
|
@@ -749,8 +725,9 @@ export class OxyServices {
|
|
|
749
725
|
*/
|
|
750
726
|
async getProfileRecommendations() {
|
|
751
727
|
return this.withAuthRetry(async () => {
|
|
752
|
-
|
|
753
|
-
|
|
728
|
+
return await this.makeRequest('GET', '/api/profiles/recommendations', undefined, {
|
|
729
|
+
cache: true
|
|
730
|
+
});
|
|
754
731
|
}, 'getProfileRecommendations');
|
|
755
732
|
}
|
|
756
733
|
|
|
@@ -759,8 +736,10 @@ export class OxyServices {
|
|
|
759
736
|
*/
|
|
760
737
|
async getUserById(userId) {
|
|
761
738
|
try {
|
|
762
|
-
|
|
763
|
-
|
|
739
|
+
return await this.makeRequest('GET', `/api/users/${userId}`, undefined, {
|
|
740
|
+
cache: true,
|
|
741
|
+
cacheTTL: 5 * 60 * 1000 // 5 minutes cache
|
|
742
|
+
});
|
|
764
743
|
} catch (error) {
|
|
765
744
|
throw this.handleError(error);
|
|
766
745
|
}
|
|
@@ -771,8 +750,10 @@ export class OxyServices {
|
|
|
771
750
|
*/
|
|
772
751
|
async getCurrentUser() {
|
|
773
752
|
return this.withAuthRetry(async () => {
|
|
774
|
-
|
|
775
|
-
|
|
753
|
+
return await this.makeRequest('GET', '/api/users/me', undefined, {
|
|
754
|
+
cache: true,
|
|
755
|
+
cacheTTL: 1 * 60 * 1000 // 1 minute cache for current user
|
|
756
|
+
});
|
|
776
757
|
}, 'getCurrentUser');
|
|
777
758
|
}
|
|
778
759
|
|
|
@@ -781,20 +762,134 @@ export class OxyServices {
|
|
|
781
762
|
*/
|
|
782
763
|
async updateProfile(updates) {
|
|
783
764
|
try {
|
|
784
|
-
|
|
785
|
-
|
|
765
|
+
return await this.makeRequest('PUT', '/api/users/me', updates, {
|
|
766
|
+
cache: false
|
|
767
|
+
});
|
|
786
768
|
} catch (error) {
|
|
787
769
|
throw this.handleError(error);
|
|
788
770
|
}
|
|
789
771
|
}
|
|
790
772
|
|
|
773
|
+
// ============================================================================
|
|
774
|
+
// LANGUAGE METHODS
|
|
775
|
+
// ============================================================================
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Get the current language from storage or user profile
|
|
779
|
+
* @param storageKeyPrefix - Optional prefix for storage key (default: 'oxy_session')
|
|
780
|
+
* @returns The current language code (e.g., 'en-US') or null if not set
|
|
781
|
+
*/
|
|
782
|
+
async getCurrentLanguage(storageKeyPrefix = 'oxy_session') {
|
|
783
|
+
try {
|
|
784
|
+
// First try to get from user profile if authenticated
|
|
785
|
+
try {
|
|
786
|
+
const user = await this.getCurrentUser();
|
|
787
|
+
const userLanguage = user?.language;
|
|
788
|
+
if (userLanguage) {
|
|
789
|
+
return normalizeLanguageCode(userLanguage) || userLanguage;
|
|
790
|
+
}
|
|
791
|
+
} catch (e) {
|
|
792
|
+
// User not authenticated or error, continue to storage
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// Fall back to storage
|
|
796
|
+
const storage = await this.getStorage();
|
|
797
|
+
const storageKey = `${storageKeyPrefix}_language`;
|
|
798
|
+
const storedLanguage = await storage.getItem(storageKey);
|
|
799
|
+
if (storedLanguage) {
|
|
800
|
+
return normalizeLanguageCode(storedLanguage) || storedLanguage;
|
|
801
|
+
}
|
|
802
|
+
return null;
|
|
803
|
+
} catch (error) {
|
|
804
|
+
if (__DEV__) {
|
|
805
|
+
console.warn('Failed to get current language:', error);
|
|
806
|
+
}
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Get the current language with metadata (name, nativeName, etc.)
|
|
813
|
+
* @param storageKeyPrefix - Optional prefix for storage key (default: 'oxy_session')
|
|
814
|
+
* @returns Language metadata object or null if not set
|
|
815
|
+
*/
|
|
816
|
+
async getCurrentLanguageMetadata(storageKeyPrefix = 'oxy_session') {
|
|
817
|
+
const languageCode = await this.getCurrentLanguage(storageKeyPrefix);
|
|
818
|
+
return getLanguageMetadata(languageCode);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Get the current language name (e.g., 'English')
|
|
823
|
+
* @param storageKeyPrefix - Optional prefix for storage key (default: 'oxy_session')
|
|
824
|
+
* @returns Language name or null if not set
|
|
825
|
+
*/
|
|
826
|
+
async getCurrentLanguageName(storageKeyPrefix = 'oxy_session') {
|
|
827
|
+
const languageCode = await this.getCurrentLanguage(storageKeyPrefix);
|
|
828
|
+
if (!languageCode) return null;
|
|
829
|
+
return getLanguageName(languageCode);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Get the current native language name (e.g., 'Español')
|
|
834
|
+
* @param storageKeyPrefix - Optional prefix for storage key (default: 'oxy_session')
|
|
835
|
+
* @returns Native language name or null if not set
|
|
836
|
+
*/
|
|
837
|
+
async getCurrentNativeLanguageName(storageKeyPrefix = 'oxy_session') {
|
|
838
|
+
const languageCode = await this.getCurrentLanguage(storageKeyPrefix);
|
|
839
|
+
if (!languageCode) return null;
|
|
840
|
+
return getNativeLanguageName(languageCode);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Get appropriate storage for the platform (similar to DeviceManager)
|
|
845
|
+
* @private
|
|
846
|
+
*/
|
|
847
|
+
async getStorage() {
|
|
848
|
+
const isReactNative = typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
|
|
849
|
+
if (isReactNative) {
|
|
850
|
+
try {
|
|
851
|
+
const asyncStorageModule = await import('@react-native-async-storage/async-storage');
|
|
852
|
+
const storage = asyncStorageModule.default;
|
|
853
|
+
return {
|
|
854
|
+
getItem: storage.getItem.bind(storage),
|
|
855
|
+
setItem: storage.setItem.bind(storage),
|
|
856
|
+
removeItem: storage.removeItem.bind(storage)
|
|
857
|
+
};
|
|
858
|
+
} catch (error) {
|
|
859
|
+
console.error('AsyncStorage not available in React Native:', error);
|
|
860
|
+
throw new Error('AsyncStorage is required in React Native environment');
|
|
861
|
+
}
|
|
862
|
+
} else {
|
|
863
|
+
// Use localStorage for web
|
|
864
|
+
return {
|
|
865
|
+
getItem: async key => {
|
|
866
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
867
|
+
return localStorage.getItem(key);
|
|
868
|
+
}
|
|
869
|
+
return null;
|
|
870
|
+
},
|
|
871
|
+
setItem: async (key, value) => {
|
|
872
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
873
|
+
localStorage.setItem(key, value);
|
|
874
|
+
}
|
|
875
|
+
},
|
|
876
|
+
removeItem: async key => {
|
|
877
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
878
|
+
localStorage.removeItem(key);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
791
885
|
/**
|
|
792
886
|
* Update user by ID (admin function)
|
|
793
887
|
*/
|
|
794
888
|
async updateUser(userId, updates) {
|
|
795
889
|
try {
|
|
796
|
-
|
|
797
|
-
|
|
890
|
+
return await this.makeRequest('PUT', `/api/users/${userId}`, updates, {
|
|
891
|
+
cache: false
|
|
892
|
+
});
|
|
798
893
|
} catch (error) {
|
|
799
894
|
throw this.handleError(error);
|
|
800
895
|
}
|
|
@@ -805,8 +900,9 @@ export class OxyServices {
|
|
|
805
900
|
*/
|
|
806
901
|
async followUser(userId) {
|
|
807
902
|
try {
|
|
808
|
-
|
|
809
|
-
|
|
903
|
+
return await this.makeRequest('POST', `/api/users/${userId}/follow`, undefined, {
|
|
904
|
+
cache: false
|
|
905
|
+
});
|
|
810
906
|
} catch (error) {
|
|
811
907
|
throw this.handleError(error);
|
|
812
908
|
}
|
|
@@ -817,8 +913,9 @@ export class OxyServices {
|
|
|
817
913
|
*/
|
|
818
914
|
async unfollowUser(userId) {
|
|
819
915
|
try {
|
|
820
|
-
|
|
821
|
-
|
|
916
|
+
return await this.makeRequest('DELETE', `/api/users/${userId}/follow`, undefined, {
|
|
917
|
+
cache: false
|
|
918
|
+
});
|
|
822
919
|
} catch (error) {
|
|
823
920
|
throw this.handleError(error);
|
|
824
921
|
}
|
|
@@ -829,8 +926,10 @@ export class OxyServices {
|
|
|
829
926
|
*/
|
|
830
927
|
async getFollowStatus(userId) {
|
|
831
928
|
try {
|
|
832
|
-
|
|
833
|
-
|
|
929
|
+
return await this.makeRequest('GET', `/api/users/${userId}/follow-status`, undefined, {
|
|
930
|
+
cache: true,
|
|
931
|
+
cacheTTL: 1 * 60 * 1000 // 1 minute cache
|
|
932
|
+
});
|
|
834
933
|
} catch (error) {
|
|
835
934
|
throw this.handleError(error);
|
|
836
935
|
}
|
|
@@ -842,8 +941,15 @@ export class OxyServices {
|
|
|
842
941
|
async getUserFollowers(userId, pagination) {
|
|
843
942
|
try {
|
|
844
943
|
const params = buildPaginationParams(pagination || {});
|
|
845
|
-
const
|
|
846
|
-
|
|
944
|
+
const response = await this.makeRequest('GET', `/api/users/${userId}/followers`, params, {
|
|
945
|
+
cache: true,
|
|
946
|
+
cacheTTL: 2 * 60 * 1000 // 2 minutes cache
|
|
947
|
+
});
|
|
948
|
+
return {
|
|
949
|
+
followers: response.data || [],
|
|
950
|
+
total: response.pagination.total,
|
|
951
|
+
hasMore: response.pagination.hasMore
|
|
952
|
+
};
|
|
847
953
|
} catch (error) {
|
|
848
954
|
throw this.handleError(error);
|
|
849
955
|
}
|
|
@@ -855,8 +961,15 @@ export class OxyServices {
|
|
|
855
961
|
async getUserFollowing(userId, pagination) {
|
|
856
962
|
try {
|
|
857
963
|
const params = buildPaginationParams(pagination || {});
|
|
858
|
-
const
|
|
859
|
-
|
|
964
|
+
const response = await this.makeRequest('GET', `/api/users/${userId}/following`, params, {
|
|
965
|
+
cache: true,
|
|
966
|
+
cacheTTL: 2 * 60 * 1000 // 2 minutes cache
|
|
967
|
+
});
|
|
968
|
+
return {
|
|
969
|
+
following: response.data || [],
|
|
970
|
+
total: response.pagination.total,
|
|
971
|
+
hasMore: response.pagination.hasMore
|
|
972
|
+
};
|
|
860
973
|
} catch (error) {
|
|
861
974
|
throw this.handleError(error);
|
|
862
975
|
}
|
|
@@ -867,8 +980,9 @@ export class OxyServices {
|
|
|
867
980
|
*/
|
|
868
981
|
async getNotifications() {
|
|
869
982
|
return this.withAuthRetry(async () => {
|
|
870
|
-
|
|
871
|
-
|
|
983
|
+
return await this.makeRequest('GET', '/api/notifications', undefined, {
|
|
984
|
+
cache: false // Don't cache notifications - always get fresh data
|
|
985
|
+
});
|
|
872
986
|
}, 'getNotifications');
|
|
873
987
|
}
|
|
874
988
|
|
|
@@ -877,8 +991,10 @@ export class OxyServices {
|
|
|
877
991
|
*/
|
|
878
992
|
async getUnreadCount() {
|
|
879
993
|
try {
|
|
880
|
-
const res = await this.
|
|
881
|
-
|
|
994
|
+
const res = await this.makeRequest('GET', '/api/notifications/unread-count', undefined, {
|
|
995
|
+
cache: false // Don't cache unread count - always get fresh data
|
|
996
|
+
});
|
|
997
|
+
return res.count;
|
|
882
998
|
} catch (error) {
|
|
883
999
|
throw this.handleError(error);
|
|
884
1000
|
}
|
|
@@ -889,8 +1005,9 @@ export class OxyServices {
|
|
|
889
1005
|
*/
|
|
890
1006
|
async createNotification(data) {
|
|
891
1007
|
try {
|
|
892
|
-
|
|
893
|
-
|
|
1008
|
+
return await this.makeRequest('POST', '/api/notifications', data, {
|
|
1009
|
+
cache: false
|
|
1010
|
+
});
|
|
894
1011
|
} catch (error) {
|
|
895
1012
|
throw this.handleError(error);
|
|
896
1013
|
}
|
|
@@ -901,7 +1018,9 @@ export class OxyServices {
|
|
|
901
1018
|
*/
|
|
902
1019
|
async markNotificationAsRead(notificationId) {
|
|
903
1020
|
try {
|
|
904
|
-
await this.
|
|
1021
|
+
await this.makeRequest('PUT', `/api/notifications/${notificationId}/read`, undefined, {
|
|
1022
|
+
cache: false
|
|
1023
|
+
});
|
|
905
1024
|
} catch (error) {
|
|
906
1025
|
throw this.handleError(error);
|
|
907
1026
|
}
|
|
@@ -912,7 +1031,9 @@ export class OxyServices {
|
|
|
912
1031
|
*/
|
|
913
1032
|
async markAllNotificationsAsRead() {
|
|
914
1033
|
try {
|
|
915
|
-
await this.
|
|
1034
|
+
await this.makeRequest('PUT', '/api/notifications/read-all', undefined, {
|
|
1035
|
+
cache: false
|
|
1036
|
+
});
|
|
916
1037
|
} catch (error) {
|
|
917
1038
|
throw this.handleError(error);
|
|
918
1039
|
}
|
|
@@ -923,7 +1044,9 @@ export class OxyServices {
|
|
|
923
1044
|
*/
|
|
924
1045
|
async deleteNotification(notificationId) {
|
|
925
1046
|
try {
|
|
926
|
-
await this.
|
|
1047
|
+
await this.makeRequest('DELETE', `/api/notifications/${notificationId}`, undefined, {
|
|
1048
|
+
cache: false
|
|
1049
|
+
});
|
|
927
1050
|
} catch (error) {
|
|
928
1051
|
throw this.handleError(error);
|
|
929
1052
|
}
|
|
@@ -938,8 +1061,9 @@ export class OxyServices {
|
|
|
938
1061
|
*/
|
|
939
1062
|
async createPayment(data) {
|
|
940
1063
|
try {
|
|
941
|
-
|
|
942
|
-
|
|
1064
|
+
return await this.makeRequest('POST', '/api/payments', data, {
|
|
1065
|
+
cache: false
|
|
1066
|
+
});
|
|
943
1067
|
} catch (error) {
|
|
944
1068
|
throw this.handleError(error);
|
|
945
1069
|
}
|
|
@@ -950,8 +1074,10 @@ export class OxyServices {
|
|
|
950
1074
|
*/
|
|
951
1075
|
async getPayment(paymentId) {
|
|
952
1076
|
try {
|
|
953
|
-
|
|
954
|
-
|
|
1077
|
+
return await this.makeRequest('GET', `/api/payments/${paymentId}`, undefined, {
|
|
1078
|
+
cache: true,
|
|
1079
|
+
cacheTTL: 5 * 60 * 1000 // 5 minutes cache
|
|
1080
|
+
});
|
|
955
1081
|
} catch (error) {
|
|
956
1082
|
throw this.handleError(error);
|
|
957
1083
|
}
|
|
@@ -962,8 +1088,9 @@ export class OxyServices {
|
|
|
962
1088
|
*/
|
|
963
1089
|
async getUserPayments() {
|
|
964
1090
|
try {
|
|
965
|
-
|
|
966
|
-
|
|
1091
|
+
return await this.makeRequest('GET', '/api/payments/user', undefined, {
|
|
1092
|
+
cache: false // Don't cache user payments - always get fresh data
|
|
1093
|
+
});
|
|
967
1094
|
} catch (error) {
|
|
968
1095
|
throw this.handleError(error);
|
|
969
1096
|
}
|
|
@@ -978,8 +1105,10 @@ export class OxyServices {
|
|
|
978
1105
|
*/
|
|
979
1106
|
async getUserKarma(userId) {
|
|
980
1107
|
try {
|
|
981
|
-
|
|
982
|
-
|
|
1108
|
+
return await this.makeRequest('GET', `/api/karma/${userId}`, undefined, {
|
|
1109
|
+
cache: true,
|
|
1110
|
+
cacheTTL: 2 * 60 * 1000 // 2 minutes cache
|
|
1111
|
+
});
|
|
983
1112
|
} catch (error) {
|
|
984
1113
|
throw this.handleError(error);
|
|
985
1114
|
}
|
|
@@ -990,11 +1119,12 @@ export class OxyServices {
|
|
|
990
1119
|
*/
|
|
991
1120
|
async giveKarma(userId, amount, reason) {
|
|
992
1121
|
try {
|
|
993
|
-
|
|
1122
|
+
return await this.makeRequest('POST', `/api/karma/${userId}/give`, {
|
|
994
1123
|
amount,
|
|
995
1124
|
reason
|
|
1125
|
+
}, {
|
|
1126
|
+
cache: false
|
|
996
1127
|
});
|
|
997
|
-
return res.data;
|
|
998
1128
|
} catch (error) {
|
|
999
1129
|
throw this.handleError(error);
|
|
1000
1130
|
}
|
|
@@ -1005,8 +1135,10 @@ export class OxyServices {
|
|
|
1005
1135
|
*/
|
|
1006
1136
|
async getUserKarmaTotal(userId) {
|
|
1007
1137
|
try {
|
|
1008
|
-
|
|
1009
|
-
|
|
1138
|
+
return await this.makeRequest('GET', `/api/karma/${userId}/total`, undefined, {
|
|
1139
|
+
cache: true,
|
|
1140
|
+
cacheTTL: 2 * 60 * 1000 // 2 minutes cache
|
|
1141
|
+
});
|
|
1010
1142
|
} catch (error) {
|
|
1011
1143
|
throw this.handleError(error);
|
|
1012
1144
|
}
|
|
@@ -1017,11 +1149,13 @@ export class OxyServices {
|
|
|
1017
1149
|
*/
|
|
1018
1150
|
async getUserKarmaHistory(userId, limit, offset) {
|
|
1019
1151
|
try {
|
|
1020
|
-
const params =
|
|
1021
|
-
if (limit) params.
|
|
1022
|
-
if (offset) params.
|
|
1023
|
-
|
|
1024
|
-
|
|
1152
|
+
const params = {};
|
|
1153
|
+
if (limit) params.limit = limit;
|
|
1154
|
+
if (offset) params.offset = offset;
|
|
1155
|
+
return await this.makeRequest('GET', `/api/karma/${userId}/history`, params, {
|
|
1156
|
+
cache: true,
|
|
1157
|
+
cacheTTL: 2 * 60 * 1000 // 2 minutes cache
|
|
1158
|
+
});
|
|
1025
1159
|
} catch (error) {
|
|
1026
1160
|
throw this.handleError(error);
|
|
1027
1161
|
}
|
|
@@ -1032,8 +1166,10 @@ export class OxyServices {
|
|
|
1032
1166
|
*/
|
|
1033
1167
|
async getKarmaLeaderboard() {
|
|
1034
1168
|
try {
|
|
1035
|
-
|
|
1036
|
-
|
|
1169
|
+
return await this.makeRequest('GET', '/api/karma/leaderboard', undefined, {
|
|
1170
|
+
cache: true,
|
|
1171
|
+
cacheTTL: 5 * 60 * 1000 // 5 minutes cache
|
|
1172
|
+
});
|
|
1037
1173
|
} catch (error) {
|
|
1038
1174
|
throw this.handleError(error);
|
|
1039
1175
|
}
|
|
@@ -1044,8 +1180,10 @@ export class OxyServices {
|
|
|
1044
1180
|
*/
|
|
1045
1181
|
async getKarmaRules() {
|
|
1046
1182
|
try {
|
|
1047
|
-
|
|
1048
|
-
|
|
1183
|
+
return await this.makeRequest('GET', '/api/karma/rules', undefined, {
|
|
1184
|
+
cache: true,
|
|
1185
|
+
cacheTTL: 30 * 60 * 1000 // 30 minutes cache (rules don't change often)
|
|
1186
|
+
});
|
|
1049
1187
|
} catch (error) {
|
|
1050
1188
|
throw this.handleError(error);
|
|
1051
1189
|
}
|
|
@@ -1061,8 +1199,9 @@ export class OxyServices {
|
|
|
1061
1199
|
async deleteFile(fileId) {
|
|
1062
1200
|
try {
|
|
1063
1201
|
// Central Asset Service delete with force=true behavior controlled by caller via assetDelete
|
|
1064
|
-
|
|
1065
|
-
|
|
1202
|
+
return await this.makeRequest('DELETE', `/api/assets/${encodeURIComponent(fileId)}`, undefined, {
|
|
1203
|
+
cache: false
|
|
1204
|
+
});
|
|
1066
1205
|
} catch (error) {
|
|
1067
1206
|
throw this.handleError(error);
|
|
1068
1207
|
}
|
|
@@ -1077,7 +1216,7 @@ export class OxyServices {
|
|
|
1077
1216
|
if (variant) params.set('variant', variant);
|
|
1078
1217
|
if (expiresIn) params.set('expiresIn', String(expiresIn));
|
|
1079
1218
|
params.set('fallback', 'placeholderVisible');
|
|
1080
|
-
const token = this.
|
|
1219
|
+
const token = this.httpClient.getAccessToken();
|
|
1081
1220
|
if (token) params.set('token', token);
|
|
1082
1221
|
|
|
1083
1222
|
// Use params.toString() to detect whether there are query params.
|
|
@@ -1103,12 +1242,12 @@ export class OxyServices {
|
|
|
1103
1242
|
*/
|
|
1104
1243
|
async listUserFiles(limit, offset) {
|
|
1105
1244
|
try {
|
|
1106
|
-
const
|
|
1107
|
-
if (limit)
|
|
1108
|
-
if (offset)
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1245
|
+
const paramsObj = {};
|
|
1246
|
+
if (limit) paramsObj.limit = limit;
|
|
1247
|
+
if (offset) paramsObj.offset = offset;
|
|
1248
|
+
return await this.makeRequest('GET', '/api/assets', paramsObj, {
|
|
1249
|
+
cache: false // Don't cache file lists - always get fresh data
|
|
1250
|
+
});
|
|
1112
1251
|
} catch (error) {
|
|
1113
1252
|
throw this.handleError(error);
|
|
1114
1253
|
}
|
|
@@ -1121,8 +1260,14 @@ export class OxyServices {
|
|
|
1121
1260
|
*/
|
|
1122
1261
|
async getFileContentAsText(fileId, variant) {
|
|
1123
1262
|
try {
|
|
1124
|
-
const
|
|
1125
|
-
|
|
1263
|
+
const params = variant ? {
|
|
1264
|
+
variant
|
|
1265
|
+
} : undefined;
|
|
1266
|
+
const urlRes = await this.makeRequest('GET', `/api/assets/${encodeURIComponent(fileId)}/url`, params, {
|
|
1267
|
+
cache: true,
|
|
1268
|
+
cacheTTL: 10 * 60 * 1000 // 10 minutes cache for URLs
|
|
1269
|
+
});
|
|
1270
|
+
const downloadUrl = urlRes?.url;
|
|
1126
1271
|
const response = await fetch(downloadUrl);
|
|
1127
1272
|
return await response.text();
|
|
1128
1273
|
} catch (error) {
|
|
@@ -1135,8 +1280,14 @@ export class OxyServices {
|
|
|
1135
1280
|
*/
|
|
1136
1281
|
async getFileContentAsBlob(fileId, variant) {
|
|
1137
1282
|
try {
|
|
1138
|
-
const
|
|
1139
|
-
|
|
1283
|
+
const params = variant ? {
|
|
1284
|
+
variant
|
|
1285
|
+
} : undefined;
|
|
1286
|
+
const urlRes = await this.makeRequest('GET', `/api/assets/${encodeURIComponent(fileId)}/url`, params, {
|
|
1287
|
+
cache: true,
|
|
1288
|
+
cacheTTL: 10 * 60 * 1000 // 10 minutes cache for URLs
|
|
1289
|
+
});
|
|
1290
|
+
const downloadUrl = urlRes?.url;
|
|
1140
1291
|
const response = await fetch(downloadUrl);
|
|
1141
1292
|
return await response.blob();
|
|
1142
1293
|
} catch (error) {
|
|
@@ -1171,12 +1322,13 @@ export class OxyServices {
|
|
|
1171
1322
|
*/
|
|
1172
1323
|
async assetInit(sha256, size, mime) {
|
|
1173
1324
|
try {
|
|
1174
|
-
|
|
1325
|
+
return await this.makeRequest('POST', '/api/assets/init', {
|
|
1175
1326
|
sha256,
|
|
1176
1327
|
size,
|
|
1177
1328
|
mime
|
|
1329
|
+
}, {
|
|
1330
|
+
cache: false
|
|
1178
1331
|
});
|
|
1179
|
-
return res.data;
|
|
1180
1332
|
} catch (error) {
|
|
1181
1333
|
throw this.handleError(error);
|
|
1182
1334
|
}
|
|
@@ -1187,15 +1339,16 @@ export class OxyServices {
|
|
|
1187
1339
|
*/
|
|
1188
1340
|
async assetComplete(fileId, originalName, size, mime, visibility, metadata) {
|
|
1189
1341
|
try {
|
|
1190
|
-
|
|
1342
|
+
return await this.makeRequest('POST', '/api/assets/complete', {
|
|
1191
1343
|
fileId,
|
|
1192
1344
|
originalName,
|
|
1193
1345
|
size,
|
|
1194
1346
|
mime,
|
|
1195
1347
|
visibility,
|
|
1196
1348
|
metadata
|
|
1349
|
+
}, {
|
|
1350
|
+
cache: false
|
|
1197
1351
|
});
|
|
1198
|
-
return res.data;
|
|
1199
1352
|
} catch (error) {
|
|
1200
1353
|
throw this.handleError(error);
|
|
1201
1354
|
}
|
|
@@ -1219,10 +1372,11 @@ export class OxyServices {
|
|
|
1219
1372
|
// Fallback: direct upload via API to avoid CORS issues
|
|
1220
1373
|
const fd = new FormData();
|
|
1221
1374
|
fd.append('file', file);
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
}
|
|
1375
|
+
// Use httpClient directly for FormData uploads (bypasses RequestManager for special handling)
|
|
1376
|
+
await this.httpClient.request({
|
|
1377
|
+
method: 'POST',
|
|
1378
|
+
url: `/api/assets/${encodeURIComponent(initResponse.fileId)}/upload-direct`,
|
|
1379
|
+
data: fd
|
|
1226
1380
|
});
|
|
1227
1381
|
}
|
|
1228
1382
|
|
|
@@ -1273,8 +1427,9 @@ export class OxyServices {
|
|
|
1273
1427
|
};
|
|
1274
1428
|
if (visibility) body.visibility = visibility;
|
|
1275
1429
|
if (webhookUrl) body.webhookUrl = webhookUrl;
|
|
1276
|
-
|
|
1277
|
-
|
|
1430
|
+
return await this.makeRequest('POST', `/api/assets/${fileId}/links`, body, {
|
|
1431
|
+
cache: false
|
|
1432
|
+
});
|
|
1278
1433
|
} catch (error) {
|
|
1279
1434
|
throw this.handleError(error);
|
|
1280
1435
|
}
|
|
@@ -1285,14 +1440,13 @@ export class OxyServices {
|
|
|
1285
1440
|
*/
|
|
1286
1441
|
async assetUnlink(fileId, app, entityType, entityId) {
|
|
1287
1442
|
try {
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1443
|
+
return await this.makeRequest('DELETE', `/api/assets/${fileId}/links`, {
|
|
1444
|
+
app,
|
|
1445
|
+
entityType,
|
|
1446
|
+
entityId
|
|
1447
|
+
}, {
|
|
1448
|
+
cache: false
|
|
1294
1449
|
});
|
|
1295
|
-
return res.data;
|
|
1296
1450
|
} catch (error) {
|
|
1297
1451
|
throw this.handleError(error);
|
|
1298
1452
|
}
|
|
@@ -1303,8 +1457,10 @@ export class OxyServices {
|
|
|
1303
1457
|
*/
|
|
1304
1458
|
async assetGet(fileId) {
|
|
1305
1459
|
try {
|
|
1306
|
-
|
|
1307
|
-
|
|
1460
|
+
return await this.makeRequest('GET', `/api/assets/${fileId}`, undefined, {
|
|
1461
|
+
cache: true,
|
|
1462
|
+
cacheTTL: 5 * 60 * 1000 // 5 minutes cache
|
|
1463
|
+
});
|
|
1308
1464
|
} catch (error) {
|
|
1309
1465
|
throw this.handleError(error);
|
|
1310
1466
|
}
|
|
@@ -1315,13 +1471,13 @@ export class OxyServices {
|
|
|
1315
1471
|
*/
|
|
1316
1472
|
async assetGetUrl(fileId, variant, expiresIn) {
|
|
1317
1473
|
try {
|
|
1318
|
-
const params =
|
|
1319
|
-
if (variant) params.
|
|
1320
|
-
if (expiresIn) params.
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1474
|
+
const params = {};
|
|
1475
|
+
if (variant) params.variant = variant;
|
|
1476
|
+
if (expiresIn) params.expiresIn = expiresIn;
|
|
1477
|
+
return await this.makeRequest('GET', `/api/assets/${fileId}/url`, params, {
|
|
1478
|
+
cache: true,
|
|
1479
|
+
cacheTTL: 10 * 60 * 1000 // 10 minutes cache for URLs
|
|
1480
|
+
});
|
|
1325
1481
|
} catch (error) {
|
|
1326
1482
|
throw this.handleError(error);
|
|
1327
1483
|
}
|
|
@@ -1332,8 +1488,9 @@ export class OxyServices {
|
|
|
1332
1488
|
*/
|
|
1333
1489
|
async assetRestore(fileId) {
|
|
1334
1490
|
try {
|
|
1335
|
-
|
|
1336
|
-
|
|
1491
|
+
return await this.makeRequest('POST', `/api/assets/${fileId}/restore`, undefined, {
|
|
1492
|
+
cache: false
|
|
1493
|
+
});
|
|
1337
1494
|
} catch (error) {
|
|
1338
1495
|
throw this.handleError(error);
|
|
1339
1496
|
}
|
|
@@ -1344,9 +1501,12 @@ export class OxyServices {
|
|
|
1344
1501
|
*/
|
|
1345
1502
|
async assetDelete(fileId, force = false) {
|
|
1346
1503
|
try {
|
|
1347
|
-
const params = force ?
|
|
1348
|
-
|
|
1349
|
-
|
|
1504
|
+
const params = force ? {
|
|
1505
|
+
force: 'true'
|
|
1506
|
+
} : undefined;
|
|
1507
|
+
return await this.makeRequest('DELETE', `/api/assets/${fileId}`, params, {
|
|
1508
|
+
cache: false
|
|
1509
|
+
});
|
|
1350
1510
|
} catch (error) {
|
|
1351
1511
|
throw this.handleError(error);
|
|
1352
1512
|
}
|
|
@@ -1372,10 +1532,11 @@ export class OxyServices {
|
|
|
1372
1532
|
*/
|
|
1373
1533
|
async assetUpdateVisibility(fileId, visibility) {
|
|
1374
1534
|
try {
|
|
1375
|
-
|
|
1535
|
+
return await this.makeRequest('PATCH', `/api/assets/${fileId}/visibility`, {
|
|
1376
1536
|
visibility
|
|
1537
|
+
}, {
|
|
1538
|
+
cache: false
|
|
1377
1539
|
});
|
|
1378
|
-
return res.data;
|
|
1379
1540
|
} catch (error) {
|
|
1380
1541
|
throw this.handleError(error);
|
|
1381
1542
|
}
|
|
@@ -1430,8 +1591,11 @@ export class OxyServices {
|
|
|
1430
1591
|
*/
|
|
1431
1592
|
async getDeveloperApps() {
|
|
1432
1593
|
try {
|
|
1433
|
-
const res = await this.
|
|
1434
|
-
|
|
1594
|
+
const res = await this.makeRequest('GET', '/api/developer/apps', undefined, {
|
|
1595
|
+
cache: true,
|
|
1596
|
+
cacheTTL: 2 * 60 * 1000 // 2 minutes cache
|
|
1597
|
+
});
|
|
1598
|
+
return res.apps || [];
|
|
1435
1599
|
} catch (error) {
|
|
1436
1600
|
throw this.handleError(error);
|
|
1437
1601
|
}
|
|
@@ -1442,8 +1606,10 @@ export class OxyServices {
|
|
|
1442
1606
|
*/
|
|
1443
1607
|
async createDeveloperApp(data) {
|
|
1444
1608
|
try {
|
|
1445
|
-
const res = await this.
|
|
1446
|
-
|
|
1609
|
+
const res = await this.makeRequest('POST', '/api/developer/apps', data, {
|
|
1610
|
+
cache: false
|
|
1611
|
+
});
|
|
1612
|
+
return res.app;
|
|
1447
1613
|
} catch (error) {
|
|
1448
1614
|
throw this.handleError(error);
|
|
1449
1615
|
}
|
|
@@ -1454,8 +1620,11 @@ export class OxyServices {
|
|
|
1454
1620
|
*/
|
|
1455
1621
|
async getDeveloperApp(appId) {
|
|
1456
1622
|
try {
|
|
1457
|
-
const res = await this.
|
|
1458
|
-
|
|
1623
|
+
const res = await this.makeRequest('GET', `/api/developer/apps/${appId}`, undefined, {
|
|
1624
|
+
cache: true,
|
|
1625
|
+
cacheTTL: 5 * 60 * 1000 // 5 minutes cache
|
|
1626
|
+
});
|
|
1627
|
+
return res.app;
|
|
1459
1628
|
} catch (error) {
|
|
1460
1629
|
throw this.handleError(error);
|
|
1461
1630
|
}
|
|
@@ -1466,8 +1635,10 @@ export class OxyServices {
|
|
|
1466
1635
|
*/
|
|
1467
1636
|
async updateDeveloperApp(appId, data) {
|
|
1468
1637
|
try {
|
|
1469
|
-
const res = await this.
|
|
1470
|
-
|
|
1638
|
+
const res = await this.makeRequest('PATCH', `/api/developer/apps/${appId}`, data, {
|
|
1639
|
+
cache: false
|
|
1640
|
+
});
|
|
1641
|
+
return res.app;
|
|
1471
1642
|
} catch (error) {
|
|
1472
1643
|
throw this.handleError(error);
|
|
1473
1644
|
}
|
|
@@ -1478,8 +1649,9 @@ export class OxyServices {
|
|
|
1478
1649
|
*/
|
|
1479
1650
|
async regenerateDeveloperAppSecret(appId) {
|
|
1480
1651
|
try {
|
|
1481
|
-
|
|
1482
|
-
|
|
1652
|
+
return await this.makeRequest('POST', `/api/developer/apps/${appId}/regenerate-secret`, undefined, {
|
|
1653
|
+
cache: false
|
|
1654
|
+
});
|
|
1483
1655
|
} catch (error) {
|
|
1484
1656
|
throw this.handleError(error);
|
|
1485
1657
|
}
|
|
@@ -1490,8 +1662,9 @@ export class OxyServices {
|
|
|
1490
1662
|
*/
|
|
1491
1663
|
async deleteDeveloperApp(appId) {
|
|
1492
1664
|
try {
|
|
1493
|
-
|
|
1494
|
-
|
|
1665
|
+
return await this.makeRequest('DELETE', `/api/developer/apps/${appId}`, undefined, {
|
|
1666
|
+
cache: false
|
|
1667
|
+
});
|
|
1495
1668
|
} catch (error) {
|
|
1496
1669
|
throw this.handleError(error);
|
|
1497
1670
|
}
|
|
@@ -1506,11 +1679,12 @@ export class OxyServices {
|
|
|
1506
1679
|
*/
|
|
1507
1680
|
async updateLocation(latitude, longitude) {
|
|
1508
1681
|
try {
|
|
1509
|
-
|
|
1682
|
+
return await this.makeRequest('POST', '/api/location', {
|
|
1510
1683
|
latitude,
|
|
1511
1684
|
longitude
|
|
1685
|
+
}, {
|
|
1686
|
+
cache: false
|
|
1512
1687
|
});
|
|
1513
|
-
return res.data;
|
|
1514
1688
|
} catch (error) {
|
|
1515
1689
|
throw this.handleError(error);
|
|
1516
1690
|
}
|
|
@@ -1521,9 +1695,12 @@ export class OxyServices {
|
|
|
1521
1695
|
*/
|
|
1522
1696
|
async getNearbyUsers(radius) {
|
|
1523
1697
|
try {
|
|
1524
|
-
const params = radius ?
|
|
1525
|
-
|
|
1526
|
-
|
|
1698
|
+
const params = radius ? {
|
|
1699
|
+
radius
|
|
1700
|
+
} : undefined;
|
|
1701
|
+
return await this.makeRequest('GET', '/api/location/nearby', params, {
|
|
1702
|
+
cache: false // Don't cache location data - always get fresh data
|
|
1703
|
+
});
|
|
1527
1704
|
} catch (error) {
|
|
1528
1705
|
throw this.handleError(error);
|
|
1529
1706
|
}
|
|
@@ -1538,10 +1715,13 @@ export class OxyServices {
|
|
|
1538
1715
|
*/
|
|
1539
1716
|
async trackEvent(eventName, properties) {
|
|
1540
1717
|
try {
|
|
1541
|
-
await this.
|
|
1718
|
+
await this.makeRequest('POST', '/api/analytics/events', {
|
|
1542
1719
|
event: eventName,
|
|
1543
1720
|
properties
|
|
1544
|
-
}
|
|
1721
|
+
}, {
|
|
1722
|
+
cache: false,
|
|
1723
|
+
retry: false
|
|
1724
|
+
}); // Don't retry analytics events
|
|
1545
1725
|
} catch (error) {
|
|
1546
1726
|
throw this.handleError(error);
|
|
1547
1727
|
}
|
|
@@ -1552,11 +1732,13 @@ export class OxyServices {
|
|
|
1552
1732
|
*/
|
|
1553
1733
|
async getAnalytics(startDate, endDate) {
|
|
1554
1734
|
try {
|
|
1555
|
-
const params =
|
|
1556
|
-
if (startDate) params.
|
|
1557
|
-
if (endDate) params.
|
|
1558
|
-
|
|
1559
|
-
|
|
1735
|
+
const params = {};
|
|
1736
|
+
if (startDate) params.startDate = startDate;
|
|
1737
|
+
if (endDate) params.endDate = endDate;
|
|
1738
|
+
return await this.makeRequest('GET', '/api/analytics', params, {
|
|
1739
|
+
cache: true,
|
|
1740
|
+
cacheTTL: 5 * 60 * 1000 // 5 minutes cache
|
|
1741
|
+
});
|
|
1560
1742
|
} catch (error) {
|
|
1561
1743
|
throw this.handleError(error);
|
|
1562
1744
|
}
|
|
@@ -1571,8 +1753,9 @@ export class OxyServices {
|
|
|
1571
1753
|
*/
|
|
1572
1754
|
async registerDevice(deviceData) {
|
|
1573
1755
|
try {
|
|
1574
|
-
|
|
1575
|
-
|
|
1756
|
+
return await this.makeRequest('POST', '/api/devices', deviceData, {
|
|
1757
|
+
cache: false
|
|
1758
|
+
});
|
|
1576
1759
|
} catch (error) {
|
|
1577
1760
|
throw this.handleError(error);
|
|
1578
1761
|
}
|
|
@@ -1583,8 +1766,9 @@ export class OxyServices {
|
|
|
1583
1766
|
*/
|
|
1584
1767
|
async getUserDevices() {
|
|
1585
1768
|
try {
|
|
1586
|
-
|
|
1587
|
-
|
|
1769
|
+
return await this.makeRequest('GET', '/api/devices', undefined, {
|
|
1770
|
+
cache: false // Don't cache device list - always get fresh data
|
|
1771
|
+
});
|
|
1588
1772
|
} catch (error) {
|
|
1589
1773
|
throw this.handleError(error);
|
|
1590
1774
|
}
|
|
@@ -1595,7 +1779,9 @@ export class OxyServices {
|
|
|
1595
1779
|
*/
|
|
1596
1780
|
async removeDevice(deviceId) {
|
|
1597
1781
|
try {
|
|
1598
|
-
await this.
|
|
1782
|
+
await this.makeRequest('DELETE', `/api/devices/${deviceId}`, undefined, {
|
|
1783
|
+
cache: false
|
|
1784
|
+
});
|
|
1599
1785
|
} catch (error) {
|
|
1600
1786
|
throw this.handleError(error);
|
|
1601
1787
|
}
|
|
@@ -1603,11 +1789,17 @@ export class OxyServices {
|
|
|
1603
1789
|
|
|
1604
1790
|
/**
|
|
1605
1791
|
* Get device sessions
|
|
1792
|
+
* Note: Not cached by default to ensure fresh data, but can be cached via makeRequest if needed
|
|
1606
1793
|
*/
|
|
1607
1794
|
async getDeviceSessions(sessionId) {
|
|
1608
1795
|
try {
|
|
1609
|
-
|
|
1610
|
-
|
|
1796
|
+
// Use makeRequest for consistent error handling and optional caching
|
|
1797
|
+
// Cache disabled by default to ensure fresh session data
|
|
1798
|
+
return await this.makeRequest('GET', `/api/session/device/sessions/${sessionId}`, undefined, {
|
|
1799
|
+
cache: false,
|
|
1800
|
+
// Don't cache sessions - always get fresh data
|
|
1801
|
+
deduplicate: true // Deduplicate concurrent requests for same sessionId
|
|
1802
|
+
});
|
|
1611
1803
|
} catch (error) {
|
|
1612
1804
|
throw this.handleError(error);
|
|
1613
1805
|
}
|
|
@@ -1621,8 +1813,13 @@ export class OxyServices {
|
|
|
1621
1813
|
const params = new URLSearchParams();
|
|
1622
1814
|
if (deviceId) params.append('deviceId', deviceId);
|
|
1623
1815
|
if (excludeCurrent) params.append('excludeCurrent', 'true');
|
|
1624
|
-
const
|
|
1625
|
-
|
|
1816
|
+
const urlParams = {};
|
|
1817
|
+
params.forEach((value, key) => {
|
|
1818
|
+
urlParams[key] = value;
|
|
1819
|
+
});
|
|
1820
|
+
return await this.makeRequest('POST', `/api/session/device/logout-all/${sessionId}`, urlParams, {
|
|
1821
|
+
cache: false
|
|
1822
|
+
});
|
|
1626
1823
|
} catch (error) {
|
|
1627
1824
|
throw this.handleError(error);
|
|
1628
1825
|
}
|
|
@@ -1633,10 +1830,11 @@ export class OxyServices {
|
|
|
1633
1830
|
*/
|
|
1634
1831
|
async updateDeviceName(sessionId, deviceName) {
|
|
1635
1832
|
try {
|
|
1636
|
-
|
|
1833
|
+
return await this.makeRequest('PUT', `/api/session/device/name/${sessionId}`, {
|
|
1637
1834
|
deviceName
|
|
1835
|
+
}, {
|
|
1836
|
+
cache: false
|
|
1638
1837
|
});
|
|
1639
|
-
return res.data;
|
|
1640
1838
|
} catch (error) {
|
|
1641
1839
|
throw this.handleError(error);
|
|
1642
1840
|
}
|
|
@@ -1651,8 +1849,12 @@ export class OxyServices {
|
|
|
1651
1849
|
*/
|
|
1652
1850
|
async fetchLinkMetadata(url) {
|
|
1653
1851
|
try {
|
|
1654
|
-
|
|
1655
|
-
|
|
1852
|
+
return await this.makeRequest('GET', '/api/link-metadata', {
|
|
1853
|
+
url
|
|
1854
|
+
}, {
|
|
1855
|
+
cache: true,
|
|
1856
|
+
cacheTTL: 30 * 60 * 1000 // 30 minutes cache for link metadata
|
|
1857
|
+
});
|
|
1656
1858
|
} catch (error) {
|
|
1657
1859
|
throw this.handleError(error);
|
|
1658
1860
|
}
|