@oxyhq/services 5.2.4 → 5.2.6

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 (33) hide show
  1. package/lib/commonjs/ui/components/OxyProvider.js +22 -3
  2. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  3. package/lib/commonjs/ui/context/OxyContext.js +31 -3
  4. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  5. package/lib/commonjs/ui/navigation/OxyRouter.js +11 -2
  6. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  7. package/lib/module/ui/components/OxyProvider.js +22 -3
  8. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  9. package/lib/module/ui/context/OxyContext.js +31 -3
  10. package/lib/module/ui/context/OxyContext.js.map +1 -1
  11. package/lib/module/ui/navigation/OxyRouter.js +11 -2
  12. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  13. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  14. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  15. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  16. package/package.json +1 -1
  17. package/src/ui/components/OxyProvider.tsx +25 -3
  18. package/src/ui/context/OxyContext.tsx +32 -2
  19. package/src/ui/navigation/OxyRouter.tsx +14 -1
  20. package/lib/commonjs/ui/context/LegacyOxyContext.js +0 -643
  21. package/lib/commonjs/ui/context/LegacyOxyContext.js.map +0 -1
  22. package/lib/commonjs/ui/context/SecureOxyContext.js +0 -408
  23. package/lib/commonjs/ui/context/SecureOxyContext.js.map +0 -1
  24. package/lib/module/ui/context/LegacyOxyContext.js +0 -639
  25. package/lib/module/ui/context/LegacyOxyContext.js.map +0 -1
  26. package/lib/module/ui/context/SecureOxyContext.js +0 -403
  27. package/lib/module/ui/context/SecureOxyContext.js.map +0 -1
  28. package/lib/typescript/ui/context/LegacyOxyContext.d.ts +0 -40
  29. package/lib/typescript/ui/context/LegacyOxyContext.d.ts.map +0 -1
  30. package/lib/typescript/ui/context/SecureOxyContext.d.ts +0 -39
  31. package/lib/typescript/ui/context/SecureOxyContext.d.ts.map +0 -1
  32. package/src/ui/context/LegacyOxyContext.tsx +0 -735
  33. package/src/ui/context/SecureOxyContext.tsx +0 -473
