@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.
Files changed (353) hide show
  1. package/README.md +71 -0
  2. package/lib/commonjs/core/HttpClient.js +238 -0
  3. package/lib/commonjs/core/HttpClient.js.map +1 -0
  4. package/lib/commonjs/core/OxyServices.js +530 -332
  5. package/lib/commonjs/core/OxyServices.js.map +1 -1
  6. package/lib/commonjs/core/RequestManager.js +199 -0
  7. package/lib/commonjs/core/RequestManager.js.map +1 -0
  8. package/lib/commonjs/core/index.js +38 -1
  9. package/lib/commonjs/core/index.js.map +1 -1
  10. package/lib/commonjs/i18n/index.js +37 -1
  11. package/lib/commonjs/i18n/index.js.map +1 -1
  12. package/lib/commonjs/i18n/locales/ar-SA.json +128 -0
  13. package/lib/commonjs/i18n/locales/ca-ES.json +128 -0
  14. package/lib/commonjs/i18n/locales/de-DE.json +128 -0
  15. package/lib/commonjs/i18n/locales/en-US.json +85 -12
  16. package/lib/commonjs/i18n/locales/es-ES.json +58 -6
  17. package/lib/commonjs/i18n/locales/fr-FR.json +128 -0
  18. package/lib/commonjs/i18n/locales/it-IT.json +128 -0
  19. package/lib/commonjs/i18n/locales/ja-JP.json +127 -0
  20. package/lib/commonjs/i18n/locales/ko-KR.json +128 -0
  21. package/lib/commonjs/i18n/locales/pt-PT.json +128 -0
  22. package/lib/commonjs/i18n/locales/zh-CN.json +128 -0
  23. package/lib/commonjs/index.js +36 -0
  24. package/lib/commonjs/index.js.map +1 -1
  25. package/lib/commonjs/ui/components/Avatar.js +94 -27
  26. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  27. package/lib/commonjs/ui/components/FollowButton.js +1 -0
  28. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  29. package/lib/commonjs/ui/components/FontLoader.js +22 -42
  30. package/lib/commonjs/ui/components/FontLoader.js.map +1 -1
  31. package/lib/commonjs/ui/components/OxyProvider.js +5 -8
  32. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  33. package/lib/commonjs/ui/components/StepBasedScreen.js +64 -44
  34. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
  35. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +14 -35
  36. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
  37. package/lib/commonjs/ui/components/internal/PinInput.js +2 -2
  38. package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
  39. package/lib/commonjs/ui/components/internal/TextField.js +13 -8
  40. package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
  41. package/lib/commonjs/ui/context/OxyContext.js +443 -371
  42. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  43. package/lib/commonjs/ui/hooks/useSessionSocket.js +80 -22
  44. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  45. package/lib/commonjs/ui/index.js +4 -1
  46. package/lib/commonjs/ui/index.js.map +1 -1
  47. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +32 -2
  48. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +101 -59
  50. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/FileManagementScreen.js +3 -2
  52. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +75 -117
  54. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/SignInScreen.js +43 -50
  56. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/SignUpScreen.js +14 -16
  58. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  59. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +188 -142
  60. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  61. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +10 -10
  62. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  63. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +2 -4
  64. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  65. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +45 -25
  66. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  67. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js +88 -53
  68. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
  69. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +79 -58
  70. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  71. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +61 -52
  72. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  73. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +218 -39
  74. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  75. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js +77 -50
  76. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js.map +1 -1
  77. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +424 -71
  78. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  79. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +55 -30
  80. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  81. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +64 -46
  82. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  83. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +84 -146
  84. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  85. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +113 -34
  86. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  87. package/lib/commonjs/ui/stores/accountStore.js +237 -0
  88. package/lib/commonjs/ui/stores/accountStore.js.map +1 -0
  89. package/lib/commonjs/ui/stores/authStore.js +17 -20
  90. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  91. package/lib/commonjs/ui/styles/authStyles.js +16 -8
  92. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  93. package/lib/commonjs/ui/styles/index.js +11 -0
  94. package/lib/commonjs/ui/styles/index.js.map +1 -1
  95. package/lib/commonjs/ui/styles/spacing.js +51 -0
  96. package/lib/commonjs/ui/styles/spacing.js.map +1 -0
  97. package/lib/commonjs/utils/asyncUtils.js +9 -22
  98. package/lib/commonjs/utils/asyncUtils.js.map +1 -1
  99. package/lib/commonjs/utils/cache.js +259 -0
  100. package/lib/commonjs/utils/cache.js.map +1 -0
  101. package/lib/commonjs/utils/index.js +99 -0
  102. package/lib/commonjs/utils/index.js.map +1 -1
  103. package/lib/commonjs/utils/languageUtils.js +159 -0
  104. package/lib/commonjs/utils/languageUtils.js.map +1 -0
  105. package/lib/commonjs/utils/requestUtils.js +217 -0
  106. package/lib/commonjs/utils/requestUtils.js.map +1 -0
  107. package/lib/commonjs/utils/sessionUtils.js +191 -0
  108. package/lib/commonjs/utils/sessionUtils.js.map +1 -0
  109. package/lib/commonjs/utils/validationUtils.js +1 -1
  110. package/lib/module/core/HttpClient.js +232 -0
  111. package/lib/module/core/HttpClient.js.map +1 -0
  112. package/lib/module/core/OxyServices.js +528 -326
  113. package/lib/module/core/OxyServices.js.map +1 -1
  114. package/lib/module/core/RequestManager.js +194 -0
  115. package/lib/module/core/RequestManager.js.map +1 -0
  116. package/lib/module/core/index.js +2 -0
  117. package/lib/module/core/index.js.map +1 -1
  118. package/lib/module/i18n/index.js +37 -1
  119. package/lib/module/i18n/index.js.map +1 -1
  120. package/lib/module/i18n/locales/ar-SA.json +128 -0
  121. package/lib/module/i18n/locales/ca-ES.json +128 -0
  122. package/lib/module/i18n/locales/de-DE.json +128 -0
  123. package/lib/module/i18n/locales/en-US.json +85 -12
  124. package/lib/module/i18n/locales/es-ES.json +58 -6
  125. package/lib/module/i18n/locales/fr-FR.json +128 -0
  126. package/lib/module/i18n/locales/it-IT.json +128 -0
  127. package/lib/module/i18n/locales/ja-JP.json +127 -0
  128. package/lib/module/i18n/locales/ko-KR.json +128 -0
  129. package/lib/module/i18n/locales/pt-PT.json +128 -0
  130. package/lib/module/i18n/locales/zh-CN.json +128 -0
  131. package/lib/module/index.js +2 -0
  132. package/lib/module/index.js.map +1 -1
  133. package/lib/module/ui/components/Avatar.js +94 -27
  134. package/lib/module/ui/components/Avatar.js.map +1 -1
  135. package/lib/module/ui/components/FollowButton.js +1 -0
  136. package/lib/module/ui/components/FollowButton.js.map +1 -1
  137. package/lib/module/ui/components/FontLoader.js +23 -43
  138. package/lib/module/ui/components/FontLoader.js.map +1 -1
  139. package/lib/module/ui/components/OxyProvider.js +6 -8
  140. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  141. package/lib/module/ui/components/StepBasedScreen.js +65 -45
  142. package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
  143. package/lib/module/ui/components/internal/GroupedPillButtons.js +14 -35
  144. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
  145. package/lib/module/ui/components/internal/PinInput.js +2 -2
  146. package/lib/module/ui/components/internal/PinInput.js.map +1 -1
  147. package/lib/module/ui/components/internal/TextField.js +13 -8
  148. package/lib/module/ui/components/internal/TextField.js.map +1 -1
  149. package/lib/module/ui/context/OxyContext.js +442 -370
  150. package/lib/module/ui/context/OxyContext.js.map +1 -1
  151. package/lib/module/ui/hooks/useSessionSocket.js +80 -22
  152. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  153. package/lib/module/ui/index.js +4 -2
  154. package/lib/module/ui/index.js.map +1 -1
  155. package/lib/module/ui/screens/AccountSettingsScreen.js +33 -2
  156. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  157. package/lib/module/ui/screens/AccountSwitcherScreen.js +102 -60
  158. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  159. package/lib/module/ui/screens/FileManagementScreen.js +3 -2
  160. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  161. package/lib/module/ui/screens/LanguageSelectorScreen.js +73 -117
  162. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  163. package/lib/module/ui/screens/SignInScreen.js +44 -51
  164. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  165. package/lib/module/ui/screens/SignUpScreen.js +14 -16
  166. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  167. package/lib/module/ui/screens/WelcomeNewUserScreen.js +187 -143
  168. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  169. package/lib/module/ui/screens/internal/SignInPasswordStep.js +10 -10
  170. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  171. package/lib/module/ui/screens/internal/SignInUsernameStep.js +2 -4
  172. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  173. package/lib/module/ui/screens/steps/RecoverRequestStep.js +45 -25
  174. package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  175. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js +89 -54
  176. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
  177. package/lib/module/ui/screens/steps/RecoverSuccessStep.js +80 -59
  178. package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  179. package/lib/module/ui/screens/steps/RecoverVerifyStep.js +62 -53
  180. package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  181. package/lib/module/ui/screens/steps/SignInPasswordStep.js +219 -40
  182. package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  183. package/lib/module/ui/screens/steps/SignInTotpStep.js +78 -51
  184. package/lib/module/ui/screens/steps/SignInTotpStep.js.map +1 -1
  185. package/lib/module/ui/screens/steps/SignInUsernameStep.js +426 -73
  186. package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  187. package/lib/module/ui/screens/steps/SignUpIdentityStep.js +55 -30
  188. package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  189. package/lib/module/ui/screens/steps/SignUpSecurityStep.js +65 -47
  190. package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  191. package/lib/module/ui/screens/steps/SignUpSummaryStep.js +84 -146
  192. package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  193. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +114 -35
  194. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  195. package/lib/module/ui/stores/accountStore.js +229 -0
  196. package/lib/module/ui/stores/accountStore.js.map +1 -0
  197. package/lib/module/ui/stores/authStore.js +17 -20
  198. package/lib/module/ui/stores/authStore.js.map +1 -1
  199. package/lib/module/ui/styles/authStyles.js +16 -8
  200. package/lib/module/ui/styles/authStyles.js.map +1 -1
  201. package/lib/module/ui/styles/index.js +1 -0
  202. package/lib/module/ui/styles/index.js.map +1 -1
  203. package/lib/module/ui/styles/spacing.js +48 -0
  204. package/lib/module/ui/styles/spacing.js.map +1 -0
  205. package/lib/module/utils/asyncUtils.js +10 -22
  206. package/lib/module/utils/asyncUtils.js.map +1 -1
  207. package/lib/module/utils/cache.js +250 -0
  208. package/lib/module/utils/cache.js.map +1 -0
  209. package/lib/module/utils/index.js +7 -0
  210. package/lib/module/utils/index.js.map +1 -1
  211. package/lib/module/utils/languageUtils.js +151 -0
  212. package/lib/module/utils/languageUtils.js.map +1 -0
  213. package/lib/module/utils/requestUtils.js +210 -0
  214. package/lib/module/utils/requestUtils.js.map +1 -0
  215. package/lib/module/utils/sessionUtils.js +180 -0
  216. package/lib/module/utils/sessionUtils.js.map +1 -0
  217. package/lib/module/utils/validationUtils.js +1 -1
  218. package/lib/typescript/core/HttpClient.d.ts +64 -0
  219. package/lib/typescript/core/HttpClient.d.ts.map +1 -0
  220. package/lib/typescript/core/OxyServices.d.ts +86 -73
  221. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  222. package/lib/typescript/core/RequestManager.d.ts +67 -0
  223. package/lib/typescript/core/RequestManager.d.ts.map +1 -0
  224. package/lib/typescript/core/index.d.ts +2 -0
  225. package/lib/typescript/core/index.d.ts.map +1 -1
  226. package/lib/typescript/i18n/index.d.ts.map +1 -1
  227. package/lib/typescript/index.d.ts +2 -0
  228. package/lib/typescript/index.d.ts.map +1 -1
  229. package/lib/typescript/models/interfaces.d.ts +15 -0
  230. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  231. package/lib/typescript/models/session.d.ts +1 -0
  232. package/lib/typescript/models/session.d.ts.map +1 -1
  233. package/lib/typescript/ui/components/Avatar.d.ts +6 -7
  234. package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
  235. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  236. package/lib/typescript/ui/components/FontLoader.d.ts +3 -3
  237. package/lib/typescript/ui/components/FontLoader.d.ts.map +1 -1
  238. package/lib/typescript/ui/components/OxyProvider.d.ts +2 -2
  239. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  240. package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -1
  241. package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
  242. package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
  243. package/lib/typescript/ui/context/OxyContext.d.ts +5 -0
  244. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  245. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  246. package/lib/typescript/ui/index.d.ts +2 -2
  247. package/lib/typescript/ui/index.d.ts.map +1 -1
  248. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  249. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  250. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts +3 -3
  251. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  252. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  253. package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
  254. package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  255. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  256. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -1
  257. package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts.map +1 -1
  258. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -1
  259. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -1
  260. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +2 -0
  261. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
  262. package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts.map +1 -1
  263. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
  264. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -1
  265. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -1
  266. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -1
  267. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -1
  268. package/lib/typescript/ui/stores/accountStore.d.ts +34 -0
  269. package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -0
  270. package/lib/typescript/ui/stores/authStore.d.ts +7 -3
  271. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  272. package/lib/typescript/ui/styles/authStyles.d.ts +19 -2
  273. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
  274. package/lib/typescript/ui/styles/index.d.ts +1 -0
  275. package/lib/typescript/ui/styles/index.d.ts.map +1 -1
  276. package/lib/typescript/ui/styles/spacing.d.ts +43 -0
  277. package/lib/typescript/ui/styles/spacing.d.ts.map +1 -0
  278. package/lib/typescript/utils/asyncUtils.d.ts +2 -0
  279. package/lib/typescript/utils/asyncUtils.d.ts.map +1 -1
  280. package/lib/typescript/utils/cache.d.ts +128 -0
  281. package/lib/typescript/utils/cache.d.ts.map +1 -0
  282. package/lib/typescript/utils/index.d.ts +4 -0
  283. package/lib/typescript/utils/index.d.ts.map +1 -1
  284. package/lib/typescript/utils/languageUtils.d.ts +38 -0
  285. package/lib/typescript/utils/languageUtils.d.ts.map +1 -0
  286. package/lib/typescript/utils/requestUtils.d.ts +122 -0
  287. package/lib/typescript/utils/requestUtils.d.ts.map +1 -0
  288. package/lib/typescript/utils/sessionUtils.d.ts +55 -0
  289. package/lib/typescript/utils/sessionUtils.d.ts.map +1 -0
  290. package/lib/typescript/utils/validationUtils.d.ts +1 -1
  291. package/package.json +1 -1
  292. package/src/core/HttpClient.ts +277 -0
  293. package/src/core/OxyServices.ts +461 -352
  294. package/src/core/RequestManager.ts +240 -0
  295. package/src/core/index.ts +10 -0
  296. package/src/i18n/index.ts +36 -0
  297. package/src/i18n/locales/ar-SA.json +128 -0
  298. package/src/i18n/locales/ca-ES.json +128 -0
  299. package/src/i18n/locales/de-DE.json +128 -0
  300. package/src/i18n/locales/en-US.json +85 -12
  301. package/src/i18n/locales/es-ES.json +58 -6
  302. package/src/i18n/locales/fr-FR.json +128 -0
  303. package/src/i18n/locales/it-IT.json +128 -0
  304. package/src/i18n/locales/ja-JP.json +127 -0
  305. package/src/i18n/locales/ko-KR.json +128 -0
  306. package/src/i18n/locales/pt-PT.json +128 -0
  307. package/src/i18n/locales/zh-CN.json +128 -0
  308. package/src/index.ts +10 -0
  309. package/src/models/interfaces.ts +19 -0
  310. package/src/models/session.ts +1 -1
  311. package/src/ui/components/Avatar.tsx +151 -35
  312. package/src/ui/components/FollowButton.tsx +1 -0
  313. package/src/ui/components/FontLoader.tsx +17 -37
  314. package/src/ui/components/OxyProvider.tsx +14 -13
  315. package/src/ui/components/StepBasedScreen.tsx +66 -43
  316. package/src/ui/components/internal/GroupedPillButtons.tsx +15 -31
  317. package/src/ui/components/internal/PinInput.tsx +2 -2
  318. package/src/ui/components/internal/TextField.tsx +7 -6
  319. package/src/ui/context/OxyContext.tsx +441 -326
  320. package/src/ui/hooks/useSessionSocket.ts +72 -18
  321. package/src/ui/index.ts +4 -1
  322. package/src/ui/screens/AccountSettingsScreen.tsx +34 -2
  323. package/src/ui/screens/AccountSwitcherScreen.tsx +102 -68
  324. package/src/ui/screens/FileManagementScreen.tsx +16 -16
  325. package/src/ui/screens/LanguageSelectorScreen.tsx +86 -143
  326. package/src/ui/screens/SignInScreen.tsx +59 -43
  327. package/src/ui/screens/SignUpScreen.tsx +14 -15
  328. package/src/ui/screens/WelcomeNewUserScreen.tsx +153 -105
  329. package/src/ui/screens/internal/SignInPasswordStep.tsx +4 -6
  330. package/src/ui/screens/internal/SignInUsernameStep.tsx +1 -1
  331. package/src/ui/screens/steps/RecoverRequestStep.tsx +34 -24
  332. package/src/ui/screens/steps/RecoverResetPasswordStep.tsx +65 -36
  333. package/src/ui/screens/steps/RecoverSuccessStep.tsx +71 -47
  334. package/src/ui/screens/steps/RecoverVerifyStep.tsx +60 -50
  335. package/src/ui/screens/steps/SignInPasswordStep.tsx +190 -32
  336. package/src/ui/screens/steps/SignInTotpStep.tsx +68 -34
  337. package/src/ui/screens/steps/SignInUsernameStep.tsx +446 -63
  338. package/src/ui/screens/steps/SignUpIdentityStep.tsx +49 -35
  339. package/src/ui/screens/steps/SignUpSecurityStep.tsx +56 -39
  340. package/src/ui/screens/steps/SignUpSummaryStep.tsx +99 -89
  341. package/src/ui/screens/steps/SignUpWelcomeStep.tsx +88 -20
  342. package/src/ui/stores/accountStore.ts +285 -0
  343. package/src/ui/stores/authStore.ts +16 -19
  344. package/src/ui/styles/authStyles.ts +16 -8
  345. package/src/ui/styles/index.ts +1 -0
  346. package/src/ui/styles/spacing.ts +46 -0
  347. package/src/utils/asyncUtils.ts +10 -24
  348. package/src/utils/cache.ts +264 -0
  349. package/src/utils/index.ts +19 -0
  350. package/src/utils/languageUtils.ts +174 -0
  351. package/src/utils/requestUtils.ts +234 -0
  352. package/src/utils/sessionUtils.ts +206 -0
  353. 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
