@oxyhq/services 5.9.1 → 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 -1707
- 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 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/session.js +2 -0
- package/lib/{module/types/middleware.js.map → commonjs/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 -1694
- 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/{commonjs/types/middleware.js.map → module/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 -657
- 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 +26 -1769
- 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/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/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/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/types/middleware.ts +0 -20
package/src/core/index.ts
CHANGED
|
@@ -1,1782 +1,39 @@
|
|
|
1
|
-
import axios, { AxiosInstance, AxiosError, AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios';
|
|
2
|
-
import { jwtDecode } from 'jwt-decode';
|
|
3
|
-
|
|
4
|
-
// Remove all FormData, form-data, and polyfill logic. Delete uploadFile and uploadFiles methods. Add a comment to use the new raw upload approach instead.
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
OxyConfig,
|
|
8
|
-
User,
|
|
9
|
-
LoginResponse,
|
|
10
|
-
Notification,
|
|
11
|
-
Wallet,
|
|
12
|
-
Transaction,
|
|
13
|
-
TransferFundsRequest,
|
|
14
|
-
PurchaseRequest,
|
|
15
|
-
WithdrawalRequest,
|
|
16
|
-
TransactionResponse,
|
|
17
|
-
KarmaRule,
|
|
18
|
-
KarmaHistory,
|
|
19
|
-
KarmaLeaderboardEntry,
|
|
20
|
-
KarmaAwardRequest,
|
|
21
|
-
ApiError,
|
|
22
|
-
PaymentMethod,
|
|
23
|
-
PaymentRequest,
|
|
24
|
-
PaymentResponse,
|
|
25
|
-
AnalyticsData,
|
|
26
|
-
FollowerDetails,
|
|
27
|
-
ContentViewer,
|
|
28
|
-
// File management interfaces
|
|
29
|
-
FileMetadata,
|
|
30
|
-
FileUploadResponse,
|
|
31
|
-
FileListResponse,
|
|
32
|
-
FileUpdateRequest,
|
|
33
|
-
FileDeleteResponse,
|
|
34
|
-
// Device session interfaces
|
|
35
|
-
DeviceSession,
|
|
36
|
-
DeviceSessionsResponse,
|
|
37
|
-
DeviceSessionLogoutResponse,
|
|
38
|
-
UpdateDeviceNameResponse
|
|
39
|
-
} from '../models/interfaces';
|
|
40
|
-
|
|
41
|
-
// Import secure session types
|
|
42
|
-
import { SecureLoginResponse, SecureClientSession } from '../models/secureSession';
|
|
43
|
-
|
|
44
1
|
/**
|
|
45
|
-
*
|
|
46
|
-
*/
|
|
47
|
-
export const OXY_CLOUD_URL = 'https://cloud.oxy.so';
|
|
48
|
-
|
|
49
|
-
// Export device management utilities
|
|
50
|
-
export { DeviceManager } from '../utils/deviceManager';
|
|
51
|
-
export type { DeviceFingerprint, StoredDeviceInfo } from '../utils/deviceManager';
|
|
52
|
-
|
|
53
|
-
interface JwtPayload {
|
|
54
|
-
exp: number;
|
|
55
|
-
userId: string;
|
|
56
|
-
[key: string]: any;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* OxyServices - Client library for interacting with the Oxy API
|
|
2
|
+
* OxyServices Core Module - Modular Architecture
|
|
61
3
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
4
|
+
* This module exports the main OxyServices class and all individual service modules
|
|
5
|
+
* for a clean, maintainable, and focused architecture.
|
|
64
6
|
*/
|
|
65
|
-
export class OxyServices {
|
|
66
|
-
private client: AxiosInstance;
|
|
67
|
-
private accessToken: string | null = null;
|
|
68
|
-
private refreshToken: string | null = null;
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Creates a new instance of the OxyServices client
|
|
72
|
-
* @param config - Configuration for the client
|
|
73
|
-
*/
|
|
74
|
-
constructor(config: OxyConfig) {
|
|
75
|
-
this.client = axios.create({
|
|
76
|
-
baseURL: config.baseURL,
|
|
77
|
-
timeout: 10000 // 10 second timeout
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// Interceptor for adding auth header and handling token refresh
|
|
81
|
-
this.client.interceptors.request.use(async (req: InternalAxiosRequestConfig) => {
|
|
82
|
-
if (!this.accessToken) {
|
|
83
|
-
return req;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Check if token is expired and refresh if needed
|
|
87
|
-
try {
|
|
88
|
-
const decoded = jwtDecode<JwtPayload>(this.accessToken);
|
|
89
|
-
const currentTime = Math.floor(Date.now() / 1000);
|
|
90
|
-
|
|
91
|
-
// If token expires in less than 60 seconds, refresh it
|
|
92
|
-
if (decoded.exp - currentTime < 60) {
|
|
93
|
-
// For session-based tokens, get a new token from the session
|
|
94
|
-
if (decoded.sessionId) {
|
|
95
|
-
try {
|
|
96
|
-
const res = await this.client.get(`/secure-session/token/${decoded.sessionId}`);
|
|
97
|
-
this.accessToken = res.data.accessToken;
|
|
98
|
-
} catch (refreshError) {
|
|
99
|
-
// If refresh fails, clear tokens
|
|
100
|
-
this.clearTokens();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
} catch (error) {
|
|
105
|
-
// If token can't be decoded, continue with request and let server handle it
|
|
106
|
-
console.warn('Error decoding JWT token', error);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
req.headers = req.headers || {};
|
|
110
|
-
req.headers.Authorization = `Bearer ${this.accessToken}`;
|
|
111
|
-
return req;
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// Response interceptor for handling errors
|
|
115
|
-
this.client.interceptors.response.use(
|
|
116
|
-
response => response,
|
|
117
|
-
async (error: AxiosError) => {
|
|
118
|
-
const originalRequest = error.config;
|
|
119
|
-
// If the error is due to an expired token and we haven't tried refreshing yet
|
|
120
|
-
if (
|
|
121
|
-
error.response?.status === 401 &&
|
|
122
|
-
this.accessToken &&
|
|
123
|
-
originalRequest &&
|
|
124
|
-
!originalRequest.headers?.['X-Retry-After-Refresh']
|
|
125
|
-
) {
|
|
126
|
-
try {
|
|
127
|
-
// Check if token is session-based and try to refresh
|
|
128
|
-
const decoded = jwtDecode<JwtPayload>(this.accessToken);
|
|
129
|
-
if (decoded.sessionId) {
|
|
130
|
-
const res = await this.client.get(`/secure-session/token/${decoded.sessionId}`);
|
|
131
|
-
this.accessToken = res.data.accessToken;
|
|
132
|
-
|
|
133
|
-
// Retry the original request with new token
|
|
134
|
-
const newRequest = { ...originalRequest };
|
|
135
|
-
if (newRequest.headers) {
|
|
136
|
-
newRequest.headers.Authorization = `Bearer ${this.accessToken}`;
|
|
137
|
-
newRequest.headers['X-Retry-After-Refresh'] = 'true';
|
|
138
|
-
}
|
|
139
|
-
return this.client(newRequest);
|
|
140
|
-
}
|
|
141
|
-
} catch (refreshError) {
|
|
142
|
-
// If refresh fails, force user to login again
|
|
143
|
-
this.clearTokens();
|
|
144
|
-
return Promise.reject(refreshError);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Format error response
|
|
149
|
-
const apiError: ApiError = {
|
|
150
|
-
message: (error.response?.data as any)?.error || (error.response?.data as any)?.message || 'An unknown error occurred',
|
|
151
|
-
code: (error.response?.data as any)?.code || 'UNKNOWN_ERROR',
|
|
152
|
-
status: error.response?.status || 500,
|
|
153
|
-
details: error.response?.data
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// If the error is an invalid session, clear tokens
|
|
157
|
-
if (apiError.code === 'INVALID_SESSION' || apiError.message === 'Invalid session') {
|
|
158
|
-
this.clearTokens();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return Promise.reject(apiError);
|
|
162
|
-
}
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Gets the base URL configured for this OxyServices instance
|
|
168
|
-
* @returns The base URL
|
|
169
|
-
*/
|
|
170
|
-
public getBaseURL(): string {
|
|
171
|
-
return this.client.defaults.baseURL || '';
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Set authentication tokens manually
|
|
176
|
-
* @param accessToken - The access token
|
|
177
|
-
* @param refreshToken - The refresh token (optional for session-based auth)
|
|
178
|
-
*/
|
|
179
|
-
public setTokens(accessToken: string, refreshToken: string = ''): void {
|
|
180
|
-
this.accessToken = accessToken;
|
|
181
|
-
this.refreshToken = refreshToken;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Clear stored authentication tokens
|
|
186
|
-
*/
|
|
187
|
-
public clearTokens(): void {
|
|
188
|
-
this.accessToken = null;
|
|
189
|
-
this.refreshToken = null;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Get the current user ID from the stored token
|
|
194
|
-
* @returns User ID or null if not authenticated
|
|
195
|
-
*/
|
|
196
|
-
public getCurrentUserId(): string | null {
|
|
197
|
-
if (!this.accessToken) return null;
|
|
198
|
-
|
|
199
|
-
try {
|
|
200
|
-
const decoded = jwtDecode<JwtPayload>(this.accessToken);
|
|
201
|
-
return decoded.userId || decoded.id || null;
|
|
202
|
-
} catch (error) {
|
|
203
|
-
return null;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Internal method to check if we have an access token
|
|
209
|
-
* @private
|
|
210
|
-
* @returns Boolean indicating if access token exists
|
|
211
|
-
* @internal - Use `isAuthenticated` from useOxy() context in UI components instead
|
|
212
|
-
*/
|
|
213
|
-
private hasAccessToken(): boolean {
|
|
214
|
-
return this.accessToken !== null;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Validate current access token
|
|
219
|
-
* @returns Boolean indicating if the token is valid
|
|
220
|
-
*/
|
|
221
|
-
async validate(): Promise<boolean> {
|
|
222
|
-
try {
|
|
223
|
-
// Check if token contains sessionId (new session-based system)
|
|
224
|
-
if (this.accessToken) {
|
|
225
|
-
try {
|
|
226
|
-
const decoded = jwtDecode<JwtPayload>(this.accessToken);
|
|
227
|
-
if (decoded.sessionId) {
|
|
228
|
-
// Use session-based validation
|
|
229
|
-
const res = await this.client.get(`/secure-session/validate/${decoded.sessionId}`);
|
|
230
|
-
return res.data.valid;
|
|
231
|
-
}
|
|
232
|
-
} catch (decodeError) {
|
|
233
|
-
// If token can't be decoded, fall back to old validation
|
|
234
|
-
console.warn('Error decoding JWT token for session validation:', decodeError);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Fall back to old validation method
|
|
239
|
-
const res = await this.client.get('/auth/validate');
|
|
240
|
-
return res.data.valid;
|
|
241
|
-
} catch (error) {
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/* Session Management Methods */
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Get device sessions for a specific session ID
|
|
250
|
-
* @param sessionId - The session ID to get device sessions for
|
|
251
|
-
* @param deviceId - Optional device ID filter
|
|
252
|
-
* @returns Array of device sessions
|
|
253
|
-
*/
|
|
254
|
-
async getDeviceSessions(sessionId: string, deviceId?: string): Promise<DeviceSession[]> {
|
|
255
|
-
try {
|
|
256
|
-
const params = deviceId ? { deviceId } : {};
|
|
257
|
-
const res = await this.client.get(`/secure-session/device/sessions/${sessionId}`, { params });
|
|
258
|
-
|
|
259
|
-
// Map backend response to frontend interface
|
|
260
|
-
return (res.data.sessions || []).map((session: any) => ({
|
|
261
|
-
sessionId: session.sessionId,
|
|
262
|
-
deviceId: res.data.deviceId || '',
|
|
263
|
-
deviceName: session.deviceInfo?.deviceName || 'Unknown Device',
|
|
264
|
-
isActive: true, // All returned sessions are active
|
|
265
|
-
lastActive: session.lastActive,
|
|
266
|
-
expiresAt: session.expiresAt || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
267
|
-
isCurrent: session.sessionId === sessionId,
|
|
268
|
-
user: session.user,
|
|
269
|
-
createdAt: session.createdAt
|
|
270
|
-
}));
|
|
271
|
-
} catch (error) {
|
|
272
|
-
throw this.handleError(error);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Logout all device sessions for a specific device
|
|
278
|
-
* @param sessionId - The session ID
|
|
279
|
-
* @param deviceId - Optional device ID (uses current session's device if not provided)
|
|
280
|
-
* @param excludeCurrent - Whether to exclude the current session from logout
|
|
281
|
-
* @returns Logout response
|
|
282
|
-
*/
|
|
283
|
-
async logoutAllDeviceSessions(sessionId: string, deviceId?: string, excludeCurrent?: boolean): Promise<DeviceSessionLogoutResponse> {
|
|
284
|
-
try {
|
|
285
|
-
const data: any = {};
|
|
286
|
-
if (deviceId) data.deviceId = deviceId;
|
|
287
|
-
if (excludeCurrent !== undefined) data.excludeCurrent = excludeCurrent;
|
|
288
|
-
|
|
289
|
-
const res = await this.client.post(`/secure-session/device/logout-all/${sessionId}`, data);
|
|
290
|
-
return res.data;
|
|
291
|
-
} catch (error) {
|
|
292
|
-
throw this.handleError(error);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Update device name for a session
|
|
298
|
-
* @param sessionId - The session ID
|
|
299
|
-
* @param deviceName - The new device name
|
|
300
|
-
* @returns Update response
|
|
301
|
-
*/
|
|
302
|
-
async updateDeviceName(sessionId: string, deviceName: string): Promise<UpdateDeviceNameResponse> {
|
|
303
|
-
try {
|
|
304
|
-
const res = await this.client.put(`/secure-session/device/name/${sessionId}`, { deviceName });
|
|
305
|
-
return res.data;
|
|
306
|
-
} catch (error) {
|
|
307
|
-
throw this.handleError(error);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/* Profile Methods */
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* Fetch profile by username
|
|
315
|
-
* @param username - The username to look up
|
|
316
|
-
* @returns User profile data
|
|
317
|
-
*/
|
|
318
|
-
async getProfileByUsername(username: string): Promise<User> {
|
|
319
|
-
try {
|
|
320
|
-
const res = await this.client.get(`/profiles/username/${username}`);
|
|
321
|
-
return res.data;
|
|
322
|
-
} catch (error) {
|
|
323
|
-
throw this.handleError(error);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Search profiles
|
|
329
|
-
* @param query - Search query string
|
|
330
|
-
* @param limit - Maximum number of results to return
|
|
331
|
-
* @param offset - Number of results to skip for pagination
|
|
332
|
-
* @returns Array of matching user profiles
|
|
333
|
-
*/
|
|
334
|
-
async searchProfiles(query: string, limit?: number, offset?: number): Promise<User[]> {
|
|
335
|
-
try {
|
|
336
|
-
const params: Record<string, any> = { query };
|
|
337
|
-
if (limit !== undefined) params.limit = limit;
|
|
338
|
-
if (offset !== undefined) params.offset = offset;
|
|
339
|
-
const res = await this.client.get('/profiles/search', { params });
|
|
340
|
-
return res.data;
|
|
341
|
-
} catch (error) {
|
|
342
|
-
throw this.handleError(error);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Get recommended profiles for the authenticated user
|
|
348
|
-
* @returns Array of recommended profiles
|
|
349
|
-
*/
|
|
350
|
-
async getProfileRecommendations(): Promise<Array<{
|
|
351
|
-
id: string;
|
|
352
|
-
username: string;
|
|
353
|
-
name?: { first?: string; last?: string; full?: string };
|
|
354
|
-
description?: string;
|
|
355
|
-
_count?: { followers: number; following: number };
|
|
356
|
-
[key: string]: any;
|
|
357
|
-
}>> {
|
|
358
|
-
try {
|
|
359
|
-
const res = await this.client.get('/profiles/recommendations');
|
|
360
|
-
return res.data;
|
|
361
|
-
} catch (error) {
|
|
362
|
-
throw this.handleError(error);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/* User Methods */
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Get general user by ID
|
|
370
|
-
* @param userId - The user ID to look up
|
|
371
|
-
* @returns User data
|
|
372
|
-
*/
|
|
373
|
-
async getUserById(userId: string): Promise<User> {
|
|
374
|
-
try {
|
|
375
|
-
const res = await this.client.get(`/users/${userId}`);
|
|
376
|
-
return res.data;
|
|
377
|
-
} catch (error) {
|
|
378
|
-
throw this.handleError(error);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Get the currently authenticated user's profile
|
|
384
|
-
* @returns User data for the current user
|
|
385
|
-
*/
|
|
386
|
-
async getCurrentUser(): Promise<User> {
|
|
387
|
-
try {
|
|
388
|
-
console.log('OxyServices: Fetching current user...');
|
|
389
|
-
const res = await this.client.get('/users/me');
|
|
390
|
-
console.log('OxyServices: Current user response:', {
|
|
391
|
-
hasUser: !!res.data,
|
|
392
|
-
userLinksMetadata: res.data?.linksMetadata,
|
|
393
|
-
userLinks: res.data?.links,
|
|
394
|
-
userWebsite: res.data?.website
|
|
395
|
-
});
|
|
396
|
-
return res.data;
|
|
397
|
-
} catch (error) {
|
|
398
|
-
console.error('OxyServices: Error fetching current user:', error);
|
|
399
|
-
throw this.handleError(error);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* Update the authenticated user's profile
|
|
405
|
-
* @param updates - Object containing fields to update
|
|
406
|
-
* @returns Updated user data
|
|
407
|
-
*/
|
|
408
|
-
async updateProfile(updates: Record<string, any>): Promise<User> {
|
|
409
|
-
try {
|
|
410
|
-
console.log('OxyServices: Updating profile with:', updates);
|
|
411
|
-
const res = await this.client.put('/users/me', updates);
|
|
412
|
-
console.log('OxyServices: Profile update response:', res.data);
|
|
413
|
-
return res.data;
|
|
414
|
-
} catch (error) {
|
|
415
|
-
console.error('OxyServices: Error updating profile:', error);
|
|
416
|
-
throw this.handleError(error);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Update user profile (requires auth)
|
|
422
|
-
* @param userId - User ID to update (must match authenticated user or have admin rights)
|
|
423
|
-
* @param updates - Object containing fields to update
|
|
424
|
-
* @returns Updated user data
|
|
425
|
-
*/
|
|
426
|
-
async updateUser(userId: string, updates: Record<string, any>): Promise<User> {
|
|
427
|
-
try {
|
|
428
|
-
const res = await this.client.put(`/users/${userId}`, updates);
|
|
429
|
-
return res.data;
|
|
430
|
-
} catch (error) {
|
|
431
|
-
throw this.handleError(error);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Follow a user
|
|
437
|
-
* @param userId - User ID to follow
|
|
438
|
-
* @returns Status of the follow operation
|
|
439
|
-
*/
|
|
440
|
-
async followUser(userId: string): Promise<{ success: boolean; message: string }> {
|
|
441
|
-
try {
|
|
442
|
-
const res = await this.client.post(`/users/${userId}/follow`);
|
|
443
|
-
return res.data;
|
|
444
|
-
} catch (error) {
|
|
445
|
-
throw this.handleError(error);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Unfollow a user
|
|
451
|
-
* @param userId - User ID to unfollow
|
|
452
|
-
* @returns Status of the unfollow operation
|
|
453
|
-
*/
|
|
454
|
-
async unfollowUser(userId: string): Promise<{ success: boolean; message: string }> {
|
|
455
|
-
try {
|
|
456
|
-
const res = await this.client.delete(`/users/${userId}/follow`);
|
|
457
|
-
return res.data;
|
|
458
|
-
} catch (error) {
|
|
459
|
-
throw this.handleError(error);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* Get follow status for a user
|
|
465
|
-
* @param userId - User ID to check follow status for
|
|
466
|
-
* @returns Whether the current user is following the specified user
|
|
467
|
-
*/
|
|
468
|
-
async getFollowStatus(userId: string): Promise<{ isFollowing: boolean }> {
|
|
469
|
-
try {
|
|
470
|
-
const res = await this.client.get(`/users/${userId}/following-status`);
|
|
471
|
-
return res.data;
|
|
472
|
-
} catch (error) {
|
|
473
|
-
throw this.handleError(error);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
/**
|
|
478
|
-
* Get all followers of a user
|
|
479
|
-
* @param userId - User ID to get followers for
|
|
480
|
-
* @param limit - Maximum number of followers to return
|
|
481
|
-
* @param offset - Number of followers to skip for pagination
|
|
482
|
-
* @returns Array of users who follow the specified user and pagination info
|
|
483
|
-
*/
|
|
484
|
-
async getUserFollowers(
|
|
485
|
-
userId: string,
|
|
486
|
-
limit?: number,
|
|
487
|
-
offset?: number
|
|
488
|
-
): Promise<{ followers: User[]; total: number; hasMore: boolean }> {
|
|
489
|
-
try {
|
|
490
|
-
const params: Record<string, any> = {};
|
|
491
|
-
if (limit !== undefined) params.limit = limit;
|
|
492
|
-
if (offset !== undefined) params.offset = offset;
|
|
493
|
-
const res = await this.client.get(`/users/${userId}/followers`, { params });
|
|
494
|
-
return res.data;
|
|
495
|
-
} catch (error) {
|
|
496
|
-
throw this.handleError(error);
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* Get all users that a user is following
|
|
502
|
-
* @param userId - User ID to get following list for
|
|
503
|
-
* @param limit - Maximum number of users to return
|
|
504
|
-
* @param offset - Number of users to skip for pagination
|
|
505
|
-
* @returns Array of users the specified user follows and pagination info
|
|
506
|
-
*/
|
|
507
|
-
async getUserFollowing(
|
|
508
|
-
userId: string,
|
|
509
|
-
limit?: number,
|
|
510
|
-
offset?: number
|
|
511
|
-
): Promise<{ following: User[]; total: number; hasMore: boolean }> {
|
|
512
|
-
try {
|
|
513
|
-
const params: Record<string, any> = {};
|
|
514
|
-
if (limit !== undefined) params.limit = limit;
|
|
515
|
-
if (offset !== undefined) params.offset = offset;
|
|
516
|
-
const res = await this.client.get(`/users/${userId}/following`, { params });
|
|
517
|
-
return res.data;
|
|
518
|
-
} catch (error) {
|
|
519
|
-
throw this.handleError(error);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
/* Notification Methods */
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* Fetch all notifications for the authenticated user
|
|
527
|
-
* @returns Array of notifications
|
|
528
|
-
*/
|
|
529
|
-
async getNotifications(): Promise<Notification[]> {
|
|
530
|
-
try {
|
|
531
|
-
const res = await this.client.get('/notifications');
|
|
532
|
-
return res.data;
|
|
533
|
-
} catch (error) {
|
|
534
|
-
throw this.handleError(error);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* Get count of unread notifications
|
|
540
|
-
* @returns Number of unread notifications
|
|
541
|
-
*/
|
|
542
|
-
async getUnreadCount(): Promise<number> {
|
|
543
|
-
try {
|
|
544
|
-
const res = await this.client.get('/notifications/unread-count');
|
|
545
|
-
return res.data;
|
|
546
|
-
} catch (error) {
|
|
547
|
-
throw this.handleError(error);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
/**
|
|
552
|
-
* Create a new notification (admin use)
|
|
553
|
-
* @param data - Notification data
|
|
554
|
-
* @returns Created notification
|
|
555
|
-
*/
|
|
556
|
-
async createNotification(data: Partial<Notification>): Promise<Notification> {
|
|
557
|
-
try {
|
|
558
|
-
const res = await this.client.post('/notifications', data);
|
|
559
|
-
return res.data;
|
|
560
|
-
} catch (error) {
|
|
561
|
-
throw this.handleError(error);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* Mark a single notification as read
|
|
567
|
-
* @param notificationId - ID of notification to mark as read
|
|
568
|
-
*/
|
|
569
|
-
async markNotificationAsRead(notificationId: string): Promise<void> {
|
|
570
|
-
try {
|
|
571
|
-
await this.client.put(`/notifications/${notificationId}/read`);
|
|
572
|
-
} catch (error) {
|
|
573
|
-
throw this.handleError(error);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
/**
|
|
578
|
-
* Mark all notifications as read
|
|
579
|
-
*/
|
|
580
|
-
async markAllNotificationsAsRead(): Promise<void> {
|
|
581
|
-
try {
|
|
582
|
-
await this.client.put('/notifications/read-all');
|
|
583
|
-
} catch (error) {
|
|
584
|
-
throw this.handleError(error);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
/**
|
|
589
|
-
* Delete a notification
|
|
590
|
-
* @param notificationId - ID of notification to delete
|
|
591
|
-
*/
|
|
592
|
-
async deleteNotification(notificationId: string): Promise<void> {
|
|
593
|
-
try {
|
|
594
|
-
await this.client.delete(`/notifications/${notificationId}`);
|
|
595
|
-
} catch (error) {
|
|
596
|
-
throw this.handleError(error);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
/* Payment Methods */
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* Process a payment
|
|
604
|
-
* @param data - Payment data including user ID, plan, and payment method
|
|
605
|
-
* @returns Payment result with transaction ID
|
|
606
|
-
*/
|
|
607
|
-
async processPayment(data: PaymentRequest): Promise<PaymentResponse> {
|
|
608
|
-
try {
|
|
609
|
-
const res = await this.client.post('/payments/process', data);
|
|
610
|
-
return res.data;
|
|
611
|
-
} catch (error) {
|
|
612
|
-
throw this.handleError(error);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
/**
|
|
617
|
-
* Validate a payment method
|
|
618
|
-
* @param paymentMethod - Payment method to validate
|
|
619
|
-
* @returns Object indicating if the payment method is valid
|
|
620
|
-
*/
|
|
621
|
-
async validatePaymentMethod(paymentMethod: any): Promise<{ valid: boolean }> {
|
|
622
|
-
try {
|
|
623
|
-
const res = await this.client.post('/payments/validate', { paymentMethod });
|
|
624
|
-
return res.data;
|
|
625
|
-
} catch (error) {
|
|
626
|
-
throw this.handleError(error);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
/**
|
|
631
|
-
* Get saved payment methods for a user
|
|
632
|
-
* @param userId - User ID to get payment methods for
|
|
633
|
-
* @returns Array of payment methods
|
|
634
|
-
*/
|
|
635
|
-
async getPaymentMethods(userId: string): Promise<PaymentMethod[]> {
|
|
636
|
-
try {
|
|
637
|
-
const res = await this.client.get(`/payments/methods/${userId}`);
|
|
638
|
-
return res.data;
|
|
639
|
-
} catch (error) {
|
|
640
|
-
throw this.handleError(error);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
/* Analytics Methods */
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* Get analytics data
|
|
648
|
-
* @param userId - User ID to get analytics for
|
|
649
|
-
* @param period - Time period for analytics (e.g., "day", "week", "month")
|
|
650
|
-
* @returns Analytics data
|
|
651
|
-
*/
|
|
652
|
-
async getAnalytics(userId: string, period?: string): Promise<AnalyticsData> {
|
|
653
|
-
try {
|
|
654
|
-
const params: Record<string, any> = { userID: userId };
|
|
655
|
-
if (period) params.period = period;
|
|
656
|
-
const res = await this.client.get('/analytics', { params });
|
|
657
|
-
return res.data;
|
|
658
|
-
} catch (error) {
|
|
659
|
-
throw this.handleError(error);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
/**
|
|
664
|
-
* Update analytics (internal use)
|
|
665
|
-
* @param userId - User ID to update analytics for
|
|
666
|
-
* @param type - Type of analytics to update
|
|
667
|
-
* @param data - Analytics data to update
|
|
668
|
-
* @returns Message indicating success
|
|
669
|
-
*/
|
|
670
|
-
async updateAnalytics(userId: string, type: string, data: Record<string, any>): Promise<{ message: string }> {
|
|
671
|
-
try {
|
|
672
|
-
const res = await this.client.post('/analytics/update', { userID: userId, type, data });
|
|
673
|
-
return res.data;
|
|
674
|
-
} catch (error) {
|
|
675
|
-
throw this.handleError(error);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
/**
|
|
680
|
-
* Get content viewers analytics
|
|
681
|
-
* @param userId - User ID to get viewer data for
|
|
682
|
-
* @param period - Time period for analytics
|
|
683
|
-
* @returns Array of content viewer data
|
|
684
|
-
*/
|
|
685
|
-
async getContentViewers(userId: string, period?: string): Promise<ContentViewer[]> {
|
|
686
|
-
try {
|
|
687
|
-
const params: Record<string, any> = { userID: userId };
|
|
688
|
-
if (period) params.period = period;
|
|
689
|
-
const res = await this.client.get('/analytics/viewers', { params });
|
|
690
|
-
return res.data;
|
|
691
|
-
} catch (error) {
|
|
692
|
-
throw this.handleError(error);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
/**
|
|
697
|
-
* Get follower analytics details
|
|
698
|
-
* @param userId - User ID to get follower data for
|
|
699
|
-
* @param period - Time period for follower data
|
|
700
|
-
* @returns Follower details
|
|
701
|
-
*/
|
|
702
|
-
async getFollowerDetails(userId: string, period?: string): Promise<FollowerDetails> {
|
|
703
|
-
try {
|
|
704
|
-
const params: Record<string, any> = { userID: userId };
|
|
705
|
-
if (period) params.period = period;
|
|
706
|
-
const res = await this.client.get('/analytics/followers', { params });
|
|
707
|
-
return res.data;
|
|
708
|
-
} catch (error) {
|
|
709
|
-
throw this.handleError(error);
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
/* Wallet Methods */
|
|
714
|
-
|
|
715
|
-
/**
|
|
716
|
-
* Get wallet info
|
|
717
|
-
* @param userId - User ID to get wallet for
|
|
718
|
-
* @returns Wallet data
|
|
719
|
-
*/
|
|
720
|
-
async getWallet(userId: string): Promise<Wallet> {
|
|
721
|
-
try {
|
|
722
|
-
const res = await this.client.get(`/wallet/${userId}`);
|
|
723
|
-
return res.data;
|
|
724
|
-
} catch (error) {
|
|
725
|
-
throw this.handleError(error);
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
7
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
* @param userId - User ID to get transactions for
|
|
732
|
-
* @param limit - Maximum number of transactions to return
|
|
733
|
-
* @param offset - Number of transactions to skip for pagination
|
|
734
|
-
* @returns Array of transactions and pagination info
|
|
735
|
-
*/
|
|
736
|
-
async getTransactionHistory(
|
|
737
|
-
userId: string,
|
|
738
|
-
limit?: number,
|
|
739
|
-
offset?: number
|
|
740
|
-
): Promise<{ transactions: Transaction[]; total: number; hasMore: boolean }> {
|
|
741
|
-
try {
|
|
742
|
-
const params: Record<string, any> = {};
|
|
743
|
-
if (limit !== undefined) params.limit = limit;
|
|
744
|
-
if (offset !== undefined) params.offset = offset;
|
|
745
|
-
const res = await this.client.get(`/wallet/transactions/${userId}`, { params });
|
|
746
|
-
return res.data;
|
|
747
|
-
} catch (error) {
|
|
748
|
-
throw this.handleError(error);
|
|
749
|
-
}
|
|
750
|
-
}
|
|
8
|
+
// Main OxyServices class (backward compatible)
|
|
9
|
+
export { OxyServicesMain as OxyServices } from './OxyServicesMain';
|
|
751
10
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
} catch (error) {
|
|
762
|
-
throw this.handleError(error);
|
|
763
|
-
}
|
|
764
|
-
}
|
|
11
|
+
// Individual service classes for focused usage
|
|
12
|
+
export { AuthService } from './auth/AuthService';
|
|
13
|
+
export { UserService } from './users/UserService';
|
|
14
|
+
export { PaymentService } from './payments/PaymentService';
|
|
15
|
+
export { KarmaService } from './karma/KarmaService';
|
|
16
|
+
export { FileService } from './files/FileService';
|
|
17
|
+
export { LocationService } from './locations/LocationService';
|
|
18
|
+
export { AnalyticsService } from './analytics/AnalyticsService';
|
|
19
|
+
export { DeviceService } from './devices/DeviceService';
|
|
765
20
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
* @param data - Transfer details including source, destination, and amount
|
|
769
|
-
* @returns Transaction response
|
|
770
|
-
*/
|
|
771
|
-
async transferFunds(data: TransferFundsRequest): Promise<TransactionResponse> {
|
|
772
|
-
try {
|
|
773
|
-
const res = await this.client.post('/wallet/transfer', data);
|
|
774
|
-
return res.data;
|
|
775
|
-
} catch (error) {
|
|
776
|
-
throw this.handleError(error);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
21
|
+
// Base class for custom service extensions
|
|
22
|
+
export { OxyServices as BaseOxyServices } from './OxyServices';
|
|
779
23
|
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
* @param data - Purchase details including user, item, and amount
|
|
783
|
-
* @returns Transaction response
|
|
784
|
-
*/
|
|
785
|
-
async processPurchase(data: PurchaseRequest): Promise<TransactionResponse> {
|
|
786
|
-
try {
|
|
787
|
-
const res = await this.client.post('/wallet/purchase', data);
|
|
788
|
-
return res.data;
|
|
789
|
-
} catch (error) {
|
|
790
|
-
throw this.handleError(error);
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
/**
|
|
795
|
-
* Request a withdrawal
|
|
796
|
-
* @param data - Withdrawal details including user, amount, and address
|
|
797
|
-
* @returns Transaction response
|
|
798
|
-
*/
|
|
799
|
-
async requestWithdrawal(data: WithdrawalRequest): Promise<TransactionResponse> {
|
|
800
|
-
try {
|
|
801
|
-
const res = await this.client.post('/wallet/withdraw', data);
|
|
802
|
-
return res.data;
|
|
803
|
-
} catch (error) {
|
|
804
|
-
throw this.handleError(error);
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
/* Karma Methods */
|
|
809
|
-
|
|
810
|
-
/**
|
|
811
|
-
* Get karma leaderboard
|
|
812
|
-
* @returns Array of karma leaderboard entries
|
|
813
|
-
*/
|
|
814
|
-
async getKarmaLeaderboard(): Promise<KarmaLeaderboardEntry[]> {
|
|
815
|
-
try {
|
|
816
|
-
const res = await this.client.get('/karma/leaderboard');
|
|
817
|
-
return res.data;
|
|
818
|
-
} catch (error) {
|
|
819
|
-
throw this.handleError(error);
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
/**
|
|
824
|
-
* Get karma rules
|
|
825
|
-
* @returns Array of karma rules
|
|
826
|
-
*/
|
|
827
|
-
async getKarmaRules(): Promise<KarmaRule[]> {
|
|
828
|
-
try {
|
|
829
|
-
const res = await this.client.get('/karma/rules');
|
|
830
|
-
return res.data;
|
|
831
|
-
} catch (error) {
|
|
832
|
-
throw this.handleError(error);
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* Get total karma for a user
|
|
838
|
-
* @param userId - User ID to get karma for
|
|
839
|
-
* @returns Object with total karma points
|
|
840
|
-
*/
|
|
841
|
-
async getUserKarmaTotal(userId: string): Promise<{ total: number }> {
|
|
842
|
-
try {
|
|
843
|
-
const res = await this.client.get(`/karma/${userId}/total`);
|
|
844
|
-
return res.data;
|
|
845
|
-
} catch (error) {
|
|
846
|
-
throw this.handleError(error);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
/**
|
|
851
|
-
* Get karma history for a user
|
|
852
|
-
* @param userId - User ID to get karma history for
|
|
853
|
-
* @param limit - Maximum number of history entries to return
|
|
854
|
-
* @param offset - Number of entries to skip for pagination
|
|
855
|
-
* @returns Karma history entries and pagination info
|
|
856
|
-
*/
|
|
857
|
-
async getUserKarmaHistory(
|
|
858
|
-
userId: string,
|
|
859
|
-
limit?: number,
|
|
860
|
-
offset?: number
|
|
861
|
-
): Promise<{ history: KarmaHistory[]; total: number; hasMore: boolean }> {
|
|
862
|
-
try {
|
|
863
|
-
const params: Record<string, any> = {};
|
|
864
|
-
if (limit !== undefined) params.limit = limit;
|
|
865
|
-
if (offset !== undefined) params.offset = offset;
|
|
866
|
-
const res = await this.client.get(`/karma/${userId}/history`, { params });
|
|
867
|
-
return res.data;
|
|
868
|
-
} catch (error) {
|
|
869
|
-
throw this.handleError(error);
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
/**
|
|
874
|
-
* Award karma points to a user
|
|
875
|
-
* @param data - Karma award details
|
|
876
|
-
* @returns Karma award response
|
|
877
|
-
*/
|
|
878
|
-
async awardKarma(data: KarmaAwardRequest): Promise<{ success: boolean; message: string; history: KarmaHistory }> {
|
|
879
|
-
try {
|
|
880
|
-
const res = await this.client.post('/karma/award', data);
|
|
881
|
-
return res.data;
|
|
882
|
-
} catch (error) {
|
|
883
|
-
throw this.handleError(error);
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
/**
|
|
888
|
-
* Deduct karma points from a user
|
|
889
|
-
* @param data - Karma deduction details
|
|
890
|
-
* @returns Karma deduction response
|
|
891
|
-
*/
|
|
892
|
-
async deductKarma(data: KarmaAwardRequest): Promise<{ success: boolean; message: string; history: KarmaHistory }> {
|
|
893
|
-
try {
|
|
894
|
-
const res = await this.client.post('/karma/deduct', data);
|
|
895
|
-
return res.data;
|
|
896
|
-
} catch (error) {
|
|
897
|
-
throw this.handleError(error);
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
/**
|
|
902
|
-
* Create or update karma rule (admin)
|
|
903
|
-
* @param data - Karma rule data
|
|
904
|
-
* @returns Created or updated karma rule
|
|
905
|
-
*/
|
|
906
|
-
async createOrUpdateKarmaRule(data: Partial<KarmaRule>): Promise<KarmaRule> {
|
|
907
|
-
try {
|
|
908
|
-
const res = await this.client.post('/karma/rules', data);
|
|
909
|
-
return res.data;
|
|
910
|
-
} catch (error) {
|
|
911
|
-
throw this.handleError(error);
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
/* File Management Methods */
|
|
916
|
-
|
|
917
|
-
/**
|
|
918
|
-
* Upload a file using GridFS
|
|
919
|
-
* @param file - The file to upload (File or Blob in browser, Buffer in Node.js)
|
|
920
|
-
* @param filename - The name of the file
|
|
921
|
-
* @param metadata - Optional metadata to associate with the file
|
|
922
|
-
* @returns File metadata including ID and download URL
|
|
923
|
-
*/
|
|
924
|
-
async uploadFile(
|
|
925
|
-
file: File | Blob | any, // Use 'any' to handle Buffer type in cross-platform scenarios
|
|
926
|
-
filename: string,
|
|
927
|
-
metadata?: Record<string, any>
|
|
928
|
-
): Promise<FileMetadata> {
|
|
929
|
-
// This method is deprecated. Use uploadFilesRaw instead.
|
|
930
|
-
// For now, we'll throw an error as the underlying logic is removed.
|
|
931
|
-
throw new Error('uploadFile is deprecated. Use uploadFilesRaw instead.');
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
/**
|
|
935
|
-
* Upload multiple files using GridFS
|
|
936
|
-
* @param files - Array of files to upload
|
|
937
|
-
* @param filenames - Array of filenames (must match files array length)
|
|
938
|
-
* @param metadata - Optional metadata to associate with all files
|
|
939
|
-
* @returns Array of file metadata
|
|
940
|
-
*/
|
|
941
|
-
async uploadFiles(
|
|
942
|
-
files: (File | Blob | any)[],
|
|
943
|
-
filenames: string[],
|
|
944
|
-
metadata?: Record<string, any>
|
|
945
|
-
): Promise<FileUploadResponse> {
|
|
946
|
-
// This method is deprecated. Use uploadFilesRaw instead.
|
|
947
|
-
// For now, we'll throw an error as the underlying logic is removed.
|
|
948
|
-
throw new Error('uploadFiles is deprecated. Use uploadFilesRaw instead.');
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
/**
|
|
952
|
-
* Get file metadata by ID
|
|
953
|
-
* @param fileId - ID of the file to retrieve metadata for
|
|
954
|
-
* @returns File metadata
|
|
955
|
-
*/
|
|
956
|
-
async getFileMetadata(fileId: string): Promise<FileMetadata> {
|
|
957
|
-
try {
|
|
958
|
-
const res = await this.client.get(`/files/${fileId}/metadata`);
|
|
959
|
-
return res.data;
|
|
960
|
-
} catch (error) {
|
|
961
|
-
throw this.handleError(error);
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
/**
|
|
966
|
-
* Update file metadata
|
|
967
|
-
* @param fileId - ID of the file to update
|
|
968
|
-
* @param updates - Metadata updates to apply
|
|
969
|
-
* @returns Updated file metadata
|
|
970
|
-
*/
|
|
971
|
-
async updateFileMetadata(fileId: string, updates: FileUpdateRequest): Promise<FileMetadata> {
|
|
972
|
-
try {
|
|
973
|
-
const res = await this.client.put(`/files/${fileId}/metadata`, updates);
|
|
974
|
-
return res.data;
|
|
975
|
-
} catch (error) {
|
|
976
|
-
throw this.handleError(error);
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
/**
|
|
981
|
-
* Delete a file by ID
|
|
982
|
-
* @param fileId - ID of the file to delete
|
|
983
|
-
* @returns Status of the delete operation
|
|
984
|
-
*/
|
|
985
|
-
async deleteFile(fileId: string): Promise<FileDeleteResponse> {
|
|
986
|
-
try {
|
|
987
|
-
console.log('Deleting file with ID:', fileId);
|
|
988
|
-
const res = await this.client.delete(`/files/${fileId}`);
|
|
989
|
-
console.log('Delete response:', res.data);
|
|
990
|
-
return res.data;
|
|
991
|
-
} catch (error: any) {
|
|
992
|
-
console.error('Delete file error:', error);
|
|
993
|
-
console.error('Error response:', error.response?.data);
|
|
994
|
-
console.error('Error status:', error.response?.status);
|
|
995
|
-
|
|
996
|
-
// Provide more specific error messages based on status code
|
|
997
|
-
if (error.response?.status === 404) {
|
|
998
|
-
throw new Error('File not found or already deleted');
|
|
999
|
-
} else if (error.response?.status === 403) {
|
|
1000
|
-
throw new Error('You do not have permission to delete this file');
|
|
1001
|
-
} else if (error.response?.status === 400) {
|
|
1002
|
-
throw new Error('Invalid file ID format');
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
throw this.handleError(error);
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
/**
|
|
1010
|
-
* Get download URL for a file
|
|
1011
|
-
* @param fileId - ID of the file to get download URL for
|
|
1012
|
-
* @returns Full URL to download the file
|
|
1013
|
-
*/
|
|
1014
|
-
getFileDownloadUrl(fileId: string): string {
|
|
1015
|
-
return `${this.client.defaults.baseURL}/files/${fileId}`;
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
/**
|
|
1019
|
-
* Stream a file (useful for playing audio/video without full download)
|
|
1020
|
-
* @param fileId - ID of the file to stream
|
|
1021
|
-
* @returns Full URL to stream the file
|
|
1022
|
-
*/
|
|
1023
|
-
getFileStreamUrl(fileId: string): string {
|
|
1024
|
-
return `${this.client.defaults.baseURL}/files/${fileId}`;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
/**
|
|
1028
|
-
* List files for a specific user
|
|
1029
|
-
* @param userId - User ID to list files for
|
|
1030
|
-
* @param limit - Maximum number of files to return
|
|
1031
|
-
* @param offset - Number of files to skip for pagination
|
|
1032
|
-
* @param filters - Optional filters for the file list (e.g., contentType)
|
|
1033
|
-
* @returns Array of file metadata and pagination info
|
|
1034
|
-
*/
|
|
1035
|
-
async listUserFiles(
|
|
1036
|
-
userId: string,
|
|
1037
|
-
limit?: number,
|
|
1038
|
-
offset?: number,
|
|
1039
|
-
filters?: Record<string, any>
|
|
1040
|
-
): Promise<FileListResponse> {
|
|
1041
|
-
try {
|
|
1042
|
-
const params: Record<string, any> = {};
|
|
1043
|
-
if (limit !== undefined) params.limit = limit;
|
|
1044
|
-
if (offset !== undefined) params.offset = offset;
|
|
1045
|
-
if (filters) Object.assign(params, filters);
|
|
1046
|
-
|
|
1047
|
-
const res = await this.client.get(`/files/list/${userId}`, { params });
|
|
1048
|
-
|
|
1049
|
-
// Handle backend response format: backend returns FileMetadata[] directly
|
|
1050
|
-
// but interface expects { files: FileMetadata[], total: number, hasMore: boolean }
|
|
1051
|
-
const rawFiles = Array.isArray(res.data) ? res.data : res.data.files || [];
|
|
1052
|
-
|
|
1053
|
-
// Transform GridFS files to match FileMetadata interface (map _id to id)
|
|
1054
|
-
const filesArray = rawFiles.map((file: any) => ({
|
|
1055
|
-
...file,
|
|
1056
|
-
id: file._id?.toString() || file.id,
|
|
1057
|
-
uploadDate: file.uploadDate?.toISOString ? file.uploadDate.toISOString() : file.uploadDate
|
|
1058
|
-
}));
|
|
1059
|
-
|
|
1060
|
-
return {
|
|
1061
|
-
files: filesArray,
|
|
1062
|
-
total: filesArray.length,
|
|
1063
|
-
hasMore: false // No pagination in current backend implementation
|
|
1064
|
-
};
|
|
1065
|
-
} catch (error) {
|
|
1066
|
-
throw this.handleError(error);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
/**
|
|
1071
|
-
* Sign up a new user and create a session
|
|
1072
|
-
* @param username - Desired username
|
|
1073
|
-
* @param email - User's email address
|
|
1074
|
-
* @param password - User's password
|
|
1075
|
-
* @returns Object containing the message, token and user data
|
|
1076
|
-
*/
|
|
1077
|
-
async signUp(username: string, email: string, password: string): Promise<{ message: string; token: string; user: User }> {
|
|
1078
|
-
try {
|
|
1079
|
-
// First, create the user account
|
|
1080
|
-
const res = await this.client.post('/secure-session/register', { username, email, password });
|
|
1081
|
-
const { message, user } = res.data;
|
|
1082
|
-
|
|
1083
|
-
// Then log them in to create a session
|
|
1084
|
-
const loginRes = await this.secureLogin(username, password);
|
|
1085
|
-
|
|
1086
|
-
// Get the access token for the session
|
|
1087
|
-
const tokenRes = await this.getTokenBySession(loginRes.sessionId);
|
|
1088
|
-
|
|
1089
|
-
return {
|
|
1090
|
-
message,
|
|
1091
|
-
token: tokenRes.accessToken,
|
|
1092
|
-
user: loginRes.user as User
|
|
1093
|
-
};
|
|
1094
|
-
} catch (error) {
|
|
1095
|
-
throw this.handleError(error);
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
/**
|
|
1100
|
-
* Secure login that creates a device-based session
|
|
1101
|
-
* @param username - User's username or email
|
|
1102
|
-
* @param password - User's password
|
|
1103
|
-
* @param deviceName - Optional device name
|
|
1104
|
-
* @param deviceFingerprint - Optional device fingerprint
|
|
1105
|
-
* @returns Login response with session data
|
|
1106
|
-
*/
|
|
1107
|
-
async secureLogin(username: string, password: string, deviceName?: string, deviceFingerprint?: any): Promise<SecureLoginResponse> {
|
|
1108
|
-
try {
|
|
1109
|
-
const payload: any = {
|
|
1110
|
-
username,
|
|
1111
|
-
password,
|
|
1112
|
-
deviceName
|
|
1113
|
-
};
|
|
1114
|
-
|
|
1115
|
-
if (deviceFingerprint) {
|
|
1116
|
-
payload.deviceFingerprint = deviceFingerprint;
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
const res = await this.client.post('/secure-session/login', payload);
|
|
1120
|
-
return res.data;
|
|
1121
|
-
} catch (error) {
|
|
1122
|
-
throw this.handleError(error);
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
/**
|
|
1127
|
-
* Get full user data by session ID
|
|
1128
|
-
* @param sessionId - The session ID
|
|
1129
|
-
* @returns Full user data
|
|
1130
|
-
*/
|
|
1131
|
-
async getUserBySession(sessionId: string): Promise<User> {
|
|
1132
|
-
try {
|
|
1133
|
-
const res = await this.client.get(`/secure-session/user/${sessionId}`);
|
|
1134
|
-
return res.data.user;
|
|
1135
|
-
} catch (error) {
|
|
1136
|
-
throw this.handleError(error);
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
/**
|
|
1141
|
-
* Get access token by session ID (for API calls)
|
|
1142
|
-
* @param sessionId - The session ID
|
|
1143
|
-
* @returns Access token and expiry info
|
|
1144
|
-
*/
|
|
1145
|
-
async getTokenBySession(sessionId: string): Promise<{ accessToken: string; expiresAt: string }> {
|
|
1146
|
-
try {
|
|
1147
|
-
const res = await this.client.get(`/secure-session/token/${sessionId}`);
|
|
1148
|
-
// Set the token for subsequent API calls
|
|
1149
|
-
this.accessToken = res.data.accessToken;
|
|
1150
|
-
return res.data;
|
|
1151
|
-
} catch (error) {
|
|
1152
|
-
throw this.handleError(error);
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
/**
|
|
1157
|
-
* Get all active sessions for current user
|
|
1158
|
-
* @param sessionId - Current session ID
|
|
1159
|
-
* @returns Array of user sessions
|
|
1160
|
-
*/
|
|
1161
|
-
async getSessionsBySessionId(sessionId: string): Promise<any[]> {
|
|
1162
|
-
console.log('getSessionsBySessionId called with sessionId:', sessionId);
|
|
1163
|
-
try {
|
|
1164
|
-
const res = await this.client.get(`/secure-session/sessions/${sessionId}`);
|
|
1165
|
-
console.log('getSessionsBySessionId response:', res.data);
|
|
1166
|
-
return res.data.sessions;
|
|
1167
|
-
} catch (error) {
|
|
1168
|
-
console.error('getSessionsBySessionId error:', error);
|
|
1169
|
-
throw this.handleError(error);
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
/**
|
|
1174
|
-
* Logout specific session
|
|
1175
|
-
* @param sessionId - Current session ID
|
|
1176
|
-
* @param targetSessionId - Optional target session to logout (defaults to current)
|
|
1177
|
-
*/
|
|
1178
|
-
async logoutSecureSession(sessionId: string, targetSessionId?: string): Promise<void> {
|
|
1179
|
-
try {
|
|
1180
|
-
await this.client.post(`/secure-session/logout/${sessionId}`, {
|
|
1181
|
-
targetSessionId
|
|
1182
|
-
});
|
|
1183
|
-
|
|
1184
|
-
// If we're logging out the current session, clear the access token
|
|
1185
|
-
if (!targetSessionId || targetSessionId === sessionId) {
|
|
1186
|
-
this.accessToken = null;
|
|
1187
|
-
this.refreshToken = null;
|
|
1188
|
-
}
|
|
1189
|
-
} catch (error) {
|
|
1190
|
-
throw this.handleError(error);
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
/**
|
|
1195
|
-
* Logout all sessions for current user
|
|
1196
|
-
* @param sessionId - Current session ID
|
|
1197
|
-
*/
|
|
1198
|
-
async logoutAllSecureSessions(sessionId: string): Promise<void> {
|
|
1199
|
-
console.log('logoutAllSecureSessions called with sessionId:', sessionId);
|
|
1200
|
-
console.log('API client defaults:', this.client.defaults);
|
|
1201
|
-
|
|
1202
|
-
try {
|
|
1203
|
-
const response = await this.client.post(`/secure-session/logout-all/${sessionId}`);
|
|
1204
|
-
console.log('logoutAllSecureSessions response:', response.status, response.data);
|
|
1205
|
-
|
|
1206
|
-
// Clear tokens since all sessions are logged out
|
|
1207
|
-
this.accessToken = null;
|
|
1208
|
-
this.refreshToken = null;
|
|
1209
|
-
console.log('Tokens cleared successfully');
|
|
1210
|
-
} catch (error) {
|
|
1211
|
-
console.error('logoutAllSecureSessions error:', error);
|
|
1212
|
-
if (error && typeof error === 'object' && 'response' in error) {
|
|
1213
|
-
const axiosError = error as any;
|
|
1214
|
-
console.error('Error response data:', axiosError.response?.data);
|
|
1215
|
-
console.error('Error response status:', axiosError.response?.status);
|
|
1216
|
-
}
|
|
1217
|
-
throw this.handleError(error);
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
|
|
1221
|
-
/**
|
|
1222
|
-
* Validate session
|
|
1223
|
-
* @param sessionId - The session ID to validate
|
|
1224
|
-
* @returns Session validation status with user data
|
|
1225
|
-
*/
|
|
1226
|
-
async validateSession(sessionId: string): Promise<{ valid: boolean; expiresAt: string; lastActivity: string; user: User }> {
|
|
1227
|
-
try {
|
|
1228
|
-
const res = await this.client.get(`/secure-session/validate/${sessionId}`);
|
|
1229
|
-
return res.data;
|
|
1230
|
-
} catch (error) {
|
|
1231
|
-
throw this.handleError(error);
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
|
|
1235
|
-
/**
|
|
1236
|
-
* Validate session using x-session-id header
|
|
1237
|
-
* @param sessionId - The session ID to validate (sent as header)
|
|
1238
|
-
* @param deviceFingerprint - Optional device fingerprint for enhanced security
|
|
1239
|
-
* @returns Session validation status with user data
|
|
1240
|
-
*/
|
|
1241
|
-
async validateSessionFromHeader(sessionId: string, deviceFingerprint?: string): Promise<{ valid: boolean; expiresAt: string; lastActivity: string; user: User; sessionId?: string }> {
|
|
1242
|
-
try {
|
|
1243
|
-
const headers: any = {
|
|
1244
|
-
'x-session-id': sessionId
|
|
1245
|
-
};
|
|
1246
|
-
|
|
1247
|
-
if (deviceFingerprint) {
|
|
1248
|
-
headers['x-device-fingerprint'] = deviceFingerprint;
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
const res = await this.client.get('/secure-session/validate-header', { headers });
|
|
1252
|
-
return res.data;
|
|
1253
|
-
} catch (error) {
|
|
1254
|
-
throw this.handleError(error);
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
/**
|
|
1259
|
-
* Validate session using automatic header detection
|
|
1260
|
-
* The validateSession endpoint will automatically read from x-session-id header
|
|
1261
|
-
* @param sessionId - The session ID to validate (sent as header)
|
|
1262
|
-
* @param deviceFingerprint - Optional device fingerprint for enhanced security
|
|
1263
|
-
* @returns Session validation status with user data
|
|
1264
|
-
*/
|
|
1265
|
-
async validateSessionAuto(sessionId: string, deviceFingerprint?: string): Promise<{ valid: boolean; expiresAt: string; lastActivity: string; user: User; source?: string }> {
|
|
1266
|
-
try {
|
|
1267
|
-
const headers: any = {
|
|
1268
|
-
'x-session-id': sessionId
|
|
1269
|
-
};
|
|
1270
|
-
|
|
1271
|
-
if (deviceFingerprint) {
|
|
1272
|
-
headers['x-device-fingerprint'] = deviceFingerprint;
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
// Call the regular validateSession endpoint which now auto-reads from headers
|
|
1276
|
-
// Use 'auto' as placeholder since the controller reads from header
|
|
1277
|
-
const res = await this.client.get('/secure-session/validate/auto', { headers });
|
|
1278
|
-
return res.data;
|
|
1279
|
-
} catch (error) {
|
|
1280
|
-
throw this.handleError(error);
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
/**
|
|
1285
|
-
* Create authentication middleware for Express.js applications
|
|
1286
|
-
* This is the recommended way to protect routes in server applications
|
|
1287
|
-
* @returns Express middleware function
|
|
1288
|
-
*/
|
|
1289
|
-
public createAuthMiddleware() {
|
|
1290
|
-
return async (req: any, res: any, next: any) => {
|
|
1291
|
-
try {
|
|
1292
|
-
const authHeader = req.headers.authorization;
|
|
1293
|
-
|
|
1294
|
-
if (!authHeader?.startsWith('Bearer ')) {
|
|
1295
|
-
return res.status(401).json({
|
|
1296
|
-
error: 'Authentication required',
|
|
1297
|
-
message: 'Invalid or missing authorization header'
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
const token = authHeader.split(' ')[1];
|
|
1302
|
-
|
|
1303
|
-
// Use the authenticateToken method
|
|
1304
|
-
const result = await this.authenticateToken(token);
|
|
1305
|
-
|
|
1306
|
-
if (!result.valid) {
|
|
1307
|
-
return res.status(401).json({
|
|
1308
|
-
error: 'Invalid token',
|
|
1309
|
-
message: result.error || 'The provided authentication token is invalid'
|
|
1310
|
-
});
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
// Set user information on request object
|
|
1314
|
-
req.userId = result.userId || undefined;
|
|
1315
|
-
req.accessToken = token;
|
|
1316
|
-
|
|
1317
|
-
if (result.user) {
|
|
1318
|
-
req.user = result.user;
|
|
1319
|
-
} else if (result.userId) {
|
|
1320
|
-
req.user = { id: result.userId };
|
|
1321
|
-
}
|
|
1322
|
-
|
|
1323
|
-
next();
|
|
1324
|
-
} catch (error) {
|
|
1325
|
-
console.error('Auth middleware error:', error);
|
|
1326
|
-
return res.status(500).json({
|
|
1327
|
-
error: 'Server error',
|
|
1328
|
-
message: 'An error occurred while authenticating your request'
|
|
1329
|
-
});
|
|
1330
|
-
}
|
|
1331
|
-
};
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
/**
|
|
1335
|
-
* Helper method for validating tokens without Express middleware
|
|
1336
|
-
* Useful for standalone token validation in various contexts
|
|
1337
|
-
* @param token - The access token to validate
|
|
1338
|
-
* @returns Object with validation result and user information
|
|
1339
|
-
*/
|
|
1340
|
-
public async authenticateToken(token: string): Promise<{
|
|
1341
|
-
valid: boolean;
|
|
1342
|
-
userId?: string;
|
|
1343
|
-
user?: any;
|
|
1344
|
-
error?: string;
|
|
1345
|
-
}> {
|
|
1346
|
-
try {
|
|
1347
|
-
if (!token) {
|
|
1348
|
-
return {
|
|
1349
|
-
valid: false,
|
|
1350
|
-
error: 'Token is required'
|
|
1351
|
-
};
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
// Check if token contains sessionId (new session-based system)
|
|
1355
|
-
try {
|
|
1356
|
-
const decoded = jwtDecode<JwtPayload>(token);
|
|
1357
|
-
const userId = decoded.userId || decoded.id;
|
|
1358
|
-
|
|
1359
|
-
if (decoded.sessionId) {
|
|
1360
|
-
// Use session-based validation
|
|
1361
|
-
const tempOxyServices = new OxyServices({
|
|
1362
|
-
baseURL: this.client.defaults.baseURL || ''
|
|
1363
|
-
});
|
|
1364
|
-
tempOxyServices.setTokens(token, '');
|
|
1365
|
-
|
|
1366
|
-
const validation = await tempOxyServices.validateSession(decoded.sessionId);
|
|
1367
|
-
|
|
1368
|
-
if (validation.valid) {
|
|
1369
|
-
return {
|
|
1370
|
-
valid: true,
|
|
1371
|
-
userId,
|
|
1372
|
-
user: validation.user
|
|
1373
|
-
};
|
|
1374
|
-
} else {
|
|
1375
|
-
return {
|
|
1376
|
-
valid: false,
|
|
1377
|
-
error: 'Invalid or expired session'
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1380
|
-
} else {
|
|
1381
|
-
// Use old validation method
|
|
1382
|
-
const tempOxyServices = new OxyServices({
|
|
1383
|
-
baseURL: this.client.defaults.baseURL || ''
|
|
1384
|
-
});
|
|
1385
|
-
tempOxyServices.setTokens(token, '');
|
|
1386
|
-
|
|
1387
|
-
const isValid = await tempOxyServices.validate();
|
|
1388
|
-
|
|
1389
|
-
if (!isValid) {
|
|
1390
|
-
return {
|
|
1391
|
-
valid: false,
|
|
1392
|
-
error: 'Invalid or expired token'
|
|
1393
|
-
};
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
if (!userId) {
|
|
1397
|
-
return {
|
|
1398
|
-
valid: false,
|
|
1399
|
-
error: 'Invalid token payload'
|
|
1400
|
-
};
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
|
-
// Try to get user profile
|
|
1404
|
-
let user;
|
|
1405
|
-
try {
|
|
1406
|
-
user = await tempOxyServices.getUserById(userId);
|
|
1407
|
-
} catch (error) {
|
|
1408
|
-
// Continue without full user data
|
|
1409
|
-
user = { id: userId };
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
return {
|
|
1413
|
-
valid: true,
|
|
1414
|
-
userId,
|
|
1415
|
-
user
|
|
1416
|
-
};
|
|
1417
|
-
}
|
|
1418
|
-
} catch (decodeError) {
|
|
1419
|
-
return {
|
|
1420
|
-
valid: false,
|
|
1421
|
-
error: 'Invalid token payload'
|
|
1422
|
-
};
|
|
1423
|
-
}
|
|
1424
|
-
} catch (error) {
|
|
1425
|
-
return {
|
|
1426
|
-
valid: false,
|
|
1427
|
-
error: error instanceof Error ? error.message : 'Token validation failed'
|
|
1428
|
-
};
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
/**
|
|
1433
|
-
* Centralized error handling
|
|
1434
|
-
* @private
|
|
1435
|
-
* @param error - Error object from API call
|
|
1436
|
-
* @returns Formatted API error
|
|
1437
|
-
*/
|
|
1438
|
-
private handleError(error: any): ApiError {
|
|
1439
|
-
if (error && error.code && error.status) {
|
|
1440
|
-
// Already formatted as ApiError
|
|
1441
|
-
return error as ApiError;
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
const apiError: ApiError = {
|
|
1445
|
-
message: error?.message || (error?.response?.data as any)?.message || 'Unknown error occurred',
|
|
1446
|
-
code: (error?.response?.data as any)?.code || 'UNKNOWN_ERROR',
|
|
1447
|
-
status: error?.response?.status || 500,
|
|
1448
|
-
details: error?.response?.data
|
|
1449
|
-
};
|
|
1450
|
-
|
|
1451
|
-
return apiError;
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
/**
|
|
1455
|
-
* Check if a username is available
|
|
1456
|
-
* @param username - The username to check
|
|
1457
|
-
* @returns Promise with availability status
|
|
1458
|
-
*/
|
|
1459
|
-
async checkUsernameAvailability(username: string): Promise<{ available: boolean; message: string }> {
|
|
1460
|
-
try {
|
|
1461
|
-
const res = await this.client.get(`/auth/check-username/${username}`);
|
|
1462
|
-
return res.data;
|
|
1463
|
-
} catch (error: any) {
|
|
1464
|
-
// If the endpoint doesn't exist, fall back to basic validation
|
|
1465
|
-
if (error.response?.status === 404) {
|
|
1466
|
-
console.warn('Username validation endpoint not found, using fallback validation');
|
|
1467
|
-
return { available: true, message: 'Username validation not available' };
|
|
1468
|
-
}
|
|
1469
|
-
|
|
1470
|
-
// If it's a validation error (400), return the error message
|
|
1471
|
-
if (error.response?.status === 400) {
|
|
1472
|
-
return error.response.data;
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
|
-
// For other errors, log and return a fallback
|
|
1476
|
-
console.error('Username validation error:', error);
|
|
1477
|
-
return { available: true, message: 'Unable to validate username' };
|
|
1478
|
-
}
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
/**
|
|
1482
|
-
* Check if an email is available
|
|
1483
|
-
* @param email - The email to check
|
|
1484
|
-
* @returns Promise with availability status
|
|
1485
|
-
*/
|
|
1486
|
-
async checkEmailAvailability(email: string): Promise<{ available: boolean; message: string }> {
|
|
1487
|
-
try {
|
|
1488
|
-
const res = await this.client.post('/auth/check-email', { email });
|
|
1489
|
-
return res.data;
|
|
1490
|
-
} catch (error: any) {
|
|
1491
|
-
// If the endpoint doesn't exist, fall back to basic validation
|
|
1492
|
-
if (error.response?.status === 404) {
|
|
1493
|
-
console.warn('Email validation endpoint not found, using fallback validation');
|
|
1494
|
-
return { available: true, message: 'Email validation not available' };
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
// If it's a validation error (400), return the error message
|
|
1498
|
-
if (error.response?.status === 400) {
|
|
1499
|
-
return error.response.data;
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
// For other errors, log and return a fallback
|
|
1503
|
-
console.error('Email validation error:', error);
|
|
1504
|
-
return { available: true, message: 'Unable to validate email' };
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
/**
|
|
1509
|
-
* Get user profile by username
|
|
1510
|
-
* @param username - The username to look up
|
|
1511
|
-
* @returns Promise with user profile
|
|
1512
|
-
*/
|
|
1513
|
-
async getUserProfileByUsername(username: string): Promise<User> {
|
|
1514
|
-
try {
|
|
1515
|
-
const res = await this.client.get(`/profiles/username/${username}`);
|
|
1516
|
-
return res.data;
|
|
1517
|
-
} catch (error) {
|
|
1518
|
-
throw this.handleError(error);
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
|
-
/**
|
|
1523
|
-
* Health check endpoint to verify API connectivity
|
|
1524
|
-
* @returns Health status and basic server info
|
|
1525
|
-
*/
|
|
1526
|
-
async healthCheck(): Promise<{
|
|
1527
|
-
status: string;
|
|
1528
|
-
users?: number;
|
|
1529
|
-
timestamp?: string;
|
|
1530
|
-
[key: string]: any
|
|
1531
|
-
}> {
|
|
1532
|
-
try {
|
|
1533
|
-
const res = await this.client.get('/');
|
|
1534
|
-
return res.data;
|
|
1535
|
-
} catch (error) {
|
|
1536
|
-
throw this.handleError(error);
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
/**
|
|
1541
|
-
* Download file content using authenticated request
|
|
1542
|
-
* @param fileId - The file ID to download
|
|
1543
|
-
* @returns Response object for further processing
|
|
1544
|
-
*/
|
|
1545
|
-
async downloadFileContent(fileId: string): Promise<Response> {
|
|
1546
|
-
try {
|
|
1547
|
-
const downloadUrl = this.getFileDownloadUrl(fileId);
|
|
1548
|
-
const response = await fetch(downloadUrl);
|
|
1549
|
-
|
|
1550
|
-
if (!response.ok) {
|
|
1551
|
-
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
return response;
|
|
1555
|
-
} catch (error) {
|
|
1556
|
-
throw this.handleError(error);
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
/**
|
|
1561
|
-
* Get file content as text using authenticated request
|
|
1562
|
-
* @param fileId - The file ID to get content for
|
|
1563
|
-
* @returns File content as string
|
|
1564
|
-
*/
|
|
1565
|
-
async getFileContentAsText(fileId: string): Promise<string> {
|
|
1566
|
-
try {
|
|
1567
|
-
const response = await this.downloadFileContent(fileId);
|
|
1568
|
-
return await response.text();
|
|
1569
|
-
} catch (error) {
|
|
1570
|
-
throw this.handleError(error);
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
/**
|
|
1575
|
-
* Get file content as blob using authenticated request
|
|
1576
|
-
* @param fileId - The file ID to get content for
|
|
1577
|
-
* @returns File content as blob
|
|
1578
|
-
*/
|
|
1579
|
-
async getFileContentAsBlob(fileId: string): Promise<Blob> {
|
|
1580
|
-
try {
|
|
1581
|
-
const response = await this.downloadFileContent(fileId);
|
|
1582
|
-
return await response.blob();
|
|
1583
|
-
} catch (error) {
|
|
1584
|
-
throw this.handleError(error);
|
|
1585
|
-
}
|
|
1586
|
-
}
|
|
1587
|
-
|
|
1588
|
-
/**
|
|
1589
|
-
* Fetch metadata for a URL (title, description, image)
|
|
1590
|
-
* @param url - The URL to fetch metadata for
|
|
1591
|
-
* @returns Promise with metadata object
|
|
1592
|
-
*/
|
|
1593
|
-
async fetchLinkMetadata(url: string): Promise<{
|
|
1594
|
-
url: string;
|
|
1595
|
-
title: string;
|
|
1596
|
-
description: string;
|
|
1597
|
-
image?: string;
|
|
1598
|
-
}> {
|
|
1599
|
-
try {
|
|
1600
|
-
const response = await this.client.post('/link-metadata/fetch-metadata', { url });
|
|
1601
|
-
return response.data;
|
|
1602
|
-
} catch (error) {
|
|
1603
|
-
throw this.handleError(error);
|
|
1604
|
-
}
|
|
1605
|
-
}
|
|
1606
|
-
|
|
1607
|
-
/**
|
|
1608
|
-
* Search for locations using the enhanced location search API
|
|
1609
|
-
* @param query - Search query string
|
|
1610
|
-
* @param limit - Maximum number of results (default: 5)
|
|
1611
|
-
* @param countrycodes - Optional country codes filter (e.g., "us,ca")
|
|
1612
|
-
* @returns Promise with array of location results
|
|
1613
|
-
*/
|
|
1614
|
-
async searchLocations(query: string, limit: number = 5, countrycodes?: string): Promise<any[]> {
|
|
1615
|
-
try {
|
|
1616
|
-
const params = new URLSearchParams({
|
|
1617
|
-
query,
|
|
1618
|
-
limit: limit.toString()
|
|
1619
|
-
});
|
|
1620
|
-
if (countrycodes) {
|
|
1621
|
-
params.append('countrycodes', countrycodes);
|
|
1622
|
-
}
|
|
1623
|
-
const res = await this.client.get(`/location-search/search?${params.toString()}`);
|
|
1624
|
-
return res.data.results;
|
|
1625
|
-
} catch (error) {
|
|
1626
|
-
throw this.handleError(error);
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
/**
|
|
1631
|
-
* Get detailed information about a specific location by coordinates
|
|
1632
|
-
* @param lat - Latitude
|
|
1633
|
-
* @param lon - Longitude
|
|
1634
|
-
* @returns Promise with detailed location information
|
|
1635
|
-
*/
|
|
1636
|
-
async getLocationDetails(lat: number, lon: number): Promise<any> {
|
|
1637
|
-
try {
|
|
1638
|
-
const res = await this.client.get(`/location-search/details?lat=${lat}&lon=${lon}`);
|
|
1639
|
-
return res.data.result;
|
|
1640
|
-
} catch (error) {
|
|
1641
|
-
throw this.handleError(error);
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
/**
|
|
1646
|
-
* Find locations near a point using geospatial queries
|
|
1647
|
-
* @param lat - Latitude
|
|
1648
|
-
* @param lon - Longitude
|
|
1649
|
-
* @param maxDistance - Maximum distance in meters (default: 10000)
|
|
1650
|
-
* @param limit - Maximum number of results (default: 10)
|
|
1651
|
-
* @param skip - Number of results to skip (default: 0)
|
|
1652
|
-
* @returns Promise with nearby locations
|
|
1653
|
-
*/
|
|
1654
|
-
async findLocationsNear(
|
|
1655
|
-
lat: number,
|
|
1656
|
-
lon: number,
|
|
1657
|
-
maxDistance: number = 10000,
|
|
1658
|
-
limit: number = 10,
|
|
1659
|
-
skip: number = 0
|
|
1660
|
-
): Promise<any> {
|
|
1661
|
-
try {
|
|
1662
|
-
const params = new URLSearchParams({
|
|
1663
|
-
lat: lat.toString(),
|
|
1664
|
-
lon: lon.toString(),
|
|
1665
|
-
maxDistance: maxDistance.toString(),
|
|
1666
|
-
limit: limit.toString(),
|
|
1667
|
-
skip: skip.toString()
|
|
1668
|
-
});
|
|
1669
|
-
const res = await this.client.get(`/location-search/near?${params.toString()}`);
|
|
1670
|
-
return res.data;
|
|
1671
|
-
} catch (error) {
|
|
1672
|
-
throw this.handleError(error);
|
|
1673
|
-
}
|
|
1674
|
-
}
|
|
1675
|
-
|
|
1676
|
-
/**
|
|
1677
|
-
* Search locations in database by text
|
|
1678
|
-
* @param query - Search query
|
|
1679
|
-
* @param limit - Maximum number of results (default: 10)
|
|
1680
|
-
* @param skip - Number of results to skip (default: 0)
|
|
1681
|
-
* @param type - Filter by location type
|
|
1682
|
-
* @param country - Filter by country
|
|
1683
|
-
* @param city - Filter by city
|
|
1684
|
-
* @returns Promise with search results
|
|
1685
|
-
*/
|
|
1686
|
-
async searchLocationsInDB(
|
|
1687
|
-
query: string,
|
|
1688
|
-
limit: number = 10,
|
|
1689
|
-
skip: number = 0,
|
|
1690
|
-
type?: string,
|
|
1691
|
-
country?: string,
|
|
1692
|
-
city?: string
|
|
1693
|
-
): Promise<any> {
|
|
1694
|
-
try {
|
|
1695
|
-
const params = new URLSearchParams({
|
|
1696
|
-
query,
|
|
1697
|
-
limit: limit.toString(),
|
|
1698
|
-
skip: skip.toString()
|
|
1699
|
-
});
|
|
1700
|
-
if (type) params.append('type', type);
|
|
1701
|
-
if (country) params.append('country', country);
|
|
1702
|
-
if (city) params.append('city', city);
|
|
1703
|
-
|
|
1704
|
-
const res = await this.client.get(`/location-search/db-search?${params.toString()}`);
|
|
1705
|
-
return res.data;
|
|
1706
|
-
} catch (error) {
|
|
1707
|
-
throw this.handleError(error);
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
|
|
1711
|
-
/**
|
|
1712
|
-
* Get location statistics
|
|
1713
|
-
* @returns Promise with location statistics
|
|
1714
|
-
*/
|
|
1715
|
-
async getLocationStats(): Promise<any> {
|
|
1716
|
-
try {
|
|
1717
|
-
const res = await this.client.get('/location-search/stats');
|
|
1718
|
-
return res.data.stats;
|
|
1719
|
-
} catch (error) {
|
|
1720
|
-
throw this.handleError(error);
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
/**
|
|
1725
|
-
* Get cache statistics
|
|
1726
|
-
* @returns Promise with cache statistics
|
|
1727
|
-
*/
|
|
1728
|
-
async getLocationCacheStats(): Promise<any> {
|
|
1729
|
-
try {
|
|
1730
|
-
const res = await this.client.get('/location-search/cache/stats');
|
|
1731
|
-
return res.data.stats;
|
|
1732
|
-
} catch (error) {
|
|
1733
|
-
throw this.handleError(error);
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
|
|
1737
|
-
/**
|
|
1738
|
-
* Clear location cache
|
|
1739
|
-
* @returns Promise with success status
|
|
1740
|
-
*/
|
|
1741
|
-
async clearLocationCache(): Promise<any> {
|
|
1742
|
-
try {
|
|
1743
|
-
const res = await this.client.delete('/location-search/cache');
|
|
1744
|
-
return res.data;
|
|
1745
|
-
} catch (error) {
|
|
1746
|
-
throw this.handleError(error);
|
|
1747
|
-
}
|
|
1748
|
-
}
|
|
1749
|
-
|
|
1750
|
-
/**
|
|
1751
|
-
* Get performance statistics
|
|
1752
|
-
* @returns Promise with performance statistics
|
|
1753
|
-
*/
|
|
1754
|
-
async getLocationPerformanceStats(): Promise<any> {
|
|
1755
|
-
try {
|
|
1756
|
-
const res = await this.client.get('/location-search/performance');
|
|
1757
|
-
return res.data;
|
|
1758
|
-
} catch (error) {
|
|
1759
|
-
throw this.handleError(error);
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
|
|
1764
|
-
// Default export for backward compatibility
|
|
1765
|
-
export default OxyServices;
|
|
24
|
+
// Constants
|
|
25
|
+
export { OXY_CLOUD_URL } from './files/FileService';
|
|
1766
26
|
|
|
1767
27
|
// Re-export all models and types for convenience
|
|
1768
28
|
export * from '../models/interfaces';
|
|
1769
|
-
export * from '../models/
|
|
29
|
+
export * from '../models/session';
|
|
1770
30
|
|
|
1771
|
-
//
|
|
1772
|
-
|
|
1773
|
-
export type {
|
|
31
|
+
// Export device management utilities
|
|
32
|
+
export { DeviceManager } from '../utils/deviceManager';
|
|
33
|
+
export type { DeviceFingerprint, StoredDeviceInfo } from '../utils/deviceManager';
|
|
1774
34
|
|
|
1775
|
-
//
|
|
1776
|
-
|
|
1777
|
-
return oxyServices.createAuthMiddleware();
|
|
1778
|
-
};
|
|
35
|
+
// Import the main class for default export
|
|
36
|
+
import { OxyServicesMain } from './OxyServicesMain';
|
|
1779
37
|
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
}
|
|
38
|
+
// Default export for backward compatibility
|
|
39
|
+
export default OxyServicesMain;
|