@@ -1,473 +0,0 @@
1
- import React, { createContext, useContext, useState, useEffect, useCallback, ReactNode, useMemo } from 'react';
2
- import { OxyServices } from '../../core';
3
- import { User } from '../../models/interfaces';
4
- import { SecureLoginResponse, SecureClientSession, MinimalUserData } from '../../models/secureSession';
5
-
6
- // Define the secure context shape
7
- export interface SecureOxyContextState {
8
- // Authentication state
9
- user: User | null; // Current active user (loaded from server)
10
- minimalUser: MinimalUserData | null; // Minimal user data for UI
11
- sessions: SecureClientSession[]; // All active sessions
12
- activeSessionId: string | null;
13
- isAuthenticated: boolean;
14
- isLoading: boolean;
15
- error: string | null;
16
-
17
- // Auth methods
18
- secureLogin: (username: string, password: string, deviceName?: string) => Promise<User>;
19
- logout: (targetSessionId?: string) => Promise<void>;
20
- logoutAll: () => Promise<void>;
21
- signUp: (username: string, email: string, password: string) => Promise<User>;
22
-
23
- // Multi-session methods
24
- switchSession: (sessionId: string) => Promise<void>;
25
- removeSession: (sessionId: string) => Promise<void>;
26
- refreshSessions: () => Promise<void>;
27
-
28
- // Access to services
29
- oxyServices: OxyServices;
30
- bottomSheetRef?: React.RefObject<any>;
31
-
32
- // Methods to directly control the bottom sheet
33
- showBottomSheet?: (screenOrConfig?: string | { screen: string; props?: Record<string, any> }) => void;
34
- hideBottomSheet?: () => void;
35
- }
36
-
37
- // Create the context with default values
38
- const SecureOxyContext = createContext<SecureOxyContextState | null>(null);
39
-
40
- // Props for the SecureOxyContextProvider
41
- export interface SecureOxyContextProviderProps {
42
- children: ReactNode;
43
- oxyServices: OxyServices;
44
- storageKeyPrefix?: string;
45
- onAuthStateChange?: (user: User | null) => void;
46
- bottomSheetRef?: React.RefObject<any>;
47
- }
48
-
49
- // Platform storage implementation
50
- interface StorageInterface {
51
- getItem: (key: string) => Promise<string | null>;
52
- setItem: (key: string, value: string) => Promise<void>;
53
- removeItem: (key: string) => Promise<void>;
54
- clear: () => Promise<void>;
55
- }
56
-
57
- // Web localStorage implementation
58
- class WebStorage implements StorageInterface {
59
- async getItem(key: string): Promise<string | null> {
60
- return localStorage.getItem(key);
61
- }
62
-
63
- async setItem(key: string, value: string): Promise<void> {
64
- localStorage.setItem(key, value);
65
- }
66
-
67
- async removeItem(key: string): Promise<void> {
68
- localStorage.removeItem(key);
69
- }
70
-
71
- async clear(): Promise<void> {
72
- localStorage.clear();
73
- }
74
- }
75
-
76
- // React Native AsyncStorage implementation
77
- let AsyncStorage: StorageInterface;
78
-
79
- // Determine the platform and set up storage
80
- const isReactNative = (): boolean => {
81
- return typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
82
- };
83
-
84
- // Get appropriate storage for the platform
85
- const getStorage = async (): Promise<StorageInterface> => {
86
- if (isReactNative()) {
87
- if (!AsyncStorage) {
88
- try {
89
- const asyncStorageModule = await import('@react-native-async-storage/async-storage');
90
- AsyncStorage = asyncStorageModule.default;
91
- } catch (error) {
92
- console.error('Failed to import AsyncStorage:', error);
93
- throw new Error('AsyncStorage is required in React Native environment');
94
- }
95
- }
96
- return AsyncStorage;
97
- }
98
-
99
- return new WebStorage();
100
- };
101
-
102
- // Storage keys for secure sessions
103
- const getSecureStorageKeys = (prefix = 'oxy_secure') => ({
104
- sessions: `${prefix}_sessions`, // Array of SecureClientSession objects
105
- activeSessionId: `${prefix}_active_session_id`, // ID of currently active session
106
- });
107
-
108
- export const SecureOxyContextProvider: React.FC<SecureOxyContextProviderProps> = ({
109
- children,
110
- oxyServices,
111
- storageKeyPrefix = 'oxy_secure',
112
- onAuthStateChange,
113
- bottomSheetRef,
114
- }) => {
115
- // Authentication state
116
- const [user, setUser] = useState<User | null>(null);
117
- const [minimalUser, setMinimalUser] = useState<MinimalUserData | null>(null);
118
- const [sessions, setSessions] = useState<SecureClientSession[]>([]);
119
- const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
120
- const [isLoading, setIsLoading] = useState(true);
121
- const [error, setError] = useState<string | null>(null);
122
- const [storage, setStorage] = useState<StorageInterface | null>(null);
123
-
124
- // Storage keys (memoized to prevent infinite loops)
125
- const keys = useMemo(() => getSecureStorageKeys(storageKeyPrefix), [storageKeyPrefix]);
126
-
127
- // Initialize storage
128
- useEffect(() => {
129
- const initStorage = async () => {
130
- try {
131
- const platformStorage = await getStorage();
132
- setStorage(platformStorage);
133
- } catch (error) {
134
- console.error('Failed to initialize storage:', error);
135
- setError('Failed to initialize storage');
136
- }
137
- };
138
-
139
- initStorage();
140
- }, []);
141
-
142
- // Effect to initialize authentication state
143
- useEffect(() => {
144
- const initAuth = async () => {
145
- if (!storage) return;
146
-
147
- setIsLoading(true);
148
- try {
149
- // Load stored sessions
150
- const sessionsData = await storage.getItem(keys.sessions);
151
- const storedActiveSessionId = await storage.getItem(keys.activeSessionId);
152
-
153
- console.log('SecureAuth - sessionsData:', sessionsData);
154
- console.log('SecureAuth - activeSessionId:', storedActiveSessionId);
155
-
156
- if (sessionsData) {
157
- const parsedSessions: SecureClientSession[] = JSON.parse(sessionsData);
158
- setSessions(parsedSessions);
159
-
160
- if (storedActiveSessionId && parsedSessions.length > 0) {
161
- const activeSession = parsedSessions.find(s => s.sessionId === storedActiveSessionId);
162
-
163
- if (activeSession) {
164
- console.log('SecureAuth - activeSession found:', activeSession);
165
-
166
- // Validate session
167
- try {
168
- const validation = await oxyServices.validateSession(activeSession.sessionId);
169
-
170
- if (validation.valid) {
171
- console.log('SecureAuth - session validated successfully');
172
- setActiveSessionId(activeSession.sessionId);
173
-
174
- // Get access token for API calls
175
- await oxyServices.getTokenBySession(activeSession.sessionId);
176
-
177
- // Load full user data
178
- const fullUser = await oxyServices.getUserBySession(activeSession.sessionId);
179
- setUser(fullUser);
180
- setMinimalUser({
181
- id: fullUser.id,
182
- username: fullUser.username,
183
- avatar: fullUser.avatar
184
- });
185
-
186
- if (onAuthStateChange) {
187
- onAuthStateChange(fullUser);
188
- }
189
- } else {
190
- console.log('SecureAuth - session invalid, removing');
191
- await removeInvalidSession(activeSession.sessionId);
192
- }
193
- } catch (error) {
194
- console.error('SecureAuth - session validation error:', error);
195
- await removeInvalidSession(activeSession.sessionId);
196
- }
197
- }
198
- }
199
- }
200
- } catch (err) {
201
- console.error('Secure auth initialization error:', err);
202
- await clearAllStorage();
203
- } finally {
204
- setIsLoading(false);
205
- }
206
- };
207
-
208
- if (storage) {
209
- initAuth();
210
- }
211
- }, [storage, oxyServices, keys, onAuthStateChange]);
212
-
213
- // Remove invalid session
214
- const removeInvalidSession = useCallback(async (sessionId: string): Promise<void> => {
215
- const filteredSessions = sessions.filter(s => s.sessionId !== sessionId);
216
- setSessions(filteredSessions);
217
- await saveSessionsToStorage(filteredSessions);
218
-
219
- // If there are other sessions, switch to the first one
220
- if (filteredSessions.length > 0) {
221
- await switchToSession(filteredSessions[0].sessionId);
222
- } else {
223
- // No valid sessions left
224
- setActiveSessionId(null);
225
- setUser(null);
226
- setMinimalUser(null);
227
- await storage?.removeItem(keys.activeSessionId);
228
-
229
- if (onAuthStateChange) {
230
- onAuthStateChange(null);
231
- }
232
- }
233
- }, [sessions, storage, keys, onAuthStateChange]);
234
-
235
- // Save sessions to storage
236
- const saveSessionsToStorage = useCallback(async (sessionsList: SecureClientSession[]): Promise<void> => {
237
- if (!storage) return;
238
- await storage.setItem(keys.sessions, JSON.stringify(sessionsList));
239
- }, [storage, keys.sessions]);
240
-
241
- // Save active session ID to storage
242
- const saveActiveSessionId = useCallback(async (sessionId: string): Promise<void> => {
243
- if (!storage) return;
244
- await storage.setItem(keys.activeSessionId, sessionId);
245
- }, [storage, keys.activeSessionId]);
246
-
247
- // Clear all storage
248
- const clearAllStorage = useCallback(async (): Promise<void> => {
249
- if (!storage) return;
250
- try {
251
- await storage.removeItem(keys.sessions);
252
- await storage.removeItem(keys.activeSessionId);
253
- } catch (err) {
254
- console.error('Clear secure storage error:', err);
255
- }
256
- }, [storage, keys]);
257
-
258
- // Switch to a different session
259
- const switchToSession = useCallback(async (sessionId: string): Promise<void> => {
260
- try {
261
- setIsLoading(true);
262
-
263
- // Get access token for this session
264
- await oxyServices.getTokenBySession(sessionId);
265
-
266
- // Load full user data
267
- const fullUser = await oxyServices.getUserBySession(sessionId);
268
-
269
- setActiveSessionId(sessionId);
270
- setUser(fullUser);
271
- setMinimalUser({
272
- id: fullUser.id,
273
- username: fullUser.username,
274
- avatar: fullUser.avatar
275
- });
276
-
277
- await saveActiveSessionId(sessionId);
278
-
279
- if (onAuthStateChange) {
280
- onAuthStateChange(fullUser);
281
- }
282
- } catch (error) {
283
- console.error('Switch session error:', error);
284
- setError('Failed to switch session');
285
- } finally {
286
- setIsLoading(false);
287
- }
288
- }, [oxyServices, onAuthStateChange, saveActiveSessionId]);
289
-
290
- // Secure login method
291
- const secureLogin = async (username: string, password: string, deviceName?: string): Promise<User> => {
292
- if (!storage) throw new Error('Storage not initialized');
293
-
294
- setIsLoading(true);
295
- setError(null);
296
-
297
- try {
298
- const response: SecureLoginResponse = await oxyServices.secureLogin(username, password, deviceName);
299
-
300
- // Create client session object
301
- const clientSession: SecureClientSession = {
302
- sessionId: response.sessionId,
303
- deviceId: response.deviceId,
304
- expiresAt: response.expiresAt,
305
- lastActive: new Date().toISOString()
306
- };
307
-
308
- // Add to sessions list
309
- const updatedSessions = [...sessions, clientSession];
310
- setSessions(updatedSessions);
311
- await saveSessionsToStorage(updatedSessions);
312
-
313
- // Set as active session
314
- setActiveSessionId(response.sessionId);
315
- await saveActiveSessionId(response.sessionId);
316
-
317
- // Get access token for API calls
318
- await oxyServices.getTokenBySession(response.sessionId);
319
-
320
- // Load full user data
321
- const fullUser = await oxyServices.getUserBySession(response.sessionId);
322
- setUser(fullUser);
323
- setMinimalUser(response.user);
324
-
325
- if (onAuthStateChange) {
326
- onAuthStateChange(fullUser);
327
- }
328
-
329
- return fullUser;
330
- } catch (error: any) {
331
- setError(error.message || 'Login failed');
332
- throw error;
333
- } finally {
334
- setIsLoading(false);
335
- }
336
- };
337
-
338
- // Logout method
339
- const logout = async (targetSessionId?: string): Promise<void> => {
340
- if (!activeSessionId) return;
341
-
342
- try {
343
- const sessionToLogout = targetSessionId || activeSessionId;
344
- await oxyServices.logoutSecureSession(activeSessionId, sessionToLogout);
345
-
346
- // Remove session from local storage
347
- const filteredSessions = sessions.filter(s => s.sessionId !== sessionToLogout);
348
- setSessions(filteredSessions);
349
- await saveSessionsToStorage(filteredSessions);
350
-
351
- // If logging out active session
352
- if (sessionToLogout === activeSessionId) {
353
- if (filteredSessions.length > 0) {
354
- // Switch to another session
355
- await switchToSession(filteredSessions[0].sessionId);
356
- } else {
357
- // No sessions left
358
- setActiveSessionId(null);
359
- setUser(null);
360
- setMinimalUser(null);
361
- await storage?.removeItem(keys.activeSessionId);
362
-
363
- if (onAuthStateChange) {
364
- onAuthStateChange(null);
365
- }
366
- }
367
- }
368
- } catch (error) {
369
- console.error('Logout error:', error);
370
- setError('Logout failed');
371
- }
372
- };
373
-
374
- // Logout all sessions
375
- const logoutAll = async (): Promise<void> => {
376
- if (!activeSessionId) return;
377
-
378
- try {
379
- await oxyServices.logoutAllSecureSessions(activeSessionId);
380
-
381
- // Clear all local data
382
- setSessions([]);
383
- setActiveSessionId(null);
384
- setUser(null);
385
- setMinimalUser(null);
386
- await clearAllStorage();
387
-
388
- if (onAuthStateChange) {
389
- onAuthStateChange(null);
390
- }
391
- } catch (error) {
392
- console.error('Logout all error:', error);
393
- setError('Logout all failed');
394
- }
395
- };
396
-
397
- // Sign up method (placeholder - you can implement based on your needs)
398
- const signUp = async (username: string, email: string, password: string): Promise<User> => {
399
- // Implement sign up logic similar to secureLogin
400
- throw new Error('Sign up not implemented yet');
401
- };
402
-
403
- // Switch session method
404
- const switchSession = async (sessionId: string): Promise<void> => {
405
- await switchToSession(sessionId);
406
- };
407
-
408
- // Remove session method
409
- const removeSession = async (sessionId: string): Promise<void> => {
410
- await logout(sessionId);
411
- };
412
-
413
- // Refresh sessions method
414
- const refreshSessions = async (): Promise<void> => {
415
- if (!activeSessionId) return;
416
-
417
- try {
418
- const serverSessions = await oxyServices.getSessionsBySessionId(activeSessionId);
419
-
420
- // Update local sessions with server data
421
- const updatedSessions: SecureClientSession[] = serverSessions.map(serverSession => ({
422
- sessionId: serverSession.sessionId,
423
- deviceId: serverSession.deviceId,
424
- expiresAt: new Date().toISOString(), // You might want to get this from server
425
- lastActive: new Date().toISOString()
426
- }));
427
-
428
- setSessions(updatedSessions);
429
- await saveSessionsToStorage(updatedSessions);
430
- } catch (error) {
431
- console.error('Refresh sessions error:', error);
432
- }
433
- };
434
-
435
- // Context value
436
- const contextValue: SecureOxyContextState = {
437
- user,
438
- minimalUser,
439
- sessions,
440
- activeSessionId,
441
- isAuthenticated: !!user,
442
- isLoading,
443
- error,
444
- secureLogin,
445
- logout,
446
- logoutAll,
447
- signUp,
448
- switchSession,
449
- removeSession,
450
- refreshSessions,
451
- oxyServices,
452
- bottomSheetRef,
453
- showBottomSheet: undefined, // Implement as needed
454
- hideBottomSheet: undefined, // Implement as needed
455
- };
456
-
457
- return (
458
- <SecureOxyContext.Provider value={contextValue}>
459
- {children}
460
- </SecureOxyContext.Provider>
461
- );
462
- };
463
-
464
- // Hook to use the secure context
465
- export const useSecureOxyContext = (): SecureOxyContextState => {
466
- const context = useContext(SecureOxyContext);
467
- if (!context) {
468
- throw new Error('useSecureOxyContext must be used within a SecureOxyContextProvider');
469
- }
470
- return context;
471
- };
472
-
473
- export default SecureOxyContext;