@oxyhq/services 5.7.5 → 5.8.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 (303) hide show
  1. package/README.md +76 -76
  2. package/lib/commonjs/core/index.js +177 -102
  3. package/lib/commonjs/core/index.js.map +1 -1
  4. package/lib/commonjs/index.js +69 -28
  5. package/lib/commonjs/index.js.map +1 -1
  6. package/lib/commonjs/ui/components/Avatar.js +15 -6
  7. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  8. package/lib/commonjs/ui/components/FollowButton.js +100 -12
  9. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  10. package/lib/commonjs/ui/components/GroupedItem.js +58 -13
  11. package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
  12. package/lib/commonjs/ui/components/GroupedSection.js +7 -1
  13. package/lib/commonjs/ui/components/GroupedSection.js.map +1 -1
  14. package/lib/commonjs/ui/components/Header.js +356 -0
  15. package/lib/commonjs/ui/components/Header.js.map +1 -0
  16. package/lib/commonjs/ui/components/OxyProvider.js +28 -7
  17. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  18. package/lib/commonjs/ui/components/index.js +7 -0
  19. package/lib/commonjs/ui/components/index.js.map +1 -1
  20. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +1 -1
  21. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
  22. package/lib/commonjs/ui/components/internal/TextField.js +606 -546
  23. package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
  24. package/lib/commonjs/ui/components/internal/TextField.md +436 -0
  25. package/lib/commonjs/ui/context/OxyContext.js +181 -199
  26. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  27. package/lib/commonjs/ui/hooks/index.js +6 -0
  28. package/lib/commonjs/ui/hooks/index.js.map +1 -1
  29. package/lib/commonjs/ui/hooks/useFollow.js +59 -2
  30. package/lib/commonjs/ui/hooks/useFollow.js.map +1 -1
  31. package/lib/commonjs/ui/hooks/useSessionSocket.js +5 -2
  32. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  33. package/lib/commonjs/ui/navigation/OxyRouter.js +11 -1
  34. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  35. package/lib/commonjs/ui/screens/AccountCenterScreen.js +6 -6
  36. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  37. package/lib/commonjs/ui/screens/AccountManagementDemo.js +3 -3
  38. package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -1
  39. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +241 -598
  40. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  41. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +1160 -406
  42. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  43. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +135 -237
  44. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  45. package/lib/commonjs/ui/screens/AppInfoScreen.js +246 -463
  46. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  47. package/lib/commonjs/ui/screens/FeedbackScreen.js +3 -3
  48. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +808 -650
  50. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/ProfileScreen.js +214 -37
  52. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/RecoverAccountScreen.js +51 -72
  54. package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/SessionManagementScreen.js +11 -29
  56. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/SignInScreen.js +30 -303
  58. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  59. package/lib/commonjs/ui/screens/SignUpScreen.js +4 -4
  60. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  61. package/lib/commonjs/ui/screens/UserLinksScreen.js +90 -0
  62. package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -0
  63. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +19 -31
  64. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  65. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +7 -10
  66. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  67. package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js +11 -5
  68. package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
  69. package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js +11 -4
  70. package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
  71. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +9 -6
  72. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  73. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +3 -30
  74. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  75. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +37 -46
  76. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  77. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +9 -12
  78. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  79. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +9 -12
  80. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  81. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +9 -12
  82. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  83. package/lib/commonjs/ui/stores/authStore.js +36 -6
  84. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  85. package/lib/commonjs/ui/stores/followStore.js +106 -1
  86. package/lib/commonjs/ui/stores/followStore.js.map +1 -1
  87. package/lib/commonjs/ui/styles/authStyles.js +337 -0
  88. package/lib/commonjs/ui/styles/authStyles.js.map +1 -0
  89. package/lib/commonjs/ui/styles/index.js +11 -0
  90. package/lib/commonjs/ui/styles/index.js.map +1 -1
  91. package/lib/module/core/index.js +177 -41
  92. package/lib/module/core/index.js.map +1 -1
  93. package/lib/module/index.js +24 -4
  94. package/lib/module/index.js.map +1 -1
  95. package/lib/module/ui/components/Avatar.js +15 -6
  96. package/lib/module/ui/components/Avatar.js.map +1 -1
  97. package/lib/module/ui/components/FollowButton.js +101 -13
  98. package/lib/module/ui/components/FollowButton.js.map +1 -1
  99. package/lib/module/ui/components/GroupedItem.js +59 -14
  100. package/lib/module/ui/components/GroupedItem.js.map +1 -1
  101. package/lib/module/ui/components/GroupedSection.js +7 -1
  102. package/lib/module/ui/components/GroupedSection.js.map +1 -1
  103. package/lib/module/ui/components/Header.js +351 -0
  104. package/lib/module/ui/components/Header.js.map +1 -0
  105. package/lib/module/ui/components/OxyProvider.js +30 -9
  106. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  107. package/lib/module/ui/components/index.js +1 -0
  108. package/lib/module/ui/components/index.js.map +1 -1
  109. package/lib/module/ui/components/internal/GroupedPillButtons.js +1 -1
  110. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
  111. package/lib/module/ui/components/internal/TextField.js +607 -547
  112. package/lib/module/ui/components/internal/TextField.js.map +1 -1
  113. package/lib/module/ui/components/internal/TextField.md +436 -0
  114. package/lib/module/ui/context/OxyContext.js +180 -198
  115. package/lib/module/ui/context/OxyContext.js.map +1 -1
  116. package/lib/module/ui/hooks/index.js +1 -1
  117. package/lib/module/ui/hooks/index.js.map +1 -1
  118. package/lib/module/ui/hooks/useFollow.js +57 -1
  119. package/lib/module/ui/hooks/useFollow.js.map +1 -1
  120. package/lib/module/ui/hooks/useSessionSocket.js +5 -2
  121. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  122. package/lib/module/ui/navigation/OxyRouter.js +11 -1
  123. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  124. package/lib/module/ui/screens/AccountCenterScreen.js +6 -6
  125. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  126. package/lib/module/ui/screens/AccountManagementDemo.js +3 -3
  127. package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -1
  128. package/lib/module/ui/screens/AccountOverviewScreen.js +242 -597
  129. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  130. package/lib/module/ui/screens/AccountSettingsScreen.js +1161 -407
  131. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  132. package/lib/module/ui/screens/AccountSwitcherScreen.js +135 -237
  133. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  134. package/lib/module/ui/screens/AppInfoScreen.js +248 -465
  135. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  136. package/lib/module/ui/screens/FeedbackScreen.js +3 -3
  137. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  138. package/lib/module/ui/screens/PaymentGatewayScreen.js +809 -651
  139. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  140. package/lib/module/ui/screens/ProfileScreen.js +214 -37
  141. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  142. package/lib/module/ui/screens/RecoverAccountScreen.js +53 -74
  143. package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
  144. package/lib/module/ui/screens/SessionManagementScreen.js +11 -29
  145. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  146. package/lib/module/ui/screens/SignInScreen.js +32 -305
  147. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  148. package/lib/module/ui/screens/SignUpScreen.js +5 -5
  149. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  150. package/lib/module/ui/screens/UserLinksScreen.js +85 -0
  151. package/lib/module/ui/screens/UserLinksScreen.js.map +1 -0
  152. package/lib/module/ui/screens/internal/SignInPasswordStep.js +19 -31
  153. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  154. package/lib/module/ui/screens/internal/SignInUsernameStep.js +7 -10
  155. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  156. package/lib/module/ui/screens/internal/SignUpIdentityStep.js +11 -5
  157. package/lib/module/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
  158. package/lib/module/ui/screens/internal/SignUpSecurityStep.js +11 -4
  159. package/lib/module/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
  160. package/lib/module/ui/screens/karma/KarmaAboutScreen.js +9 -6
  161. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  162. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +3 -30
  163. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  164. package/lib/module/ui/screens/karma/KarmaFAQScreen.js +37 -46
  165. package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  166. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +9 -12
  167. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  168. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +9 -12
  169. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  170. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +9 -12
  171. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  172. package/lib/module/ui/stores/authStore.js +36 -6
  173. package/lib/module/ui/stores/authStore.js.map +1 -1
  174. package/lib/module/ui/stores/followStore.js +106 -1
  175. package/lib/module/ui/stores/followStore.js.map +1 -1
  176. package/lib/module/ui/styles/authStyles.js +332 -0
  177. package/lib/module/ui/styles/authStyles.js.map +1 -0
  178. package/lib/module/ui/styles/index.js +1 -0
  179. package/lib/module/ui/styles/index.js.map +1 -1
  180. package/lib/typescript/core/index.d.ts +68 -24
  181. package/lib/typescript/core/index.d.ts.map +1 -1
  182. package/lib/typescript/index.d.ts +13 -3
  183. package/lib/typescript/index.d.ts.map +1 -1
  184. package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
  185. package/lib/typescript/ui/components/FollowButton.d.ts +1 -0
  186. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  187. package/lib/typescript/ui/components/GroupedItem.d.ts +6 -0
  188. package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
  189. package/lib/typescript/ui/components/GroupedSection.d.ts +6 -0
  190. package/lib/typescript/ui/components/GroupedSection.d.ts.map +1 -1
  191. package/lib/typescript/ui/components/Header.d.ts +24 -0
  192. package/lib/typescript/ui/components/Header.d.ts.map +1 -0
  193. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  194. package/lib/typescript/ui/components/index.d.ts +1 -0
  195. package/lib/typescript/ui/components/index.d.ts.map +1 -1
  196. package/lib/typescript/ui/components/internal/TextField.d.ts +31 -16
  197. package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
  198. package/lib/typescript/ui/context/OxyContext.d.ts +5 -2
  199. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  200. package/lib/typescript/ui/hooks/index.d.ts +1 -1
  201. package/lib/typescript/ui/hooks/index.d.ts.map +1 -1
  202. package/lib/typescript/ui/hooks/useFollow.d.ts +20 -0
  203. package/lib/typescript/ui/hooks/useFollow.d.ts.map +1 -1
  204. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  205. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  206. package/lib/typescript/ui/navigation/types.d.ts +9 -2
  207. package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
  208. package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  209. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  210. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  211. package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
  212. package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  213. package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
  214. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts +5 -1
  215. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
  216. package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
  217. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  218. package/lib/typescript/ui/screens/UserLinksScreen.d.ts +15 -0
  219. package/lib/typescript/ui/screens/UserLinksScreen.d.ts.map +1 -0
  220. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +1 -1
  221. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  222. package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts +0 -1
  223. package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
  224. package/lib/typescript/ui/screens/internal/SignUpIdentityStep.d.ts.map +1 -1
  225. package/lib/typescript/ui/screens/internal/SignUpSecurityStep.d.ts.map +1 -1
  226. package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
  227. package/lib/typescript/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
  228. package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
  229. package/lib/typescript/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
  230. package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
  231. package/lib/typescript/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
  232. package/lib/typescript/ui/stores/authStore.d.ts +3 -1
  233. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  234. package/lib/typescript/ui/stores/followStore.d.ts +10 -0
  235. package/lib/typescript/ui/stores/followStore.d.ts.map +1 -1
  236. package/lib/typescript/ui/styles/authStyles.d.ts +326 -0
  237. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -0
  238. package/lib/typescript/ui/styles/index.d.ts +1 -0
  239. package/lib/typescript/ui/styles/index.d.ts.map +1 -1
  240. package/package.json +1 -4
  241. package/src/core/index.ts +195 -41
  242. package/src/index.ts +64 -4
  243. package/src/ui/components/Avatar.tsx +11 -5
  244. package/src/ui/components/FollowButton.tsx +95 -11
  245. package/src/ui/components/GroupedItem.tsx +57 -9
  246. package/src/ui/components/GroupedSection.tsx +12 -0
  247. package/src/ui/components/Header.tsx +405 -0
  248. package/src/ui/components/OxyProvider.tsx +37 -15
  249. package/src/ui/components/index.ts +1 -0
  250. package/src/ui/components/internal/GroupedPillButtons.tsx +1 -1
  251. package/src/ui/components/internal/TextField.md +436 -0
  252. package/src/ui/components/internal/TextField.tsx +720 -620
  253. package/src/ui/context/OxyContext.tsx +211 -195
  254. package/src/ui/hooks/index.ts +1 -1
  255. package/src/ui/hooks/useFollow.ts +63 -0
  256. package/src/ui/hooks/useSessionSocket.ts +5 -2
  257. package/src/ui/navigation/OxyRouter.tsx +11 -1
  258. package/src/ui/navigation/types.ts +10 -2
  259. package/src/ui/screens/AccountCenterScreen.tsx +5 -5
  260. package/src/ui/screens/AccountManagementDemo.tsx +9 -9
  261. package/src/ui/screens/AccountOverviewScreen.tsx +265 -414
  262. package/src/ui/screens/AccountSettingsScreen.tsx +1173 -403
  263. package/src/ui/screens/AccountSwitcherScreen.tsx +158 -202
  264. package/src/ui/screens/AppInfoScreen.tsx +270 -497
  265. package/src/ui/screens/FeedbackScreen.tsx +3 -3
  266. package/src/ui/screens/PaymentGatewayScreen.tsx +668 -365
  267. package/src/ui/screens/ProfileScreen.tsx +196 -33
  268. package/src/ui/screens/RecoverAccountScreen.tsx +46 -74
  269. package/src/ui/screens/SessionManagementScreen.tsx +14 -22
  270. package/src/ui/screens/SignInScreen.tsx +27 -294
  271. package/src/ui/screens/SignUpScreen.tsx +5 -5
  272. package/src/ui/screens/UserLinksScreen.tsx +96 -0
  273. package/src/ui/screens/internal/SignInPasswordStep.tsx +11 -22
  274. package/src/ui/screens/internal/SignInUsernameStep.tsx +3 -10
  275. package/src/ui/screens/internal/SignUpIdentityStep.tsx +2 -5
  276. package/src/ui/screens/internal/SignUpSecurityStep.tsx +3 -4
  277. package/src/ui/screens/karma/KarmaAboutScreen.tsx +9 -2
  278. package/src/ui/screens/karma/KarmaCenterScreen.tsx +1 -20
  279. package/src/ui/screens/karma/KarmaFAQScreen.tsx +40 -24
  280. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +9 -3
  281. package/src/ui/screens/karma/KarmaRewardsScreen.tsx +9 -3
  282. package/src/ui/screens/karma/KarmaRulesScreen.tsx +9 -3
  283. package/src/ui/stores/authStore.ts +34 -7
  284. package/src/ui/stores/followStore.ts +102 -1
  285. package/src/ui/styles/authStyles.ts +352 -0
  286. package/src/ui/styles/index.ts +1 -0
  287. package/lib/commonjs/core/auth-manager.js +0 -440
  288. package/lib/commonjs/core/auth-manager.js.map +0 -1
  289. package/lib/commonjs/core/use-auth.js +0 -244
  290. package/lib/commonjs/core/use-auth.js.map +0 -1
  291. package/lib/module/core/auth-manager.js +0 -432
  292. package/lib/module/core/auth-manager.js.map +0 -1
  293. package/lib/module/core/use-auth.js +0 -235
  294. package/lib/module/core/use-auth.js.map +0 -1
  295. package/lib/typescript/core/auth-manager.d.ts +0 -136
  296. package/lib/typescript/core/auth-manager.d.ts.map +0 -1
  297. package/lib/typescript/core/use-auth.d.ts +0 -79
  298. package/lib/typescript/core/use-auth.d.ts.map +0 -1
  299. package/src/__tests__/middleware.test.ts +0 -105
  300. package/src/__tests__/setup.ts +0 -10
  301. package/src/__tests__/zero-config-auth.test.ts +0 -607
  302. package/src/core/auth-manager.ts +0 -500
  303. package/src/core/use-auth.tsx +0 -245
