@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.
- package/lib/commonjs/adapters/expo/crypto.js +56 -0
- package/lib/commonjs/adapters/expo/crypto.js.map +1 -0
- package/lib/commonjs/adapters/expo/fetch.js +30 -0
- package/lib/commonjs/adapters/expo/fetch.js.map +1 -0
- package/lib/commonjs/adapters/expo/index.js +48 -0
- package/lib/commonjs/adapters/expo/index.js.map +1 -0
- package/lib/commonjs/adapters/expo/storage.js +201 -0
- package/lib/commonjs/adapters/expo/storage.js.map +1 -0
- package/lib/commonjs/adapters/index.js +41 -0
- package/lib/commonjs/adapters/index.js.map +1 -0
- package/lib/commonjs/adapters/node/crypto.js +40 -0
- package/lib/commonjs/adapters/node/crypto.js.map +1 -0
- package/lib/commonjs/adapters/node/fetch.js +62 -0
- package/lib/commonjs/adapters/node/fetch.js.map +1 -0
- package/lib/commonjs/adapters/node/index.js +34 -0
- package/lib/commonjs/adapters/node/index.js.map +1 -0
- package/lib/commonjs/adapters/node/storage.js +163 -0
- package/lib/commonjs/adapters/node/storage.js.map +1 -0
- package/lib/commonjs/core/identity-session/DeviceManager.js +237 -0
- package/lib/commonjs/core/identity-session/DeviceManager.js.map +1 -0
- package/lib/commonjs/core/identity-session/INTEGRATION_GUIDE.md +287 -0
- package/lib/commonjs/core/identity-session/IdentityManager.js +400 -0
- package/lib/commonjs/core/identity-session/IdentityManager.js.map +1 -0
- package/lib/commonjs/core/identity-session/IdentitySessionCore.js +394 -0
- package/lib/commonjs/core/identity-session/IdentitySessionCore.js.map +1 -0
- package/lib/commonjs/core/identity-session/RefreshManager.js +137 -0
- package/lib/commonjs/core/identity-session/RefreshManager.js.map +1 -0
- package/lib/commonjs/core/identity-session/SessionManager.js +427 -0
- package/lib/commonjs/core/identity-session/SessionManager.js.map +1 -0
- package/lib/commonjs/core/identity-session/createIdentitySessionCore.js +24 -0
- package/lib/commonjs/core/identity-session/createIdentitySessionCore.js.map +1 -0
- package/lib/commonjs/core/identity-session/errors.js +176 -0
- package/lib/commonjs/core/identity-session/errors.js.map +1 -0
- package/lib/commonjs/core/identity-session/index.js +80 -0
- package/lib/commonjs/core/identity-session/index.js.map +1 -0
- package/lib/commonjs/core/identity-session/types.js +2 -0
- package/lib/commonjs/core/identity-session/types.js.map +1 -0
- package/lib/commonjs/core/index.js +2 -21
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/index.js +58 -8
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/interfaces.js +7 -0
- package/lib/commonjs/models/interfaces.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +434 -820
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useAvatarPicker.js +52 -0
- package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +1 -0
- package/lib/commonjs/ui/hooks/useIdentityTransfer.js +125 -0
- package/lib/commonjs/ui/hooks/useIdentityTransfer.js.map +1 -0
- package/lib/commonjs/ui/hooks/useTransferCodesPersistence.js +81 -0
- package/lib/commonjs/ui/hooks/useTransferCodesPersistence.js.map +1 -0
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +7 -2
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +12 -5
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +2 -2
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ProfileScreen.js +6 -6
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/utils/sessionHelpers.js +7 -1
- package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/commonjs/utils/index.js +0 -7
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/utils/sessionUtils.js +8 -1
- package/lib/commonjs/utils/sessionUtils.js.map +1 -1
- package/lib/module/adapters/expo/crypto.js +51 -0
- package/lib/module/adapters/expo/crypto.js.map +1 -0
- package/lib/module/adapters/expo/fetch.js +26 -0
- package/lib/module/adapters/expo/fetch.js.map +1 -0
- package/lib/module/adapters/expo/index.js +45 -0
- package/lib/module/adapters/expo/index.js.map +1 -0
- package/lib/module/adapters/expo/storage.js +198 -0
- package/lib/module/adapters/expo/storage.js.map +1 -0
- package/lib/module/adapters/index.js +38 -0
- package/lib/module/adapters/index.js.map +1 -0
- package/lib/module/adapters/node/crypto.js +36 -0
- package/lib/module/adapters/node/crypto.js.map +1 -0
- package/lib/module/adapters/node/fetch.js +57 -0
- package/lib/module/adapters/node/fetch.js.map +1 -0
- package/lib/module/adapters/node/index.js +31 -0
- package/lib/module/adapters/node/index.js.map +1 -0
- package/lib/module/adapters/node/storage.js +159 -0
- package/lib/module/adapters/node/storage.js.map +1 -0
- package/lib/module/core/identity-session/DeviceManager.js +232 -0
- package/lib/module/core/identity-session/DeviceManager.js.map +1 -0
- package/lib/module/core/identity-session/INTEGRATION_GUIDE.md +287 -0
- package/lib/module/core/identity-session/IdentityManager.js +395 -0
- package/lib/module/core/identity-session/IdentityManager.js.map +1 -0
- package/lib/module/core/identity-session/IdentitySessionCore.js +390 -0
- package/lib/module/core/identity-session/IdentitySessionCore.js.map +1 -0
- package/lib/module/core/identity-session/RefreshManager.js +132 -0
- package/lib/module/core/identity-session/RefreshManager.js.map +1 -0
- package/lib/module/core/identity-session/SessionManager.js +422 -0
- package/lib/module/core/identity-session/SessionManager.js.map +1 -0
- package/lib/module/core/identity-session/createIdentitySessionCore.js +21 -0
- package/lib/module/core/identity-session/createIdentitySessionCore.js.map +1 -0
- package/lib/module/core/identity-session/errors.js +170 -0
- package/lib/module/core/identity-session/errors.js.map +1 -0
- package/lib/module/core/identity-session/index.js +17 -0
- package/lib/module/core/identity-session/index.js.map +1 -0
- package/lib/module/core/identity-session/types.js +2 -0
- package/lib/module/core/identity-session/types.js.map +1 -0
- package/lib/module/core/index.js +2 -3
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/index.js +12 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/interfaces.js +7 -0
- package/lib/module/models/interfaces.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +436 -822
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useAvatarPicker.js +48 -0
- package/lib/module/ui/hooks/useAvatarPicker.js.map +1 -0
- package/lib/module/ui/hooks/useIdentityTransfer.js +121 -0
- package/lib/module/ui/hooks/useIdentityTransfer.js.map +1 -0
- package/lib/module/ui/hooks/useTransferCodesPersistence.js +77 -0
- package/lib/module/ui/hooks/useTransferCodesPersistence.js.map +1 -0
- package/lib/module/ui/screens/AccountCenterScreen.js +7 -2
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +12 -5
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +2 -2
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +6 -6
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/utils/sessionHelpers.js +7 -1
- package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/module/utils/index.js +2 -1
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/sessionUtils.js +8 -1
- package/lib/module/utils/sessionUtils.js.map +1 -1
- package/lib/typescript/adapters/expo/crypto.d.ts +17 -0
- package/lib/typescript/adapters/expo/crypto.d.ts.map +1 -0
- package/lib/typescript/adapters/expo/fetch.d.ts +16 -0
- package/lib/typescript/adapters/expo/fetch.d.ts.map +1 -0
- package/lib/typescript/adapters/expo/index.d.ts +23 -0
- package/lib/typescript/adapters/expo/index.d.ts.map +1 -0
- package/lib/typescript/adapters/expo/storage.d.ts +23 -0
- package/lib/typescript/adapters/expo/storage.d.ts.map +1 -0
- package/lib/typescript/adapters/index.d.ts +13 -0
- package/lib/typescript/adapters/index.d.ts.map +1 -0
- package/lib/typescript/adapters/node/crypto.d.ts +17 -0
- package/lib/typescript/adapters/node/crypto.d.ts.map +1 -0
- package/lib/typescript/adapters/node/fetch.d.ts +16 -0
- package/lib/typescript/adapters/node/fetch.d.ts.map +1 -0
- package/lib/typescript/adapters/node/index.d.ts +23 -0
- package/lib/typescript/adapters/node/index.d.ts.map +1 -0
- package/lib/typescript/adapters/node/storage.d.ts +23 -0
- package/lib/typescript/adapters/node/storage.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/DeviceManager.d.ts +64 -0
- package/lib/typescript/core/identity-session/DeviceManager.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/IdentityManager.d.ts +88 -0
- package/lib/typescript/core/identity-session/IdentityManager.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/IdentitySessionCore.d.ts +141 -0
- package/lib/typescript/core/identity-session/IdentitySessionCore.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/RefreshManager.d.ts +36 -0
- package/lib/typescript/core/identity-session/RefreshManager.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/SessionManager.d.ts +104 -0
- package/lib/typescript/core/identity-session/SessionManager.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/createIdentitySessionCore.d.ts +11 -0
- package/lib/typescript/core/identity-session/createIdentitySessionCore.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/errors.d.ts +63 -0
- package/lib/typescript/core/identity-session/errors.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/index.d.ts +14 -0
- package/lib/typescript/core/identity-session/index.d.ts.map +1 -0
- package/lib/typescript/core/identity-session/types.d.ts +196 -0
- package/lib/typescript/core/identity-session/types.d.ts.map +1 -0
- package/lib/typescript/core/index.d.ts +1 -3
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +2 -2
- package/lib/typescript/index.d.ts +3 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +5 -36
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/models/session.d.ts +3 -16
- package/lib/typescript/models/session.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +2 -25
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts +7 -8
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/mutations/useServicesMutations.d.ts +1 -1
- package/lib/typescript/ui/hooks/mutations/useServicesMutations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts +5 -5
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useAvatarPicker.d.ts +18 -0
- package/lib/typescript/ui/hooks/useAvatarPicker.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/useIdentityTransfer.d.ts +24 -0
- package/lib/typescript/ui/hooks/useIdentityTransfer.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/useTransferCodesPersistence.d.ts +6 -0
- package/lib/typescript/ui/hooks/useTransferCodesPersistence.d.ts.map +1 -0
- package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/utils/sessionHelpers.d.ts +1 -0
- package/lib/typescript/ui/utils/sessionHelpers.d.ts.map +1 -1
- package/lib/typescript/utils/index.d.ts +0 -2
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/lib/typescript/utils/sessionUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/adapters/expo/crypto.ts +55 -0
- package/src/adapters/expo/fetch.ts +28 -0
- package/src/adapters/expo/index.ts +51 -0
- package/src/adapters/expo/storage.ts +228 -0
- package/src/adapters/index.ts +40 -0
- package/src/adapters/node/crypto.ts +39 -0
- package/src/adapters/node/fetch.ts +59 -0
- package/src/adapters/node/index.ts +37 -0
- package/src/adapters/node/storage.ts +170 -0
- package/src/core/identity-session/DeviceManager.ts +273 -0
- package/src/core/identity-session/INTEGRATION_GUIDE.md +287 -0
- package/src/core/identity-session/IdentityManager.ts +474 -0
- package/src/core/identity-session/IdentitySessionCore.ts +464 -0
- package/src/core/identity-session/RefreshManager.ts +189 -0
- package/src/core/identity-session/SessionManager.ts +500 -0
- package/src/core/identity-session/createIdentitySessionCore.ts +19 -0
- package/src/core/identity-session/errors.ts +197 -0
- package/src/core/identity-session/index.ts +15 -0
- package/src/core/identity-session/types.ts +188 -0
- package/src/core/index.ts +3 -4
- package/src/index.ts +28 -3
- package/src/models/interfaces.ts +12 -39
- package/src/models/session.ts +6 -16
- package/src/ui/context/OxyContext.tsx +442 -871
- package/src/ui/hooks/auth/index.ts +1 -0
- package/src/ui/hooks/useAvatarPicker.ts +62 -0
- package/src/ui/hooks/useIdentityTransfer.ts +135 -0
- package/src/ui/hooks/useTransferCodesPersistence.ts +80 -0
- package/src/ui/screens/AccountCenterScreen.tsx +7 -2
- package/src/ui/screens/AccountSettingsScreen.tsx +15 -8
- package/src/ui/screens/AccountSwitcherScreen.tsx +2 -2
- package/src/ui/screens/ProfileScreen.tsx +10 -10
- package/src/ui/utils/sessionHelpers.ts +7 -0
- package/src/utils/index.ts +1 -2
- package/src/utils/sessionUtils.ts +8 -0
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +0 -732
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +0 -1
- package/lib/commonjs/ui/context/hooks/useDeviceManagement.js +0 -73
- package/lib/commonjs/ui/context/hooks/useDeviceManagement.js.map +0 -1
- package/lib/commonjs/ui/hooks/useDeviceManagement.js +0 -73
- package/lib/commonjs/ui/hooks/useDeviceManagement.js.map +0 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +0 -281
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +0 -1
- package/lib/commonjs/utils/deviceManager.js +0 -177
- package/lib/commonjs/utils/deviceManager.js.map +0 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +0 -726
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +0 -1
- package/lib/module/ui/context/hooks/useDeviceManagement.js +0 -68
- package/lib/module/ui/context/hooks/useDeviceManagement.js.map +0 -1
- package/lib/module/ui/hooks/useDeviceManagement.js +0 -68
- package/lib/module/ui/hooks/useDeviceManagement.js.map +0 -1
- package/lib/module/ui/hooks/useSessionManagement.js +0 -276
- package/lib/module/ui/hooks/useSessionManagement.js.map +0 -1
- package/lib/module/utils/deviceManager.js +0 -171
- package/lib/module/utils/deviceManager.js.map +0 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +0 -59
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +0 -1
- package/lib/typescript/ui/context/hooks/useDeviceManagement.d.ts +0 -27
- package/lib/typescript/ui/context/hooks/useDeviceManagement.d.ts.map +0 -1
- package/lib/typescript/ui/hooks/useDeviceManagement.d.ts +0 -27
- package/lib/typescript/ui/hooks/useDeviceManagement.d.ts.map +0 -1
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts +0 -41
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +0 -1
- package/lib/typescript/utils/deviceManager.d.ts +0 -66
- package/lib/typescript/utils/deviceManager.d.ts.map +0 -1
- package/src/ui/context/hooks/useAuthOperations.ts +0 -801
- package/src/ui/context/hooks/useDeviceManagement.ts +0 -108
- package/src/ui/hooks/useDeviceManagement.ts +0 -108
- package/src/ui/hooks/useSessionManagement.ts +0 -401
- 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
|
+
|