@oxyhq/services 5.16.40 → 5.16.41

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 (267) hide show
  1. package/lib/commonjs/adapters/expo/crypto.js +56 -0
  2. package/lib/commonjs/adapters/expo/crypto.js.map +1 -0
  3. package/lib/commonjs/adapters/expo/fetch.js +30 -0
  4. package/lib/commonjs/adapters/expo/fetch.js.map +1 -0
  5. package/lib/commonjs/adapters/expo/index.js +48 -0
  6. package/lib/commonjs/adapters/expo/index.js.map +1 -0
  7. package/lib/commonjs/adapters/expo/storage.js +201 -0
  8. package/lib/commonjs/adapters/expo/storage.js.map +1 -0
  9. package/lib/commonjs/adapters/index.js +41 -0
  10. package/lib/commonjs/adapters/index.js.map +1 -0
  11. package/lib/commonjs/adapters/node/crypto.js +40 -0
  12. package/lib/commonjs/adapters/node/crypto.js.map +1 -0
  13. package/lib/commonjs/adapters/node/fetch.js +62 -0
  14. package/lib/commonjs/adapters/node/fetch.js.map +1 -0
  15. package/lib/commonjs/adapters/node/index.js +34 -0
  16. package/lib/commonjs/adapters/node/index.js.map +1 -0
  17. package/lib/commonjs/adapters/node/storage.js +163 -0
  18. package/lib/commonjs/adapters/node/storage.js.map +1 -0
  19. package/lib/commonjs/core/identity-session/DeviceManager.js +237 -0
  20. package/lib/commonjs/core/identity-session/DeviceManager.js.map +1 -0
  21. package/lib/commonjs/core/identity-session/INTEGRATION_GUIDE.md +287 -0
  22. package/lib/commonjs/core/identity-session/IdentityManager.js +400 -0
  23. package/lib/commonjs/core/identity-session/IdentityManager.js.map +1 -0
  24. package/lib/commonjs/core/identity-session/IdentitySessionCore.js +394 -0
  25. package/lib/commonjs/core/identity-session/IdentitySessionCore.js.map +1 -0
  26. package/lib/commonjs/core/identity-session/RefreshManager.js +137 -0
  27. package/lib/commonjs/core/identity-session/RefreshManager.js.map +1 -0
  28. package/lib/commonjs/core/identity-session/SessionManager.js +427 -0
  29. package/lib/commonjs/core/identity-session/SessionManager.js.map +1 -0
  30. package/lib/commonjs/core/identity-session/createIdentitySessionCore.js +24 -0
  31. package/lib/commonjs/core/identity-session/createIdentitySessionCore.js.map +1 -0
  32. package/lib/commonjs/core/identity-session/errors.js +176 -0
  33. package/lib/commonjs/core/identity-session/errors.js.map +1 -0
  34. package/lib/commonjs/core/identity-session/index.js +80 -0
  35. package/lib/commonjs/core/identity-session/index.js.map +1 -0
  36. package/lib/commonjs/core/identity-session/types.js +2 -0
  37. package/lib/commonjs/core/identity-session/types.js.map +1 -0
  38. package/lib/commonjs/core/index.js +2 -21
  39. package/lib/commonjs/core/index.js.map +1 -1
  40. package/lib/commonjs/index.js +58 -8
  41. package/lib/commonjs/index.js.map +1 -1
  42. package/lib/commonjs/models/interfaces.js +7 -0
  43. package/lib/commonjs/models/interfaces.js.map +1 -1
  44. package/lib/commonjs/ui/context/OxyContext.js +434 -820
  45. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  46. package/lib/commonjs/ui/hooks/useAvatarPicker.js +52 -0
  47. package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +1 -0
  48. package/lib/commonjs/ui/hooks/useIdentityTransfer.js +125 -0
  49. package/lib/commonjs/ui/hooks/useIdentityTransfer.js.map +1 -0
  50. package/lib/commonjs/ui/hooks/useTransferCodesPersistence.js +81 -0
  51. package/lib/commonjs/ui/hooks/useTransferCodesPersistence.js.map +1 -0
  52. package/lib/commonjs/ui/screens/AccountCenterScreen.js +7 -2
  53. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  54. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +12 -5
  55. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  56. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +2 -2
  57. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  58. package/lib/commonjs/ui/screens/ProfileScreen.js +6 -6
  59. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  60. package/lib/commonjs/ui/utils/sessionHelpers.js +7 -1
  61. package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
  62. package/lib/commonjs/utils/index.js +0 -7
  63. package/lib/commonjs/utils/index.js.map +1 -1
  64. package/lib/commonjs/utils/sessionUtils.js +8 -1
  65. package/lib/commonjs/utils/sessionUtils.js.map +1 -1
  66. package/lib/module/adapters/expo/crypto.js +51 -0
  67. package/lib/module/adapters/expo/crypto.js.map +1 -0
  68. package/lib/module/adapters/expo/fetch.js +26 -0
  69. package/lib/module/adapters/expo/fetch.js.map +1 -0
  70. package/lib/module/adapters/expo/index.js +45 -0
  71. package/lib/module/adapters/expo/index.js.map +1 -0
  72. package/lib/module/adapters/expo/storage.js +198 -0
  73. package/lib/module/adapters/expo/storage.js.map +1 -0
  74. package/lib/module/adapters/index.js +38 -0
  75. package/lib/module/adapters/index.js.map +1 -0
  76. package/lib/module/adapters/node/crypto.js +36 -0
  77. package/lib/module/adapters/node/crypto.js.map +1 -0
  78. package/lib/module/adapters/node/fetch.js +57 -0
  79. package/lib/module/adapters/node/fetch.js.map +1 -0
  80. package/lib/module/adapters/node/index.js +31 -0
  81. package/lib/module/adapters/node/index.js.map +1 -0
  82. package/lib/module/adapters/node/storage.js +159 -0
  83. package/lib/module/adapters/node/storage.js.map +1 -0
  84. package/lib/module/core/identity-session/DeviceManager.js +232 -0
  85. package/lib/module/core/identity-session/DeviceManager.js.map +1 -0
  86. package/lib/module/core/identity-session/INTEGRATION_GUIDE.md +287 -0
  87. package/lib/module/core/identity-session/IdentityManager.js +395 -0
  88. package/lib/module/core/identity-session/IdentityManager.js.map +1 -0
  89. package/lib/module/core/identity-session/IdentitySessionCore.js +390 -0
  90. package/lib/module/core/identity-session/IdentitySessionCore.js.map +1 -0
  91. package/lib/module/core/identity-session/RefreshManager.js +132 -0
  92. package/lib/module/core/identity-session/RefreshManager.js.map +1 -0
  93. package/lib/module/core/identity-session/SessionManager.js +422 -0
  94. package/lib/module/core/identity-session/SessionManager.js.map +1 -0
  95. package/lib/module/core/identity-session/createIdentitySessionCore.js +21 -0
  96. package/lib/module/core/identity-session/createIdentitySessionCore.js.map +1 -0
  97. package/lib/module/core/identity-session/errors.js +170 -0
  98. package/lib/module/core/identity-session/errors.js.map +1 -0
  99. package/lib/module/core/identity-session/index.js +17 -0
  100. package/lib/module/core/identity-session/index.js.map +1 -0
  101. package/lib/module/core/identity-session/types.js +2 -0
  102. package/lib/module/core/identity-session/types.js.map +1 -0
  103. package/lib/module/core/index.js +2 -3
  104. package/lib/module/core/index.js.map +1 -1
  105. package/lib/module/index.js +12 -2
  106. package/lib/module/index.js.map +1 -1
  107. package/lib/module/models/interfaces.js +7 -0
  108. package/lib/module/models/interfaces.js.map +1 -1
  109. package/lib/module/ui/context/OxyContext.js +436 -822
  110. package/lib/module/ui/context/OxyContext.js.map +1 -1
  111. package/lib/module/ui/hooks/useAvatarPicker.js +48 -0
  112. package/lib/module/ui/hooks/useAvatarPicker.js.map +1 -0
  113. package/lib/module/ui/hooks/useIdentityTransfer.js +121 -0
  114. package/lib/module/ui/hooks/useIdentityTransfer.js.map +1 -0
  115. package/lib/module/ui/hooks/useTransferCodesPersistence.js +77 -0
  116. package/lib/module/ui/hooks/useTransferCodesPersistence.js.map +1 -0
  117. package/lib/module/ui/screens/AccountCenterScreen.js +7 -2
  118. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  119. package/lib/module/ui/screens/AccountSettingsScreen.js +12 -5
  120. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  121. package/lib/module/ui/screens/AccountSwitcherScreen.js +2 -2
  122. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  123. package/lib/module/ui/screens/ProfileScreen.js +6 -6
  124. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  125. package/lib/module/ui/utils/sessionHelpers.js +7 -1
  126. package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
  127. package/lib/module/utils/index.js +2 -1
  128. package/lib/module/utils/index.js.map +1 -1
  129. package/lib/module/utils/sessionUtils.js +8 -1
  130. package/lib/module/utils/sessionUtils.js.map +1 -1
  131. package/lib/typescript/adapters/expo/crypto.d.ts +17 -0
  132. package/lib/typescript/adapters/expo/crypto.d.ts.map +1 -0
  133. package/lib/typescript/adapters/expo/fetch.d.ts +16 -0
  134. package/lib/typescript/adapters/expo/fetch.d.ts.map +1 -0
  135. package/lib/typescript/adapters/expo/index.d.ts +23 -0
  136. package/lib/typescript/adapters/expo/index.d.ts.map +1 -0
  137. package/lib/typescript/adapters/expo/storage.d.ts +23 -0
  138. package/lib/typescript/adapters/expo/storage.d.ts.map +1 -0
  139. package/lib/typescript/adapters/index.d.ts +13 -0
  140. package/lib/typescript/adapters/index.d.ts.map +1 -0
  141. package/lib/typescript/adapters/node/crypto.d.ts +17 -0
  142. package/lib/typescript/adapters/node/crypto.d.ts.map +1 -0
  143. package/lib/typescript/adapters/node/fetch.d.ts +16 -0
  144. package/lib/typescript/adapters/node/fetch.d.ts.map +1 -0
  145. package/lib/typescript/adapters/node/index.d.ts +23 -0
  146. package/lib/typescript/adapters/node/index.d.ts.map +1 -0
  147. package/lib/typescript/adapters/node/storage.d.ts +23 -0
  148. package/lib/typescript/adapters/node/storage.d.ts.map +1 -0
  149. package/lib/typescript/core/identity-session/DeviceManager.d.ts +64 -0
  150. package/lib/typescript/core/identity-session/DeviceManager.d.ts.map +1 -0
  151. package/lib/typescript/core/identity-session/IdentityManager.d.ts +88 -0
  152. package/lib/typescript/core/identity-session/IdentityManager.d.ts.map +1 -0
  153. package/lib/typescript/core/identity-session/IdentitySessionCore.d.ts +141 -0
  154. package/lib/typescript/core/identity-session/IdentitySessionCore.d.ts.map +1 -0
  155. package/lib/typescript/core/identity-session/RefreshManager.d.ts +36 -0
  156. package/lib/typescript/core/identity-session/RefreshManager.d.ts.map +1 -0
  157. package/lib/typescript/core/identity-session/SessionManager.d.ts +104 -0
  158. package/lib/typescript/core/identity-session/SessionManager.d.ts.map +1 -0
  159. package/lib/typescript/core/identity-session/createIdentitySessionCore.d.ts +11 -0
  160. package/lib/typescript/core/identity-session/createIdentitySessionCore.d.ts.map +1 -0
  161. package/lib/typescript/core/identity-session/errors.d.ts +63 -0
  162. package/lib/typescript/core/identity-session/errors.d.ts.map +1 -0
  163. package/lib/typescript/core/identity-session/index.d.ts +14 -0
  164. package/lib/typescript/core/identity-session/index.d.ts.map +1 -0
  165. package/lib/typescript/core/identity-session/types.d.ts +196 -0
  166. package/lib/typescript/core/identity-session/types.d.ts.map +1 -0
  167. package/lib/typescript/core/index.d.ts +1 -3
  168. package/lib/typescript/core/index.d.ts.map +1 -1
  169. package/lib/typescript/core/mixins/index.d.ts +2 -2
  170. package/lib/typescript/index.d.ts +3 -2
  171. package/lib/typescript/index.d.ts.map +1 -1
  172. package/lib/typescript/models/interfaces.d.ts +5 -36
  173. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  174. package/lib/typescript/models/session.d.ts +3 -16
  175. package/lib/typescript/models/session.d.ts.map +1 -1
  176. package/lib/typescript/ui/context/OxyContext.d.ts +2 -25
  177. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  178. package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts +7 -8
  179. package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  180. package/lib/typescript/ui/hooks/mutations/useServicesMutations.d.ts +1 -1
  181. package/lib/typescript/ui/hooks/mutations/useServicesMutations.d.ts.map +1 -1
  182. package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts +5 -5
  183. package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  184. package/lib/typescript/ui/hooks/useAvatarPicker.d.ts +18 -0
  185. package/lib/typescript/ui/hooks/useAvatarPicker.d.ts.map +1 -0
  186. package/lib/typescript/ui/hooks/useIdentityTransfer.d.ts +24 -0
  187. package/lib/typescript/ui/hooks/useIdentityTransfer.d.ts.map +1 -0
  188. package/lib/typescript/ui/hooks/useTransferCodesPersistence.d.ts +6 -0
  189. package/lib/typescript/ui/hooks/useTransferCodesPersistence.d.ts.map +1 -0
  190. package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
  191. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  192. package/lib/typescript/ui/utils/sessionHelpers.d.ts +1 -0
  193. package/lib/typescript/ui/utils/sessionHelpers.d.ts.map +1 -1
  194. package/lib/typescript/utils/index.d.ts +0 -2
  195. package/lib/typescript/utils/index.d.ts.map +1 -1
  196. package/lib/typescript/utils/sessionUtils.d.ts.map +1 -1
  197. package/package.json +1 -1
  198. package/src/adapters/expo/crypto.ts +55 -0
  199. package/src/adapters/expo/fetch.ts +28 -0
  200. package/src/adapters/expo/index.ts +51 -0
  201. package/src/adapters/expo/storage.ts +228 -0
  202. package/src/adapters/index.ts +40 -0
  203. package/src/adapters/node/crypto.ts +39 -0
  204. package/src/adapters/node/fetch.ts +59 -0
  205. package/src/adapters/node/index.ts +37 -0
  206. package/src/adapters/node/storage.ts +170 -0
  207. package/src/core/identity-session/DeviceManager.ts +273 -0
  208. package/src/core/identity-session/INTEGRATION_GUIDE.md +287 -0
  209. package/src/core/identity-session/IdentityManager.ts +474 -0
  210. package/src/core/identity-session/IdentitySessionCore.ts +464 -0
  211. package/src/core/identity-session/RefreshManager.ts +189 -0
  212. package/src/core/identity-session/SessionManager.ts +500 -0
  213. package/src/core/identity-session/createIdentitySessionCore.ts +19 -0
  214. package/src/core/identity-session/errors.ts +197 -0
  215. package/src/core/identity-session/index.ts +15 -0
  216. package/src/core/identity-session/types.ts +188 -0
  217. package/src/core/index.ts +3 -4
  218. package/src/index.ts +28 -3
  219. package/src/models/interfaces.ts +12 -39
  220. package/src/models/session.ts +6 -16
  221. package/src/ui/context/OxyContext.tsx +442 -871
  222. package/src/ui/hooks/auth/index.ts +1 -0
  223. package/src/ui/hooks/useAvatarPicker.ts +62 -0
  224. package/src/ui/hooks/useIdentityTransfer.ts +135 -0
  225. package/src/ui/hooks/useTransferCodesPersistence.ts +80 -0
  226. package/src/ui/screens/AccountCenterScreen.tsx +7 -2
  227. package/src/ui/screens/AccountSettingsScreen.tsx +15 -8
  228. package/src/ui/screens/AccountSwitcherScreen.tsx +2 -2
  229. package/src/ui/screens/ProfileScreen.tsx +10 -10
  230. package/src/ui/utils/sessionHelpers.ts +7 -0
  231. package/src/utils/index.ts +1 -2
  232. package/src/utils/sessionUtils.ts +8 -0
  233. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +0 -732
  234. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +0 -1
  235. package/lib/commonjs/ui/context/hooks/useDeviceManagement.js +0 -73
  236. package/lib/commonjs/ui/context/hooks/useDeviceManagement.js.map +0 -1
  237. package/lib/commonjs/ui/hooks/useDeviceManagement.js +0 -73
  238. package/lib/commonjs/ui/hooks/useDeviceManagement.js.map +0 -1
  239. package/lib/commonjs/ui/hooks/useSessionManagement.js +0 -281
  240. package/lib/commonjs/ui/hooks/useSessionManagement.js.map +0 -1
  241. package/lib/commonjs/utils/deviceManager.js +0 -177
  242. package/lib/commonjs/utils/deviceManager.js.map +0 -1
  243. package/lib/module/ui/context/hooks/useAuthOperations.js +0 -726
  244. package/lib/module/ui/context/hooks/useAuthOperations.js.map +0 -1
  245. package/lib/module/ui/context/hooks/useDeviceManagement.js +0 -68
  246. package/lib/module/ui/context/hooks/useDeviceManagement.js.map +0 -1
  247. package/lib/module/ui/hooks/useDeviceManagement.js +0 -68
  248. package/lib/module/ui/hooks/useDeviceManagement.js.map +0 -1
  249. package/lib/module/ui/hooks/useSessionManagement.js +0 -276
  250. package/lib/module/ui/hooks/useSessionManagement.js.map +0 -1
  251. package/lib/module/utils/deviceManager.js +0 -171
  252. package/lib/module/utils/deviceManager.js.map +0 -1
  253. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +0 -59
  254. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +0 -1
  255. package/lib/typescript/ui/context/hooks/useDeviceManagement.d.ts +0 -27
  256. package/lib/typescript/ui/context/hooks/useDeviceManagement.d.ts.map +0 -1
  257. package/lib/typescript/ui/hooks/useDeviceManagement.d.ts +0 -27
  258. package/lib/typescript/ui/hooks/useDeviceManagement.d.ts.map +0 -1
  259. package/lib/typescript/ui/hooks/useSessionManagement.d.ts +0 -41
  260. package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +0 -1
  261. package/lib/typescript/utils/deviceManager.d.ts +0 -66
  262. package/lib/typescript/utils/deviceManager.d.ts.map +0 -1
  263. package/src/ui/context/hooks/useAuthOperations.ts +0 -801
  264. package/src/ui/context/hooks/useDeviceManagement.ts +0 -108
  265. package/src/ui/hooks/useDeviceManagement.ts +0 -108
  266. package/src/ui/hooks/useSessionManagement.ts +0 -401
  267. package/src/utils/deviceManager.ts +0 -198
