@oxyhq/core 1.5.0 → 1.6.1

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 (92) hide show
  1. package/dist/cjs/AuthManager.js +14 -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/index.js +9 -1
  7. package/dist/cjs/mixins/OxyServices.analytics.js +2 -2
  8. package/dist/cjs/mixins/OxyServices.assets.js +14 -14
  9. package/dist/cjs/mixins/OxyServices.auth.js +19 -19
  10. package/dist/cjs/mixins/OxyServices.developer.js +6 -6
  11. package/dist/cjs/mixins/OxyServices.devices.js +7 -7
  12. package/dist/cjs/mixins/OxyServices.features.js +23 -23
  13. package/dist/cjs/mixins/OxyServices.fedcm.js +1 -1
  14. package/dist/cjs/mixins/OxyServices.karma.js +6 -6
  15. package/dist/cjs/mixins/OxyServices.location.js +2 -2
  16. package/dist/cjs/mixins/OxyServices.payment.js +6 -6
  17. package/dist/cjs/mixins/OxyServices.popup.js +1 -1
  18. package/dist/cjs/mixins/OxyServices.privacy.js +6 -6
  19. package/dist/cjs/mixins/OxyServices.security.js +3 -3
  20. package/dist/cjs/mixins/OxyServices.user.js +22 -22
  21. package/dist/cjs/mixins/OxyServices.utility.js +39 -10
  22. package/dist/cjs/utils/authHelpers.js +114 -0
  23. package/dist/cjs/utils/platform.js +14 -0
  24. package/dist/esm/AuthManager.js +14 -1
  25. package/dist/esm/HttpService.js +87 -69
  26. package/dist/esm/OxyServices.base.js +5 -4
  27. package/dist/esm/crypto/keyManager.js +1 -13
  28. package/dist/esm/crypto/signatureService.js +2 -15
  29. package/dist/esm/index.js +2 -0
  30. package/dist/esm/mixins/OxyServices.analytics.js +2 -2
  31. package/dist/esm/mixins/OxyServices.assets.js +14 -14
  32. package/dist/esm/mixins/OxyServices.auth.js +19 -19
  33. package/dist/esm/mixins/OxyServices.developer.js +6 -6
  34. package/dist/esm/mixins/OxyServices.devices.js +7 -7
  35. package/dist/esm/mixins/OxyServices.features.js +23 -23
  36. package/dist/esm/mixins/OxyServices.fedcm.js +1 -1
  37. package/dist/esm/mixins/OxyServices.karma.js +6 -6
  38. package/dist/esm/mixins/OxyServices.location.js +2 -2
  39. package/dist/esm/mixins/OxyServices.payment.js +6 -6
  40. package/dist/esm/mixins/OxyServices.popup.js +1 -1
  41. package/dist/esm/mixins/OxyServices.privacy.js +6 -6
  42. package/dist/esm/mixins/OxyServices.security.js +3 -3
  43. package/dist/esm/mixins/OxyServices.user.js +22 -22
  44. package/dist/esm/mixins/OxyServices.utility.js +39 -10
  45. package/dist/esm/utils/authHelpers.js +105 -0
  46. package/dist/esm/utils/platform.js +12 -0
  47. package/dist/types/HttpService.d.ts +4 -1
  48. package/dist/types/OxyServices.base.d.ts +1 -1
  49. package/dist/types/index.d.ts +2 -0
  50. package/dist/types/mixins/OxyServices.analytics.d.ts +1 -1
  51. package/dist/types/mixins/OxyServices.assets.d.ts +1 -1
  52. package/dist/types/mixins/OxyServices.auth.d.ts +1 -1
  53. package/dist/types/mixins/OxyServices.developer.d.ts +1 -1
  54. package/dist/types/mixins/OxyServices.devices.d.ts +1 -1
  55. package/dist/types/mixins/OxyServices.features.d.ts +1 -1
  56. package/dist/types/mixins/OxyServices.fedcm.d.ts +1 -1
  57. package/dist/types/mixins/OxyServices.karma.d.ts +1 -1
  58. package/dist/types/mixins/OxyServices.language.d.ts +1 -1
  59. package/dist/types/mixins/OxyServices.location.d.ts +1 -1
  60. package/dist/types/mixins/OxyServices.payment.d.ts +1 -1
  61. package/dist/types/mixins/OxyServices.popup.d.ts +1 -1
  62. package/dist/types/mixins/OxyServices.privacy.d.ts +1 -1
  63. package/dist/types/mixins/OxyServices.redirect.d.ts +1 -1
  64. package/dist/types/mixins/OxyServices.security.d.ts +1 -1
  65. package/dist/types/mixins/OxyServices.user.d.ts +1 -1
  66. package/dist/types/mixins/OxyServices.utility.d.ts +20 -6
  67. package/dist/types/utils/authHelpers.d.ts +57 -0
  68. package/dist/types/utils/platform.d.ts +8 -0
  69. package/package.json +1 -1
  70. package/src/AuthManager.ts +14 -1
  71. package/src/HttpService.ts +85 -67
  72. package/src/OxyServices.base.ts +5 -4
  73. package/src/crypto/keyManager.ts +1 -15
  74. package/src/crypto/signatureService.ts +2 -17
  75. package/src/index.ts +11 -0
  76. package/src/mixins/OxyServices.analytics.ts +2 -2
  77. package/src/mixins/OxyServices.assets.ts +14 -14
  78. package/src/mixins/OxyServices.auth.ts +19 -19
  79. package/src/mixins/OxyServices.developer.ts +6 -6
  80. package/src/mixins/OxyServices.devices.ts +7 -7
  81. package/src/mixins/OxyServices.features.ts +23 -23
  82. package/src/mixins/OxyServices.fedcm.ts +1 -1
  83. package/src/mixins/OxyServices.karma.ts +6 -6
  84. package/src/mixins/OxyServices.location.ts +2 -2
  85. package/src/mixins/OxyServices.payment.ts +6 -6
  86. package/src/mixins/OxyServices.popup.ts +1 -1
  87. package/src/mixins/OxyServices.privacy.ts +6 -6
  88. package/src/mixins/OxyServices.security.ts +3 -3
  89. package/src/mixins/OxyServices.user.ts +22 -22
  90. package/src/mixins/OxyServices.utility.ts +41 -11
  91. package/src/utils/authHelpers.ts +140 -0
  92. package/src/utils/platform.ts +14 -0
