@oxyhq/services 5.10.3 → 5.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +62 -14
  2. package/lib/commonjs/core/OxyServices.js +796 -4
  3. package/lib/commonjs/core/OxyServices.js.map +1 -1
  4. package/lib/commonjs/core/index.js +8 -83
  5. package/lib/commonjs/core/index.js.map +1 -1
  6. package/lib/commonjs/ui/screens/FileManagementScreen.js +12 -12
  7. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  8. package/lib/commonjs/ui/screens/ProfileScreen.js +2 -2
  9. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  10. package/lib/commonjs/ui/screens/SignInScreen.js +1 -1
  11. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  12. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +1 -1
  13. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  14. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +1 -1
  15. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  16. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +1 -1
  17. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  18. package/lib/commonjs/ui/stores/followStore.js +4 -4
  19. package/lib/commonjs/ui/stores/followStore.js.map +1 -1
  20. package/lib/module/core/OxyServices.js +795 -3
  21. package/lib/module/core/OxyServices.js.map +1 -1
  22. package/lib/module/core/index.js +9 -24
  23. package/lib/module/core/index.js.map +1 -1
  24. package/lib/module/ui/screens/FileManagementScreen.js +12 -12
  25. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  26. package/lib/module/ui/screens/ProfileScreen.js +2 -2
  27. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  28. package/lib/module/ui/screens/SignInScreen.js +1 -1
  29. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  30. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +1 -1
  31. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  32. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +1 -1
  33. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  34. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +1 -1
  35. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  36. package/lib/module/ui/stores/followStore.js +4 -4
  37. package/lib/module/ui/stores/followStore.js.map +1 -1
  38. package/lib/typescript/core/OxyServices.d.ts +290 -1
  39. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  40. package/lib/typescript/core/index.d.ts +7 -16
  41. package/lib/typescript/core/index.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/src/core/OxyServices.ts +880 -47
  44. package/src/core/index.ts +9 -24
  45. package/src/ui/screens/FileManagementScreen.tsx +12 -12
  46. package/src/ui/screens/ProfileScreen.tsx +3 -3
  47. package/src/ui/screens/SignInScreen.tsx +1 -1
  48. package/src/ui/screens/karma/KarmaCenterScreen.tsx +2 -2
  49. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +1 -1
  50. package/src/ui/screens/karma/KarmaRulesScreen.tsx +1 -1
  51. package/src/ui/stores/followStore.ts +4 -4
  52. package/lib/commonjs/core/OxyServicesMain.js +0 -51
  53. package/lib/commonjs/core/OxyServicesMain.js.map +0 -1
  54. package/lib/commonjs/core/analytics/AnalyticsService.js +0 -67
  55. package/lib/commonjs/core/analytics/AnalyticsService.js.map +0 -1
  56. package/lib/commonjs/core/auth/AuthService.js +0 -538
  57. package/lib/commonjs/core/auth/AuthService.js.map +0 -1
  58. package/lib/commonjs/core/devices/DeviceService.js +0 -61
  59. package/lib/commonjs/core/devices/DeviceService.js.map +0 -1
  60. package/lib/commonjs/core/files/FileService.js +0 -180
  61. package/lib/commonjs/core/files/FileService.js.map +0 -1
  62. package/lib/commonjs/core/karma/KarmaService.js +0 -100
  63. package/lib/commonjs/core/karma/KarmaService.js.map +0 -1
  64. package/lib/commonjs/core/locations/LocationService.js +0 -131
  65. package/lib/commonjs/core/locations/LocationService.js.map +0 -1
  66. package/lib/commonjs/core/payments/PaymentService.js +0 -124
  67. package/lib/commonjs/core/payments/PaymentService.js.map +0 -1
  68. package/lib/commonjs/core/users/UserService.js +0 -234
  69. package/lib/commonjs/core/users/UserService.js.map +0 -1
  70. package/lib/module/core/OxyServicesMain.js +0 -47
  71. package/lib/module/core/OxyServicesMain.js.map +0 -1
  72. package/lib/module/core/analytics/AnalyticsService.js +0 -62
  73. package/lib/module/core/analytics/AnalyticsService.js.map +0 -1
  74. package/lib/module/core/auth/AuthService.js +0 -533
  75. package/lib/module/core/auth/AuthService.js.map +0 -1
  76. package/lib/module/core/devices/DeviceService.js +0 -57
  77. package/lib/module/core/devices/DeviceService.js.map +0 -1
  78. package/lib/module/core/files/FileService.js +0 -175
  79. package/lib/module/core/files/FileService.js.map +0 -1
  80. package/lib/module/core/karma/KarmaService.js +0 -95
  81. package/lib/module/core/karma/KarmaService.js.map +0 -1
  82. package/lib/module/core/locations/LocationService.js +0 -127
  83. package/lib/module/core/locations/LocationService.js.map +0 -1
  84. package/lib/module/core/payments/PaymentService.js +0 -119
  85. package/lib/module/core/payments/PaymentService.js.map +0 -1
  86. package/lib/module/core/users/UserService.js +0 -230
  87. package/lib/module/core/users/UserService.js.map +0 -1
  88. package/lib/typescript/core/OxyServicesMain.d.ts +0 -33
  89. package/lib/typescript/core/OxyServicesMain.d.ts.map +0 -1
  90. package/lib/typescript/core/analytics/AnalyticsService.d.ts +0 -26
  91. package/lib/typescript/core/analytics/AnalyticsService.d.ts.map +0 -1
  92. package/lib/typescript/core/auth/AuthService.d.ts +0 -165
  93. package/lib/typescript/core/auth/AuthService.d.ts.map +0 -1
  94. package/lib/typescript/core/devices/DeviceService.d.ts +0 -20
  95. package/lib/typescript/core/devices/DeviceService.d.ts.map +0 -1
  96. package/lib/typescript/core/files/FileService.d.ts +0 -59
  97. package/lib/typescript/core/files/FileService.d.ts.map +0 -1
  98. package/lib/typescript/core/karma/KarmaService.d.ts +0 -50
  99. package/lib/typescript/core/karma/KarmaService.d.ts.map +0 -1
  100. package/lib/typescript/core/locations/LocationService.d.ts +0 -39
  101. package/lib/typescript/core/locations/LocationService.d.ts.map +0 -1
  102. package/lib/typescript/core/payments/PaymentService.d.ts +0 -50
  103. package/lib/typescript/core/payments/PaymentService.d.ts.map +0 -1
  104. package/lib/typescript/core/users/UserService.d.ts +0 -111
  105. package/lib/typescript/core/users/UserService.d.ts.map +0 -1
  106. package/src/core/OxyServicesMain.ts +0 -57
  107. package/src/core/analytics/AnalyticsService.ts +0 -64
  108. package/src/core/auth/AuthService.ts +0 -560
  109. package/src/core/devices/DeviceService.ts +0 -55
  110. package/src/core/files/FileService.ts +0 -198
  111. package/src/core/karma/KarmaService.ts +0 -104
  112. package/src/core/locations/LocationService.ts +0 -141
  113. package/src/core/payments/PaymentService.ts +0 -133
  114. package/src/core/users/UserService.ts +0 -241
