@oxyhq/core 1.5.0 → 1.6.0

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 (84) hide show
  1. package/dist/cjs/AuthManager.js +1 -1
  2. package/dist/cjs/HttpService.js +87 -69
  3. package/dist/cjs/OxyServices.base.js +5 -4
  4. package/dist/cjs/crypto/keyManager.js +1 -13
  5. package/dist/cjs/crypto/signatureService.js +7 -20
  6. package/dist/cjs/mixins/OxyServices.analytics.js +2 -2
  7. package/dist/cjs/mixins/OxyServices.assets.js +14 -14
  8. package/dist/cjs/mixins/OxyServices.auth.js +19 -19
  9. package/dist/cjs/mixins/OxyServices.developer.js +6 -6
  10. package/dist/cjs/mixins/OxyServices.devices.js +7 -7
  11. package/dist/cjs/mixins/OxyServices.features.js +23 -23
  12. package/dist/cjs/mixins/OxyServices.fedcm.js +1 -1
  13. package/dist/cjs/mixins/OxyServices.karma.js +6 -6
  14. package/dist/cjs/mixins/OxyServices.location.js +2 -2
  15. package/dist/cjs/mixins/OxyServices.payment.js +6 -6
  16. package/dist/cjs/mixins/OxyServices.popup.js +1 -1
  17. package/dist/cjs/mixins/OxyServices.privacy.js +6 -6
  18. package/dist/cjs/mixins/OxyServices.security.js +3 -3
  19. package/dist/cjs/mixins/OxyServices.user.js +22 -22
  20. package/dist/cjs/mixins/OxyServices.utility.js +16 -7
  21. package/dist/cjs/utils/platform.js +14 -0
  22. package/dist/esm/AuthManager.js +1 -1
  23. package/dist/esm/HttpService.js +87 -69
  24. package/dist/esm/OxyServices.base.js +5 -4
  25. package/dist/esm/crypto/keyManager.js +1 -13
  26. package/dist/esm/crypto/signatureService.js +2 -15
  27. package/dist/esm/mixins/OxyServices.analytics.js +2 -2
  28. package/dist/esm/mixins/OxyServices.assets.js +14 -14
  29. package/dist/esm/mixins/OxyServices.auth.js +19 -19
  30. package/dist/esm/mixins/OxyServices.developer.js +6 -6
  31. package/dist/esm/mixins/OxyServices.devices.js +7 -7
  32. package/dist/esm/mixins/OxyServices.features.js +23 -23
  33. package/dist/esm/mixins/OxyServices.fedcm.js +1 -1
  34. package/dist/esm/mixins/OxyServices.karma.js +6 -6
  35. package/dist/esm/mixins/OxyServices.location.js +2 -2
  36. package/dist/esm/mixins/OxyServices.payment.js +6 -6
  37. package/dist/esm/mixins/OxyServices.popup.js +1 -1
  38. package/dist/esm/mixins/OxyServices.privacy.js +6 -6
  39. package/dist/esm/mixins/OxyServices.security.js +3 -3
  40. package/dist/esm/mixins/OxyServices.user.js +22 -22
  41. package/dist/esm/mixins/OxyServices.utility.js +16 -7
  42. package/dist/esm/utils/platform.js +12 -0
  43. package/dist/types/HttpService.d.ts +4 -1
  44. package/dist/types/OxyServices.base.d.ts +1 -1
  45. package/dist/types/mixins/OxyServices.analytics.d.ts +1 -1
  46. package/dist/types/mixins/OxyServices.assets.d.ts +1 -1
  47. package/dist/types/mixins/OxyServices.auth.d.ts +1 -1
  48. package/dist/types/mixins/OxyServices.developer.d.ts +1 -1
  49. package/dist/types/mixins/OxyServices.devices.d.ts +1 -1
  50. package/dist/types/mixins/OxyServices.features.d.ts +1 -1
  51. package/dist/types/mixins/OxyServices.fedcm.d.ts +1 -1
  52. package/dist/types/mixins/OxyServices.karma.d.ts +1 -1
  53. package/dist/types/mixins/OxyServices.language.d.ts +1 -1
  54. package/dist/types/mixins/OxyServices.location.d.ts +1 -1
  55. package/dist/types/mixins/OxyServices.payment.d.ts +1 -1
  56. package/dist/types/mixins/OxyServices.popup.d.ts +1 -1
  57. package/dist/types/mixins/OxyServices.privacy.d.ts +1 -1
  58. package/dist/types/mixins/OxyServices.redirect.d.ts +1 -1
  59. package/dist/types/mixins/OxyServices.security.d.ts +1 -1
  60. package/dist/types/mixins/OxyServices.user.d.ts +1 -1
  61. package/dist/types/mixins/OxyServices.utility.d.ts +7 -6
  62. package/dist/types/utils/platform.d.ts +8 -0
  63. package/package.json +1 -1
  64. package/src/AuthManager.ts +1 -1
  65. package/src/HttpService.ts +85 -67
  66. package/src/OxyServices.base.ts +5 -4
  67. package/src/crypto/keyManager.ts +1 -15
  68. package/src/crypto/signatureService.ts +2 -17
  69. package/src/mixins/OxyServices.analytics.ts +2 -2
  70. package/src/mixins/OxyServices.assets.ts +14 -14
  71. package/src/mixins/OxyServices.auth.ts +19 -19
  72. package/src/mixins/OxyServices.developer.ts +6 -6
  73. package/src/mixins/OxyServices.devices.ts +7 -7
  74. package/src/mixins/OxyServices.features.ts +23 -23
  75. package/src/mixins/OxyServices.fedcm.ts +1 -1
  76. package/src/mixins/OxyServices.karma.ts +6 -6
  77. package/src/mixins/OxyServices.location.ts +2 -2
  78. package/src/mixins/OxyServices.payment.ts +6 -6
  79. package/src/mixins/OxyServices.popup.ts +1 -1
  80. package/src/mixins/OxyServices.privacy.ts +6 -6
  81. package/src/mixins/OxyServices.security.ts +3 -3
  82. package/src/mixins/OxyServices.user.ts +22 -22
  83. package/src/mixins/OxyServices.utility.ts +18 -8
  84. package/src/utils/platform.ts +14 -0