@@ -16,7 +16,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
16
16
  */
17
17
  async getUserKarma(userId: string): Promise<any> {
18
18
  try {
19
- return await this.makeRequest('GET', `/api/karma/${userId}`, undefined, {
19
+ return await this.makeRequest('GET', `/karma/${userId}`, undefined, {
20
20
  cache: true,
21
21
  cacheTTL: 2 * 60 * 1000, // 2 minutes cache
22
22
  });
@@ -30,7 +30,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
30
30
  */
31
31
  async giveKarma(userId: string, amount: number, reason?: string): Promise<any> {
32
32
  try {
33
- return await this.makeRequest('POST', `/api/karma/${userId}/give`, {
33
+ return await this.makeRequest('POST', `/karma/${userId}/give`, {
34
34
  amount,
35
35
  reason
36
36
  }, { cache: false });
@@ -46,7 +46,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
46
46
  */
47
47
  async getUserKarmaTotal(userId: string): Promise<any> {
48
48
  try {
49
- return await this.makeRequest('GET', `/api/karma/${userId}/total`, undefined, {
49
+ return await this.makeRequest('GET', `/karma/${userId}/total`, undefined, {
50
50
  cache: true,
51
51
  cacheTTL: CACHE_TIMES.MEDIUM,
52
52
  });
@@ -68,7 +68,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
68
68
  if (limit) params.limit = limit;
69
69
  if (offset) params.offset = offset;
70
70
 
71
- return await this.makeRequest('GET', `/api/karma/${userId}/history`, params, {
71
+ return await this.makeRequest('GET', `/karma/${userId}/history`, params, {
72
72
  cache: true,
73
73
  cacheTTL: CACHE_TIMES.MEDIUM,
74
74
  });
@@ -83,7 +83,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
83
83
  */
84
84
  async getKarmaLeaderboard(): Promise<any> {
85
85
  try {
86
- return await this.makeRequest('GET', '/api/karma/leaderboard', undefined, {
86
+ return await this.makeRequest('GET', '/karma/leaderboard', undefined, {
87
87
  cache: true,
88
88
  cacheTTL: CACHE_TIMES.LONG,
89
89
  });
@@ -98,7 +98,7 @@ export function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(Base: T)
98
98
  */
99
99
  async getKarmaRules(): Promise<any> {
100
100
  try {
101
- return await this.makeRequest('GET', '/api/karma/rules', undefined, {
101
+ return await this.makeRequest('GET', '/karma/rules', undefined, {
102
102
  cache: true,
103
103
  cacheTTL: CACHE_TIMES.EXTRA_LONG, // Rules don't change often
104
104
  });
@@ -17,7 +17,7 @@ export function OxyServicesLocationMixin<T extends typeof OxyServicesBase>(Base:
17
17
  */
18
18
  async updateLocation(latitude: number, longitude: number): Promise<any> {
19
19
  try {
20
- return await this.makeRequest('POST', '/api/location', {
20
+ return await this.makeRequest('POST', '/location', {
21
21
  latitude,
22
22
  longitude
23
23
  }, { cache: false });
@@ -34,7 +34,7 @@ export function OxyServicesLocationMixin<T extends typeof OxyServicesBase>(Base:
34
34
  async getNearbyUsers(radius?: number): Promise<any[]> {
35
35
  try {
36
36
  const params: any = radius ? { radius } : undefined;
37
- return await this.makeRequest('GET', '/api/location/nearby', params, {
37
+ return await this.makeRequest('GET', '/location/nearby', params, {
38
38
  cache: false, // Don't cache location data - always get fresh data
39
39
  });
40
40
  } catch (error) {
@@ -19,7 +19,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
19
19
  */
20
20
  async createPayment(data: any): Promise<any> {
21
21
  try {
22
- return await this.makeRequest('POST', '/api/payments', data, { cache: false });
22
+ return await this.makeRequest('POST', '/payments', data, { cache: false });
23
23
  } catch (error) {
24
24
  throw this.handleError(error);
25
25
  }
@@ -32,7 +32,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
32
32
  */
33
33
  async getPayment(paymentId: string): Promise<any> {
34
34
  try {
35
- return await this.makeRequest('GET', `/api/payments/${paymentId}`, undefined, {
35
+ return await this.makeRequest('GET', `/payments/${paymentId}`, undefined, {
36
36
  cache: true,
37
37
  cacheTTL: CACHE_TIMES.LONG,
38
38
  });
@@ -47,7 +47,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
47
47
  */
48
48
  async getUserPayments(): Promise<any[]> {
49
49
  try {
50
- return await this.makeRequest('GET', '/api/payments/user', undefined, {
50
+ return await this.makeRequest('GET', '/payments/user', undefined, {
51
51
  cache: false, // Don't cache user payments - always get fresh data
52
52
  });
53
53
  } catch (error) {
@@ -62,7 +62,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
62
62
  */
63
63
  async getSubscription(userId: string): Promise<any> {
64
64
  try {
65
- return await this.makeRequest('GET', `/api/subscription/${userId}`, undefined, {
65
+ return await this.makeRequest('GET', `/subscription/${userId}`, undefined, {
66
66
  cache: true,
67
67
  cacheTTL: CACHE_TIMES.MEDIUM,
68
68
  });
@@ -94,7 +94,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
94
94
  */
95
95
  async getWallet(userId: string): Promise<any> {
96
96
  try {
97
- return await this.makeRequest('GET', `/api/wallet/${userId}`, undefined, {
97
+ return await this.makeRequest('GET', `/wallet/${userId}`, undefined, {
98
98
  cache: true,
99
99
  cacheTTL: CACHE_TIMES.SHORT, // Cache wallet for short time as balance changes frequently
100
100
  });
@@ -132,7 +132,7 @@ export function OxyServicesPaymentMixin<T extends typeof OxyServicesBase>(Base:
132
132
  if (options?.offset) params.append('offset', options.offset.toString());
133
133
 
134
134
  const queryString = params.toString();
135
- const url = `/api/wallet/transactions/${userId}${queryString ? `?${queryString}` : ''}`;
135
+ const url = `/wallet/transactions/${userId}${queryString ? `?${queryString}` : ''}`;
136
136
 
137
137
  return await this.makeRequest('GET', url, undefined, {
138
138
  cache: false, // Don't cache transactions - always get fresh data
@@ -120,7 +120,7 @@ export function OxyServicesPopupAuthMixin<T extends typeof OxyServicesBase>(Base
120
120
  try {
121
121
  const userData = await this.makeRequest<any>(
122
122
  'GET',
123
- `/api/session/user/${session.sessionId}`,
123
+ `/session/user/${session.sessionId}`,
124
124
  undefined,
125
125
  { cache: false }
126
126
  );
@@ -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
  });
@@ -83,25 +83,36 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
83
83
  * Validates JWT tokens against the Oxy API and attaches user data to requests.
84
84
  * Uses server-side session validation for security (not just JWT decode).
85
85
  *
86
+ * **Design note — jwtDecode vs jwt.verify:**
87
+ * This middleware intentionally uses `jwtDecode()` (decode-only, no signature
88
+ * verification) for user tokens. This is by design, NOT a security gap:
89
+ * - Third-party apps using `oxy.auth()` don't have the Oxy JWT secret
90
+ * - Security comes from API-based session validation (`validateSession()`)
91
+ * which checks the session server-side on every request
92
+ * - Service tokens (type: 'service') DO use cryptographic HMAC verification
93
+ * via the `jwtSecret` option, since they are stateless
94
+ * - The backend's own `authMiddleware` uses `jwt.verify()` because it has
95
+ * direct access to `ACCESS_TOKEN_SECRET`
96
+ *
86
97
  * @example
87
98
  * ```typescript
88
99
  * import { OxyServices } from '@oxyhq/core';
89
100
  *
90
101
  * const oxy = new OxyServices({ baseURL: 'https://api.oxy.so' });
91
102
  *
92
- * // Protect all routes under /api/protected
93
- * app.use('/api/protected', oxy.auth());
103
+ * // Protect all routes under /protected
104
+ * app.use('/protected', oxy.auth());
94
105
  *
95
106
  * // Access user in route handler
96
- * app.get('/api/protected/me', (req, res) => {
107
+ * app.get('/protected/me', (req, res) => {
97
108
  * res.json({ userId: req.userId, user: req.user });
98
109
  * });
99
110
  *
100
111
  * // Load full user profile from API
101
- * app.use('/api/admin', oxy.auth({ loadUser: true }));
112
+ * app.use('/admin', oxy.auth({ loadUser: true }));
102
113
  *
103
114
  * // Optional auth - attach user if present, don't block if absent
104
- * app.use('/api/public', oxy.auth({ optional: true }));
115
+ * app.use('/public', oxy.auth({ optional: true }));
105
116
  * ```
106
117
  *
107
118
  * @param options Optional configuration
@@ -138,6 +149,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
138
149
  }
139
150
 
140
151
  const error = {
152
+ error: 'MISSING_TOKEN',
141
153
  message: 'Access token required',
142
154
  code: 'MISSING_TOKEN',
143
155
  status: 401
@@ -158,6 +170,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
158
170
  }
159
171
 
160
172
  const error = {
173
+ error: 'INVALID_TOKEN_FORMAT',
161
174
  message: 'Invalid token format',
162
175
  code: 'INVALID_TOKEN_FORMAT',
163
176
  status: 401
@@ -177,6 +190,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
177
190
  return next();
178
191
  }
179
192
  const error = {
193
+ error: 'SERVICE_TOKEN_NOT_CONFIGURED',
180
194
  message: 'Service token verification not configured',
181
195
  code: 'SERVICE_TOKEN_NOT_CONFIGURED',
182
196
  status: 403
@@ -206,13 +220,23 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
206
220
  if (sigBuf.length !== expectedBuf.length || !timingSafeEqual(sigBuf, expectedBuf)) {
207
221
  throw new Error('Invalid signature');
208
222
  }
209
- } catch {
223
+ } catch (verifyError) {
224
+ const isSignatureError = verifyError instanceof Error &&
225
+ (verifyError.message === 'Invalid signature' || verifyError.message === 'Invalid token structure');
226
+
227
+ if (!isSignatureError) {
228
+ console.error('[oxy.auth] Unexpected error during service token verification:', verifyError);
229
+ const error = { error: 'AUTH_INTERNAL_ERROR', message: 'Internal authentication error', code: 'AUTH_INTERNAL_ERROR', status: 500 };
230
+ if (onError) return onError(error);
231
+ return res.status(500).json(error);
232
+ }
233
+
210
234
  if (optional) {
211
235
  req.userId = null;
212
236
  req.user = null;
213
237
  return next();
214
238
  }
215
- const error = { message: 'Invalid service token signature', code: 'INVALID_SERVICE_TOKEN', status: 401 };
239
+ const error = { error: 'INVALID_SERVICE_TOKEN', message: 'Invalid service token signature', code: 'INVALID_SERVICE_TOKEN', status: 401 };
216
240
  if (onError) return onError(error);
217
241
  return res.status(401).json(error);
218
242
  }
@@ -224,7 +248,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
224
248
  req.user = null;
225
249
  return next();
226
250
  }
227
- const error = { message: 'Service token expired', code: 'TOKEN_EXPIRED', status: 401 };
251
+ const error = { error: 'TOKEN_EXPIRED', message: 'Service token expired', code: 'TOKEN_EXPIRED', status: 401 };
228
252
  if (onError) return onError(error);
229
253
  return res.status(401).json(error);
230
254
  }
@@ -236,7 +260,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
236
260
  req.user = null;
237
261
  return next();
238
262
  }
239
- const error = { message: 'Invalid service token: missing appId', code: 'INVALID_SERVICE_TOKEN', status: 401 };
263
+ const error = { error: 'INVALID_SERVICE_TOKEN', message: 'Invalid service token: missing appId', code: 'INVALID_SERVICE_TOKEN', status: 401 };
240
264
  if (onError) return onError(error);
241
265
  return res.status(401).json(error);
242
266
  }
@@ -268,6 +292,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
268
292
  }
269
293
 
270
294
  const error = {
295
+ error: 'INVALID_TOKEN_PAYLOAD',
271
296
  message: 'Token missing user ID',
272
297
  code: 'INVALID_TOKEN_PAYLOAD',
273
298
  status: 401
@@ -285,6 +310,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
285
310
  }
286
311
 
287
312
  const error = {
313
+ error: 'TOKEN_EXPIRED',
288
314
  message: 'Token expired',
289
315
  code: 'TOKEN_EXPIRED',
290
316
  status: 401
@@ -309,6 +335,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
309
335
  }
310
336
 
311
337
  const error = {
338
+ error: 'INVALID_SESSION',
312
339
  message: 'Session invalid or expired',
313
340
  code: 'INVALID_SESSION',
314
341
  status: 401
@@ -346,6 +373,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
346
373
  }
347
374
 
348
375
  const error = {
376
+ error: 'SESSION_VALIDATION_ERROR',
349
377
  message: 'Session validation failed',
350
378
  code: 'SESSION_VALIDATION_ERROR',
351
379
  status: 401
@@ -406,6 +434,8 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
406
434
  * Returns a middleware function for Socket.IO that validates JWT tokens
407
435
  * from the handshake auth object and attaches user data to the socket.
408
436
  *
437
+ * Uses `jwtDecode()` + API session validation (same rationale as `auth()`).
438
+ *
409
439
  * @example
410
440
  * ```typescript
411
441
  * import { OxyServices } from '@oxyhq/core';
@@ -504,7 +534,7 @@ export function OxyServicesUtilityMixin<T extends typeof OxyServicesBase>(Base:
504
534
  * });
505
535
  * ```
506
536
  */
507
- serviceAuth(options: { debug?: boolean } = {}) {
537
+ serviceAuth(options: { debug?: boolean; jwtSecret?: string } = {}) {
508
538
  const innerAuth = this.auth({ ...options });
509
539
 
510
540
  return async (req: any, res: any, next: any) => {