@@ -1,7 +1,9 @@
1
1
  import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios';
2
2
  import { jwtDecode } from 'jwt-decode';
3
- import { OxyConfig, ApiError, User } from '../models/interfaces';
3
+ import { OxyConfig, ApiError, User, Notification } from '../models/interfaces';
4
+ import { SessionLoginResponse } from '../models/session';
4
5
  import { handleHttpError } from '../utils/errorUtils';
6
+ import { buildSearchParams, buildPaginationParams, PaginationParams } from '../utils/apiUtils';
5
7
 
6
8
  interface JwtPayload {
7
9
  exp?: number;
@@ -11,10 +13,10 @@ interface JwtPayload {
11
13
  }
12
14
 
13
15
  /**
14
- * OxyServices - Base client library for interacting with the Oxy API
16
+ * OxyServices - Unified client library for interacting with the Oxy API
15
17
  *
16
- * This class provides the core HTTP client setup, token management, and error handling.
17
- * Specific functionality is delegated to focused service modules.
18
+ * This class provides all API functionality in one simple, easy-to-use interface.
19
+ * No need to manage multiple service instances - everything is available directly.
18
20
  */
19
21
  // Centralized token store
20
22
  class TokenStore {
@@ -129,92 +131,922 @@ export class OxyServices {
129
131
  });
130
132
  }
131
133
 
