@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,464 @@
1
+ /**
2
+ * Identity Session Core
3
+ *
4
+ * Main orchestrator for identity and session management.
5
+ * Provides a unified API for all identity and session operations.
6
+ */
7
+
8
+ import type { PlatformAdapter } from '../../adapters';
9
+ import type { Identity, Session, Device, BackupData, IdentitySessionEvent } from './types';
10
+ import { IdentityManager } from './IdentityManager';
11
+ import { SessionManager } from './SessionManager';
12
+ import { DeviceManager } from './DeviceManager';
13
+ import { RefreshManager } from './RefreshManager';
14
+ import {
15
+ createIdentitySessionError,
16
+ IdentitySessionErrorCodes,
17
+ } from './errors';
18
+
19
+ /**
20
+ * Identity Session Core Class
21
+ */
22
+ export class IdentitySessionCore {
23
+ private adapter: PlatformAdapter;
24
+ private identityManager: IdentityManager;
25
+ private sessionManager: SessionManager;
26
+ private deviceManager: DeviceManager;
27
+ private refreshManager: RefreshManager;
28
+ private baseURL: string | null = null;
29
+ private eventListeners: Set<(event: IdentitySessionEvent) => void> = new Set();
30
+ private initialized: boolean = false;
31
+
32
+ constructor(adapter: PlatformAdapter, baseURL?: string) {
33
+ this.adapter = adapter;
34
+ this.baseURL = baseURL || null;
35
+
36
+ // Initialize managers
37
+ this.identityManager = new IdentityManager(adapter);
38
+ this.deviceManager = new DeviceManager(adapter);
39
+ this.refreshManager = new RefreshManager(adapter, baseURL);
40
+ this.sessionManager = new SessionManager(
41
+ adapter,
42
+ this.deviceManager,
43
+ this.refreshManager,
44
+ baseURL
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Set base URL for API requests
50
+ */
51
+ setBaseURL(baseURL: string): void {
52
+ this.baseURL = baseURL;
53
+ this.sessionManager.setBaseURL(baseURL);
54
+ this.refreshManager.setBaseURL(baseURL);
55
+ }
56
+
57
+ /**
58
+ * Initialize the core (load data from storage)
59
+ */
60
+ async initialize(): Promise<void> {
61
+ if (this.initialized) {
62
+ return;
63
+ }
64
+
65
+ await this.sessionManager.initialize();
66
+ this.initialized = true;
67
+ }
68
+
69
+ /**
70
+ * Emit an event to all subscribers
71
+ */
72
+ private emit(event: IdentitySessionEvent): void {
73
+ this.eventListeners.forEach(listener => {
74
+ try {
75
+ listener(event);
76
+ } catch (error) {
77
+ console.error('[IdentitySessionCore] Error in event listener:', error);
78
+ }
79
+ });
80
+ }
81
+
82
+ // ==================== Identity Operations ====================
83
+
84
+ /**
85
+ * Get current identity (SOLO NATIVE)
86
+ */
87
+ async getCurrentIdentity(): Promise<Identity | null> {
88
+ if (this.adapter.platform !== 'native') {
89
+ return null; // Identity only exists on native
90
+ }
91
+
92
+ const publicKey = await this.identityManager.getPublicKey();
93
+ if (!publicKey) {
94
+ return null;
95
+ }
96
+
97
+ // Identity object would need to be fetched from server
98
+ // For now, return a minimal identity object
99
+ return {
100
+ id: '', // Would be fetched from server
101
+ publicKey,
102
+ } as Identity;
103
+ }
104
+
105
+ /**
106
+ * Create a new identity (SOLO NATIVE)
107
+ */
108
+ async createIdentity(username?: string): Promise<Identity> {
109
+ if (this.adapter.platform !== 'native') {
110
+ throw createIdentitySessionError(
111
+ IdentitySessionErrorCodes.IDENTITY_NOT_AVAILABLE_ON_WEB,
112
+ 'Identity creation is only available on native platforms'
113
+ );
114
+ }
115
+
116
+ try {
117
+ const publicKey = await this.identityManager.createIdentity();
118
+
119
+ const identity: Identity = {
120
+ id: '', // Will be set after sync with server
121
+ publicKey,
122
+ username,
123
+ };
124
+
125
+ this.emit({ type: 'identity:created', identity });
126
+ return identity;
127
+ } catch (error) {
128
+ throw createIdentitySessionError(
129
+ IdentitySessionErrorCodes.IDENTITY_CREATION_FAILED,
130
+ `Failed to create identity: ${error instanceof Error ? error.message : String(error)}`
131
+ );
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Import identity from backup (SOLO NATIVE)
137
+ */
138
+ async importIdentity(backupData: BackupData, password: string): Promise<Identity> {
139
+ if (this.adapter.platform !== 'native') {
140
+ throw createIdentitySessionError(
141
+ IdentitySessionErrorCodes.IDENTITY_NOT_AVAILABLE_ON_WEB,
142
+ 'Identity import is only available on native platforms'
143
+ );
144
+ }
145
+
146
+ try {
147
+ const publicKey = await this.identityManager.decryptAndImportBackup(backupData, password);
148
+
149
+ const identity: Identity = {
150
+ id: '', // Will be set after sync with server
151
+ publicKey,
152
+ };
153
+
154
+ this.emit({ type: 'identity:imported', identity });
155
+ return identity;
156
+ } catch (error) {
157
+ throw createIdentitySessionError(
158
+ IdentitySessionErrorCodes.IDENTITY_IMPORT_FAILED,
159
+ `Failed to import identity: ${error instanceof Error ? error.message : String(error)}`
160
+ );
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Delete identity (SOLO NATIVE)
166
+ */
167
+ async deleteIdentity(
168
+ skipBackup: boolean = false,
169
+ force: boolean = false,
170
+ userConfirmed: boolean = false
171
+ ): Promise<void> {
172
+ if (this.adapter.platform !== 'native') {
173
+ throw createIdentitySessionError(
174
+ IdentitySessionErrorCodes.IDENTITY_NOT_AVAILABLE_ON_WEB,
175
+ 'Identity deletion is only available on native platforms'
176
+ );
177
+ }
178
+
179
+ try {
180
+ await this.identityManager.deleteIdentity(skipBackup, force, userConfirmed);
181
+ this.emit({ type: 'identity:deleted' });
182
+ } catch (error) {
183
+ throw createIdentitySessionError(
184
+ IdentitySessionErrorCodes.IDENTITY_DELETE_FAILED,
185
+ `Failed to delete identity: ${error instanceof Error ? error.message : String(error)}`
186
+ );
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Sign a challenge (SOLO NATIVE)
192
+ */
193
+ async signChallenge(challenge: string): Promise<string> {
194
+ if (this.adapter.platform !== 'native') {
195
+ throw createIdentitySessionError(
196
+ IdentitySessionErrorCodes.IDENTITY_NOT_AVAILABLE_ON_WEB,
197
+ 'Challenge signing is only available on native platforms'
198
+ );
199
+ }
200
+
201
+ try {
202
+ return await this.identityManager.signChallenge(challenge);
203
+ } catch (error) {
204
+ throw createIdentitySessionError(
205
+ IdentitySessionErrorCodes.IDENTITY_NOT_FOUND,
206
+ `Failed to sign challenge: ${error instanceof Error ? error.message : String(error)}`
207
+ );
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Generate a random challenge string
213
+ */
214
+ async generateChallenge(): Promise<string> {
215
+ const randomBytes = await this.adapter.crypto.getRandomBytes(32);
216
+ return Array.from(randomBytes, byte => byte.toString(16).padStart(2, '0')).join('');
217
+ }
218
+
219
+ /**
220
+ * Create a registration signature (SOLO NATIVE)
221
+ */
222
+ async createRegistrationSignature(): Promise<{ signature: string; publicKey: string; timestamp: number }> {
223
+ if (this.adapter.platform !== 'native') {
224
+ throw createIdentitySessionError(
225
+ IdentitySessionErrorCodes.IDENTITY_NOT_AVAILABLE_ON_WEB,
226
+ 'Registration signature is only available on native platforms'
227
+ );
228
+ }
229
+
230
+ const publicKey = await this.identityManager.getPublicKey();
231
+ if (!publicKey) {
232
+ throw createIdentitySessionError(
233
+ IdentitySessionErrorCodes.IDENTITY_NOT_FOUND,
234
+ 'No identity found. Please create or import an identity first.'
235
+ );
236
+ }
237
+
238
+ const timestamp = Date.now();
239
+ const message = `oxy:register:${publicKey}:${timestamp}`;
240
+ const messageHash = await this.adapter.crypto.digestStringAsync('SHA256', message);
241
+ const signature = await this.identityManager.signChallenge(messageHash);
242
+
243
+ return {
244
+ signature,
245
+ publicKey,
246
+ timestamp,
247
+ };
248
+ }
249
+
250
+ /**
251
+ * Sign challenge for authentication (SOLO NATIVE)
252
+ * Returns AuthChallenge object with signature, publicKey, and timestamp
253
+ */
254
+ async signChallengeForAuth(challenge: string): Promise<{ challenge: string; signature: string; publicKey: string; timestamp: number }> {
255
+ if (this.adapter.platform !== 'native') {
256
+ throw createIdentitySessionError(
257
+ IdentitySessionErrorCodes.IDENTITY_NOT_AVAILABLE_ON_WEB,
258
+ 'Challenge signing is only available on native platforms'
259
+ );
260
+ }
261
+
262
+ const publicKey = await this.identityManager.getPublicKey();
263
+ if (!publicKey) {
264
+ throw createIdentitySessionError(
265
+ IdentitySessionErrorCodes.IDENTITY_NOT_FOUND,
266
+ 'No identity found. Please create or import an identity first.'
267
+ );
268
+ }
269
+
270
+ const timestamp = Date.now();
271
+ const message = `auth:${publicKey}:${challenge}:${timestamp}`;
272
+ const messageHash = await this.adapter.crypto.digestStringAsync('SHA256', message);
273
+ const signature = await this.identityManager.signChallenge(messageHash);
274
+
275
+ return {
276
+ challenge,
277
+ signature,
278
+ publicKey,
279
+ timestamp,
280
+ };
281
+ }
282
+
283
+ /**
284
+ * Check if identity exists
285
+ */
286
+ async hasIdentity(): Promise<boolean> {
287
+ return await this.identityManager.hasIdentity();
288
+ }
289
+
290
+ /**
291
+ * Get public key
292
+ */
293
+ async getPublicKey(): Promise<string | null> {
294
+ return await this.identityManager.getPublicKey();
295
+ }
296
+
297
+ // ==================== Session Operations ====================
298
+
299
+ /**
300
+ * Get current session (Native + Web)
301
+ */
302
+ async getSession(): Promise<Session | null> {
303
+ return await this.sessionManager.getSession();
304
+ }
305
+
306
+ /**
307
+ * Get all sessions (Native + Web)
308
+ */
309
+ async getAllSessions(): Promise<Session[]> {
310
+ return await this.sessionManager.getAllSessions();
311
+ }
312
+
313
+ /**
314
+ * Get active session ID (Native + Web)
315
+ */
316
+ async getActiveSessionId(): Promise<string | null> {
317
+ return await this.sessionManager.getActiveSessionId();
318
+ }
319
+
320
+ /**
321
+ * Create a new session (sign in) (Native + Web)
322
+ */
323
+ async createSession(deviceName?: string): Promise<Session> {
324
+ if (this.adapter.platform !== 'native') {
325
+ throw createIdentitySessionError(
326
+ IdentitySessionErrorCodes.IDENTITY_NOT_AVAILABLE_ON_WEB,
327
+ 'Session creation requires identity, which is only available on native platforms'
328
+ );
329
+ }
330
+
331
+ const publicKey = await this.identityManager.getPublicKey();
332
+ if (!publicKey) {
333
+ throw createIdentitySessionError(
334
+ IdentitySessionErrorCodes.IDENTITY_NOT_FOUND,
335
+ 'No identity found. Please create or import an identity first.'
336
+ );
337
+ }
338
+
339
+ // Generate challenge and sign it
340
+ const timestamp = Date.now();
341
+ const challenge = `auth:${publicKey}:${timestamp}`;
342
+ const signature = await this.identityManager.signChallenge(challenge);
343
+
344
+ try {
345
+ const session = await this.sessionManager.createSession(
346
+ publicKey,
347
+ signature,
348
+ timestamp,
349
+ deviceName
350
+ );
351
+
352
+ this.emit({ type: 'session:created', session });
353
+ return session;
354
+ } catch (error) {
355
+ throw createIdentitySessionError(
356
+ IdentitySessionErrorCodes.SESSION_CREATION_FAILED,
357
+ `Failed to create session: ${error instanceof Error ? error.message : String(error)}`
358
+ );
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Refresh current session (Native + Web)
364
+ */
365
+ async refreshSession(): Promise<Session> {
366
+ try {
367
+ const session = await this.sessionManager.refreshSession();
368
+ this.emit({ type: 'session:refreshed', session });
369
+ return session;
370
+ } catch (error) {
371
+ throw createIdentitySessionError(
372
+ IdentitySessionErrorCodes.SESSION_REFRESH_FAILED,
373
+ `Failed to refresh session: ${error instanceof Error ? error.message : String(error)}`
374
+ );
375
+ }
376
+ }
377
+
378
+ /**
379
+ * Invalidate a session (Native + Web)
380
+ */
381
+ async invalidateSession(sessionId?: string): Promise<void> {
382
+ try {
383
+ await this.sessionManager.invalidateSession(sessionId);
384
+ const targetSessionId = sessionId || await this.sessionManager.getActiveSessionId();
385
+ if (targetSessionId) {
386
+ this.emit({ type: 'session:invalidated', sessionId: targetSessionId });
387
+ }
388
+ } catch (error) {
389
+ throw createIdentitySessionError(
390
+ IdentitySessionErrorCodes.SESSION_INVALID,
391
+ `Failed to invalidate session: ${error instanceof Error ? error.message : String(error)}`
392
+ );
393
+ }
394
+ }
395
+
396
+ /**
397
+ * Invalidate all sessions (Native + Web)
398
+ */
399
+ async invalidateAllSessions(): Promise<void> {
400
+ try {
401
+ await this.sessionManager.invalidateAllSessions();
402
+ this.emit({ type: 'session:all-invalidated' });
403
+ } catch (error) {
404
+ throw createIdentitySessionError(
405
+ IdentitySessionErrorCodes.SESSION_INVALID,
406
+ `Failed to invalidate all sessions: ${error instanceof Error ? error.message : String(error)}`
407
+ );
408
+ }
409
+ }
410
+
411
+ // ==================== Device Operations ====================
412
+
413
+ /**
414
+ * Get current device (Native + Web)
415
+ */
416
+ async getCurrentDevice(): Promise<Device | null> {
417
+ return await this.deviceManager.getCurrentDevice();
418
+ }
419
+
420
+ // ==================== Subscriptions ====================
421
+
422
+ /**
423
+ * Subscribe to identity and session events
424
+ */
425
+ subscribe(callback: (event: IdentitySessionEvent) => void): () => void {
426
+ this.eventListeners.add(callback);
427
+
428
+ // Return unsubscribe function
429
+ return () => {
430
+ this.eventListeners.delete(callback);
431
+ };
432
+ }
433
+
434
+ // ==================== Internal Access ====================
435
+
436
+ /**
437
+ * Get identity manager (for advanced operations)
438
+ */
439
+ getIdentityManager(): IdentityManager {
440
+ return this.identityManager;
441
+ }
442
+
443
+ /**
444
+ * Get session manager (for advanced operations)
445
+ */
446
+ getSessionManager(): SessionManager {
447
+ return this.sessionManager;
448
+ }
449
+
450
+ /**
451
+ * Get device manager (for advanced operations)
452
+ */
453
+ getDeviceManager(): DeviceManager {
454
+ return this.deviceManager;
455
+ }
456
+
457
+ /**
458
+ * Get refresh manager (for advanced operations)
459
+ */
460
+ getRefreshManager(): RefreshManager {
461
+ return this.refreshManager;
462
+ }
463
+ }
464
+
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Refresh Manager
3
+ *
4
+ * Manages token refresh operations (Native + Web)
5
+ */
6
+
7
+ import { jwtDecode } from 'jwt-decode';
8
+ import type { PlatformAdapter } from '../../adapters';
9
+ import {
10
+ createIdentitySessionError,
11
+ IdentitySessionErrorCodes,
12
+ } from './errors';
13
+
14
+ interface AccessTokenPayload {
15
+ userId: string; // MongoDB ObjectId
16
+ sessionId: string; // Session UUID
17
+ deviceId: string; // Device identifier
18
+ type: 'access';
19
+ iat?: number;
20
+ exp?: number;
21
+ }
22
+
23
+ /**
24
+ * Refresh Manager Class
25
+ */
26
+ export class RefreshManager {
27
+ private adapter: PlatformAdapter;
28
+ private baseURL: string | null = null;
29
+ private refreshPromise: Promise<void> | null = null;
30
+
31
+ constructor(adapter: PlatformAdapter, baseURL?: string) {
32
+ this.adapter = adapter;
33
+ this.baseURL = baseURL || null;
34
+ }
35
+
36
+ /**
37
+ * Set base URL for API requests
38
+ */
39
+ setBaseURL(baseURL: string): void {
40
+ this.baseURL = baseURL;
41
+ }
42
+
43
+ /**
44
+ * Check if token is expiring soon (within 60 seconds)
45
+ */
46
+ isTokenExpiringSoon(accessToken: string | null): boolean {
47
+ if (!accessToken) return false;
48
+
49
+ try {
50
+ const decoded = jwtDecode<AccessTokenPayload>(accessToken);
51
+ if (!decoded.exp) return false;
52
+
53
+ const currentTime = Math.floor(Date.now() / 1000);
54
+ return decoded.exp - currentTime < 60; // Expiring within 60 seconds
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Get userId from access token
62
+ */
63
+ getUserIdFromToken(accessToken: string | null): string | null {
64
+ if (!accessToken) return null;
65
+
66
+ try {
67
+ const decoded = jwtDecode<AccessTokenPayload>(accessToken);
68
+ return decoded.userId || null;
69
+ } catch {
70
+ return null;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Refresh access token if expiring soon
76
+ */
77
+ async refreshTokenIfNeeded(
78
+ getAccessToken: () => string | null,
79
+ setTokens: (accessToken: string, refreshToken?: string) => void,
80
+ clearTokens: () => void
81
+ ): Promise<void> {
82
+ // If already refreshing, wait for that promise
83
+ if (this.refreshPromise) {
84
+ return this.refreshPromise;
85
+ }
86
+
87
+ const accessToken = getAccessToken();
88
+ if (!accessToken) {
89
+ return; // No token to refresh
90
+ }
91
+
92
+ // If token not expiring soon, no refresh needed
93
+ if (!this.isTokenExpiringSoon(accessToken)) {
94
+ return;
95
+ }
96
+
97
+ // Start refresh
98
+ this.refreshPromise = this._performRefresh(
99
+ accessToken,
100
+ setTokens,
101
+ clearTokens
102
+ ).finally(() => {
103
+ this.refreshPromise = null;
104
+ });
105
+
106
+ return this.refreshPromise;
107
+ }
108
+
109
+ /**
110
+ * Perform token refresh
111
+ */
112
+ private async _performRefresh(
113
+ accessToken: string,
114
+ setTokens: (accessToken: string, refreshToken?: string) => void,
115
+ clearTokens: () => void
116
+ ): Promise<void> {
117
+ if (!this.baseURL) {
118
+ throw createIdentitySessionError(
119
+ IdentitySessionErrorCodes.SESSION_REFRESH_FAILED,
120
+ 'Base URL not set for refresh operations'
121
+ );
122
+ }
123
+
124
+ try {
125
+ const decoded = jwtDecode<AccessTokenPayload>(accessToken);
126
+ if (!decoded.sessionId) {
127
+ throw createIdentitySessionError(
128
+ IdentitySessionErrorCodes.MALFORMED_TOKEN,
129
+ 'Token missing sessionId'
130
+ );
131
+ }
132
+
133
+ const refreshUrl = `${this.baseURL}/api/session/token/${decoded.sessionId}`;
134
+
135
+ const response = await this.adapter.fetch.fetch(refreshUrl, {
136
+ method: 'GET',
137
+ headers: { 'Accept': 'application/json' },
138
+ signal: AbortSignal.timeout(5000),
139
+ });
140
+
141
+ if (!response.ok) {
142
+ if (response.status === 401 || response.status === 403) {
143
+ // Token is invalid, clear it
144
+ clearTokens();
145
+ throw createIdentitySessionError(
146
+ IdentitySessionErrorCodes.TOKEN_EXPIRED,
147
+ 'Token refresh failed: token is invalid'
148
+ );
149
+ }
150
+ throw createIdentitySessionError(
151
+ IdentitySessionErrorCodes.SESSION_REFRESH_FAILED,
152
+ `Token refresh failed: ${response.status}`
153
+ );
154
+ }
155
+
156
+ const data = await response.json();
157
+ const newAccessToken = data.accessToken;
158
+
159
+ if (!newAccessToken) {
160
+ throw createIdentitySessionError(
161
+ IdentitySessionErrorCodes.SESSION_REFRESH_FAILED,
162
+ 'No access token in refresh response'
163
+ );
164
+ }
165
+
166
+ // Validate new token has correct userId format (ObjectId)
167
+ const newDecoded = jwtDecode<AccessTokenPayload>(newAccessToken);
168
+ if (newDecoded.userId && !/^[0-9a-fA-F]{24}$/.test(newDecoded.userId)) {
169
+ throw createIdentitySessionError(
170
+ IdentitySessionErrorCodes.MALFORMED_TOKEN,
171
+ `Invalid userId format in refreshed token: ${newDecoded.userId.substring(0, 20)}...`
172
+ );
173
+ }
174
+
175
+ setTokens(newAccessToken, data.refreshToken);
176
+ } catch (error) {
177
+ // Clear tokens on refresh failure (likely expired or invalid)
178
+ clearTokens();
179
+ if (error instanceof Error && error.name === 'IdentitySessionError') {
180
+ throw error;
181
+ }
182
+ throw createIdentitySessionError(
183
+ IdentitySessionErrorCodes.SESSION_REFRESH_FAILED,
184
+ `Token refresh failed: ${error instanceof Error ? error.message : String(error)}`
185
+ );
186
+ }
187
+ }
188
+ }
189
+