@oxyhq/services 5.5.7 → 5.5.8

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 (34) hide show
  1. package/lib/commonjs/core/index.js +13 -13
  2. package/lib/commonjs/core/index.js.map +1 -1
  3. package/lib/commonjs/ui/context/OxyContext.js +467 -87
  4. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  5. package/lib/commonjs/ui/hooks/useAuthFetch.js +79 -45
  6. package/lib/commonjs/ui/hooks/useAuthFetch.js.map +1 -1
  7. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
  8. package/lib/module/core/index.js +13 -6
  9. package/lib/module/core/index.js.map +1 -1
  10. package/lib/module/ui/context/OxyContext.js +467 -87
  11. package/lib/module/ui/context/OxyContext.js.map +1 -1
  12. package/lib/module/ui/hooks/useAuthFetch.js +79 -45
  13. package/lib/module/ui/hooks/useAuthFetch.js.map +1 -1
  14. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  15. package/lib/typescript/core/index.d.ts +7 -6
  16. package/lib/typescript/core/index.d.ts.map +1 -1
  17. package/lib/typescript/ui/context/OxyContext.d.ts +11 -7
  18. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  19. package/lib/typescript/ui/hooks/useAuthFetch.d.ts +10 -4
  20. package/lib/typescript/ui/hooks/useAuthFetch.d.ts.map +1 -1
  21. package/package.json +1 -1
  22. package/src/__tests__/backend-middleware.test.ts +209 -0
  23. package/src/__tests__/ui/hooks/useAuthFetch.test.ts +70 -0
  24. package/src/core/index.ts +13 -7
  25. package/src/ui/context/OxyContext.tsx +522 -99
  26. package/src/ui/hooks/useAuthFetch.ts +81 -47
  27. package/src/ui/screens/SessionManagementScreen.tsx +9 -9
  28. package/lib/commonjs/core/AuthManager.js +0 -378
  29. package/lib/commonjs/core/AuthManager.js.map +0 -1
  30. package/lib/module/core/AuthManager.js +0 -373
  31. package/lib/module/core/AuthManager.js.map +0 -1
  32. package/lib/typescript/core/AuthManager.d.ts +0 -100
  33. package/lib/typescript/core/AuthManager.d.ts.map +0 -1
  34. package/src/core/AuthManager.ts +0 -389
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Integration test for refactored authentication system
3
+ * Tests the backend middleware functionality
4
+ */
5
+
6
+ import { OxyServices } from '../../core';
7
+
8
+ describe('Authentication System Integration', () => {
9
+ let oxyServices: OxyServices;
10
+ let mockReq: any;
11
+ let mockRes: any;
12
+ let mockNext: any;
13
+
14
+ beforeEach(() => {
15
+ oxyServices = new OxyServices({
16
+ baseURL: 'https://api.test.com'
17
+ });
18
+
19
+ // Mock Express request/response objects
20
+ mockReq = {
21
+ headers: {},
22
+ user: undefined,
23
+ userId: undefined,
24
+ accessToken: undefined
25
+ };
26
+
27
+ mockRes = {
28
+ status: jest.fn().mockReturnThis(),
29
+ json: jest.fn().mockReturnThis()
30
+ };
31
+
32
+ mockNext = jest.fn();
33
+ });
34
+
35
+ describe('Middleware Creation', () => {
36
+ test('should create authentication middleware', () => {
37
+ const middleware = oxyServices.createAuthenticateTokenMiddleware();
38
+ expect(typeof middleware).toBe('function');
39
+ expect(middleware.length).toBe(3); // req, res, next
40
+ });
41
+
42
+ test('should create middleware with custom options', () => {
43
+ const customErrorHandler = jest.fn();
44
+ const middleware = oxyServices.createAuthenticateTokenMiddleware({
45
+ loadFullUser: false,
46
+ onError: customErrorHandler
47
+ });
48
+
49
+ expect(typeof middleware).toBe('function');
50
+ });
51
+ });
52
+
53
+ describe('Token Validation', () => {
54
+ test('should handle missing token', async () => {
55
+ const middleware = oxyServices.createAuthenticateTokenMiddleware();
56
+
57
+ await middleware(mockReq, mockRes, mockNext);
58
+
59
+ expect(mockRes.status).toHaveBeenCalledWith(401);
60
+ expect(mockRes.json).toHaveBeenCalledWith({
61
+ message: 'Access token required',
62
+ code: 'MISSING_TOKEN'
63
+ });
64
+ expect(mockNext).not.toHaveBeenCalled();
65
+ });
66
+
67
+ test('should handle invalid token format', async () => {
68
+ mockReq.headers.authorization = 'InvalidFormat token123';
69
+
70
+ const middleware = oxyServices.createAuthenticateTokenMiddleware();
71
+ await middleware(mockReq, mockRes, mockNext);
72
+
73
+ expect(mockRes.status).toHaveBeenCalledWith(401);
74
+ expect(mockNext).not.toHaveBeenCalled();
75
+ });
76
+
77
+ test('should extract token from Bearer header', async () => {
78
+ mockReq.headers.authorization = 'Bearer valid.jwt.token';
79
+
80
+ const middleware = oxyServices.createAuthenticateTokenMiddleware();
81
+ await middleware(mockReq, mockRes, mockNext);
82
+
83
+ // Note: This will fail validation since it's not a real token,
84
+ // but we can verify the token was extracted
85
+ expect(mockRes.status).toHaveBeenCalled();
86
+ });
87
+ });
88
+
89
+ describe('Standalone Token Validation', () => {
90
+ test('should validate empty token', async () => {
91
+ const result = await oxyServices.authenticateToken('');
92
+
93
+ expect(result.valid).toBe(false);
94
+ expect(result.error).toBe('Token is required');
95
+ expect(result.userId).toBeUndefined();
96
+ expect(result.user).toBeUndefined();
97
+ });
98
+
99
+ test('should validate invalid token', async () => {
100
+ const result = await oxyServices.authenticateToken('invalid.jwt.token');
101
+
102
+ expect(result.valid).toBe(false);
103
+ expect(result.error).toBeTruthy();
104
+ expect(result.userId).toBeUndefined();
105
+ expect(result.user).toBeUndefined();
106
+ });
107
+
108
+ test('should handle validation errors gracefully', async () => {
109
+ const result = await oxyServices.authenticateToken('malformed-token');
110
+
111
+ expect(result.valid).toBe(false);
112
+ expect(result.error).toMatch(/validation failed|Invalid/i);
113
+ });
114
+ });
115
+
116
+ describe('Custom Error Handling', () => {
117
+ test('should use custom error handler when provided', async () => {
118
+ const customErrorHandler = jest.fn();
119
+ const middleware = oxyServices.createAuthenticateTokenMiddleware({
120
+ onError: customErrorHandler
121
+ });
122
+
123
+ await middleware(mockReq, mockRes, mockNext);
124
+
125
+ expect(customErrorHandler).toHaveBeenCalledWith({
126
+ message: 'Access token required',
127
+ code: 'MISSING_TOKEN',
128
+ status: 401
129
+ });
130
+ expect(mockRes.status).not.toHaveBeenCalled();
131
+ });
132
+ });
133
+
134
+ describe('Backend Integration Example', () => {
135
+ test('should work with Express.js route patterns', () => {
136
+ // Simulate Express.js app setup
137
+ const mockApp = {
138
+ get: jest.fn(),
139
+ post: jest.fn(),
140
+ use: jest.fn()
141
+ };
142
+
143
+ // Create middleware
144
+ const authenticateToken = oxyServices.createAuthenticateTokenMiddleware({
145
+ loadFullUser: true
146
+ });
147
+
148
+ // Simulate route registration
149
+ mockApp.get('/api/protected', authenticateToken, (req: any, res: any) => {
150
+ res.json({
151
+ message: 'Access granted',
152
+ user: req.user,
153
+ userId: req.userId
154
+ });
155
+ });
156
+
157
+ expect(mockApp.get).toHaveBeenCalledWith(
158
+ '/api/protected',
159
+ authenticateToken,
160
+ expect.any(Function)
161
+ );
162
+ });
163
+
164
+ test('should provide consistent interface for different auth patterns', () => {
165
+ // Pattern 1: Middleware
166
+ const middleware = oxyServices.createAuthenticateTokenMiddleware();
167
+ expect(typeof middleware).toBe('function');
168
+
169
+ // Pattern 2: Standalone validation
170
+ const validateToken = oxyServices.authenticateToken.bind(oxyServices);
171
+ expect(typeof validateToken).toBe('function');
172
+
173
+ // Pattern 3: Direct service methods
174
+ expect(typeof oxyServices.getAccessToken).toBe('function');
175
+ expect(typeof oxyServices.setTokens).toBe('function');
176
+ expect(typeof oxyServices.clearTokens).toBe('function');
177
+ });
178
+ });
179
+
180
+ describe('Zero-Config Setup Verification', () => {
181
+ test('should work with minimal configuration', () => {
182
+ // This simulates the zero-config setup promise
183
+ const minimalSetup = () => {
184
+ // Backend: Just create OxyServices and use middleware
185
+ const services = new OxyServices({ baseURL: 'https://api.example.com' });
186
+ const authMiddleware = services.createAuthenticateTokenMiddleware();
187
+
188
+ return { services, authMiddleware };
189
+ };
190
+
191
+ const { services, authMiddleware } = minimalSetup();
192
+
193
+ expect(services).toBeInstanceOf(OxyServices);
194
+ expect(typeof authMiddleware).toBe('function');
195
+ expect(services.getBaseURL()).toBe('https://api.example.com');
196
+ });
197
+
198
+ test('should support runtime configuration changes', () => {
199
+ const services = new OxyServices({ baseURL: 'https://dev-api.com' });
200
+
201
+ expect(services.getBaseURL()).toBe('https://dev-api.com');
202
+
203
+ // Simulate runtime change to production
204
+ services.setBaseURL('https://prod-api.com');
205
+
206
+ expect(services.getBaseURL()).toBe('https://prod-api.com');
207
+ });
208
+ });
209
+ });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Tests for refactored useAuthFetch hook
3
+ */
4
+
5
+ import { OxyServices } from '../../../core';
6
+
7
+ describe('useAuthFetch', () => {
8
+ let oxyServices: OxyServices;
9
+
10
+ beforeEach(() => {
11
+ oxyServices = new OxyServices({
12
+ baseURL: 'https://api.test.com'
13
+ });
14
+ });
15
+
16
+ describe('OxyServices integration', () => {
17
+ test('should set and get base URL', () => {
18
+ expect(oxyServices.getBaseURL()).toBe('https://api.test.com');
19
+
20
+ oxyServices.setBaseURL('https://new-api.test.com');
21
+ expect(oxyServices.getBaseURL()).toBe('https://new-api.test.com');
22
+ });
23
+
24
+ test('should throw error for empty base URL', () => {
25
+ expect(() => oxyServices.setBaseURL('')).toThrow('Base URL cannot be empty');
26
+ });
27
+
28
+ test('should handle token validation methods', () => {
29
+ // Test that core methods exist
30
+ expect(typeof oxyServices.getAccessToken).toBe('function');
31
+ expect(typeof oxyServices.setTokens).toBe('function');
32
+ expect(typeof oxyServices.clearTokens).toBe('function');
33
+ expect(typeof oxyServices.refreshTokens).toBe('function');
34
+ });
35
+ });
36
+
37
+ describe('URL resolution', () => {
38
+ test('should resolve relative URLs correctly', () => {
39
+ // This tests the logic that would be used in resolveURL function
40
+ const baseURL = 'https://api.test.com';
41
+
42
+ // Test relative URL with leading slash
43
+ const relativeUrl = '/api/users';
44
+ const expectedUrl = `${baseURL}${relativeUrl}`;
45
+ expect(expectedUrl).toBe('https://api.test.com/api/users');
46
+
47
+ // Test relative URL without leading slash
48
+ const relativeUrl2 = 'api/users';
49
+ const expectedUrl2 = `${baseURL}/${relativeUrl2}`;
50
+ expect(expectedUrl2).toBe('https://api.test.com/api/users');
51
+
52
+ // Test absolute URL (should remain unchanged)
53
+ const absoluteUrl = 'https://other-api.test.com/api/users';
54
+ expect(absoluteUrl).toBe('https://other-api.test.com/api/users');
55
+ });
56
+ });
57
+
58
+ describe('Authentication middleware compatibility', () => {
59
+ test('should create middleware function', () => {
60
+ const middleware = oxyServices.createAuthenticateTokenMiddleware();
61
+ expect(typeof middleware).toBe('function');
62
+ });
63
+
64
+ test('should validate tokens', async () => {
65
+ const result = await oxyServices.authenticateToken('invalid-token');
66
+ expect(result.valid).toBe(false);
67
+ expect(result.error).toBeTruthy();
68
+ });
69
+ });
70
+ });
package/src/core/index.ts CHANGED
@@ -68,14 +68,9 @@ interface JwtPayload {
68
68
  /**
69
69
  * OxyServices - Client library for interacting with the Oxy API
70
70
  *
71
- * ⚠️ IMPORTANT: For authentication operations, use the new AuthManager class instead.
72
- * This provides a centralized, professional authentication system.
73
- *
74
- * @deprecated Direct authentication methods - Use AuthManager instead
75
- * @see packages/services/docs/authentication-v2.md
71
+ * Note: For authentication status in UI components, use `isAuthenticated` from useOxy() context
72
+ * instead of checking token status directly on this service.
76
73
  */
77
- export { AuthManager } from './AuthManager';
78
-
79
74
  export class OxyServices {
80
75
  private client: AxiosInstance;
81
76
  private accessToken: string | null = null;
@@ -169,6 +164,17 @@ export class OxyServices {
169
164
  return this.client.defaults.baseURL || '';
170
165
  }
171
166
 
167
+ /**
168
+ * Sets/updates the base URL for this OxyServices instance
169
+ * @param baseURL - The new base URL to use for API requests
170
+ */
171
+ public setBaseURL(baseURL: string): void {
172
+ if (!baseURL) {
173
+ throw new Error('Base URL cannot be empty');
174
+ }
175
+ this.client.defaults.baseURL = baseURL;
176
+ }
177
+
172
178
  /**
173
179
  * Gets the currently authenticated user ID from the token
174
180
  * @returns The user ID or null if not authenticated