134
+ // ============================================================================
135
+ // CORE METHODS (HTTP Client, Token Management, Error Handling)
136
+ // ============================================================================
137
+
138
+ /**
139
+ * Get the configured base URL
140
+ */
141
+ public getBaseURL(): string {
142
+ return this.client.defaults.baseURL || '';
143
+ }
144
+
145
+ /**
146
+ * Set authentication tokens
147
+ */
148
+ public setTokens(accessToken: string, refreshToken: string = ''): void {
149
+ this.tokenStore.setTokens(accessToken, refreshToken);
150
+ }
151
+
152
+ /**
153
+ * Clear stored authentication tokens
154
+ */
155
+ public clearTokens(): void {
156
+ this.tokenStore.clearTokens();
157
+ }
158
+
159
+ /**
160
+ * Get the current user ID from the access token
161
+ */
162
+ public getCurrentUserId(): string | null {
163
+ const accessToken = this.tokenStore.getAccessToken();
164
+ if (!accessToken) {
165
+ return null;
166
+ }
167
+
168
+ try {
169
+ const decoded = jwtDecode<JwtPayload>(accessToken);
170
+ return decoded.userId || decoded.id || null;
171
+ } catch (error) {
172
+ return null;
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Check if the client has a valid access token
178
+ */
179
+ private hasAccessToken(): boolean {
180
+ return this.tokenStore.hasAccessToken();
181
+ }
182
+
183
+ /**
184
+ * Validate the current access token with the server
185
+ */
186
+ async validate(): Promise<boolean> {
187
+ if (!this.hasAccessToken()) {
188
+ return false;
189
+ }
190
+
191
+ try {
192
+ const res = await this.client.get('/api/auth/validate');
193
+ return res.data.valid === true;
194
+ } catch (error) {
195
+ return false;
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Get the HTTP client instance (protected for use by service modules)
201
+ */
202
+ protected getClient(): AxiosInstance {
203
+ return this.client;
204
+ }
205
+
206
+ /**
207
+ * Centralized error handling
208
+ */
209
+ protected handleError(error: any): ApiError {
210
+ return handleHttpError(error);
211
+ }
212
+
213
+ /**
214
+ * Health check endpoint
215
+ */
216
+ async healthCheck(): Promise<{
217
+ status: string;
218
+ users?: number;
219
+ timestamp?: string;
220
+ [key: string]: any
221
+ }> {
222
+ try {
223
+ const res = await this.client.get('/health');
224
+ return res.data;
225
+ } catch (error) {
226
+ throw this.handleError(error);
227
+ }
228
+ }
229
+
230
+ // ============================================================================
231
+ // AUTHENTICATION METHODS
232
+ // ============================================================================
233
+
234
+ /**
235
+ * Sign up a new user
236
+ */
237
+ async signUp(username: string, email: string, password: string): Promise<{ message: string; token: string; user: User }> {
238
+ try {
239
+ const res = await this.client.post('/api/auth/signup', {
240
+ username,
241
+ email,
242
+ password
243
+ });
244
+ return res.data;
245
+ } catch (error) {
246
+ throw this.handleError(error);
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Sign in with device management
252
+ */
253
+ async signIn(username: string, password: string, deviceName?: string, deviceFingerprint?: any): Promise<SessionLoginResponse> {
254
+ try {
255
+ const res = await this.client.post('/api/auth/login', {
256
+ username,
257
+ password,
258
+ deviceName,
259
+ deviceFingerprint
260
+ });
261
+ return res.data;
262
+ } catch (error) {
263
+ throw this.handleError(error);
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Get user by session ID
269
+ */
270
+ async getUserBySession(sessionId: string): Promise<User> {
271
+ try {
272
+ const res = await this.client.get(`/api/session/user/${sessionId}`);
273
+ return res.data;
274
+ } catch (error) {
275
+ throw this.handleError(error);
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Get access token by session ID and set it in the token store
281
+ */
282
+ async getTokenBySession(sessionId: string): Promise<{ accessToken: string; expiresAt: string }> {
283
+ try {
284
+ console.log('🔑 getTokenBySession - Fetching token for session:', sessionId);
285
+ const res = await this.client.get(`/api/session/token/${sessionId}`);
286
+ const { accessToken } = res.data;
287
+
288
+ console.log('🔑 getTokenBySession - Token received:', !!accessToken);
289
+
290
+ // Set the token in the centralized token store
291
+ this.setTokens(accessToken);
292
+ console.log('🔑 getTokenBySession - Token set in store');
293
+
294
+ return res.data;
295
+ } catch (error) {
296
+ console.log('❌ getTokenBySession - Error:', error);
297
+ throw this.handleError(error);
298
+ }
299
+ }
300
+
301
+ /**
302
+ * Get sessions by session ID
303
+ */
304
+ async getSessionsBySessionId(sessionId: string): Promise<any[]> {
305
+ try {
306
+ const res = await this.client.get(`/api/session/sessions/${sessionId}`);
307
+ return res.data;
308
+ } catch (error) {
309
+ throw this.handleError(error);
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Logout from a specific session
315
+ */
316
+ async logoutSession(sessionId: string, targetSessionId?: string): Promise<void> {
317
+ try {
318
+ const url = targetSessionId
319
+ ? `/api/session/logout/${sessionId}/${targetSessionId}`
320
+ : `/api/session/logout/${sessionId}`;
321
+
322
+ await this.client.post(url);
323
+ } catch (error) {
324
+ throw this.handleError(error);
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Logout from all sessions
330
+ */
331
+ async logoutAllSessions(sessionId: string): Promise<void> {
332
+ try {
333
+ await this.client.post(`/api/session/logout-all/${sessionId}`);
334
+ } catch (error) {
335
+ throw this.handleError(error);
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Validate session
341
+ */
342
+ async validateSession(
343
+ sessionId: string,
344
+ options: {
345
+ deviceFingerprint?: string;
346
+ useHeaderValidation?: boolean;
347
+ } = {}
348
+ ): Promise<{
349
+ valid: boolean;
350
+ expiresAt: string;
351
+ lastActivity: string;
352
+ user: User;
353
+ sessionId?: string;
354
+ source?: string;
355
+ }> {
356
+ try {
357
+ const params = new URLSearchParams();
358
+ if (options.deviceFingerprint) {
359
+ params.append('deviceFingerprint', options.deviceFingerprint);
360
+ }
361
+ if (options.useHeaderValidation) {
362
+ params.append('useHeaderValidation', 'true');
363
+ }
364
+
365
+ const url = `/api/session/validate/${sessionId}?${params.toString()}`;
366
+ const res = await this.client.get(url);
367
+ return res.data;
368
+ } catch (error) {
369
+ throw this.handleError(error);
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Check username availability
375
+ */
376
+ async checkUsernameAvailability(username: string): Promise<{ available: boolean; message: string }> {
377
+ try {
378
+ const res = await this.client.get(`/api/auth/check-username/${username}`);
379
+ return res.data;
380
+ } catch (error) {
381
+ throw this.handleError(error);
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Check email availability
387
+ */
388
+ async checkEmailAvailability(email: string): Promise<{ available: boolean; message: string }> {
389
+ try {
390
+ const res = await this.client.get(`/api/auth/check-email/${email}`);
391
+ return res.data;
392
+ } catch (error) {
393
+ throw this.handleError(error);
394
+ }
395
+ }
396
+
397
+ // ============================================================================
398
+ // USER METHODS
399
+ // ============================================================================
400
+
401
+ /**
402
+ * Get profile by username
403
+ */
404
+ async getProfileByUsername(username: string): Promise<User> {
405
+ try {
406
+ const res = await this.client.get(`/api/profiles/username/${username}`);
407
+ return res.data;
408
+ } catch (error) {
409
+ throw this.handleError(error);
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Search user profiles
415
+ */
416
+ async searchProfiles(query: string, pagination?: PaginationParams): Promise<User[]> {
417
+ try {
418
+ const params = { query, ...pagination };
419
+ const searchParams = buildSearchParams(params);
420
+
421
+ const res = await this.client.get(`/api/profiles/search?${searchParams.toString()}`);
422
+ return res.data;
423
+ } catch (error) {
424
+ throw this.handleError(error);
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Get profile recommendations
430
+ */
431
+ async getProfileRecommendations(): Promise<Array<{
432
+ id: string;
433
+ username: string;
434
+ name?: { first?: string; last?: string; full?: string };
435
+ description?: string;
436
+ _count?: { followers: number; following: number };
437
+ [key: string]: any;
438
+ }>> {
439
+ try {
440
+ const res = await this.client.get('/api/profiles/recommendations');
441
+ return res.data;
442
+ } catch (error) {
443
+ throw this.handleError(error);
444
+ }
445
+ }
446
+
447
+ /**
448
+ * Get user by ID
449
+ */
450
+ async getUserById(userId: string): Promise<User> {
451
+ try {
452
+ const res = await this.client.get(`/api/users/${userId}`);
453
+ return res.data;
454
+ } catch (error) {
455
+ throw this.handleError(error);
456
+ }
457
+ }
458
+
459
+ /**
460
+ * Get current user
461
+ */
462
+ async getCurrentUser(): Promise<User> {
463
+ try {
464
+ const res = await this.client.get('/api/users/me');
465
+ return res.data;
466
+ } catch (error) {
467
+ throw this.handleError(error);
468
+ }
469
+ }
470
+
471
+ /**
472
+ * Update user profile
473
+ */
474
+ async updateProfile(updates: Record<string, any>): Promise<User> {
475
+ try {
476
+ const res = await this.client.put('/api/users/me', updates);
477
+ return res.data;
478
+ } catch (error) {
479
+ throw this.handleError(error);
480
+ }
481
+ }
482
+
483
+ /**
484
+ * Update user by ID (admin function)
485
+ */
486
+ async updateUser(userId: string, updates: Record<string, any>): Promise<User> {
487
+ try {
488
+ const res = await this.client.put(`/api/users/${userId}`, updates);
489
+ return res.data;
490
+ } catch (error) {
491
+ throw this.handleError(error);
492
+ }
493
+ }
494
+
495
+ /**
496
+ * Follow a user
497
+ */
498
+ async followUser(userId: string): Promise<{ success: boolean; message: string }> {
499
+ try {
500
+ const res = await this.client.post(`/api/users/${userId}/follow`);
501
+ return res.data;
502
+ } catch (error) {
503
+ throw this.handleError(error);
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Unfollow a user
509
+ */
510
+ async unfollowUser(userId: string): Promise<{ success: boolean; message: string }> {
511
+ try {
512
+ const res = await this.client.delete(`/api/users/${userId}/follow`);
513
+ return res.data;
514
+ } catch (error) {
515
+ throw this.handleError(error);
516
+ }
517
+ }
518
+
519
+ /**
520
+ * Get follow status
521
+ */
522
+ async getFollowStatus(userId: string): Promise<{ isFollowing: boolean }> {
523
+ try {
524
+ const res = await this.client.get(`/api/users/${userId}/follow-status`);
525
+ return res.data;
526
+ } catch (error) {
527
+ throw this.handleError(error);
528
+ }
529
+ }
530
+
531
+ /**
532
+ * Get user followers
533
+ */
534
+ async getUserFollowers(
535
+ userId: string,
536
+ pagination?: PaginationParams
537
+ ): Promise<{ followers: User[]; total: number; hasMore: boolean }> {
538
+ try {
539
+ const params = buildPaginationParams(pagination || {});
540
+ const res = await this.client.get(`/api/users/${userId}/followers?${params.toString()}`);
541
+ return res.data;
542
+ } catch (error) {
543
+ throw this.handleError(error);
544
+ }
545
+ }
546
+
547
+ /**
548
+ * Get user following
549
+ */
550
+ async getUserFollowing(
551
+ userId: string,
552
+ pagination?: PaginationParams
553
+ ): Promise<{ following: User[]; total: number; hasMore: boolean }> {
554
+ try {
555
+ const params = buildPaginationParams(pagination || {});
556
+ const res = await this.client.get(`/api/users/${userId}/following?${params.toString()}`);
557
+ return res.data;
558
+ } catch (error) {
559
+ throw this.handleError(error);
560
+ }
561
+ }
562
+
563
+ /**
564
+ * Get notifications
565
+ */
566
+ async getNotifications(): Promise<Notification[]> {
567
+ try {
568
+ const res = await this.client.get('/api/notifications');
569
+ return res.data;
570
+ } catch (error) {
571
+ throw this.handleError(error);
572
+ }
573
+ }
574
+
575
+ /**
576
+ * Get unread notification count
577
+ */
578
+ async getUnreadCount(): Promise<number> {
579
+ try {
580
+ const res = await this.client.get('/api/notifications/unread-count');
581
+ return res.data.count;
582
+ } catch (error) {
583
+ throw this.handleError(error);
584
+ }
585
+ }
586
+
587
+ /**
588
+ * Create notification
589
+ */
590
+ async createNotification(data: Partial<Notification>): Promise<Notification> {
591
+ try {
592
+ const res = await this.client.post('/api/notifications', data);
593
+ return res.data;
594
+ } catch (error) {
595
+ throw this.handleError(error);
596
+ }
597
+ }
598
+
599
+ /**
600
+ * Mark notification as read
601
+ */
602
+ async markNotificationAsRead(notificationId: string): Promise<void> {
603
+ try {
604
+ await this.client.put(`/api/notifications/${notificationId}/read`);
605
+ } catch (error) {
606
+ throw this.handleError(error);
607
+ }
608
+ }
609
+
610
+ /**
611
+ * Mark all notifications as read
612
+ */
613
+ async markAllNotificationsAsRead(): Promise<void> {
614
+ try {
615
+ await this.client.put('/api/notifications/read-all');
616
+ } catch (error) {
617
+ throw this.handleError(error);
618
+ }
619
+ }
620
+
621
+ /**
622
+ * Delete notification
623
+ */
624
+ async deleteNotification(notificationId: string): Promise<void> {
625
+ try {
626
+ await this.client.delete(`/api/notifications/${notificationId}`);
627
+ } catch (error) {
628
+ throw this.handleError(error);
629
+ }
630
+ }
631
+
632
+ // ============================================================================
633
+ // PAYMENT METHODS
634
+ // ============================================================================
635
+
636
+ /**
637
+ * Create a payment
638
+ */
639
+ async createPayment(data: any): Promise<any> {
640
+ try {
641
+ const res = await this.client.post('/api/payments', data);
642
+ return res.data;
643
+ } catch (error) {
644
+ throw this.handleError(error);
645
+ }
646
+ }
647
+
132
648
  /**
133
- * Get the configured base URL
649
+ * Get payment by ID
134
650
  */
135
- public getBaseURL(): string {
136
- return this.client.defaults.baseURL || '';
651
+ async getPayment(paymentId: string): Promise<any> {
652
+ try {
653
+ const res = await this.client.get(`/api/payments/${paymentId}`);
654
+ return res.data;
655
+ } catch (error) {
656
+ throw this.handleError(error);
657
+ }
137
658
  }
138
659
 
139
660
  /**
140
- * Set authentication tokens
661
+ * Get user payments
141
662
  */
142
- public setTokens(accessToken: string, refreshToken: string = ''): void {
143
- this.tokenStore.setTokens(accessToken, refreshToken);
663
+ async getUserPayments(): Promise<any[]> {
664
+ try {
665
+ const res = await this.client.get('/api/payments/user');
666
+ return res.data;
667
+ } catch (error) {
668
+ throw this.handleError(error);
669
+ }
144
670
  }
145
671
 
672
+ // ============================================================================
673
+ // KARMA METHODS
674
+ // ============================================================================
675
+
146
676
  /**
147
- * Clear stored authentication tokens
677
+ * Get user karma
148
678
  */
149
- public clearTokens(): void {
150
- this.tokenStore.clearTokens();
679
+ async getUserKarma(userId: string): Promise<any> {
680
+ try {
681
+ const res = await this.client.get(`/api/karma/${userId}`);
682
+ return res.data;
683
+ } catch (error) {
684
+ throw this.handleError(error);
685
+ }
151
686
  }
152
687
 
153
688
  /**
154
- * Get the current user ID from the access token
689
+ * Give karma to user
155
690
  */
156
- public getCurrentUserId(): string | null {
157
- const accessToken = this.tokenStore.getAccessToken();
158
- if (!accessToken) {
159
- return null;
691
+ async giveKarma(userId: string, amount: number, reason?: string): Promise<any> {
692
+ try {
693
+ const res = await this.client.post(`/api/karma/${userId}/give`, {
694
+ amount,
695
+ reason
696
+ });
697
+ return res.data;
698
+ } catch (error) {
699
+ throw this.handleError(error);
160
700
  }
161
-
701
+ }
702
+
703
+ /**
704
+ * Get user karma total
705
+ */
706
+ async getUserKarmaTotal(userId: string): Promise<any> {
162
707
  try {
163
- const decoded = jwtDecode<JwtPayload>(accessToken);
164
- return decoded.userId || decoded.id || null;
708
+ const res = await this.client.get(`/api/karma/${userId}/total`);
709
+ return res.data;
165
710
  } catch (error) {
166
- return null;
711
+ throw this.handleError(error);
167
712
  }
168
713
  }
169
714
 
170
715
  /**
171
- * Check if the client has a valid access token
716
+ * Get user karma history
172
717
  */
173
- private hasAccessToken(): boolean {
174
- return this.tokenStore.hasAccessToken();
718
+ async getUserKarmaHistory(userId: string, limit?: number, offset?: number): Promise<any> {
719
+ try {
720
+ const params = new URLSearchParams();
721
+ if (limit) params.append('limit', limit.toString());
722
+ if (offset) params.append('offset', offset.toString());
723
+
724
+ const res = await this.client.get(`/api/karma/${userId}/history?${params.toString()}`);
725
+ return res.data;
726
+ } catch (error) {
727
+ throw this.handleError(error);
728
+ }
175
729
  }
176
730
 
177
731
  /**
178
- * Validate the current access token with the server
732
+ * Get karma leaderboard
179
733
  */
180
- async validate(): Promise<boolean> {
181
- if (!this.hasAccessToken()) {
182
- return false;
734
+ async getKarmaLeaderboard(): Promise<any> {
735
+ try {
736
+ const res = await this.client.get('/api/karma/leaderboard');
737
+ return res.data;
738
+ } catch (error) {
739
+ throw this.handleError(error);
183
740
  }
741
+ }
184
742
 
743
+ /**
744
+ * Get karma rules
745
+ */
746
+ async getKarmaRules(): Promise<any> {
185
747
  try {
186
- const res = await this.client.get('/api/auth/validate');
187
- return res.data.valid === true;
748
+ const res = await this.client.get('/api/karma/rules');
749
+ return res.data;
188
750
  } catch (error) {
189
- return false;
751
+ throw this.handleError(error);
190
752
  }
191
753
  }
192
754
 
755
+ // ============================================================================
756
+ // FILE METHODS
757
+ // ============================================================================
758
+
193
759
  /**
194
- * Get the HTTP client instance (protected for use by service modules)
760
+ * Upload file
195
761
  */
196
- protected getClient(): AxiosInstance {
197
- return this.client;
762
+ async uploadFile(file: File | FormData, options?: any): Promise<any> {
763
+ try {
764
+ const formData = file instanceof FormData ? file : new FormData();
765
+ if (file instanceof File) {
766
+ formData.append('file', file);
767
+ }
768
+
769
+ const res = await this.client.post('/api/files/upload', formData, {
770
+ headers: {
771
+ 'Content-Type': 'multipart/form-data',
772
+ },
773
+ ...options
774
+ });
775
+ return res.data;
776
+ } catch (error) {
777
+ throw this.handleError(error);
778
+ }
198
779
  }
199
780
 
200
781
  /**
201
- * Centralized error handling
782
+ * Get file by ID
202
783
  */
203
- protected handleError(error: any): ApiError {
204
- return handleHttpError(error);
784
+ async getFile(fileId: string): Promise<any> {
785
+ try {
786
+ const res = await this.client.get(`/api/files/${fileId}`);
787
+ return res.data;
788
+ } catch (error) {
789
+ throw this.handleError(error);
790
+ }
205
791
  }
206
792
 
207
793
  /**
208
- * Health check endpoint
794
+ * Delete file
209
795
  */
210
- async healthCheck(): Promise<{
211
- status: string;
212
- users?: number;
213
- timestamp?: string;
214
- [key: string]: any
796
+ async deleteFile(fileId: string): Promise<any> {
797
+ try {
798
+ const res = await this.client.delete(`/api/files/${fileId}`);
799
+ return res.data;
800
+ } catch (error) {
801
+ throw this.handleError(error);
802
+ }
803
+ }
804
+
805
+ /**
806
+ * Get file download URL
807
+ */
808
+ getFileDownloadUrl(fileId: string): string {
809
+ return `${OXY_CLOUD_URL}/files/${fileId}/download`;
810
+ }
811
+
812
+ /**
813
+ * Get file stream URL
814
+ */
815
+ getFileStreamUrl(fileId: string): string {
816
+ return `${OXY_CLOUD_URL}/files/${fileId}/stream`;
817
+ }
818
+
819
+ /**
820
+ * List user files
821
+ */
822
+ async listUserFiles(
823
+ userId: string,
824
+ limit?: number,
825
+ offset?: number,
826
+ filters?: Record<string, any>
827
+ ): Promise<any> {
828
+ try {
829
+ const params = new URLSearchParams();
830
+ if (limit) params.append('limit', limit.toString());
831
+ if (offset) params.append('offset', offset.toString());
832
+
833
+ if (filters) {
834
+ Object.entries(filters).forEach(([key, value]) => {
835
+ params.append(key, value.toString());
836
+ });
837
+ }
838
+
839
+ const res = await this.client.get(`/api/files/list/${userId}?${params.toString()}`);
840
+ return res.data;
841
+ } catch (error) {
842
+ throw this.handleError(error);
843
+ }
844
+ }
845
+
846
+ /**
847
+ * Download file content
848
+ */
849
+ async downloadFileContent(fileId: string): Promise<Response> {
850
+ try {
851
+ const res = await this.client.get(`/api/files/${fileId}`, {
852
+ responseType: 'blob'
853
+ });
854
+ return res.data;
855
+ } catch (error) {
856
+ throw this.handleError(error);
857
+ }
858
+ }
859
+
860
+ /**
861
+ * Get file content as text
862
+ */
863
+ async getFileContentAsText(fileId: string): Promise<string> {
864
+ try {
865
+ const res = await this.client.get(`/api/files/${fileId}`, {
866
+ headers: {
867
+ 'Accept': 'text/plain'
868
+ }
869
+ });
870
+ return res.data;
871
+ } catch (error) {
872
+ throw this.handleError(error);
873
+ }
874
+ }
875
+
876
+ /**
877
+ * Get file content as blob
878
+ */
879
+ async getFileContentAsBlob(fileId: string): Promise<Blob> {
880
+ try {
881
+ const res = await this.client.get(`/api/files/${fileId}`, {
882
+ responseType: 'blob'
883
+ });
884
+ return res.data;
885
+ } catch (error) {
886
+ throw this.handleError(error);
887
+ }
888
+ }
889
+
890
+ // ============================================================================
891
+ // LOCATION METHODS
892
+ // ============================================================================
893
+
894
+ /**
895
+ * Update user location
896
+ */
897
+ async updateLocation(latitude: number, longitude: number): Promise<any> {
898
+ try {
899
+ const res = await this.client.post('/api/location', {
900
+ latitude,
901
+ longitude
902
+ });
903
+ return res.data;
904
+ } catch (error) {
905
+ throw this.handleError(error);
906
+ }
907
+ }
908
+
909
+ /**
910
+ * Get nearby users
911
+ */
912
+ async getNearbyUsers(radius?: number): Promise<any[]> {
913
+ try {
914
+ const params = radius ? `?radius=${radius}` : '';
915
+ const res = await this.client.get(`/api/location/nearby${params}`);
916
+ return res.data;
917
+ } catch (error) {
918
+ throw this.handleError(error);
919
+ }
920
+ }
921
+
922
+ // ============================================================================
923
+ // ANALYTICS METHODS
924
+ // ============================================================================
925
+
926
+ /**
927
+ * Track event
928
+ */
929
+ async trackEvent(eventName: string, properties?: Record<string, any>): Promise<void> {
930
+ try {
931
+ await this.client.post('/api/analytics/events', {
932
+ event: eventName,
933
+ properties
934
+ });
935
+ } catch (error) {
936
+ throw this.handleError(error);
937
+ }
938
+ }
939
+
940
+ /**
941
+ * Get analytics data
942
+ */
943
+ async getAnalytics(startDate?: string, endDate?: string): Promise<any> {
944
+ try {
945
+ const params = new URLSearchParams();
946
+ if (startDate) params.append('startDate', startDate);
947
+ if (endDate) params.append('endDate', endDate);
948
+
949
+ const res = await this.client.get(`/api/analytics?${params.toString()}`);
950
+ return res.data;
951
+ } catch (error) {
952
+ throw this.handleError(error);
953
+ }
954
+ }
955
+
956
+ // ============================================================================
957
+ // DEVICE METHODS
958
+ // ============================================================================
959
+
960
+ /**
961
+ * Register device
962
+ */
963
+ async registerDevice(deviceData: any): Promise<any> {
964
+ try {
965
+ const res = await this.client.post('/api/devices', deviceData);
966
+ return res.data;
967
+ } catch (error) {
968
+ throw this.handleError(error);
969
+ }
970
+ }
971
+
972
+ /**
973
+ * Get user devices
974
+ */
975
+ async getUserDevices(): Promise<any[]> {
976
+ try {
977
+ const res = await this.client.get('/api/devices');
978
+ return res.data;
979
+ } catch (error) {
980
+ throw this.handleError(error);
981
+ }
982
+ }
983
+
984
+ /**
985
+ * Remove device
986
+ */
987
+ async removeDevice(deviceId: string): Promise<void> {
988
+ try {
989
+ await this.client.delete(`/api/devices/${deviceId}`);
990
+ } catch (error) {
991
+ throw this.handleError(error);
992
+ }
993
+ }
994
+
995
+ /**
996
+ * Get device sessions
997
+ */
998
+ async getDeviceSessions(sessionId: string): Promise<any[]> {
999
+ try {
1000
+ const res = await this.client.get(`/api/devices/sessions/${sessionId}`);
1001
+ return res.data;
1002
+ } catch (error) {
1003
+ throw this.handleError(error);
1004
+ }
1005
+ }
1006
+
1007
+ /**
1008
+ * Logout all device sessions
1009
+ */
1010
+ async logoutAllDeviceSessions(sessionId: string, deviceId?: string, excludeCurrent?: boolean): Promise<any> {
1011
+ try {
1012
+ const params = new URLSearchParams();
1013
+ if (deviceId) params.append('deviceId', deviceId);
1014
+ if (excludeCurrent) params.append('excludeCurrent', 'true');
1015
+
1016
+ const res = await this.client.post(`/api/devices/logout-all/${sessionId}?${params.toString()}`);
1017
+ return res.data;
1018
+ } catch (error) {
1019
+ throw this.handleError(error);
1020
+ }
1021
+ }
1022
+
1023
+ /**
1024
+ * Update device name
1025
+ */
1026
+ async updateDeviceName(sessionId: string, deviceName: string): Promise<any> {
1027
+ try {
1028
+ const res = await this.client.put(`/api/devices/name/${sessionId}`, { deviceName });
1029
+ return res.data;
1030
+ } catch (error) {
1031
+ throw this.handleError(error);
1032
+ }
1033
+ }
1034
+
1035
+ // ============================================================================
1036
+ // UTILITY METHODS
1037
+ // ============================================================================
1038
+
1039
+ /**
1040
+ * Fetch link metadata
1041
+ */
1042
+ async fetchLinkMetadata(url: string): Promise<{
1043
+ url: string;
1044
+ title: string;
1045
+ description: string;
1046
+ image?: string;
215
1047
  }> {
216
1048
  try {
217
- const res = await this.client.get('/health');
1049
+ const res = await this.client.get(`/api/link-metadata?url=${encodeURIComponent(url)}`);
218
1050
  return res.data;
219
1051
  } catch (error) {
220
1052
  throw this.handleError(error);
@@ -357,6 +1189,7 @@ export class OxyServices {
357
1189
  }
358
1190
  };
359
1191
  }
1192
+ }
360
1193
 
361
-
362
- }
1194
+ // Export the cloud URL constant
1195
+ export const OXY_CLOUD_URL = 'https://cloud.oxyhq.com';