@@ -1,607 +0,0 @@
1
- /**
2
- * Comprehensive test suite for Zero-Config Authentication
3
- */
4
-
5
- import { AuthenticationManager } from '../core/auth-manager';
6
- import { authenticateRequest, OxyRequest } from '../../api/src/middleware/zero-config-auth';
7
- import jwt from 'jsonwebtoken';
8
-
9
- // Mock AsyncStorage for React Native
10
- const mockAsyncStorage = {
11
- getItem: jest.fn(),
12
- setItem: jest.fn(),
13
- removeItem: jest.fn(),
14
- };
15
-
16
- jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage);
17
-
18
- // Mock axios
19
- const mockAxiosInstance = {
20
- get: jest.fn(),
21
- post: jest.fn(),
22
- put: jest.fn(),
23
- delete: jest.fn(),
24
- interceptors: {
25
- request: { use: jest.fn() },
26
- response: { use: jest.fn() }
27
- },
28
- defaults: { baseURL: 'http://localhost:3001' }
29
- };
30
-
31
- jest.mock('axios', () => ({
32
- create: jest.fn(() => mockAxiosInstance),
33
- }));
34
-
35
- describe('AuthenticationManager', () => {
36
- let authManager: AuthenticationManager;
37
-
38
- beforeEach(() => {
39
- jest.clearAllMocks();
40
- authManager = new AuthenticationManager('http://localhost:3001');
41
- });
42
-
43
- describe('initialization', () => {
44
- it('should create axios client with correct config', () => {
45
- expect(require('axios').create).toHaveBeenCalledWith({
46
- baseURL: 'http://localhost:3001',
47
- timeout: 15000,
48
- withCredentials: true,
49
- });
50
- });
51
-
52
- it('should setup request and response interceptors', () => {
53
- expect(mockAxiosInstance.interceptors.request.use).toHaveBeenCalled();
54
- expect(mockAxiosInstance.interceptors.response.use).toHaveBeenCalled();
55
- });
56
-
57
- it('should attempt to initialize from storage', async () => {
58
- expect(mockAsyncStorage.getItem).toHaveBeenCalledWith('@oxy/auth-tokens');
59
- });
60
- });
61
-
62
- describe('login', () => {
63
- const mockLoginResponse = {
64
- data: {
65
- success: true,
66
- accessToken: 'mock-access-token',
67
- refreshToken: 'mock-refresh-token',
68
- user: { id: 'user123', username: 'testuser' }
69
- }
70
- };
71
-
72
- beforeEach(() => {
73
- mockAxiosInstance.post.mockResolvedValue(mockLoginResponse);
74
- });
75
-
76
- it('should successfully login with valid credentials', async () => {
77
- const result = await authManager.login({ username: 'test', password: 'pass' });
78
-
79
- expect(mockAxiosInstance.post).toHaveBeenCalledWith('/auth/login', {
80
- username: 'test',
81
- password: 'pass'
82
- });
83
-
84
- expect(result).toEqual(mockLoginResponse.data);
85
- expect(mockAsyncStorage.setItem).toHaveBeenCalledWith(
86
- '@oxy/auth-tokens',
87
- JSON.stringify({
88
- accessToken: 'mock-access-token',
89
- refreshToken: 'mock-refresh-token'
90
- })
91
- );
92
- });
93
-
94
- it('should throw error for invalid credentials', async () => {
95
- mockAxiosInstance.post.mockRejectedValue(new Error('Invalid credentials'));
96
-
97
- await expect(authManager.login({ username: 'test', password: 'wrong' }))
98
- .rejects.toThrow('Invalid credentials');
99
- });
100
-
101
- it('should handle server error responses', async () => {
102
- const errorResponse = {
103
- response: {
104
- data: { message: 'Server error occurred' },
105
- status: 500
106
- }
107
- };
108
- mockAxiosInstance.post.mockRejectedValue(errorResponse);
109
-
110
- await expect(authManager.login({ username: 'test', password: 'pass' }))
111
- .rejects.toThrow('Server error occurred');
112
- });
113
- });
114
-
115
- describe('register', () => {
116
- const mockRegisterResponse = {
117
- data: {
118
- success: true,
119
- accessToken: 'mock-access-token',
120
- refreshToken: 'mock-refresh-token',
121
- user: { id: 'user123', username: 'newuser', email: 'new@test.com' }
122
- }
123
- };
124
-
125
- beforeEach(() => {
126
- mockAxiosInstance.post.mockResolvedValue(mockRegisterResponse);
127
- });
128
-
129
- it('should successfully register new user', async () => {
130
- const userData = {
131
- username: 'newuser',
132
- email: 'new@test.com',
133
- password: 'password123'
134
- };
135
-
136
- const result = await authManager.register(userData);
137
-
138
- expect(mockAxiosInstance.post).toHaveBeenCalledWith('/auth/register', userData);
139
- expect(result).toEqual(mockRegisterResponse.data);
140
- });
141
-
142
- it('should handle registration errors', async () => {
143
- const errorResponse = {
144
- response: {
145
- data: { message: 'Username already exists' },
146
- status: 400
147
- }
148
- };
149
- mockAxiosInstance.post.mockRejectedValue(errorResponse);
150
-
151
- await expect(authManager.register({
152
- username: 'existing',
153
- email: 'test@test.com',
154
- password: 'pass'
155
- })).rejects.toThrow('Username already exists');
156
- });
157
- });
158
-
159
- describe('logout', () => {
160
- beforeEach(() => {
161
- mockAxiosInstance.post.mockResolvedValue({ data: { success: true } });
162
- });
163
-
164
- it('should successfully logout and clear tokens', async () => {
165
- // Set some tokens first
166
- (authManager as any).tokens = {
167
- accessToken: 'token1',
168
- refreshToken: 'token2'
169
- };
170
-
171
- await authManager.logout();
172
-
173
- expect(mockAxiosInstance.post).toHaveBeenCalledWith('/auth/logout', {
174
- refreshToken: 'token2'
175
- });
176
- expect(mockAsyncStorage.removeItem).toHaveBeenCalledWith('@oxy/auth-tokens');
177
- });
178
-
179
- it('should clear tokens even if server logout fails', async () => {
180
- mockAxiosInstance.post.mockRejectedValue(new Error('Server error'));
181
-
182
- (authManager as any).tokens = {
183
- accessToken: 'token1',
184
- refreshToken: 'token2'
185
- };
186
-
187
- await authManager.logout();
188
-
189
- expect(mockAsyncStorage.removeItem).toHaveBeenCalledWith('@oxy/auth-tokens');
190
- });
191
- });
192
-
193
- describe('getAuthState', () => {
194
- it('should return unauthenticated state initially', () => {
195
- const state = authManager.getAuthState();
196
-
197
- expect(state).toEqual({
198
- isAuthenticated: false,
199
- user: null,
200
- tokens: null
201
- });
202
- });
203
-
204
- it('should return authenticated state when tokens are present', () => {
205
- (authManager as any).tokens = {
206
- accessToken: 'token1',
207
- refreshToken: 'token2'
208
- };
209
- (authManager as any).user = { id: 'user123', username: 'test' };
210
-
211
- const state = authManager.getAuthState();
212
-
213
- expect(state.isAuthenticated).toBe(true);
214
- expect(state.user).toEqual({ id: 'user123', username: 'test' });
215
- expect(state.tokens).toEqual({
216
- accessToken: 'token1',
217
- refreshToken: 'token2'
218
- });
219
- });
220
- });
221
-
222
- describe('onAuthStateChange', () => {
223
- it('should call callback immediately with current state', () => {
224
- const callback = jest.fn();
225
-
226
- authManager.onAuthStateChange(callback);
227
-
228
- expect(callback).toHaveBeenCalledWith({
229
- isAuthenticated: false,
230
- user: null,
231
- tokens: null
232
- });
233
- });
234
-
235
- it('should return unsubscribe function', () => {
236
- const callback = jest.fn();
237
-
238
- const unsubscribe = authManager.onAuthStateChange(callback);
239
-
240
- expect(typeof unsubscribe).toBe('function');
241
- });
242
-
243
- it('should notify listeners on state changes', () => {
244
- const callback = jest.fn();
245
- authManager.onAuthStateChange(callback);
246
-
247
- callback.mockClear();
248
-
249
- // Simulate state change
250
- (authManager as any).tokens = { accessToken: 'new-token', refreshToken: 'new-refresh' };
251
- (authManager as any).notifyStateChange();
252
-
253
- expect(callback).toHaveBeenCalledWith({
254
- isAuthenticated: true,
255
- user: null,
256
- tokens: { accessToken: 'new-token', refreshToken: 'new-refresh' }
257
- });
258
- });
259
- });
260
-
261
- describe('username and email validation', () => {
262
- it('should check username availability', async () => {
263
- const mockResponse = { data: { available: true, message: 'Username available' } };
264
- mockAxiosInstance.get.mockResolvedValue(mockResponse);
265
-
266
- const result = await authManager.checkUsernameAvailability('newuser');
267
-
268
- expect(mockAxiosInstance.get).toHaveBeenCalledWith('/auth/check-username/newuser');
269
- expect(result).toEqual({ available: true, message: 'Username available' });
270
- });
271
-
272
- it('should check email availability', async () => {
273
- const mockResponse = { data: { available: false, message: 'Email already registered' } };
274
- mockAxiosInstance.post.mockResolvedValue(mockResponse);
275
-
276
- const result = await authManager.checkEmailAvailability('test@example.com');
277
-
278
- expect(mockAxiosInstance.post).toHaveBeenCalledWith('/auth/check-email', {
279
- email: 'test@example.com'
280
- });
281
- expect(result).toEqual({ available: false, message: 'Email already registered' });
282
- });
283
-
284
- it('should handle validation errors gracefully', async () => {
285
- const errorResponse = {
286
- response: {
287
- status: 400,
288
- data: { available: false, message: 'Invalid username format' }
289
- }
290
- };
291
- mockAxiosInstance.get.mockRejectedValue(errorResponse);
292
-
293
- const result = await authManager.checkUsernameAvailability('invalid@user');
294
-
295
- expect(result).toEqual({ available: false, message: 'Invalid username format' });
296
- });
297
- });
298
- });
299
-
300
- describe('Zero-Config Backend Middleware', () => {
301
- let mockReq: Partial<OxyRequest>;
302
- let mockRes: any;
303
- let mockNext: jest.Mock;
304
-
305
- beforeEach(() => {
306
- mockReq = {
307
- headers: {},
308
- cookies: {}
309
- };
310
-
311
- mockRes = {
312
- status: jest.fn().mockReturnThis(),
313
- json: jest.fn()
314
- };
315
-
316
- mockNext = jest.fn();
317
-
318
- // Mock JWT secret
319
- process.env.ACCESS_TOKEN_SECRET = 'test-secret';
320
- });
321
-
322
- afterEach(() => {
323
- delete process.env.ACCESS_TOKEN_SECRET;
324
- });
325
-
326
- describe('authenticateRequest', () => {
327
- it('should require authentication by default', async () => {
328
- const middleware = authenticateRequest();
329
-
330
- await middleware(mockReq as any, mockRes, mockNext);
331
-
332
- expect(mockRes.status).toHaveBeenCalledWith(401);
333
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
334
- success: false,
335
- error: 'MISSING_TOKEN',
336
- message: 'Authentication required'
337
- }));
338
- expect(mockNext).not.toHaveBeenCalled();
339
- });
340
-
341
- it('should allow optional authentication', async () => {
342
- const middleware = authenticateRequest({ required: false });
343
-
344
- await middleware(mockReq as any, mockRes, mockNext);
345
-
346
- expect(mockNext).toHaveBeenCalled();
347
- expect(mockRes.status).not.toHaveBeenCalled();
348
- });
349
-
350
- it('should validate JWT tokens', async () => {
351
- const token = jwt.sign(
352
- { id: 'user123', userId: 'user123', username: 'test' },
353
- 'test-secret',
354
- { expiresIn: '1h' }
355
- );
356
-
357
- mockReq.headers!.authorization = `Bearer ${token}`;
358
-
359
- // Mock User.findById
360
- const mockUser = {
361
- _id: 'user123',
362
- id: 'user123',
363
- username: 'test',
364
- email: 'test@example.com'
365
- };
366
-
367
- jest.mock('../../api/src/models/User', () => ({
368
- findById: jest.fn().mockReturnValue({
369
- select: jest.fn().mockResolvedValue(mockUser)
370
- })
371
- }));
372
-
373
- const middleware = authenticateRequest();
374
-
375
- await middleware(mockReq as any, mockRes, mockNext);
376
-
377
- expect(mockReq.userId).toBe('user123');
378
- expect(mockNext).toHaveBeenCalled();
379
- });
380
-
381
- it('should handle expired tokens', async () => {
382
- const expiredToken = jwt.sign(
383
- { id: 'user123', userId: 'user123', username: 'test' },
384
- 'test-secret',
385
- { expiresIn: '-1h' } // Expired
386
- );
387
-
388
- mockReq.headers!.authorization = `Bearer ${expiredToken}`;
389
-
390
- const middleware = authenticateRequest();
391
-
392
- await middleware(mockReq as any, mockRes, mockNext);
393
-
394
- expect(mockRes.status).toHaveBeenCalledWith(401);
395
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
396
- error: 'TOKEN_EXPIRED',
397
- message: 'Token has expired'
398
- }));
399
- expect(mockNext).not.toHaveBeenCalled();
400
- });
401
-
402
- it('should handle invalid tokens', async () => {
403
- mockReq.headers!.authorization = 'Bearer invalid-token';
404
-
405
- const middleware = authenticateRequest();
406
-
407
- await middleware(mockReq as any, mockRes, mockNext);
408
-
409
- expect(mockRes.status).toHaveBeenCalledWith(401);
410
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
411
- error: 'INVALID_TOKEN',
412
- message: 'Invalid token'
413
- }));
414
- });
415
-
416
- it('should call custom error handler when provided', async () => {
417
- const customErrorHandler = jest.fn();
418
- const middleware = authenticateRequest({ onError: customErrorHandler });
419
-
420
- await middleware(mockReq as any, mockRes, mockNext);
421
-
422
- expect(customErrorHandler).toHaveBeenCalledWith(
423
- expect.objectContaining({
424
- code: 'MISSING_TOKEN',
425
- statusCode: 401
426
- }),
427
- mockReq,
428
- mockRes
429
- );
430
- expect(mockRes.status).not.toHaveBeenCalled();
431
- });
432
-
433
- it('should skip authentication when skipIf condition is met', async () => {
434
- const skipCondition = jest.fn().mockReturnValue(true);
435
- const middleware = authenticateRequest({ skipIf: skipCondition });
436
-
437
- await middleware(mockReq as any, mockRes, mockNext);
438
-
439
- expect(skipCondition).toHaveBeenCalledWith(mockReq);
440
- expect(mockNext).toHaveBeenCalled();
441
- expect(mockRes.status).not.toHaveBeenCalled();
442
- });
443
- });
444
-
445
- describe('token extraction', () => {
446
- it('should extract token from Authorization header', async () => {
447
- const token = jwt.sign(
448
- { id: 'user123', userId: 'user123', username: 'test' },
449
- 'test-secret',
450
- { expiresIn: '1h' }
451
- );
452
-
453
- mockReq.headers!.authorization = `Bearer ${token}`;
454
-
455
- const middleware = authenticateRequest({ loadFullUser: false });
456
- await middleware(mockReq as any, mockRes, mockNext);
457
-
458
- expect(mockReq.userId).toBe('user123');
459
- });
460
-
461
- it('should extract token from cookies as fallback', async () => {
462
- const token = jwt.sign(
463
- { id: 'user123', userId: 'user123', username: 'test' },
464
- 'test-secret',
465
- { expiresIn: '1h' }
466
- );
467
-
468
- mockReq.cookies!.accessToken = token;
469
-
470
- const middleware = authenticateRequest({ loadFullUser: false });
471
- await middleware(mockReq as any, mockRes, mockNext);
472
-
473
- expect(mockReq.userId).toBe('user123');
474
- });
475
-
476
- it('should handle malformed Authorization header', async () => {
477
- mockReq.headers!.authorization = 'InvalidFormat token';
478
-
479
- const middleware = authenticateRequest();
480
- await middleware(mockReq as any, mockRes, mockNext);
481
-
482
- expect(mockRes.status).toHaveBeenCalledWith(401);
483
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
484
- error: 'MISSING_TOKEN'
485
- }));
486
- });
487
- });
488
-
489
- describe('error handling', () => {
490
- it('should provide consistent error response format', async () => {
491
- const middleware = authenticateRequest();
492
-
493
- await middleware(mockReq as any, mockRes, mockNext);
494
-
495
- expect(mockRes.json).toHaveBeenCalledWith({
496
- success: false,
497
- error: 'MISSING_TOKEN',
498
- message: 'Authentication required',
499
- timestamp: expect.any(String)
500
- });
501
- });
502
-
503
- it('should handle internal server errors gracefully', async () => {
504
- // Force an internal error
505
- const middleware = authenticateRequest();
506
-
507
- // Mock internal error by making the middleware throw
508
- mockReq.headers = undefined as any;
509
-
510
- await middleware(mockReq as any, mockRes, mockNext);
511
-
512
- expect(mockRes.status).toHaveBeenCalledWith(expect.any(Number));
513
- expect(mockRes.json).toHaveBeenCalledWith(expect.objectContaining({
514
- success: false
515
- }));
516
- });
517
- });
518
- });
519
-
520
- describe('Integration Tests', () => {
521
- describe('Frontend-Backend Authentication Flow', () => {
522
- let authManager: AuthenticationManager;
523
-
524
- beforeEach(() => {
525
- authManager = new AuthenticationManager('http://localhost:3001');
526
- });
527
-
528
- it('should handle complete login flow', async () => {
529
- const mockLoginResponse = {
530
- data: {
531
- success: true,
532
- accessToken: 'mock-access-token',
533
- refreshToken: 'mock-refresh-token',
534
- user: { id: 'user123', username: 'testuser' }
535
- }
536
- };
537
-
538
- mockAxiosInstance.post.mockResolvedValue(mockLoginResponse);
539
-
540
- // Login
541
- const result = await authManager.login({ username: 'test', password: 'pass' });
542
- expect(result.success).toBe(true);
543
-
544
- // Check auth state
545
- const authState = authManager.getAuthState();
546
- expect(authState.isAuthenticated).toBe(true);
547
- expect(authState.user).toEqual(mockLoginResponse.data.user);
548
-
549
- // Verify tokens are stored
550
- expect(mockAsyncStorage.setItem).toHaveBeenCalledWith(
551
- '@oxy/auth-tokens',
552
- expect.stringContaining('mock-access-token')
553
- );
554
- });
555
-
556
- it('should handle authentication errors gracefully', async () => {
557
- const errorResponse = {
558
- response: {
559
- status: 401,
560
- data: { message: 'Invalid credentials' }
561
- }
562
- };
563
-
564
- mockAxiosInstance.post.mockRejectedValue(errorResponse);
565
-
566
- await expect(authManager.login({ username: 'test', password: 'wrong' }))
567
- .rejects.toThrow('Invalid credentials');
568
-
569
- const authState = authManager.getAuthState();
570
- expect(authState.isAuthenticated).toBe(false);
571
- });
572
- });
573
-
574
- describe('Token Lifecycle Management', () => {
575
- it('should automatically refresh tokens before expiration', async () => {
576
- const mockToken = jwt.sign(
577
- { id: 'user123', userId: 'user123' },
578
- 'test-secret',
579
- { expiresIn: '1m' } // Short expiry for testing
580
- );
581
-
582
- const authManager = new AuthenticationManager('http://localhost:3001');
583
-
584
- // Set tokens
585
- (authManager as any).tokens = {
586
- accessToken: mockToken,
587
- refreshToken: 'refresh-token'
588
- };
589
-
590
- // Mock refresh response
591
- mockAxiosInstance.post.mockResolvedValue({
592
- data: {
593
- accessToken: 'new-access-token',
594
- refreshToken: 'new-refresh-token'
595
- }
596
- });
597
-
598
- // Simulate a request that should trigger refresh
599
- await (authManager as any).ensureValidToken();
600
-
601
- // Verify refresh was called
602
- expect(mockAxiosInstance.post).toHaveBeenCalledWith('/auth/refresh', {
603
- refreshToken: 'refresh-token'
604
- });
605
- });
606
- });
607
- });