@oxyhq/services 5.9.2 → 5.9.3
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/README.md +1 -33
- package/lib/commonjs/core/OxyServices.js +159 -0
- package/lib/commonjs/core/OxyServices.js.map +1 -0
- package/lib/commonjs/core/OxyServicesMain.js +51 -0
- package/lib/commonjs/core/OxyServicesMain.js.map +1 -0
- package/lib/commonjs/core/analytics/AnalyticsService.js +67 -0
- package/lib/commonjs/core/analytics/AnalyticsService.js.map +1 -0
- package/lib/commonjs/core/auth/AuthService.js +526 -0
- package/lib/commonjs/core/auth/AuthService.js.map +1 -0
- package/lib/commonjs/core/devices/DeviceService.js +61 -0
- package/lib/commonjs/core/devices/DeviceService.js.map +1 -0
- package/lib/commonjs/core/files/FileService.js +176 -0
- package/lib/commonjs/core/files/FileService.js.map +1 -0
- package/lib/commonjs/core/index.js +103 -1701
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/core/karma/KarmaService.js +100 -0
- package/lib/commonjs/core/karma/KarmaService.js.map +1 -0
- package/lib/commonjs/core/locations/LocationService.js +131 -0
- package/lib/commonjs/core/locations/LocationService.js.map +1 -0
- package/lib/commonjs/core/payments/PaymentService.js +124 -0
- package/lib/commonjs/core/payments/PaymentService.js.map +1 -0
- package/lib/commonjs/core/users/UserService.js +234 -0
- package/lib/commonjs/core/users/UserService.js.map +1 -0
- package/lib/commonjs/index.js +164 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/session.js +2 -0
- package/lib/commonjs/{types/middleware.js.map → models/session.js.map} +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +28 -24
- package/lib/commonjs/ui/context/OxyContext.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/FileManagementScreen.js +12 -12
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ProfileScreen.js +2 -2
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/commonjs/ui/stores/followStore.js +4 -4
- package/lib/commonjs/ui/stores/followStore.js.map +1 -1
- package/lib/commonjs/utils/apiUtils.js +93 -0
- package/lib/commonjs/utils/apiUtils.js.map +1 -0
- package/lib/commonjs/utils/asyncUtils.js +219 -0
- package/lib/commonjs/utils/asyncUtils.js.map +1 -0
- package/lib/commonjs/utils/errorUtils.js +148 -0
- package/lib/commonjs/utils/errorUtils.js.map +1 -0
- package/lib/commonjs/utils/hookUtils.js +399 -0
- package/lib/commonjs/utils/hookUtils.js.map +1 -0
- package/lib/commonjs/utils/loggerUtils.js +160 -0
- package/lib/commonjs/utils/loggerUtils.js.map +1 -0
- package/lib/commonjs/utils/validationUtils.js +174 -0
- package/lib/commonjs/utils/validationUtils.js.map +1 -0
- package/lib/module/core/OxyServices.js +153 -0
- package/lib/module/core/OxyServices.js.map +1 -0
- package/lib/module/core/OxyServicesMain.js +47 -0
- package/lib/module/core/OxyServicesMain.js.map +1 -0
- package/lib/module/core/analytics/AnalyticsService.js +62 -0
- package/lib/module/core/analytics/AnalyticsService.js.map +1 -0
- package/lib/module/core/auth/AuthService.js +521 -0
- package/lib/module/core/auth/AuthService.js.map +1 -0
- package/lib/module/core/devices/DeviceService.js +57 -0
- package/lib/module/core/devices/DeviceService.js.map +1 -0
- package/lib/module/core/files/FileService.js +171 -0
- package/lib/module/core/files/FileService.js.map +1 -0
- package/lib/module/core/index.js +25 -1690
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/core/karma/KarmaService.js +95 -0
- package/lib/module/core/karma/KarmaService.js.map +1 -0
- package/lib/module/core/locations/LocationService.js +127 -0
- package/lib/module/core/locations/LocationService.js.map +1 -0
- package/lib/module/core/payments/PaymentService.js +119 -0
- package/lib/module/core/payments/PaymentService.js.map +1 -0
- package/lib/module/core/users/UserService.js +230 -0
- package/lib/module/core/users/UserService.js.map +1 -0
- package/lib/module/index.js +8 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/session.js +2 -0
- package/lib/module/{types/middleware.js.map → models/session.js.map} +1 -1
- package/lib/module/ui/context/OxyContext.js +28 -24
- package/lib/module/ui/context/OxyContext.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/FileManagementScreen.js +12 -12
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +2 -2
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +1 -1
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +1 -1
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/module/ui/stores/followStore.js +4 -4
- package/lib/module/ui/stores/followStore.js.map +1 -1
- package/lib/module/utils/apiUtils.js +85 -0
- package/lib/module/utils/apiUtils.js.map +1 -0
- package/lib/module/utils/asyncUtils.js +202 -0
- package/lib/module/utils/asyncUtils.js.map +1 -0
- package/lib/module/utils/errorUtils.js +139 -0
- package/lib/module/utils/errorUtils.js.map +1 -0
- package/lib/module/utils/hookUtils.js +381 -0
- package/lib/module/utils/hookUtils.js.map +1 -0
- package/lib/module/utils/loggerUtils.js +149 -0
- package/lib/module/utils/loggerUtils.js.map +1 -0
- package/lib/module/utils/validationUtils.js +154 -0
- package/lib/module/utils/validationUtils.js.map +1 -0
- package/lib/typescript/core/OxyServices.d.ts +64 -0
- package/lib/typescript/core/OxyServices.d.ts.map +1 -0
- package/lib/typescript/core/OxyServicesMain.d.ts +33 -0
- package/lib/typescript/core/OxyServicesMain.d.ts.map +1 -0
- package/lib/typescript/core/analytics/AnalyticsService.d.ts +26 -0
- package/lib/typescript/core/analytics/AnalyticsService.d.ts.map +1 -0
- package/lib/typescript/core/auth/AuthService.d.ts +165 -0
- package/lib/typescript/core/auth/AuthService.d.ts.map +1 -0
- package/lib/typescript/core/devices/DeviceService.d.ts +20 -0
- package/lib/typescript/core/devices/DeviceService.d.ts.map +1 -0
- package/lib/typescript/core/files/FileService.d.ts +59 -0
- package/lib/typescript/core/files/FileService.d.ts.map +1 -0
- package/lib/typescript/core/index.d.ts +19 -656
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/core/karma/KarmaService.d.ts +50 -0
- package/lib/typescript/core/karma/KarmaService.d.ts.map +1 -0
- package/lib/typescript/core/locations/LocationService.d.ts +39 -0
- package/lib/typescript/core/locations/LocationService.d.ts.map +1 -0
- package/lib/typescript/core/payments/PaymentService.d.ts +50 -0
- package/lib/typescript/core/payments/PaymentService.d.ts.map +1 -0
- package/lib/typescript/core/users/UserService.d.ts +111 -0
- package/lib/typescript/core/users/UserService.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +7 -3
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/{secureSession.d.ts → session.d.ts} +4 -4
- package/lib/typescript/models/session.d.ts.map +1 -0
- package/lib/typescript/ui/context/OxyContext.d.ts +2 -2
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/utils/apiUtils.d.ts +61 -0
- package/lib/typescript/utils/apiUtils.d.ts.map +1 -0
- package/lib/typescript/utils/asyncUtils.d.ts +64 -0
- package/lib/typescript/utils/asyncUtils.d.ts.map +1 -0
- package/lib/typescript/utils/errorUtils.d.ts +45 -0
- package/lib/typescript/utils/errorUtils.d.ts.map +1 -0
- package/lib/typescript/utils/hookUtils.d.ts +102 -0
- package/lib/typescript/utils/hookUtils.d.ts.map +1 -0
- package/lib/typescript/utils/loggerUtils.d.ts +49 -0
- package/lib/typescript/utils/loggerUtils.d.ts.map +1 -0
- package/lib/typescript/utils/validationUtils.d.ts +80 -0
- package/lib/typescript/utils/validationUtils.d.ts.map +1 -0
- package/package.json +2 -8
- package/src/core/OxyServices.ts +168 -0
- package/src/core/OxyServicesMain.ts +57 -0
- package/src/core/analytics/AnalyticsService.ts +64 -0
- package/src/core/auth/AuthService.ts +544 -0
- package/src/core/devices/DeviceService.ts +55 -0
- package/src/core/files/FileService.ts +194 -0
- package/src/core/index.ts +27 -1765
- package/src/core/karma/KarmaService.ts +104 -0
- package/src/core/locations/LocationService.ts +141 -0
- package/src/core/payments/PaymentService.ts +133 -0
- package/src/core/users/UserService.ts +241 -0
- package/src/index.ts +29 -8
- package/src/models/{secureSession.ts → session.ts} +5 -5
- package/src/ui/context/OxyContext.tsx +34 -30
- package/src/ui/screens/AccountSwitcherScreen.tsx +4 -4
- package/src/ui/screens/FileManagementScreen.tsx +12 -12
- package/src/ui/screens/ProfileScreen.tsx +3 -3
- package/src/ui/screens/SessionManagementScreen.tsx +2 -2
- package/src/ui/screens/SignInScreen.tsx +1 -1
- package/src/ui/screens/karma/KarmaCenterScreen.tsx +2 -2
- package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +3 -3
- package/src/ui/screens/karma/KarmaRulesScreen.tsx +3 -3
- package/src/ui/stores/followStore.ts +4 -4
- package/src/utils/apiUtils.ts +102 -0
- package/src/utils/asyncUtils.ts +265 -0
- package/src/utils/errorUtils.ts +172 -0
- package/src/utils/hookUtils.ts +397 -0
- package/src/utils/loggerUtils.ts +153 -0
- package/src/utils/validationUtils.ts +158 -0
- package/lib/commonjs/middleware.js +0 -17
- package/lib/commonjs/middleware.js.map +0 -1
- package/lib/commonjs/models/secureSession.js +0 -2
- package/lib/commonjs/models/secureSession.js.map +0 -1
- package/lib/commonjs/types/middleware.js +0 -6
- package/lib/module/middleware.js +0 -12
- package/lib/module/middleware.js.map +0 -1
- package/lib/module/models/secureSession.js +0 -2
- package/lib/module/models/secureSession.js.map +0 -1
- package/lib/module/types/middleware.js +0 -4
- package/lib/typescript/middleware.d.ts +0 -9
- package/lib/typescript/middleware.d.ts.map +0 -1
- package/lib/typescript/models/secureSession.d.ts.map +0 -1
- package/lib/typescript/types/middleware.d.ts +0 -19
- package/lib/typescript/types/middleware.d.ts.map +0 -1
- package/src/middleware.ts +0 -11
- package/src/types/middleware.ts +0 -20
|
@@ -2,7 +2,7 @@ import React, { createContext, useContext, useEffect, useCallback, ReactNode, us
|
|
|
2
2
|
import { View, Text } from 'react-native';
|
|
3
3
|
import { OxyServices } from '../../core';
|
|
4
4
|
import { User, ApiError } from '../../models/interfaces';
|
|
5
|
-
import {
|
|
5
|
+
import { SessionLoginResponse, ClientSession, MinimalUserData } from '../../models/session';
|
|
6
6
|
import { DeviceManager } from '../../utils/deviceManager';
|
|
7
7
|
import { useSessionSocket } from '../hooks/useSessionSocket';
|
|
8
8
|
import { toast } from '../../lib/sonner';
|
|
@@ -13,7 +13,7 @@ export interface OxyContextState {
|
|
|
13
13
|
// Authentication state
|
|
14
14
|
user: User | null; // Current active user (loaded from server)
|
|
15
15
|
minimalUser: MinimalUserData | null; // Minimal user data for UI
|
|
16
|
-
sessions:
|
|
16
|
+
sessions: ClientSession[]; // All active sessions
|
|
17
17
|
activeSessionId: string | null;
|
|
18
18
|
isAuthenticated: boolean; // Single source of truth for authentication - use this instead of service methods
|
|
19
19
|
isLoading: boolean;
|
|
@@ -111,8 +111,8 @@ const getStorage = async (): Promise<StorageInterface> => {
|
|
|
111
111
|
return new WebStorage();
|
|
112
112
|
};
|
|
113
113
|
|
|
114
|
-
// Storage keys for
|
|
115
|
-
const
|
|
114
|
+
// Storage keys for sessions
|
|
115
|
+
const getStorageKeys = (prefix = 'oxy_session') => ({
|
|
116
116
|
activeSessionId: `${prefix}_active_session_id`, // Only store the active session ID
|
|
117
117
|
});
|
|
118
118
|
|
|
@@ -120,7 +120,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
120
120
|
children,
|
|
121
121
|
oxyServices: providedOxyServices,
|
|
122
122
|
baseURL,
|
|
123
|
-
storageKeyPrefix = '
|
|
123
|
+
storageKeyPrefix = 'oxy_session',
|
|
124
124
|
onAuthStateChange,
|
|
125
125
|
onError,
|
|
126
126
|
bottomSheetRef,
|
|
@@ -151,14 +151,14 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
151
151
|
|
|
152
152
|
// Local state for non-auth fields
|
|
153
153
|
const [minimalUser, setMinimalUser] = React.useState<MinimalUserData | null>(null);
|
|
154
|
-
const [sessions, setSessions] = React.useState<
|
|
154
|
+
const [sessions, setSessions] = React.useState<ClientSession[]>([]);
|
|
155
155
|
const [activeSessionId, setActiveSessionId] = React.useState<string | null>(null);
|
|
156
156
|
const [storage, setStorage] = React.useState<StorageInterface | null>(null);
|
|
157
157
|
// Add a new state to track token restoration
|
|
158
158
|
const [tokenReady, setTokenReady] = React.useState(false);
|
|
159
159
|
|
|
160
160
|
// Storage keys (memoized to prevent infinite loops)
|
|
161
|
-
const keys = useMemo(() =>
|
|
161
|
+
const keys = useMemo(() => getStorageKeys(storageKeyPrefix), [storageKeyPrefix]);
|
|
162
162
|
|
|
163
163
|
// Clear all storage - defined before initAuth to avoid dependency issues
|
|
164
164
|
const clearAllStorage = useCallback(async (): Promise<void> => {
|
|
@@ -166,7 +166,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
166
166
|
try {
|
|
167
167
|
await storage.removeItem(keys.activeSessionId);
|
|
168
168
|
} catch (err) {
|
|
169
|
-
console.error('Clear
|
|
169
|
+
console.error('Clear storage error:', err);
|
|
170
170
|
}
|
|
171
171
|
}, [storage, keys]);
|
|
172
172
|
|
|
@@ -195,17 +195,19 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
195
195
|
// Only load the active session ID from storage
|
|
196
196
|
const storedActiveSessionId = await storage.getItem(keys.activeSessionId);
|
|
197
197
|
|
|
198
|
-
console.log('
|
|
199
|
-
console.log('
|
|
200
|
-
console.log('
|
|
198
|
+
console.log('Auth - activeSessionId:', storedActiveSessionId);
|
|
199
|
+
console.log('Auth - storage available:', !!storage);
|
|
200
|
+
console.log('Auth - oxyServices available:', !!oxyServices);
|
|
201
201
|
|
|
202
202
|
if (storedActiveSessionId) {
|
|
203
203
|
// Validate the stored session with the backend
|
|
204
204
|
try {
|
|
205
|
-
const validation = await oxyServices.validateSession(storedActiveSessionId
|
|
205
|
+
const validation = await oxyServices.validateSession(storedActiveSessionId, {
|
|
206
|
+
useHeaderValidation: true
|
|
207
|
+
});
|
|
206
208
|
|
|
207
209
|
if (validation.valid) {
|
|
208
|
-
console.log('
|
|
210
|
+
console.log('Auth - session validated successfully');
|
|
209
211
|
setActiveSessionId(storedActiveSessionId);
|
|
210
212
|
|
|
211
213
|
// Get access token for API calls
|
|
@@ -222,7 +224,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
222
224
|
|
|
223
225
|
// Load sessions from backend
|
|
224
226
|
const serverSessions = await oxyServices.getSessionsBySessionId(storedActiveSessionId);
|
|
225
|
-
const clientSessions:
|
|
227
|
+
const clientSessions: ClientSession[] = serverSessions.map(serverSession => ({
|
|
226
228
|
sessionId: serverSession.sessionId,
|
|
227
229
|
deviceId: serverSession.deviceId,
|
|
228
230
|
expiresAt: serverSession.expiresAt || new Date().toISOString(),
|
|
@@ -235,18 +237,18 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
235
237
|
onAuthStateChange(fullUser);
|
|
236
238
|
}
|
|
237
239
|
} else {
|
|
238
|
-
console.log('
|
|
240
|
+
console.log('Auth - session invalid, clearing storage');
|
|
239
241
|
await clearAllStorage();
|
|
240
242
|
}
|
|
241
243
|
} catch (error) {
|
|
242
|
-
console.error('
|
|
244
|
+
console.error('Auth - session validation error:', error);
|
|
243
245
|
await clearAllStorage();
|
|
244
246
|
}
|
|
245
247
|
} else {
|
|
246
|
-
console.log('
|
|
248
|
+
console.log('Auth - no stored session found, user needs to login');
|
|
247
249
|
}
|
|
248
250
|
} catch (err) {
|
|
249
|
-
console.error('
|
|
251
|
+
console.error('Auth initialization error:', err);
|
|
250
252
|
await clearAllStorage();
|
|
251
253
|
} finally {
|
|
252
254
|
useAuthStore.setState({ isLoading: false });
|
|
@@ -320,7 +322,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
320
322
|
}
|
|
321
323
|
}, [oxyServices, onAuthStateChange, loginSuccess, saveActiveSessionId]);
|
|
322
324
|
|
|
323
|
-
//
|
|
325
|
+
// Login method - only store session ID, retrieve data from backend
|
|
324
326
|
const login = useCallback(async (username: string, password: string, deviceName?: string): Promise<User> => {
|
|
325
327
|
if (!storage) throw new Error('Storage not initialized');
|
|
326
328
|
useAuthStore.setState({ isLoading: true, error: null });
|
|
@@ -332,10 +334,10 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
332
334
|
// Get or generate persistent device info
|
|
333
335
|
const deviceInfo = await DeviceManager.getDeviceInfo();
|
|
334
336
|
|
|
335
|
-
console.log('
|
|
336
|
-
console.log('
|
|
337
|
+
console.log('Auth - Using device fingerprint:', deviceFingerprint);
|
|
338
|
+
console.log('Auth - Using device ID:', deviceInfo.deviceId);
|
|
337
339
|
|
|
338
|
-
const response:
|
|
340
|
+
const response: SessionLoginResponse = await oxyServices.signIn(
|
|
339
341
|
username,
|
|
340
342
|
password,
|
|
341
343
|
deviceName || deviceInfo.deviceName || DeviceManager.getDefaultDeviceName(),
|
|
@@ -356,7 +358,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
356
358
|
|
|
357
359
|
// Load sessions from backend
|
|
358
360
|
const serverSessions = await oxyServices.getSessionsBySessionId(response.sessionId);
|
|
359
|
-
const clientSessions:
|
|
361
|
+
const clientSessions: ClientSession[] = serverSessions.map(serverSession => ({
|
|
360
362
|
sessionId: serverSession.sessionId,
|
|
361
363
|
deviceId: serverSession.deviceId,
|
|
362
364
|
expiresAt: serverSession.expiresAt || new Date().toISOString(),
|
|
@@ -384,7 +386,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
384
386
|
|
|
385
387
|
try {
|
|
386
388
|
const sessionToLogout = targetSessionId || activeSessionId;
|
|
387
|
-
await oxyServices.
|
|
389
|
+
await oxyServices.logoutSession(activeSessionId, sessionToLogout);
|
|
388
390
|
|
|
389
391
|
// Remove session from local state
|
|
390
392
|
const filteredSessions = sessions.filter(s => s.sessionId !== sessionToLogout);
|
|
@@ -430,9 +432,9 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
430
432
|
}
|
|
431
433
|
|
|
432
434
|
try {
|
|
433
|
-
console.log('Calling oxyServices.
|
|
434
|
-
await oxyServices.
|
|
435
|
-
console.log('
|
|
435
|
+
console.log('Calling oxyServices.logoutAllSessions with sessionId:', activeSessionId);
|
|
436
|
+
await oxyServices.logoutAllSessions(activeSessionId);
|
|
437
|
+
console.log('logoutAllSessions completed successfully');
|
|
436
438
|
|
|
437
439
|
// Clear all local data
|
|
438
440
|
setSessions([]);
|
|
@@ -485,7 +487,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
485
487
|
|
|
486
488
|
console.log('SignUp successful:', response);
|
|
487
489
|
|
|
488
|
-
// Now log the user in
|
|
490
|
+
// Now log the user in to create a session
|
|
489
491
|
// This will handle the session creation and device registration
|
|
490
492
|
const user = await login(username, password);
|
|
491
493
|
|
|
@@ -523,7 +525,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
523
525
|
console.log('refreshSessions: Server sessions received:', serverSessions);
|
|
524
526
|
|
|
525
527
|
// Update local sessions with server data
|
|
526
|
-
const updatedSessions:
|
|
528
|
+
const updatedSessions: ClientSession[] = serverSessions.map(serverSession => ({
|
|
527
529
|
sessionId: serverSession.sessionId,
|
|
528
530
|
deviceId: serverSession.deviceId,
|
|
529
531
|
expiresAt: serverSession.expiresAt || new Date().toISOString(),
|
|
@@ -545,7 +547,9 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
545
547
|
for (const session of otherSessions) {
|
|
546
548
|
try {
|
|
547
549
|
// Try to validate this session
|
|
548
|
-
await oxyServices.validateSession(session.sessionId
|
|
550
|
+
await oxyServices.validateSession(session.sessionId, {
|
|
551
|
+
useHeaderValidation: true
|
|
552
|
+
});
|
|
549
553
|
console.log('Found valid session, switching to:', session.sessionId);
|
|
550
554
|
await switchToSession(session.sessionId);
|
|
551
555
|
return; // Successfully switched to another session
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from 'react-native';
|
|
14
14
|
import { BaseScreenProps } from '../navigation/types';
|
|
15
15
|
import { useOxy } from '../context/OxyContext';
|
|
16
|
-
import {
|
|
16
|
+
import { ClientSession } from '../../models/session';
|
|
17
17
|
import { fontFamilies } from '../styles/fonts';
|
|
18
18
|
import { User } from '../../models/interfaces';
|
|
19
19
|
import { toast } from '../../lib/sonner';
|
|
@@ -23,7 +23,7 @@ import { Ionicons } from '@expo/vector-icons';
|
|
|
23
23
|
import Avatar from '../components/Avatar';
|
|
24
24
|
import { Header, GroupedSection } from '../components';
|
|
25
25
|
|
|
26
|
-
interface SessionWithUser extends
|
|
26
|
+
interface SessionWithUser extends ClientSession {
|
|
27
27
|
userProfile?: User;
|
|
28
28
|
isLoadingProfile?: boolean;
|
|
29
29
|
}
|
|
@@ -217,7 +217,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
217
217
|
async () => {
|
|
218
218
|
setRemoteLogoutSessionId(sessionId);
|
|
219
219
|
try {
|
|
220
|
-
await oxyServices?.
|
|
220
|
+
await oxyServices?.logoutSession(user?.sessionId || '', sessionId);
|
|
221
221
|
// Refresh device sessions list
|
|
222
222
|
await loadAllDeviceSessions();
|
|
223
223
|
toast.success(`Signed out from ${deviceName} successfully!`);
|
|
@@ -244,7 +244,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
244
244
|
async () => {
|
|
245
245
|
setLoggingOutAllDevices(true);
|
|
246
246
|
try {
|
|
247
|
-
await oxyServices?.logoutAllDeviceSessions(user?.sessionId || ''
|
|
247
|
+
await oxyServices?.logoutAllDeviceSessions(user?.sessionId || '');
|
|
248
248
|
// Refresh device sessions list
|
|
249
249
|
await loadAllDeviceSessions();
|
|
250
250
|
toast.success('Signed out from all other devices successfully!');
|
|
@@ -118,7 +118,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
118
118
|
setLoading(true);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
const response = await oxyServices.listUserFiles(targetUserId);
|
|
121
|
+
const response = await oxyServices.files.listUserFiles(targetUserId);
|
|
122
122
|
setFiles(response.files || []);
|
|
123
123
|
} catch (error: any) {
|
|
124
124
|
console.error('Failed to load files:', error);
|
|
@@ -172,7 +172,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
172
172
|
await Promise.all(
|
|
173
173
|
photosToLoad.map(async (photo) => {
|
|
174
174
|
try {
|
|
175
|
-
const downloadUrl = oxyServices.getFileDownloadUrl(photo.id);
|
|
175
|
+
const downloadUrl = oxyServices.files.getFileDownloadUrl(photo.id);
|
|
176
176
|
|
|
177
177
|
if (Platform.OS === 'web') {
|
|
178
178
|
const img = new (window as any).Image();
|
|
@@ -340,7 +340,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
340
340
|
console.log('Current user ID:', user?.id);
|
|
341
341
|
setDeleting(fileId);
|
|
342
342
|
|
|
343
|
-
const result = await oxyServices.deleteFile(fileId);
|
|
343
|
+
const result = await oxyServices.files.deleteFile(fileId);
|
|
344
344
|
console.log('Delete result:', result);
|
|
345
345
|
|
|
346
346
|
toast.success('File deleted successfully');
|
|
@@ -408,7 +408,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
408
408
|
console.log('Downloading file:', { fileId, filename });
|
|
409
409
|
|
|
410
410
|
// Use the public download URL method
|
|
411
|
-
const downloadUrl = oxyServices.getFileDownloadUrl(fileId);
|
|
411
|
+
const downloadUrl = oxyServices.files.getFileDownloadUrl(fileId);
|
|
412
412
|
console.log('Download URL:', downloadUrl);
|
|
413
413
|
|
|
414
414
|
try {
|
|
@@ -426,7 +426,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
426
426
|
console.warn('Link download failed, trying fetch method:', linkError);
|
|
427
427
|
|
|
428
428
|
// Method 2: Fallback to authenticated download
|
|
429
|
-
const blob = await oxyServices.getFileContentAsBlob(fileId);
|
|
429
|
+
const blob = await oxyServices.files.getFileContentAsBlob(fileId);
|
|
430
430
|
const url = window.URL.createObjectURL(blob);
|
|
431
431
|
|
|
432
432
|
const link = document.createElement('a');
|
|
@@ -491,11 +491,11 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
491
491
|
file.contentType.startsWith('video/') ||
|
|
492
492
|
file.contentType.startsWith('audio/')) {
|
|
493
493
|
// For images, PDFs, videos, and audio, we'll use the URL directly
|
|
494
|
-
const downloadUrl = oxyServices.getFileDownloadUrl(file.id);
|
|
494
|
+
const downloadUrl = oxyServices.files.getFileDownloadUrl(file.id);
|
|
495
495
|
setFileContent(downloadUrl);
|
|
496
496
|
} else {
|
|
497
497
|
// For text files, get the content using authenticated request
|
|
498
|
-
const content = await oxyServices.getFileContentAsText(file.id);
|
|
498
|
+
const content = await oxyServices.files.getFileContentAsText(file.id);
|
|
499
499
|
setFileContent(content);
|
|
500
500
|
}
|
|
501
501
|
} catch (error: any) {
|
|
@@ -532,7 +532,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
532
532
|
};
|
|
533
533
|
|
|
534
534
|
const renderSimplePhotoItem = useCallback((photo: FileMetadata, index: number) => {
|
|
535
|
-
const downloadUrl = oxyServices.getFileDownloadUrl(photo.id);
|
|
535
|
+
const downloadUrl = oxyServices.files.getFileDownloadUrl(photo.id);
|
|
536
536
|
|
|
537
537
|
// Calculate photo item width based on actual container size from bottom sheet
|
|
538
538
|
let itemsPerRow = 3; // Default for mobile
|
|
@@ -598,7 +598,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
598
598
|
}, [oxyServices, containerWidth]);
|
|
599
599
|
|
|
600
600
|
const renderJustifiedPhotoItem = useCallback((photo: FileMetadata, width: number, height: number, isLast: boolean) => {
|
|
601
|
-
const downloadUrl = oxyServices.getFileDownloadUrl(photo.id);
|
|
601
|
+
const downloadUrl = oxyServices.files.getFileDownloadUrl(photo.id);
|
|
602
602
|
|
|
603
603
|
return (
|
|
604
604
|
<TouchableOpacity
|
|
@@ -689,7 +689,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
689
689
|
{isImage && (
|
|
690
690
|
Platform.OS === 'web' ? (
|
|
691
691
|
<img
|
|
692
|
-
src={oxyServices.getFileDownloadUrl(file.id)}
|
|
692
|
+
src={oxyServices.files.getFileDownloadUrl(file.id)}
|
|
693
693
|
style={{
|
|
694
694
|
width: '100%',
|
|
695
695
|
height: '100%',
|
|
@@ -709,7 +709,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
709
709
|
/>
|
|
710
710
|
) : (
|
|
711
711
|
<Image
|
|
712
|
-
source={{ uri: oxyServices.getFileDownloadUrl(file.id) }}
|
|
712
|
+
source={{ uri: oxyServices.files.getFileDownloadUrl(file.id) }}
|
|
713
713
|
style={styles.previewImage}
|
|
714
714
|
resizeMode="cover"
|
|
715
715
|
onError={() => {
|
|
@@ -817,7 +817,7 @@ const FileManagementScreen: React.FC<FileManagementScreenProps> = ({
|
|
|
817
817
|
};
|
|
818
818
|
|
|
819
819
|
const renderPhotoItem = (photo: FileMetadata, index: number) => {
|
|
820
|
-
const downloadUrl = oxyServices.getFileDownloadUrl(photo.id);
|
|
820
|
+
const downloadUrl = oxyServices.files.getFileDownloadUrl(photo.id);
|
|
821
821
|
|
|
822
822
|
// Calculate photo item width based on actual container size from bottom sheet
|
|
823
823
|
let itemsPerRow = 3; // Default for mobile
|
|
@@ -61,7 +61,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
61
61
|
|
|
62
62
|
// Load user profile and karma total
|
|
63
63
|
Promise.all([
|
|
64
|
-
oxyServices.getUserById(userId).catch(err => {
|
|
64
|
+
oxyServices.users.getUserById(userId).catch((err: any) => {
|
|
65
65
|
console.error('getUserById error:', err);
|
|
66
66
|
// If this is the current user and the API call fails, use current user data as fallback
|
|
67
67
|
if (currentUser && currentUser.id === userId) {
|
|
@@ -70,8 +70,8 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ userId, username, theme,
|
|
|
70
70
|
}
|
|
71
71
|
throw err;
|
|
72
72
|
}),
|
|
73
|
-
oxyServices.getUserKarmaTotal ?
|
|
74
|
-
oxyServices.getUserKarmaTotal(userId).catch(err => {
|
|
73
|
+
oxyServices.karma.getUserKarmaTotal ?
|
|
74
|
+
oxyServices.karma.getUserKarmaTotal(userId).catch((err: any) => {
|
|
75
75
|
console.warn('getUserKarmaTotal error:', err);
|
|
76
76
|
return { total: undefined };
|
|
77
77
|
}) :
|
|
@@ -16,7 +16,7 @@ import { fontFamilies } from '../styles/fonts';
|
|
|
16
16
|
import { toast } from '../../lib/sonner';
|
|
17
17
|
import { Ionicons } from '@expo/vector-icons';
|
|
18
18
|
import OxyIcon from '../components/icon/OxyIcon';
|
|
19
|
-
import {
|
|
19
|
+
import { ClientSession } from '../../models/session';
|
|
20
20
|
import { confirmAction } from '../utils/confirmAction';
|
|
21
21
|
import { Header } from '../components';
|
|
22
22
|
|
|
@@ -189,7 +189,7 @@ const SessionManagementScreen: React.FC<BaseScreenProps> = ({
|
|
|
189
189
|
>
|
|
190
190
|
{userSessions.length > 0 ? (
|
|
191
191
|
<>
|
|
192
|
-
{userSessions.map((session:
|
|
192
|
+
{userSessions.map((session: ClientSession) => (
|
|
193
193
|
<View
|
|
194
194
|
key={session.sessionId}
|
|
195
195
|
style={[
|
|
@@ -136,7 +136,7 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
136
136
|
|
|
137
137
|
try {
|
|
138
138
|
// First check if username exists by trying to get profile
|
|
139
|
-
const profile = await oxyServices.
|
|
139
|
+
const profile = await oxyServices.users.getProfileByUsername(usernameToValidate);
|
|
140
140
|
|
|
141
141
|
if (profile) {
|
|
142
142
|
const profileData = {
|
|
@@ -38,8 +38,8 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
38
38
|
setIsLoading(true);
|
|
39
39
|
setError(null);
|
|
40
40
|
Promise.all([
|
|
41
|
-
oxyServices.getUserKarmaTotal(user.id),
|
|
42
|
-
oxyServices.getUserKarmaHistory(user.id, 20, 0),
|
|
41
|
+
oxyServices.karma.getUserKarmaTotal(user.id),
|
|
42
|
+
oxyServices.karma.getUserKarmaHistory(user.id, 20, 0),
|
|
43
43
|
])
|
|
44
44
|
.then(([totalRes, historyRes]) => {
|
|
45
45
|
setKarmaTotal(totalRes.total);
|
|
@@ -19,9 +19,9 @@ const KarmaLeaderboardScreen: React.FC<BaseScreenProps> = ({ goBack, theme, navi
|
|
|
19
19
|
useEffect(() => {
|
|
20
20
|
setIsLoading(true);
|
|
21
21
|
setError(null);
|
|
22
|
-
oxyServices.getKarmaLeaderboard()
|
|
23
|
-
.then((data) => setLeaderboard(Array.isArray(data) ? data : []))
|
|
24
|
-
.catch((err) => setError(err.message || 'Failed to load leaderboard'))
|
|
22
|
+
oxyServices.karma.getKarmaLeaderboard()
|
|
23
|
+
.then((data: any) => setLeaderboard(Array.isArray(data) ? data : []))
|
|
24
|
+
.catch((err: any) => setError(err.message || 'Failed to load leaderboard'))
|
|
25
25
|
.finally(() => setIsLoading(false));
|
|
26
26
|
}, [oxyServices]);
|
|
27
27
|
|
|
@@ -18,9 +18,9 @@ const KarmaRulesScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
|
|
|
18
18
|
useEffect(() => {
|
|
19
19
|
setIsLoading(true);
|
|
20
20
|
setError(null);
|
|
21
|
-
oxyServices.getKarmaRules()
|
|
22
|
-
.then((data) => setRules(Array.isArray(data) ? data : []))
|
|
23
|
-
.catch((err) => setError(err.message || 'Failed to load rules'))
|
|
21
|
+
oxyServices.karma.getKarmaRules()
|
|
22
|
+
.then((data: any) => setRules(Array.isArray(data) ? data : []))
|
|
23
|
+
.catch((err: any) => setError(err.message || 'Failed to load rules'))
|
|
24
24
|
.finally(() => setIsLoading(false));
|
|
25
25
|
}, [oxyServices]);
|
|
26
26
|
|
|
@@ -53,7 +53,7 @@ export const useFollowStore = create<FollowState>((set: any, get: any) => ({
|
|
|
53
53
|
errors: { ...state.errors, [userId]: null },
|
|
54
54
|
}));
|
|
55
55
|
try {
|
|
56
|
-
const response = await oxyServices.getFollowStatus(userId);
|
|
56
|
+
const response = await oxyServices.users.getFollowStatus(userId);
|
|
57
57
|
set((state: FollowState) => ({
|
|
58
58
|
followingUsers: { ...state.followingUsers, [userId]: response.isFollowing },
|
|
59
59
|
fetchingUsers: { ...state.fetchingUsers, [userId]: false },
|
|
@@ -75,10 +75,10 @@ export const useFollowStore = create<FollowState>((set: any, get: any) => ({
|
|
|
75
75
|
let response: any;
|
|
76
76
|
let newFollowState;
|
|
77
77
|
if (isCurrentlyFollowing) {
|
|
78
|
-
response = await oxyServices.unfollowUser(userId);
|
|
78
|
+
response = await oxyServices.users.unfollowUser(userId);
|
|
79
79
|
newFollowState = false;
|
|
80
80
|
} else {
|
|
81
|
-
response = await oxyServices.followUser(userId);
|
|
81
|
+
response = await oxyServices.users.followUser(userId);
|
|
82
82
|
newFollowState = true;
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -158,7 +158,7 @@ export const useFollowStore = create<FollowState>((set: any, get: any) => ({
|
|
|
158
158
|
loadingCounts: { ...state.loadingCounts, [userId]: true },
|
|
159
159
|
}));
|
|
160
160
|
try {
|
|
161
|
-
const user = await oxyServices.getUserById(userId);
|
|
161
|
+
const user = await oxyServices.users.getUserById(userId);
|
|
162
162
|
if (user && user._count) {
|
|
163
163
|
set((state: FollowState) => ({
|
|
164
164
|
followerCounts: {
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for common API patterns
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Build URL search parameters from an object
|
|
7
|
+
* @param params Object with parameter key-value pairs
|
|
8
|
+
* @returns URLSearchParams instance
|
|
9
|
+
*/
|
|
10
|
+
export function buildSearchParams(params: Record<string, any>): URLSearchParams {
|
|
11
|
+
const searchParams = new URLSearchParams();
|
|
12
|
+
|
|
13
|
+
for (const [key, value] of Object.entries(params)) {
|
|
14
|
+
if (value !== undefined && value !== null) {
|
|
15
|
+
searchParams.append(key, value.toString());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return searchParams;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Build URL with search parameters
|
|
24
|
+
* @param baseUrl Base URL
|
|
25
|
+
* @param params Object with parameter key-value pairs
|
|
26
|
+
* @returns Complete URL with search parameters
|
|
27
|
+
*/
|
|
28
|
+
export function buildUrl(baseUrl: string, params?: Record<string, any>): string {
|
|
29
|
+
if (!params) return baseUrl;
|
|
30
|
+
|
|
31
|
+
const searchParams = buildSearchParams(params);
|
|
32
|
+
const queryString = searchParams.toString();
|
|
33
|
+
|
|
34
|
+
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Common pagination parameters
|
|
39
|
+
*/
|
|
40
|
+
export interface PaginationParams {
|
|
41
|
+
limit?: number;
|
|
42
|
+
offset?: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Build pagination search parameters
|
|
47
|
+
* @param params Pagination parameters
|
|
48
|
+
* @returns URLSearchParams with pagination
|
|
49
|
+
*/
|
|
50
|
+
export function buildPaginationParams(params: PaginationParams): URLSearchParams {
|
|
51
|
+
return buildSearchParams(params);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Common API response wrapper
|
|
56
|
+
*/
|
|
57
|
+
export interface ApiResponse<T = any> {
|
|
58
|
+
data: T;
|
|
59
|
+
message?: string;
|
|
60
|
+
success?: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Common error response wrapper
|
|
65
|
+
*/
|
|
66
|
+
export interface ErrorResponse {
|
|
67
|
+
message: string;
|
|
68
|
+
code: string;
|
|
69
|
+
status: number;
|
|
70
|
+
details?: any;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Validate required parameters
|
|
75
|
+
* @param params Object to validate
|
|
76
|
+
* @param requiredKeys Array of required keys
|
|
77
|
+
* @throws Error if any required key is missing
|
|
78
|
+
*/
|
|
79
|
+
export function validateRequiredParams(params: Record<string, any>, requiredKeys: string[]): void {
|
|
80
|
+
const missing = requiredKeys.filter(key => params[key] === undefined || params[key] === null);
|
|
81
|
+
|
|
82
|
+
if (missing.length > 0) {
|
|
83
|
+
throw new Error(`Missing required parameters: ${missing.join(', ')}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Safe JSON parsing with error handling
|
|
89
|
+
* @param data Data to parse
|
|
90
|
+
* @param fallback Fallback value if parsing fails
|
|
91
|
+
* @returns Parsed data or fallback
|
|
92
|
+
*/
|
|
93
|
+
export function safeJsonParse<T>(data: any, fallback: T): T {
|
|
94
|
+
if (typeof data === 'string') {
|
|
95
|
+
try {
|
|
96
|
+
return JSON.parse(data);
|
|
97
|
+
} catch {
|
|
98
|
+
return fallback;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return data as T;
|
|
102
|
+
}
|