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