@@ -0,0 +1,500 @@
1
+ /**
2
+ * Session Manager
3
+ *
4
+ * Manages user sessions (Native + Web)
5
+ * Handles session creation, storage, refresh, and invalidation.
6
+ */
7
+
8
+ import { jwtDecode } from 'jwt-decode';
9
+ import type { PlatformAdapter } from '../../adapters';
10
+ import type { Session, Identity } from './types';
11
+ import { DeviceManager } from './DeviceManager';
12
+ import { RefreshManager } from './RefreshManager';
13
+ import {
14
+ createIdentitySessionError,
15
+ IdentitySessionErrorCodes,
16
+ } from './errors';
17
+
18
+ const SESSION_STORAGE_KEY = 'oxy_sessions';
19
+ const ACTIVE_SESSION_ID_KEY = 'oxy_active_session_id';
20
+ const TOKEN_STORAGE_KEY = 'oxy_tokens';
21
+
22
+ interface AccessTokenPayload {
23
+ userId: string; // MongoDB ObjectId
24
+ sessionId: string; // Session UUID
25
+ deviceId: string; // Device identifier
26
+ type: 'access';
27
+ iat?: number;
28
+ exp?: number;
29
+ }
30
+
31
+ interface TokenStore {
32
+ accessToken: string | null;
33
+ refreshToken: string | null;
34
+ }
35
+
36
+ /**
37
+ * Session Manager Class
38
+ */
39
+ export class SessionManager {
40
+ private adapter: PlatformAdapter;
41
+ private deviceManager: DeviceManager;
42
+ private refreshManager: RefreshManager;
43
+ private baseURL: string | null = null;
44
+ private cachedSessions: Session[] | null = null;
45
+ private cachedActiveSessionId: string | null = null;
46
+ private tokenStore: TokenStore = {
47
+ accessToken: null,
48
+ refreshToken: null,
49
+ };
50
+
51
+ constructor(
52
+ adapter: PlatformAdapter,
53
+ deviceManager: DeviceManager,
54
+ refreshManager: RefreshManager,
55
+ baseURL?: string
56
+ ) {
57
+ this.adapter = adapter;
58
+ this.deviceManager = deviceManager;
59
+ this.refreshManager = refreshManager;
60
+ this.baseURL = baseURL || null;
61
+
62
+ if (baseURL) {
63
+ this.refreshManager.setBaseURL(baseURL);
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Set base URL for API requests
69
+ */
70
+ setBaseURL(baseURL: string): void {
71
+ this.baseURL = baseURL;
72
+ this.refreshManager.setBaseURL(baseURL);
73
+ }
74
+
75
+ /**
76
+ * Invalidate cached sessions
77
+ */
78
+ invalidateCache(): void {
79
+ this.cachedSessions = null;
80
+ this.cachedActiveSessionId = null;
81
+ }
82
+
83
+ /**
84
+ * Load tokens from storage
85
+ */
86
+ private async loadTokens(): Promise<void> {
87
+ try {
88
+ const stored = await this.adapter.storage.get(TOKEN_STORAGE_KEY);
89
+ if (stored) {
90
+ this.tokenStore = JSON.parse(stored);
91
+ }
92
+ } catch (error) {
93
+ console.warn('[SessionManager] Failed to load tokens:', error);
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Save tokens to storage
99
+ */
100
+ private async saveTokens(): Promise<void> {
101
+ try {
102
+ await this.adapter.storage.set(TOKEN_STORAGE_KEY, JSON.stringify(this.tokenStore));
103
+ } catch (error) {
104
+ console.warn('[SessionManager] Failed to save tokens:', error);
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Get access token
110
+ */
111
+ getAccessToken(): string | null {
112
+ return this.tokenStore.accessToken;
113
+ }
114
+
115
+ /**
116
+ * Get refresh token
117
+ */
118
+ getRefreshToken(): string | null {
119
+ return this.tokenStore.refreshToken;
120
+ }
121
+
122
+ /**
123
+ * Set tokens
124
+ */
125
+ async setTokens(accessToken: string, refreshToken?: string): Promise<void> {
126
+ this.tokenStore.accessToken = accessToken;
127
+ if (refreshToken) {
128
+ this.tokenStore.refreshToken = refreshToken;
129
+ }
130
+ await this.saveTokens();
131
+ }
132
+
133
+ /**
134
+ * Clear tokens
135
+ */
136
+ async clearTokens(): Promise<void> {
137
+ this.tokenStore.accessToken = null;
138
+ this.tokenStore.refreshToken = null;
139
+ await this.saveTokens();
140
+ }
141
+
142
+ /**
143
+ * Load sessions from storage
144
+ */
145
+ async loadSessions(): Promise<Session[]> {
146
+ if (this.cachedSessions) {
147
+ return this.cachedSessions;
148
+ }
149
+
150
+ try {
151
+ const stored = await this.adapter.storage.get(SESSION_STORAGE_KEY);
152
+ if (stored) {
153
+ this.cachedSessions = JSON.parse(stored);
154
+ return this.cachedSessions || [];
155
+ }
156
+ } catch (error) {
157
+ console.warn('[SessionManager] Failed to load sessions:', error);
158
+ }
159
+
160
+ this.cachedSessions = [];
161
+ return [];
162
+ }
163
+
164
+ /**
165
+ * Save sessions to storage
166
+ */
167
+ private async saveSessions(sessions: Session[]): Promise<void> {
168
+ try {
169
+ await this.adapter.storage.set(SESSION_STORAGE_KEY, JSON.stringify(sessions));
170
+ this.cachedSessions = sessions;
171
+ } catch (error) {
172
+ console.warn('[SessionManager] Failed to save sessions:', error);
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Get active session ID
178
+ */
179
+ async getActiveSessionId(): Promise<string | null> {
180
+ if (this.cachedActiveSessionId !== null) {
181
+ return this.cachedActiveSessionId;
182
+ }
183
+
184
+ try {
185
+ const stored = await this.adapter.storage.get(ACTIVE_SESSION_ID_KEY);
186
+ this.cachedActiveSessionId = stored;
187
+ return stored;
188
+ } catch (error) {
189
+ console.warn('[SessionManager] Failed to load active session ID:', error);
190
+ return null;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Set active session ID
196
+ */
197
+ async setActiveSessionId(sessionId: string | null): Promise<void> {
198
+ try {
199
+ if (sessionId) {
200
+ await this.adapter.storage.set(ACTIVE_SESSION_ID_KEY, sessionId);
201
+ } else {
202
+ await this.adapter.storage.remove(ACTIVE_SESSION_ID_KEY);
203
+ }
204
+ this.cachedActiveSessionId = sessionId;
205
+ } catch (error) {
206
+ console.warn('[SessionManager] Failed to save active session ID:', error);
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Get all sessions
212
+ */
213
+ async getAllSessions(): Promise<Session[]> {
214
+ return await this.loadSessions();
215
+ }
216
+
217
+ /**
218
+ * Get current session
219
+ */
220
+ async getSession(): Promise<Session | null> {
221
+ await this.loadTokens();
222
+ const accessToken = this.getAccessToken();
223
+ if (!accessToken) {
224
+ return null;
225
+ }
226
+
227
+ try {
228
+ const decoded = jwtDecode<AccessTokenPayload>(accessToken);
229
+ const sessionId = decoded.sessionId;
230
+ const userId = decoded.userId;
231
+
232
+ if (!sessionId || !userId) {
233
+ return null;
234
+ }
235
+
236
+ const sessions = await this.loadSessions();
237
+ const session = sessions.find(s => s.sessionId === sessionId);
238
+
239
+ if (session) {
240
+ return session;
241
+ }
242
+
243
+ // Create session from token if not found in storage
244
+ const device = await this.deviceManager.getCurrentDevice();
245
+ if (!device) {
246
+ return null;
247
+ }
248
+
249
+ const deviceInfo = await this.deviceManager.getDeviceInfo();
250
+
251
+ return {
252
+ sessionId,
253
+ userId,
254
+ deviceId: device.deviceId,
255
+ expiresAt: decoded.exp ? new Date(decoded.exp * 1000).toISOString() : new Date(Date.now() + 3600000).toISOString(),
256
+ lastActive: new Date().toISOString(),
257
+ deviceInfo,
258
+ isCurrent: true,
259
+ accessToken,
260
+ };
261
+ } catch (error) {
262
+ console.warn('[SessionManager] Failed to decode token:', error);
263
+ return null;
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Create a new session (sign in)
269
+ */
270
+ async createSession(
271
+ publicKey: string,
272
+ signature: string,
273
+ timestamp: number,
274
+ deviceName?: string
275
+ ): Promise<Session> {
276
+ if (!this.baseURL) {
277
+ throw createIdentitySessionError(
278
+ IdentitySessionErrorCodes.SESSION_CREATION_FAILED,
279
+ 'Base URL not set for session creation'
280
+ );
281
+ }
282
+
283
+ const device = await this.deviceManager.getCurrentDevice();
284
+ if (!device) {
285
+ throw createIdentitySessionError(
286
+ IdentitySessionErrorCodes.DEVICE_NOT_FOUND,
287
+ 'Device not found'
288
+ );
289
+ }
290
+
291
+ // Update device name if provided
292
+ if (deviceName) {
293
+ await this.deviceManager.updateDeviceName(deviceName);
294
+ }
295
+
296
+ const deviceInfo = await this.deviceManager.getDeviceInfo();
297
+
298
+ try {
299
+ const response = await this.adapter.fetch.fetch(`${this.baseURL}/api/auth/login`, {
300
+ method: 'POST',
301
+ headers: {
302
+ 'Content-Type': 'application/json',
303
+ 'Accept': 'application/json',
304
+ },
305
+ body: JSON.stringify({
306
+ publicKey,
307
+ signature,
308
+ timestamp,
309
+ deviceId: device.deviceId,
310
+ deviceInfo,
311
+ }),
312
+ });
313
+
314
+ if (!response.ok) {
315
+ const errorData = await response.json().catch(() => ({}));
316
+ throw createIdentitySessionError(
317
+ IdentitySessionErrorCodes.SESSION_CREATION_FAILED,
318
+ errorData.message || `Login failed: ${response.status}`,
319
+ response.status
320
+ );
321
+ }
322
+
323
+ const data = await response.json();
324
+ const { accessToken, refreshToken, user, sessionId, deviceId, expiresAt } = data;
325
+
326
+ if (!accessToken || !sessionId) {
327
+ throw createIdentitySessionError(
328
+ IdentitySessionErrorCodes.SESSION_CREATION_FAILED,
329
+ 'Invalid response from login endpoint'
330
+ );
331
+ }
332
+
333
+ // Set tokens
334
+ await this.setTokens(accessToken, refreshToken);
335
+
336
+ // Create session object
337
+ const session: Session = {
338
+ sessionId,
339
+ userId: user.id || user._id, // MongoDB ObjectId
340
+ deviceId: deviceId || device.deviceId,
341
+ expiresAt: expiresAt || new Date(Date.now() + 3600000).toISOString(),
342
+ lastActive: new Date().toISOString(),
343
+ deviceInfo,
344
+ isCurrent: true,
345
+ accessToken,
346
+ refreshToken,
347
+ };
348
+
349
+ // Save session
350
+ const sessions = await this.loadSessions();
351
+ const existingIndex = sessions.findIndex(s => s.sessionId === sessionId);
352
+ if (existingIndex >= 0) {
353
+ sessions[existingIndex] = session;
354
+ } else {
355
+ sessions.push(session);
356
+ }
357
+
358
+ // Mark all other sessions as not current
359
+ sessions.forEach(s => {
360
+ if (s.sessionId !== sessionId) {
361
+ s.isCurrent = false;
362
+ }
363
+ });
364
+
365
+ await this.saveSessions(sessions);
366
+ await this.setActiveSessionId(sessionId);
367
+
368
+ return session;
369
+ } catch (error) {
370
+ if (error instanceof Error && error.name === 'IdentitySessionError') {
371
+ throw error;
372
+ }
373
+ throw createIdentitySessionError(
374
+ IdentitySessionErrorCodes.SESSION_CREATION_FAILED,
375
+ `Failed to create session: ${error instanceof Error ? error.message : String(error)}`
376
+ );
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Refresh current session
382
+ */
383
+ async refreshSession(): Promise<Session> {
384
+ const session = await this.getSession();
385
+ if (!session) {
386
+ throw createIdentitySessionError(
387
+ IdentitySessionErrorCodes.SESSION_NOT_FOUND,
388
+ 'No active session to refresh'
389
+ );
390
+ }
391
+
392
+ // Refresh token first
393
+ await this.refreshManager.refreshTokenIfNeeded(
394
+ () => this.getAccessToken(),
395
+ (accessToken, refreshToken) => this.setTokens(accessToken, refreshToken),
396
+ () => this.clearTokens()
397
+ );
398
+
399
+ // Get updated session
400
+ const refreshedSession = await this.getSession();
401
+ if (!refreshedSession) {
402
+ throw createIdentitySessionError(
403
+ IdentitySessionErrorCodes.SESSION_REFRESH_FAILED,
404
+ 'Session not found after refresh'
405
+ );
406
+ }
407
+
408
+ // Update session in storage
409
+ const sessions = await this.loadSessions();
410
+ const index = sessions.findIndex(s => s.sessionId === refreshedSession.sessionId);
411
+ if (index >= 0) {
412
+ sessions[index] = refreshedSession;
413
+ await this.saveSessions(sessions);
414
+ }
415
+
416
+ return refreshedSession;
417
+ }
418
+
419
+ /**
420
+ * Invalidate a session
421
+ */
422
+ async invalidateSession(sessionId?: string): Promise<void> {
423
+ const targetSessionId = sessionId || await this.getActiveSessionId();
424
+ if (!targetSessionId) {
425
+ return;
426
+ }
427
+
428
+ if (!this.baseURL) {
429
+ // Just clear local storage if no base URL
430
+ await this.clearLocalSession(targetSessionId);
431
+ return;
432
+ }
433
+
434
+ try {
435
+ await this.adapter.fetch.fetch(`${this.baseURL}/api/session/${targetSessionId}/logout`, {
436
+ method: 'POST',
437
+ headers: {
438
+ 'Accept': 'application/json',
439
+ },
440
+ });
441
+ } catch (error) {
442
+ // Continue with local cleanup even if API call fails
443
+ console.warn('[SessionManager] Failed to invalidate session on server:', error);
444
+ }
445
+
446
+ await this.clearLocalSession(targetSessionId);
447
+ }
448
+
449
+ /**
450
+ * Clear local session data
451
+ */
452
+ private async clearLocalSession(sessionId: string): Promise<void> {
453
+ const sessions = await this.loadSessions();
454
+ const filtered = sessions.filter(s => s.sessionId !== sessionId);
455
+ await this.saveSessions(filtered);
456
+
457
+ // If this was the active session, clear it
458
+ const activeSessionId = await this.getActiveSessionId();
459
+ if (activeSessionId === sessionId) {
460
+ await this.setActiveSessionId(null);
461
+ await this.clearTokens();
462
+ }
463
+ }
464
+
465
+ /**
466
+ * Invalidate all sessions
467
+ */
468
+ async invalidateAllSessions(): Promise<void> {
469
+ const sessions = await this.loadSessions();
470
+
471
+ if (this.baseURL) {
472
+ // Try to invalidate all sessions on server
473
+ await Promise.allSettled(
474
+ sessions.map(session =>
475
+ this.adapter.fetch.fetch(`${this.baseURL}/api/session/${session.sessionId}/logout`, {
476
+ method: 'POST',
477
+ headers: { 'Accept': 'application/json' },
478
+ }).catch(() => {
479
+ // Ignore individual failures
480
+ })
481
+ )
482
+ );
483
+ }
484
+
485
+ // Clear all local session data
486
+ await this.saveSessions([]);
487
+ await this.setActiveSessionId(null);
488
+ await this.clearTokens();
489
+ this.invalidateCache();
490
+ }
491
+
492
+ /**
493
+ * Initialize - load tokens and sessions from storage
494
+ */
495
+ async initialize(): Promise<void> {
496
+ await this.loadTokens();
497
+ await this.loadSessions();
498
+ }
499
+ }
500
+
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Create Identity Session Core
3
+ *
4
+ * Factory function to create and initialize IdentitySessionCore
5
+ */
6
+
7
+ import { createPlatformAdapter } from '../../adapters';
8
+ import { IdentitySessionCore } from './IdentitySessionCore';
9
+
10
+ /**
11
+ * Create and initialize IdentitySessionCore
12
+ */
13
+ export async function createIdentitySessionCore(baseURL?: string): Promise<IdentitySessionCore> {
14
+ const adapter = await createPlatformAdapter();
15
+ const core = new IdentitySessionCore(adapter, baseURL);
16
+ await core.initialize();
17
+ return core;
18
+ }
19
+