@oxyhq/services 5.16.39 → 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 -704
- 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 -698
- 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 -773
- 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,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages device identification and device sessions (Native + Web)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { PlatformAdapter } from '../../adapters';
|
|
8
|
+
import type { Device, DeviceInfo } from './types';
|
|
9
|
+
import {
|
|
10
|
+
createIdentitySessionError,
|
|
11
|
+
IdentitySessionErrorCodes,
|
|
12
|
+
} from './errors';
|
|
13
|
+
|
|
14
|
+
const DEVICE_STORAGE_KEY = 'oxy_device_info';
|
|
15
|
+
|
|
16
|
+
interface StoredDeviceInfo {
|
|
17
|
+
deviceId: string;
|
|
18
|
+
deviceName?: string;
|
|
19
|
+
fingerprint?: string;
|
|
20
|
+
createdAt: string;
|
|
21
|
+
lastUsed: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Device Manager Class
|
|
26
|
+
*/
|
|
27
|
+
export class DeviceManager {
|
|
28
|
+
private adapter: PlatformAdapter;
|
|
29
|
+
private cachedDevice: Device | null = null;
|
|
30
|
+
|
|
31
|
+
constructor(adapter: PlatformAdapter) {
|
|
32
|
+
this.adapter = adapter;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Invalidate cached device
|
|
37
|
+
*/
|
|
38
|
+
invalidateCache(): void {
|
|
39
|
+
this.cachedDevice = null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get device fingerprint
|
|
44
|
+
*/
|
|
45
|
+
private getDeviceFingerprint(): Record<string, unknown> {
|
|
46
|
+
const fingerprint: Record<string, unknown> = {
|
|
47
|
+
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown',
|
|
48
|
+
platform: typeof navigator !== 'undefined' ? navigator.platform : 'unknown',
|
|
49
|
+
language: typeof navigator !== 'undefined' ? navigator.language : undefined,
|
|
50
|
+
timezone: typeof Intl !== 'undefined' ? Intl.DateTimeFormat().resolvedOptions().timeZone : undefined,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Add screen info if available
|
|
54
|
+
if (typeof screen !== 'undefined') {
|
|
55
|
+
fingerprint.screen = {
|
|
56
|
+
width: screen.width,
|
|
57
|
+
height: screen.height,
|
|
58
|
+
colorDepth: screen.colorDepth,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return fingerprint;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Generate a unique device ID
|
|
67
|
+
*/
|
|
68
|
+
private async generateDeviceId(): Promise<string> {
|
|
69
|
+
const randomBytes = await this.adapter.crypto.getRandomBytes(32);
|
|
70
|
+
return Array.from(randomBytes, byte => byte.toString(16).padStart(2, '0')).join('');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get a user-friendly device name based on platform
|
|
75
|
+
*/
|
|
76
|
+
private getDefaultDeviceName(): string {
|
|
77
|
+
const fingerprint = this.getDeviceFingerprint();
|
|
78
|
+
const platform = (fingerprint.platform as string || '').toLowerCase();
|
|
79
|
+
const userAgent = (fingerprint.userAgent as string || '').toLowerCase();
|
|
80
|
+
|
|
81
|
+
if (platform.includes('win')) return 'Windows Computer';
|
|
82
|
+
if (platform.includes('mac')) return 'Mac Computer';
|
|
83
|
+
if (platform.includes('linux')) return 'Linux Computer';
|
|
84
|
+
if (userAgent.includes('iphone')) return 'iPhone';
|
|
85
|
+
if (userAgent.includes('ipad')) return 'iPad';
|
|
86
|
+
if (userAgent.includes('android')) return 'Android Device';
|
|
87
|
+
if (this.adapter.platform === 'web') return 'Web Browser';
|
|
88
|
+
|
|
89
|
+
return 'Unknown Device';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get stored device info or create new one
|
|
94
|
+
*/
|
|
95
|
+
async getCurrentDevice(): Promise<Device | null> {
|
|
96
|
+
if (this.cachedDevice) {
|
|
97
|
+
return this.cachedDevice;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const stored = await this.adapter.storage.get(DEVICE_STORAGE_KEY);
|
|
102
|
+
|
|
103
|
+
if (stored) {
|
|
104
|
+
const deviceInfo: StoredDeviceInfo = JSON.parse(stored);
|
|
105
|
+
|
|
106
|
+
// Update last used timestamp
|
|
107
|
+
deviceInfo.lastUsed = new Date().toISOString();
|
|
108
|
+
await this.saveDeviceInfo(deviceInfo);
|
|
109
|
+
|
|
110
|
+
const device: Device = {
|
|
111
|
+
deviceId: deviceInfo.deviceId,
|
|
112
|
+
deviceName: deviceInfo.deviceName,
|
|
113
|
+
deviceType: this.getDeviceType(),
|
|
114
|
+
platform: this.adapter.platform === 'native' ? 'ios' : 'web', // Simplified
|
|
115
|
+
fingerprint: deviceInfo.fingerprint,
|
|
116
|
+
createdAt: deviceInfo.createdAt,
|
|
117
|
+
updatedAt: deviceInfo.lastUsed,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
this.cachedDevice = device;
|
|
121
|
+
return device;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Create new device info
|
|
125
|
+
return await this.createNewDevice();
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('[DeviceManager] Error getting device info:', error);
|
|
128
|
+
return await this.createNewDevice();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Create new device info and store it
|
|
134
|
+
*/
|
|
135
|
+
async createNewDevice(): Promise<Device> {
|
|
136
|
+
const deviceId = await this.generateDeviceId();
|
|
137
|
+
const fingerprint = JSON.stringify(this.getDeviceFingerprint());
|
|
138
|
+
const now = new Date().toISOString();
|
|
139
|
+
|
|
140
|
+
const device: Device = {
|
|
141
|
+
deviceId,
|
|
142
|
+
deviceName: this.getDefaultDeviceName(),
|
|
143
|
+
deviceType: this.getDeviceType(),
|
|
144
|
+
platform: this.adapter.platform === 'native' ? 'ios' : 'web', // Simplified
|
|
145
|
+
fingerprint,
|
|
146
|
+
createdAt: now,
|
|
147
|
+
updatedAt: now,
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const deviceInfo: StoredDeviceInfo = {
|
|
151
|
+
deviceId,
|
|
152
|
+
deviceName: device.deviceName,
|
|
153
|
+
fingerprint,
|
|
154
|
+
createdAt: now,
|
|
155
|
+
lastUsed: now,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
await this.saveDeviceInfo(deviceInfo);
|
|
159
|
+
this.cachedDevice = device;
|
|
160
|
+
|
|
161
|
+
return device;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get device type
|
|
166
|
+
*/
|
|
167
|
+
private getDeviceType(): string {
|
|
168
|
+
if (this.adapter.platform === 'web') {
|
|
169
|
+
return 'desktop'; // Simplified - could detect mobile web
|
|
170
|
+
}
|
|
171
|
+
// For native, would need Platform.OS detection
|
|
172
|
+
return 'mobile';
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Save device info to storage
|
|
177
|
+
*/
|
|
178
|
+
private async saveDeviceInfo(deviceInfo: StoredDeviceInfo): Promise<void> {
|
|
179
|
+
try {
|
|
180
|
+
await this.adapter.storage.set(DEVICE_STORAGE_KEY, JSON.stringify(deviceInfo));
|
|
181
|
+
} catch (error) {
|
|
182
|
+
console.error('[DeviceManager] Error saving device info:', error);
|
|
183
|
+
throw createIdentitySessionError(
|
|
184
|
+
IdentitySessionErrorCodes.DEVICE_CREATION_FAILED,
|
|
185
|
+
`Failed to save device info: ${error instanceof Error ? error.message : String(error)}`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Update device name
|
|
192
|
+
*/
|
|
193
|
+
async updateDeviceName(deviceName: string): Promise<Device> {
|
|
194
|
+
const device = await this.getCurrentDevice();
|
|
195
|
+
if (!device) {
|
|
196
|
+
throw createIdentitySessionError(
|
|
197
|
+
IdentitySessionErrorCodes.DEVICE_NOT_FOUND,
|
|
198
|
+
'Device not found'
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
device.deviceName = deviceName;
|
|
203
|
+
device.updatedAt = new Date().toISOString();
|
|
204
|
+
|
|
205
|
+
const deviceInfo: StoredDeviceInfo = {
|
|
206
|
+
deviceId: device.deviceId,
|
|
207
|
+
deviceName: device.deviceName,
|
|
208
|
+
fingerprint: device.fingerprint,
|
|
209
|
+
createdAt: device.createdAt || new Date().toISOString(),
|
|
210
|
+
lastUsed: device.updatedAt,
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
await this.saveDeviceInfo(deviceInfo);
|
|
214
|
+
this.cachedDevice = device;
|
|
215
|
+
|
|
216
|
+
return device;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get device info for session creation
|
|
221
|
+
*/
|
|
222
|
+
async getDeviceInfo(): Promise<DeviceInfo> {
|
|
223
|
+
const device = await this.getCurrentDevice();
|
|
224
|
+
if (!device) {
|
|
225
|
+
throw createIdentitySessionError(
|
|
226
|
+
IdentitySessionErrorCodes.DEVICE_NOT_FOUND,
|
|
227
|
+
'Device not found'
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const fingerprint = this.getDeviceFingerprint();
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
deviceName: device.deviceName,
|
|
235
|
+
deviceType: device.deviceType,
|
|
236
|
+
platform: device.platform,
|
|
237
|
+
browser: typeof navigator !== 'undefined' ? this.getBrowserName() : undefined,
|
|
238
|
+
os: typeof navigator !== 'undefined' ? navigator.platform : undefined,
|
|
239
|
+
lastActive: new Date().toISOString(),
|
|
240
|
+
userAgent: fingerprint.userAgent as string,
|
|
241
|
+
fingerprint: device.fingerprint,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Get browser name from user agent
|
|
247
|
+
*/
|
|
248
|
+
private getBrowserName(): string | undefined {
|
|
249
|
+
if (typeof navigator === 'undefined') return undefined;
|
|
250
|
+
|
|
251
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
252
|
+
if (ua.includes('chrome')) return 'Chrome';
|
|
253
|
+
if (ua.includes('firefox')) return 'Firefox';
|
|
254
|
+
if (ua.includes('safari') && !ua.includes('chrome')) return 'Safari';
|
|
255
|
+
if (ua.includes('edge')) return 'Edge';
|
|
256
|
+
if (ua.includes('opera')) return 'Opera';
|
|
257
|
+
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Clear stored device info
|
|
263
|
+
*/
|
|
264
|
+
async clearDeviceInfo(): Promise<void> {
|
|
265
|
+
try {
|
|
266
|
+
await this.adapter.storage.remove(DEVICE_STORAGE_KEY);
|
|
267
|
+
this.invalidateCache();
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error('[DeviceManager] Error clearing device info:', error);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Identity Session Core - Integration Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Identity Session Core provides a unified API for identity and session management across all platforms (React Native, Web, Node). All identity and session operations go through this core - never access `KeyManager`, storage, or APIs directly.
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
UI/Hooks Layer
|
|
11
|
+
↓
|
|
12
|
+
IdentitySessionCore (unified API)
|
|
13
|
+
↓
|
|
14
|
+
Managers (Identity, Session, Device, Refresh)
|
|
15
|
+
↓
|
|
16
|
+
Platform Adapters (Expo 54, Node)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Key Principles
|
|
20
|
+
|
|
21
|
+
1. **Frontend: Use `useOxy()` hook** - This is the only API you need for React/React Native applications
|
|
22
|
+
2. **Backend: Use `createIdentitySessionCore()`** - Only for Node.js/backend applications
|
|
23
|
+
3. **Never access storage, APIs, or KeyManager directly** - Always go through the core or `useOxy()`
|
|
24
|
+
4. **Identity operations are NATIVE ONLY** - Web cannot create/import identities
|
|
25
|
+
5. **Session operations work on NATIVE + WEB** - sessions can be used on both platforms
|
|
26
|
+
6. **Models are aligned with backend** - same types, same error codes
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @oxyhq/services
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Basic Usage
|
|
35
|
+
|
|
36
|
+
### Using the React Hook (Recommended)
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { OxyProvider, useOxy } from '@oxyhq/services';
|
|
40
|
+
import { Platform } from 'react-native';
|
|
41
|
+
|
|
42
|
+
function App() {
|
|
43
|
+
return (
|
|
44
|
+
<OxyProvider baseURL="https://api.example.com">
|
|
45
|
+
<MyComponent />
|
|
46
|
+
</OxyProvider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function MyComponent() {
|
|
51
|
+
const { createIdentity, signIn, hasIdentity, isLoading, error } = useOxy();
|
|
52
|
+
|
|
53
|
+
const handleCreateIdentity = async () => {
|
|
54
|
+
if (Platform.OS === 'web') {
|
|
55
|
+
alert('Identity creation is only available on native platforms');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const result = await createIdentity('myusername');
|
|
61
|
+
console.log('Identity created, synced:', result.synced);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.error('Failed to create identity:', err);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const handleSignIn = async () => {
|
|
68
|
+
try {
|
|
69
|
+
const user = await signIn('My Device');
|
|
70
|
+
console.log('Signed in:', user);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
console.error('Failed to sign in:', err);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
if (error) return <Text>Error: {error}</Text>;
|
|
77
|
+
if (isLoading) return <Text>Loading...</Text>;
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<View>
|
|
81
|
+
<Button onPress={handleCreateIdentity} title="Create Identity" />
|
|
82
|
+
<Button onPress={handleSignIn} title="Sign In" />
|
|
83
|
+
</View>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Direct Core Usage (Backend/Node.js Only)
|
|
89
|
+
|
|
90
|
+
**Note:** For frontend applications, always use `useOxy()` hook. Direct core usage is only for backend/Node.js applications.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { createIdentitySessionCore } from '@oxyhq/services';
|
|
94
|
+
|
|
95
|
+
// Backend/Node.js only
|
|
96
|
+
const core = await createIdentitySessionCore('https://api.example.com');
|
|
97
|
+
const identity = await core.getCurrentIdentity();
|
|
98
|
+
const session = await core.getSession();
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## API Reference
|
|
102
|
+
|
|
103
|
+
### Using `useOxy` Hook (Recommended)
|
|
104
|
+
|
|
105
|
+
The `useOxy` hook provides all identity and session operations through a simple, reactive API:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const {
|
|
109
|
+
// Identity (Native Only)
|
|
110
|
+
createIdentity,
|
|
111
|
+
importIdentity,
|
|
112
|
+
deleteIdentityAndClearAccount,
|
|
113
|
+
hasIdentity,
|
|
114
|
+
getPublicKey,
|
|
115
|
+
isIdentitySynced,
|
|
116
|
+
syncIdentity,
|
|
117
|
+
identity,
|
|
118
|
+
publicKey,
|
|
119
|
+
identitySyncState,
|
|
120
|
+
|
|
121
|
+
// Session (Native + Web)
|
|
122
|
+
signIn,
|
|
123
|
+
logout,
|
|
124
|
+
logoutAll,
|
|
125
|
+
switchSession,
|
|
126
|
+
refreshSession,
|
|
127
|
+
session,
|
|
128
|
+
sessions,
|
|
129
|
+
activeSessionId,
|
|
130
|
+
isAuthenticated,
|
|
131
|
+
|
|
132
|
+
// Device (Native + Web)
|
|
133
|
+
getDeviceSessions,
|
|
134
|
+
logoutAllDeviceSessions,
|
|
135
|
+
updateDeviceName,
|
|
136
|
+
device,
|
|
137
|
+
|
|
138
|
+
// State
|
|
139
|
+
user,
|
|
140
|
+
isLoading,
|
|
141
|
+
isTokenReady,
|
|
142
|
+
isStorageReady,
|
|
143
|
+
error,
|
|
144
|
+
} = useOxy();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Identity Operations (Native Only)
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// Create new identity
|
|
151
|
+
const result = await createIdentity(username?);
|
|
152
|
+
// result.synced indicates if identity was synced with backend
|
|
153
|
+
|
|
154
|
+
// Import identity from backup
|
|
155
|
+
const result = await importIdentity(backupData, password, username?);
|
|
156
|
+
// result.synced indicates if identity was synced with backend
|
|
157
|
+
|
|
158
|
+
// Delete identity and clear all account data
|
|
159
|
+
await deleteIdentityAndClearAccount(skipBackup?, force?, userConfirmed?);
|
|
160
|
+
|
|
161
|
+
// Check if identity exists
|
|
162
|
+
const has = await hasIdentity();
|
|
163
|
+
|
|
164
|
+
// Get public key
|
|
165
|
+
const publicKey = await getPublicKey();
|
|
166
|
+
|
|
167
|
+
// Check if identity is synced
|
|
168
|
+
const synced = await isIdentitySynced();
|
|
169
|
+
|
|
170
|
+
// Manually sync identity
|
|
171
|
+
const user = await syncIdentity(username?);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Session Operations (Native + Web)
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// Sign in (create session)
|
|
178
|
+
const user = await signIn(deviceName?);
|
|
179
|
+
|
|
180
|
+
// Logout (invalidate current or specific session)
|
|
181
|
+
await logout(sessionId?);
|
|
182
|
+
|
|
183
|
+
// Logout all sessions
|
|
184
|
+
await logoutAll();
|
|
185
|
+
|
|
186
|
+
// Switch to different session
|
|
187
|
+
await switchSession(sessionId);
|
|
188
|
+
|
|
189
|
+
// Refresh current session
|
|
190
|
+
const session = await refreshSession();
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Device Operations (Native + Web)
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// Get all device sessions
|
|
197
|
+
const deviceSessions = await getDeviceSessions();
|
|
198
|
+
|
|
199
|
+
// Logout all sessions for current device
|
|
200
|
+
await logoutAllDeviceSessions();
|
|
201
|
+
|
|
202
|
+
// Update device name
|
|
203
|
+
await updateDeviceName(deviceName);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Direct Core Usage (Advanced)
|
|
207
|
+
|
|
208
|
+
For advanced use cases, you can access the core directly:
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { createIdentitySessionCore } from '@oxyhq/services';
|
|
212
|
+
|
|
213
|
+
const core = await createIdentitySessionCore('https://api.example.com');
|
|
214
|
+
const identity = await core.getCurrentIdentity();
|
|
215
|
+
const session = await core.getSession();
|
|
216
|
+
|
|
217
|
+
// Subscribe to events
|
|
218
|
+
const unsubscribe = core.subscribe((event) => {
|
|
219
|
+
switch (event.type) {
|
|
220
|
+
case 'identity:created':
|
|
221
|
+
console.log('Identity created:', event.identity);
|
|
222
|
+
break;
|
|
223
|
+
case 'session:created':
|
|
224
|
+
console.log('Session created:', event.session);
|
|
225
|
+
break;
|
|
226
|
+
case 'session:invalidated':
|
|
227
|
+
console.log('Session invalidated:', event.sessionId);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Cleanup
|
|
233
|
+
unsubscribe();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Error Handling
|
|
237
|
+
|
|
238
|
+
All errors use unified error codes:
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
import {
|
|
242
|
+
IdentitySessionError,
|
|
243
|
+
IdentitySessionErrorCodes
|
|
244
|
+
} from '@oxyhq/services';
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
await createIdentity();
|
|
248
|
+
} catch (error) {
|
|
249
|
+
if (error instanceof IdentitySessionError) {
|
|
250
|
+
switch (error.code) {
|
|
251
|
+
case IdentitySessionErrorCodes.IDENTITY_NOT_AVAILABLE_ON_WEB:
|
|
252
|
+
// Handle web platform error
|
|
253
|
+
break;
|
|
254
|
+
case IdentitySessionErrorCodes.IDENTITY_ALREADY_EXISTS:
|
|
255
|
+
// Handle already exists error
|
|
256
|
+
break;
|
|
257
|
+
default:
|
|
258
|
+
console.error('Error:', error.message);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Type Exports
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
import type {
|
|
268
|
+
Identity,
|
|
269
|
+
Session,
|
|
270
|
+
Device,
|
|
271
|
+
DeviceInfo,
|
|
272
|
+
BackupData,
|
|
273
|
+
IdentitySessionEvent,
|
|
274
|
+
} from '@oxyhq/services';
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Platform Detection
|
|
278
|
+
|
|
279
|
+
The core automatically detects the platform and validates operations. Identity operations will throw `IDENTITY_NOT_AVAILABLE_ON_WEB` on web platforms.
|
|
280
|
+
|
|
281
|
+
## Notes
|
|
282
|
+
|
|
283
|
+
- The core handles all platform-specific logic internally
|
|
284
|
+
- Storage, crypto, and fetch are abstracted through platform adapters
|
|
285
|
+
- All models are aligned with backend (IUser, ISession)
|
|
286
|
+
- Error codes are unified across frontend and backend
|
|
287
|
+
- The core is designed to be "plugged in" to any Oxy app (Mention, Homiio, Noted, etc.)
|