@@ -53,7 +53,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
53
53
  */
54
54
  async getBlockedUsers(): Promise<BlockedUser[]> {
55
55
  try {
56
- return await this.makeRequest<BlockedUser[]>('GET', '/api/privacy/blocked', undefined, {
56
+ return await this.makeRequest<BlockedUser[]>('GET', '/privacy/blocked', undefined, {
57
57
  cache: true,
58
58
  cacheTTL: 1 * 60 * 1000, // 1 minute cache
59
59
  });
@@ -72,7 +72,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
72
72
  if (!userId) {
73
73
  throw new Error('User ID is required');
74
74
  }
75
- return await this.makeRequest<{ message: string }>('POST', `/api/privacy/blocked/${userId}`, undefined, {
75
+ return await this.makeRequest<{ message: string }>('POST', `/privacy/blocked/${userId}`, undefined, {
76
76
  cache: false,
77
77
  });
78
78
  } catch (error) {
@@ -90,7 +90,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
90
90
  if (!userId) {
91
91
  throw new Error('User ID is required');
92
92
  }
93
- return await this.makeRequest<{ message: string }>('DELETE', `/api/privacy/blocked/${userId}`, undefined, {
93
+ return await this.makeRequest<{ message: string }>('DELETE', `/privacy/blocked/${userId}`, undefined, {
94
94
  cache: false,
95
95
  });
96
96
  } catch (error) {
@@ -121,7 +121,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
121
121
  */
122
122
  async getRestrictedUsers(): Promise<RestrictedUser[]> {
123
123
  try {
124
- return await this.makeRequest<RestrictedUser[]>('GET', '/api/privacy/restricted', undefined, {
124
+ return await this.makeRequest<RestrictedUser[]>('GET', '/privacy/restricted', undefined, {
125
125
  cache: true,
126
126
  cacheTTL: 1 * 60 * 1000, // 1 minute cache
127
127
  });
@@ -140,7 +140,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
140
140
  if (!userId) {
141
141
  throw new Error('User ID is required');
142
142
  }
143
- return await this.makeRequest<{ message: string }>('POST', `/api/privacy/restricted/${userId}`, undefined, {
143
+ return await this.makeRequest<{ message: string }>('POST', `/privacy/restricted/${userId}`, undefined, {
144
144
  cache: false,
145
145
  });
146
146
  } catch (error) {
@@ -158,7 +158,7 @@ export function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase>(Base:
158
158
  if (!userId) {
159
159
  throw new Error('User ID is required');
160
160
  }
161
- return await this.makeRequest<{ message: string }>('DELETE', `/api/privacy/restricted/${userId}`, undefined, {
161
+ return await this.makeRequest<{ message: string }>('DELETE', `/privacy/restricted/${userId}`, undefined, {
162
162
  cache: false,
163
163
  });
164
164
  } catch (error) {
@@ -31,7 +31,7 @@ export function OxyServicesSecurityMixin<T extends typeof OxyServicesBase>(Base:
31
31
 
32
32
  const response = await this.makeRequest<SecurityActivityResponse>(
33
33
  'GET',
34
- '/api/security/activity',
34
+ '/security/activity',
35
35
  params,
36
36
  { cache: false }
37
37
  );
@@ -65,7 +65,7 @@ export function OxyServicesSecurityMixin<T extends typeof OxyServicesBase>(Base:
65
65
  try {
66
66
  await this.makeRequest<{ success: boolean }>(
67
67
  'POST',
68
- '/api/security/activity/private-key-exported',
68
+ '/security/activity/private-key-exported',
69
69
  { deviceId },
70
70
  { cache: false }
71
71
  );
@@ -87,7 +87,7 @@ export function OxyServicesSecurityMixin<T extends typeof OxyServicesBase>(Base:
87
87
  try {
88
88
  await this.makeRequest<{ success: boolean }>(
89
89
  'POST',
90
- '/api/security/activity/backup-created',
90
+ '/security/activity/backup-created',
91
91
  { deviceId },
92
92
  { cache: false }
93
93
  );
@@ -15,7 +15,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
15
15
  */
16
16
  async getProfileByUsername(username: string): Promise<User> {
17
17
  try {
18
- return await this.makeRequest<User>('GET', `/api/profiles/username/${username}`, undefined, {
18
+ return await this.makeRequest<User>('GET', `/profiles/username/${username}`, undefined, {
19
19
  cache: true,
20
20
  cacheTTL: 5 * 60 * 1000, // 5 minutes cache for profiles
21
21
  });
@@ -35,7 +35,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
35
35
 
36
36
  const response = await this.makeRequest<SearchProfilesResponse | User[]>(
37
37
  'GET',
38
- '/api/profiles/search',
38
+ '/profiles/search',
39
39
  paramsObj,
40
40
  {
41
41
  cache: true,
@@ -97,7 +97,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
97
97
  [key: string]: any;
98
98
  }>> {
99
99
  return this.withAuthRetry(async () => {
100
- return await this.makeRequest('GET', '/api/profiles/recommendations', undefined, { cache: true });
100
+ return await this.makeRequest('GET', '/profiles/recommendations', undefined, { cache: true });
101
101
  }, 'getProfileRecommendations');
102
102
  }
103
103
 
@@ -106,7 +106,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
106
106
  */
107
107
  async getUserById(userId: string): Promise<User> {
108
108
  try {
109
- return await this.makeRequest<User>('GET', `/api/users/${userId}`, undefined, {
109
+ return await this.makeRequest<User>('GET', `/users/${userId}`, undefined, {
110
110
  cache: true,
111
111
  cacheTTL: 5 * 60 * 1000, // 5 minutes cache
112
112
  });
@@ -120,7 +120,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
120
120
  */
121
121
  async getCurrentUser(): Promise<User> {
122
122
  return this.withAuthRetry(async () => {
123
- return await this.makeRequest<User>('GET', '/api/users/me', undefined, {
123
+ return await this.makeRequest<User>('GET', '/users/me', undefined, {
124
124
  cache: true,
125
125
  cacheTTL: 1 * 60 * 1000, // 1 minute cache for current user
126
126
  });
@@ -133,7 +133,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
133
133
  */
134
134
  async updateProfile(updates: Record<string, any>): Promise<User> {
135
135
  try {
136
- return await this.makeRequest<User>('PUT', '/api/users/me', updates, { cache: false });
136
+ return await this.makeRequest<User>('PUT', '/users/me', updates, { cache: false });
137
137
  } catch (error) {
138
138
  const errorAny = error as any;
139
139
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -162,7 +162,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
162
162
  async getPrivacySettings(userId?: string): Promise<any> {
163
163
  try {
164
164
  const id = userId || (await this.getCurrentUser()).id;
165
- return await this.makeRequest<any>('GET', `/api/privacy/${id}/privacy`, undefined, {
165
+ return await this.makeRequest<any>('GET', `/privacy/${id}/privacy`, undefined, {
166
166
  cache: true,
167
167
  cacheTTL: 2 * 60 * 1000, // 2 minutes cache
168
168
  });
@@ -179,7 +179,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
179
179
  async updatePrivacySettings(settings: Record<string, any>, userId?: string): Promise<any> {
180
180
  try {
181
181
  const id = userId || (await this.getCurrentUser()).id;
182
- return await this.makeRequest<any>('PATCH', `/api/privacy/${id}/privacy`, settings, {
182
+ return await this.makeRequest<any>('PATCH', `/privacy/${id}/privacy`, settings, {
183
183
  cache: false,
184
184
  });
185
185
  } catch (error) {
@@ -192,7 +192,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
192
192
  */
193
193
  async requestAccountVerification(reason: string, evidence?: string): Promise<{ message: string; requestId: string }> {
194
194
  try {
195
- return await this.makeRequest<{ message: string; requestId: string }>('POST', '/api/users/verify/request', {
195
+ return await this.makeRequest<{ message: string; requestId: string }>('POST', '/users/verify/request', {
196
196
  reason,
197
197
  evidence,
198
198
  }, { cache: false });
@@ -209,7 +209,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
209
209
  // Use httpService for blob responses (it handles blob responses automatically)
210
210
  const result = await this.getClient().request<Blob>({
211
211
  method: 'GET',
212
- url: `/api/users/me/data`,
212
+ url: `/users/me/data`,
213
213
  params: { format },
214
214
  cache: false,
215
215
  });
@@ -227,7 +227,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
227
227
  */
228
228
  async deleteAccount(password: string, confirmText: string): Promise<{ message: string }> {
229
229
  try {
230
- return await this.makeRequest<{ message: string }>('DELETE', '/api/users/me', {
230
+ return await this.makeRequest<{ message: string }>('DELETE', '/users/me', {
231
231
  password,
232
232
  confirmText,
233
233
  }, { cache: false });
@@ -242,7 +242,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
242
242
  */
243
243
  async followUser(userId: string): Promise<{ success: boolean; message: string }> {
244
244
  try {
245
- return await this.makeRequest('POST', `/api/users/${userId}/follow`, undefined, { cache: false });
245
+ return await this.makeRequest('POST', `/users/${userId}/follow`, undefined, { cache: false });
246
246
  } catch (error) {
247
247
  throw this.handleError(error);
248
248
  }
@@ -253,7 +253,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
253
253
  */
254
254
  async unfollowUser(userId: string): Promise<{ success: boolean; message: string }> {
255
255
  try {
256
- return await this.makeRequest('DELETE', `/api/users/${userId}/follow`, undefined, { cache: false });
256
+ return await this.makeRequest('DELETE', `/users/${userId}/follow`, undefined, { cache: false });
257
257
  } catch (error) {
258
258
  throw this.handleError(error);
259
259
  }
@@ -264,7 +264,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
264
264
  */
265
265
  async getFollowStatus(userId: string): Promise<{ isFollowing: boolean }> {
266
266
  try {
267
- return await this.makeRequest('GET', `/api/users/${userId}/follow-status`, undefined, {
267
+ return await this.makeRequest('GET', `/users/${userId}/follow-status`, undefined, {
268
268
  cache: true,
269
269
  cacheTTL: 1 * 60 * 1000, // 1 minute cache
270
270
  });
@@ -282,7 +282,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
282
282
  ): Promise<{ followers: User[]; total: number; hasMore: boolean }> {
283
283
  try {
284
284
  const params = buildPaginationParams(pagination || {});
285
- const response = await this.makeRequest<{ data: User[]; pagination: { total: number; hasMore: boolean } }>('GET', `/api/users/${userId}/followers`, params, {
285
+ const response = await this.makeRequest<{ data: User[]; pagination: { total: number; hasMore: boolean } }>('GET', `/users/${userId}/followers`, params, {
286
286
  cache: true,
287
287
  cacheTTL: 2 * 60 * 1000, // 2 minutes cache
288
288
  });
@@ -305,7 +305,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
305
305
  ): Promise<{ following: User[]; total: number; hasMore: boolean }> {
306
306
  try {
307
307
  const params = buildPaginationParams(pagination || {});
308
- const response = await this.makeRequest<{ data: User[]; pagination: { total: number; hasMore: boolean } }>('GET', `/api/users/${userId}/following`, params, {
308
+ const response = await this.makeRequest<{ data: User[]; pagination: { total: number; hasMore: boolean } }>('GET', `/users/${userId}/following`, params, {
309
309
  cache: true,
310
310
  cacheTTL: 2 * 60 * 1000, // 2 minutes cache
311
311
  });
@@ -324,7 +324,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
324
324
  */
325
325
  async getNotifications(): Promise<Notification[]> {
326
326
  return this.withAuthRetry(async () => {
327
- return await this.makeRequest<Notification[]>('GET', '/api/notifications', undefined, {
327
+ return await this.makeRequest<Notification[]>('GET', '/notifications', undefined, {
328
328
  cache: false, // Don't cache notifications - always get fresh data
329
329
  });
330
330
  }, 'getNotifications');
@@ -335,7 +335,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
335
335
  */
336
336
  async getUnreadCount(): Promise<number> {
337
337
  try {
338
- const res = await this.makeRequest<{ count: number }>('GET', '/api/notifications/unread-count', undefined, {
338
+ const res = await this.makeRequest<{ count: number }>('GET', '/notifications/unread-count', undefined, {
339
339
  cache: false, // Don't cache unread count - always get fresh data
340
340
  });
341
341
  return res.count;
@@ -349,7 +349,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
349
349
  */
350
350
  async createNotification(data: Partial<Notification>): Promise<Notification> {
351
351
  try {
352
- return await this.makeRequest<Notification>('POST', '/api/notifications', data, { cache: false });
352
+ return await this.makeRequest<Notification>('POST', '/notifications', data, { cache: false });
353
353
  } catch (error) {
354
354
  throw this.handleError(error);
355
355
  }
@@ -360,7 +360,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
360
360
  */
361
361
  async markNotificationAsRead(notificationId: string): Promise<void> {
362
362
  try {
363
- await this.makeRequest('PUT', `/api/notifications/${notificationId}/read`, undefined, { cache: false });
363
+ await this.makeRequest('PUT', `/notifications/${notificationId}/read`, undefined, { cache: false });
364
364
  } catch (error) {
365
365
  throw this.handleError(error);
366
366
  }
@@ -371,7 +371,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
371
371
  */
372
372
  async markAllNotificationsAsRead(): Promise<void> {
373
373
  try {
374
- await this.makeRequest('PUT', '/api/notifications/read-all', undefined, { cache: false });
374
+ await this.makeRequest('PUT', '/notifications/read-all', undefined, { cache: false });
375
375
  } catch (error) {
376
376
  throw this.handleError(error);
377
377
  }
@@ -382,7 +382,7 @@ export function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T)
382
382
  */
383
383
  async deleteNotification(notificationId: string): Promise<void> {
384
384
  try {
385
- await this.makeRequest('DELETE', `/api/notifications/${notificationId}`, undefined, { cache: false });
385
+ await this.makeRequest('DELETE', `/notifications/${notificationId}`, undefined, { cache: false });
386
386
  } catch (error) {
387
387
  throw this.handleError(error);
388
388
  }
@@ -68,7 +68,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
68
68
  title: string;
69
69
  description: string;
70
70
  image?: string;
71
- }>('GET', '/api/link-metadata', { url }, {
71
+ }>('GET', '/link-metadata', { url }, {
72
72
  cache: true,
73
73
  cacheTTL: CACHE_TIMES.EXTRA_LONG,
74
74
  });
@@ -89,19 +89,19 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
89
89
  *
90
90
  * const oxy = new OxyServices({ baseURL: 'https://api.oxy.so' });
91
91
  *
92
- * // Protect all routes under /api/protected
93
- * app.use('/api/protected', oxy.auth());
92
+ * // Protect all routes under /protected
93
+ * app.use('/protected', oxy.auth());
94
94
  *
95
95
  * // Access user in route handler
96
- * app.get('/api/protected/me', (req, res) => {
96
+ * app.get('/protected/me', (req, res) => {
97
97
  * res.json({ userId: req.userId, user: req.user });
98
98
  * });
99
99
  *
100
100
  * // Load full user profile from API
101
- * app.use('/api/admin', oxy.auth({ loadUser: true }));
101
+ * app.use('/admin', oxy.auth({ loadUser: true }));
102
102
  *
103
103
  * // Optional auth - attach user if present, don't block if absent
104
- * app.use('/api/public', oxy.auth({ optional: true }));
104
+ * app.use('/public', oxy.auth({ optional: true }));
105
105
  * ```
106
106
  *
107
107
  * @param options Optional configuration
@@ -206,7 +206,17 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
206
206
  if (sigBuf.length !== expectedBuf.length || !timingSafeEqual(sigBuf, expectedBuf)) {
207
207
  throw new Error('Invalid signature');
208
208
  }
209
- } catch {
209
+ } catch (verifyError) {
210
+ const isSignatureError = verifyError instanceof Error &&
211
+ (verifyError.message === 'Invalid signature' || verifyError.message === 'Invalid token structure');
212
+
213
+ if (!isSignatureError) {
214
+ console.error('[oxy.auth] Unexpected error during service token verification:', verifyError);
215
+ const error = { message: 'Internal authentication error', code: 'AUTH_INTERNAL_ERROR', status: 500 };
216
+ if (onError) return onError(error);
217
+ return res.status(500).json(error);
218
+ }
219
+
210
220
  if (optional) {
211
221
  req.userId = null;
212
222
  req.user = null;
@@ -504,7 +514,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
504
514
  * });
505
515
  * ```
506
516
  */
507
- serviceAuth(options: { debug?: boolean } = {}) {
517
+ serviceAuth(options: { debug?: boolean; jwtSecret?: string } = {}) {
508
518
  const innerAuth = this.auth({ ...options });
509
519
 
510
520
  return async (req: any, res: any, next: any) => {
@@ -88,6 +88,20 @@ export function isAndroid(): boolean {
88
88
  return getPlatformOS() === 'android';
89
89
  }
90
90
 
91
+ /**
92
+ * Check if running in React Native
93
+ */
94
+ export function isReactNative(): boolean {
95
+ return typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
96
+ }
97
+
98
+ /**
99
+ * Check if running in Node.js
100
+ */
101
+ export function isNodeJS(): boolean {
102
+ return typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
103
+ }
104
+
91
105
  /**
92
106
  * Set the platform OS explicitly
93
107
  * Called by React Native entry point to register the platform