- * No need to manage multiple service instances - everything is available directly.
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.client = axios.create({
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
- this.tokenStore = TokenStore.getInstance();
143
- this.setupInterceptors();
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
- try {
149
- TokenStore.getInstance().clearTokens();
150
- } catch {}
121
+ HttpClient.__resetTokensForTests();
151
122
  }
152
123
 
153
124
  /**
154
- * Setup axios interceptors for authentication and error handling
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
- setupInterceptors() {
157
- // Request interceptor for adding auth header and handling token refresh
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.client.defaults.baseURL || '';
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.tokenStore.setTokens(accessToken, refreshToken);
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.tokenStore.clearTokens();
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.tokenStore.getAccessToken();
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.tokenStore.hasAccessToken();
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.tokenStore.hasAccessToken();
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.tokenStore.getAccessToken();
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.tokenStore.hasAccessToken()) {
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.tokenStore.hasAccessToken()) {
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.client.get('/api/auth/validate');
375
- return res.data.valid === true;
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
- const res = await this.client.get('/health');
406
- return res.data;
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.client.post('/api/auth/signup', {
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 || !res.data || typeof res.data === 'object' && Object.keys(res.data).length === 0) {
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.data;
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
- const res = await this.client.post('/api/auth/recover/request', {
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
- const res = await this.client.post('/api/auth/recover/verify', {
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
- const res = await this.client.post('/api/auth/recover/reset', {
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
- const res = await this.client.post('/api/auth/recover/totp/reset', {
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
- const res = await this.client.post('/api/auth/recover/backup/reset', {
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
- const res = await this.client.post('/api/auth/recover/recovery-key/reset', {
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
- const res = await this.client.post('/api/auth/login', {
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
- const res = await this.client.post('/api/auth/totp/verify-login', {
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
- const res = await this.client.get(`/api/session/user/${sessionId}`);
558
- return res.data;
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
- console.log('🔑 getTokenBySession - Fetching token for session:', sessionId);
570
- const res = await this.client.get(`/api/session/token/${sessionId}`);
571
- const {
572
- accessToken
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
- console.log('🔑 getTokenBySession - Token set in store');
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
- const res = await this.client.get(`/api/session/sessions/${sessionId}`);
592
- return res.data;
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.client.post(url);
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.client.post(`/api/session/logout-all/${sessionId}`);
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}?${params.toString()}`;
634
- const res = await this.client.get(url);
635
- return res.data;
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
- const res = await this.client.get(`/api/auth/check-username/${username}`);
647
- return res.data;
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
- const res = await this.client.get(`/api/auth/check-email/${email}`);
659
- return res.data;
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
- const res = await this.client.get(`/api/profiles/username/${username}`);
675
- return res.data;
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
- const res = await this.client.post('/api/auth/totp/enroll/start', {
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
- headers: {
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
- const res = await this.client.post('/api/auth/totp/enroll/verify', {
677
+ return await this.makeRequest('POST', '/api/auth/totp/enroll/verify', {
702
678
  sessionId,
703
679
  code
704
680
  }, {
705
- headers: {
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
- const res = await this.client.post('/api/auth/totp/disable', {
689
+ return await this.makeRequest('POST', '/api/auth/totp/disable', {
717
690
  sessionId,
718
691
  code
719
692
  }, {
720
- headers: {
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 res = await this.client.get(`/api/profiles/search?${searchParams.toString()}`);
741
- return res.data;
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
- const res = await this.client.get('/api/profiles/recommendations');
753
- return res.data;
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
- const res = await this.client.get(`/api/users/${userId}`);
763
- return res.data;
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
- const res = await this.client.get('/api/users/me');
775
- return res.data;
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
- const res = await this.client.put('/api/users/me', updates);
785
- return res.data;
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
- const res = await this.client.put(`/api/users/${userId}`, updates);
797
- return res.data;
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
- const res = await this.client.post(`/api/users/${userId}/follow`);
809
- return res.data;
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
- const res = await this.client.delete(`/api/users/${userId}/follow`);
821
- return res.data;
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
- const res = await this.client.get(`/api/users/${userId}/follow-status`);
833
- return res.data;
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 res = await this.client.get(`/api/users/${userId}/followers?${params.toString()}`);
846
- return res.data;
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 res = await this.client.get(`/api/users/${userId}/following?${params.toString()}`);
859
- return res.data;
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
- const res = await this.client.get('/api/notifications');
871
- return res.data;
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.client.get('/api/notifications/unread-count');
881
- return res.data.count;
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
- const res = await this.client.post('/api/notifications', data);
893
- return res.data;
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.client.put(`/api/notifications/${notificationId}/read`);
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.client.put('/api/notifications/read-all');
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.client.delete(`/api/notifications/${notificationId}`);
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
- const res = await this.client.post('/api/payments', data);
942
- return res.data;
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
- const res = await this.client.get(`/api/payments/${paymentId}`);
954
- return res.data;
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
- const res = await this.client.get('/api/payments/user');
966
- return res.data;
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
- const res = await this.client.get(`/api/karma/${userId}`);
982
- return res.data;
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
- const res = await this.client.post(`/api/karma/${userId}/give`, {
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
- const res = await this.client.get(`/api/karma/${userId}/total`);
1009
- return res.data;
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 = new URLSearchParams();
1021
- if (limit) params.append('limit', limit.toString());
1022
- if (offset) params.append('offset', offset.toString());
1023
- const res = await this.client.get(`/api/karma/${userId}/history?${params.toString()}`);
1024
- return res.data;
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
- const res = await this.client.get('/api/karma/leaderboard');
1036
- return res.data;
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
- const res = await this.client.get('/api/karma/rules');
1048
- return res.data;
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
- const res = await this.client.delete(`/api/assets/${encodeURIComponent(fileId)}`);
1065
- return res.data;
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.tokenStore.getAccessToken();
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 params = new URLSearchParams();
1107
- if (limit) params.append('limit', String(limit));
1108
- if (offset) params.append('offset', String(offset));
1109
- const qs = params.toString();
1110
- const res = await this.client.get(`/api/assets${qs ? `?${qs}` : ''}`);
1111
- return res.data;
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 urlRes = await this.client.get(`/api/assets/${encodeURIComponent(fileId)}/url${variant ? `?variant=${encodeURIComponent(variant)}` : ''}`);
1125
- const downloadUrl = urlRes.data?.url;
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 urlRes = await this.client.get(`/api/assets/${encodeURIComponent(fileId)}/url${variant ? `?variant=${encodeURIComponent(variant)}` : ''}`);
1139
- const downloadUrl = urlRes.data?.url;
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
- const res = await this.client.post('/api/assets/init', {
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
- const res = await this.client.post('/api/assets/complete', {
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
- await this.client.post(`/api/assets/${encodeURIComponent(initResponse.fileId)}/upload-direct`, fd, {
1223
- headers: {
1224
- 'Content-Type': 'multipart/form-data'
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
- const res = await this.client.post(`/api/assets/${fileId}/links`, body);
1277
- return res.data;
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
- const res = await this.client.delete(`/api/assets/${fileId}/links`, {
1289
- data: {
1290
- app,
1291
- entityType,
1292
- entityId
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
- const res = await this.client.get(`/api/assets/${fileId}`);
1307
- return res.data;
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 = new URLSearchParams();
1319
- if (variant) params.set('variant', variant);
1320
- if (expiresIn) params.set('expiresIn', expiresIn.toString());
1321
- const queryString = params.toString();
1322
- const url = `/api/assets/${fileId}/url${queryString ? `?${queryString}` : ''}`;
1323
- const res = await this.client.get(url);
1324
- return res.data;
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
- const res = await this.client.post(`/api/assets/${fileId}/restore`);
1336
- return res.data;
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 ? '?force=true' : '';
1348
- const res = await this.client.delete(`/api/assets/${fileId}${params}`);
1349
- return res.data;
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
- const res = await this.client.patch(`/api/assets/${fileId}/visibility`, {
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.client.get('/api/developer/apps');
1434
- return res.data;
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.client.post('/api/developer/apps', data);
1446
- return res.data;
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.client.get(`/api/developer/apps/${appId}`);
1458
- return res.data;
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.client.patch(`/api/developer/apps/${appId}`, data);
1470
- return res.data;
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
- const res = await this.client.post(`/api/developer/apps/${appId}/regenerate-secret`);
1482
- return res.data;
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
- const res = await this.client.delete(`/api/developer/apps/${appId}`);
1494
- return res.data;
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
- const res = await this.client.post('/api/location', {
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 ? `?radius=${radius}` : '';
1525
- const res = await this.client.get(`/api/location/nearby${params}`);
1526
- return res.data;
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.client.post('/api/analytics/events', {
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 = new URLSearchParams();
1556
- if (startDate) params.append('startDate', startDate);
1557
- if (endDate) params.append('endDate', endDate);
1558
- const res = await this.client.get(`/api/analytics?${params.toString()}`);
1559
- return res.data;
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
- const res = await this.client.post('/api/devices', deviceData);
1575
- return res.data;
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
- const res = await this.client.get('/api/devices');
1587
- return res.data;
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.client.delete(`/api/devices/${deviceId}`);
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
- const res = await this.client.get(`/api/devices/sessions/${sessionId}`);
1610
- return res.data;
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 res = await this.client.post(`/api/devices/logout-all/${sessionId}?${params.toString()}`);
1625
- return res.data;
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
- const res = await this.client.put(`/api/devices/name/${sessionId}`, {
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
- const res = await this.client.get(`/api/link-metadata?url=${encodeURIComponent(url)}`);
1655
- return res.data;
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
  }