@oxyhq/services 5.7.2 → 5.7.4

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 (56) hide show
  1. package/README.md +287 -80
  2. package/lib/commonjs/core/index.js +0 -57
  3. package/lib/commonjs/core/index.js.map +1 -1
  4. package/lib/commonjs/node/index.js +49 -2
  5. package/lib/commonjs/node/index.js.map +1 -1
  6. package/lib/commonjs/node/middleware.js +227 -0
  7. package/lib/commonjs/node/middleware.js.map +1 -0
  8. package/lib/commonjs/ui/context/OxyContext.js +9 -29
  9. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  10. package/lib/commonjs/ui/hooks/useSessionSocket.js +1 -4
  11. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  12. package/lib/commonjs/ui/index.js +16 -1
  13. package/lib/commonjs/ui/index.js.map +1 -1
  14. package/lib/commonjs/ui/zero-config/index.js +25 -0
  15. package/lib/commonjs/ui/zero-config/index.js.map +1 -0
  16. package/lib/commonjs/ui/zero-config/provider.js +278 -0
  17. package/lib/commonjs/ui/zero-config/provider.js.map +1 -0
  18. package/lib/module/core/index.js +0 -57
  19. package/lib/module/core/index.js.map +1 -1
  20. package/lib/module/node/index.js +11 -1
  21. package/lib/module/node/index.js.map +1 -1
  22. package/lib/module/node/middleware.js +199 -0
  23. package/lib/module/node/middleware.js.map +1 -0
  24. package/lib/module/ui/context/OxyContext.js +9 -29
  25. package/lib/module/ui/context/OxyContext.js.map +1 -1
  26. package/lib/module/ui/hooks/useSessionSocket.js +1 -4
  27. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  28. package/lib/module/ui/index.js +16 -1
  29. package/lib/module/ui/index.js.map +1 -1
  30. package/lib/module/ui/zero-config/index.js +8 -0
  31. package/lib/module/ui/zero-config/index.js.map +1 -0
  32. package/lib/module/ui/zero-config/provider.js +270 -0
  33. package/lib/module/ui/zero-config/provider.js.map +1 -0
  34. package/lib/typescript/core/index.d.ts +0 -6
  35. package/lib/typescript/core/index.d.ts.map +1 -1
  36. package/lib/typescript/node/index.d.ts +7 -1
  37. package/lib/typescript/node/index.d.ts.map +1 -1
  38. package/lib/typescript/node/middleware.d.ts +92 -0
  39. package/lib/typescript/node/middleware.d.ts.map +1 -0
  40. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  41. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  42. package/lib/typescript/ui/index.d.ts +2 -1
  43. package/lib/typescript/ui/index.d.ts.map +1 -1
  44. package/lib/typescript/ui/zero-config/index.d.ts +5 -0
  45. package/lib/typescript/ui/zero-config/index.d.ts.map +1 -0
  46. package/lib/typescript/ui/zero-config/provider.d.ts +84 -0
  47. package/lib/typescript/ui/zero-config/provider.d.ts.map +1 -0
  48. package/package.json +6 -1
  49. package/src/core/index.ts +0 -60
  50. package/src/node/index.ts +17 -1
  51. package/src/node/middleware.ts +234 -0
  52. package/src/ui/context/OxyContext.tsx +9 -29
  53. package/src/ui/hooks/useSessionSocket.ts +1 -4
  54. package/src/ui/index.ts +19 -1
  55. package/src/ui/zero-config/index.ts +11 -0
  56. package/src/ui/zero-config/provider.tsx +310 -0
package/README.md CHANGED
@@ -1,137 +1,347 @@
1
1
  # OxyHQServices
2
2
 
3
- A TypeScript client library for the Oxy API providing authentication, user management, and UI components for React and React Native applications.
3
+ A TypeScript client library for the Oxy API providing **zero-config** authentication, user management, and UI components for React and React Native applications.
4
+
5
+ ## ✨ Zero-Config Quick Start
6
+
7
+ ### Frontend (React/Next.js) - 2 lines of code:
8
+
9
+ ```jsx
10
+ import { OxyZeroConfigProvider, useOxyZeroConfig } from '@oxyhq/services/ui';
11
+
12
+ // 1. Wrap your app
13
+ function App() {
14
+ return (
15
+ <OxyZeroConfigProvider>
16
+ <YourApp />
17
+ </OxyZeroConfigProvider>
18
+ );
19
+ }
20
+
21
+ // 2. Use authentication anywhere
22
+ function Dashboard() {
23
+ const { user, login, logout, isAuthenticated } = useOxyZeroConfig();
24
+
25
+ if (isAuthenticated) {
26
+ return <div>Welcome {user.username}! <button onClick={logout}>Logout</button></div>;
27
+ }
28
+
29
+ return <button onClick={() => login('user', 'password')}>Login</button>;
30
+ }
31
+ ```
32
+
33
+ ### Backend (Express.js) - 1 line of code:
34
+
35
+ ```js
36
+ import express from 'express';
37
+ import { createOxyAuth } from '@oxyhq/services/node';
38
+
39
+ const app = express();
40
+
41
+ // Zero-config auth - req.user automatically available
42
+ app.use('/api', createOxyAuth());
43
+
44
+ app.get('/api/profile', (req, res) => {
45
+ res.json({ user: req.user }); // req.user populated automatically!
46
+ });
47
+ ```
48
+
49
+ **That's it!** No complex configuration, no manual token management, no middleware setup.
4
50
 
5
51
  ## Table of Contents
6
52
 
53
+ - [Zero-Config Guide](#-zero-config-quick-start)
7
54
  - [Features](#features)
8
- - [Quick Start](#quick-start)
55
+ - [Installation](#installation)
56
+ - [Complete Examples](#complete-examples)
57
+ - [Advanced Usage](#advanced-usage)
9
58
  - [Documentation](#documentation)
10
- - [UI Components](#ui-components)
11
- - [Package Exports](#package-exports)
12
- - [Requirements](#requirements)
13
- - [Development](#development)
14
- - [Integration](#integration)
15
- - [License](#license)
59
+ - [Migration Guide](#migration-guide)
16
60
 
17
61
  ## Features
18
62
 
19
- - 🔐 **Authentication**: JWT-based auth with automatic token refresh
63
+ - 🚀 **Zero-Config**: Get authentication working in 2-3 lines of code
64
+ - 🔐 **Automatic Token Management**: Tokens saved, restored, and refreshed automatically
20
65
  - 👥 **User Management**: Profile operations and social features
21
- - 🎨 **UI Components**: Pre-built React components for common functionality
66
+ - 🎨 **UI Components**: Pre-built React components for common functionality
22
67
  - 📱 **Cross-Platform**: Works in React Native and web applications
23
68
  - 🔧 **TypeScript**: Full type safety and IntelliSense support
69
+ - 🔄 **Auto Backend Integration**: Frontend automatically sends tokens to backend
70
+ - 📦 **Express Middleware**: One-line backend authentication with `req.user` support
24
71
 
25
- ## Quick Start
72
+ ## Installation
26
73
 
27
74
  ```bash
28
75
  npm install @oxyhq/services
29
76
  ```
30
77
 
31
- ```typescript
32
- import { OxyServices } from '@oxyhq/services';
78
+ ## Complete Examples
79
+
80
+ ### React Application
81
+
82
+ **App.js**
83
+ ```jsx
84
+ import React from 'react';
85
+ import { OxyZeroConfigProvider } from '@oxyhq/services/ui';
86
+ import Dashboard from './Dashboard';
87
+
88
+ export default function App() {
89
+ return (
90
+ <OxyZeroConfigProvider>
91
+ <Dashboard />
92
+ </OxyZeroConfigProvider>
93
+ );
94
+ }
95
+ ```
96
+
97
+ **Dashboard.js**
98
+ ```jsx
99
+ import React from 'react';
100
+ import { useOxyZeroConfig } from '@oxyhq/services/ui';
101
+
102
+ export default function Dashboard() {
103
+ const { user, login, logout, isAuthenticated, isLoading } = useOxyZeroConfig();
104
+
105
+ if (isLoading) return <div>Loading...</div>;
106
+
107
+ if (!isAuthenticated) {
108
+ return (
109
+ <div>
110
+ <h1>Please log in</h1>
111
+ <button onClick={() => login('demo', 'password')}>Login</button>
112
+ </div>
113
+ );
114
+ }
115
+
116
+ return (
117
+ <div>
118
+ <h1>Welcome, {user.username}!</h1>
119
+ <button onClick={logout}>Logout</button>
120
+ </div>
121
+ );
122
+ }
123
+ ```
124
+
125
+ ### Express.js Backend
126
+
127
+ **server.js**
128
+ ```js
129
+ import express from 'express';
130
+ import { createOxyAuth } from '@oxyhq/services/node';
33
131
 
34
- const oxy = new OxyServices({
35
- baseURL: 'http://localhost:3000'
132
+ const app = express();
133
+ app.use(express.json());
134
+
135
+ // Public routes
136
+ app.get('/', (req, res) => {
137
+ res.json({ message: 'Public endpoint' });
36
138
  });
37
139
 
38
- // Authenticate
39
- const response = await oxy.auth.login({
40
- email: 'user@example.com',
41
- password: 'password'
140
+ // Protected routes - zero config!
141
+ app.use('/api', createOxyAuth());
142
+
143
+ // req.user is automatically available
144
+ app.get('/api/profile', (req, res) => {
145
+ res.json({
146
+ message: `Hello ${req.user.username}!`,
147
+ user: req.user
148
+ });
42
149
  });
43
150
 
44
- // Get current user
45
- const user = await oxy.users.getCurrentUser();
151
+ app.listen(3000, () => console.log('Server running on port 3000'));
46
152
  ```
47
153
 
48
- ## Documentation
154
+ ### Next.js Full-Stack
49
155
 
50
- For comprehensive documentation, API reference, and examples:
156
+ **pages/_app.js**
157
+ ```jsx
158
+ import { OxyZeroConfigProvider } from '@oxyhq/services/ui';
51
159
 
52
- - [📚 Full Documentation](./docs/README.md)
53
- - [🚀 Quick Start Guide](./docs/quick-start.md)
54
- - [🔐 Core API Reference](./docs/core-api.md)
55
- - [💼 Integration Examples](./docs/examples/)
160
+ export default function App({ Component, pageProps }) {
161
+ return (
162
+ <OxyZeroConfigProvider>
163
+ <Component {...pageProps} />
164
+ </OxyZeroConfigProvider>
165
+ );
166
+ }
167
+ ```
56
168
 
57
- ## UI Components
169
+ **pages/api/user.js**
170
+ ```js
171
+ import { createOxyAuth } from '@oxyhq/services/node';
172
+
173
+ const auth = createOxyAuth();
174
+
175
+ export default async function handler(req, res) {
176
+ // Apply authentication
177
+ await new Promise((resolve, reject) => {
178
+ auth(req, res, (err) => {
179
+ if (err) reject(err);
180
+ else resolve();
181
+ });
182
+ });
183
+
184
+ // req.user is now available
185
+ res.json({ user: req.user });
186
+ }
187
+ ```
58
188
 
59
- Import and use pre-built React components:
189
+ ## Advanced Usage
60
190
 
61
- ```typescript
62
- import { OxyProvider, Avatar, FollowButton } from '@oxyhq/services/ui';
191
+ ### Configuration Options
192
+
193
+ **Frontend**
194
+ ```jsx
195
+ <OxyZeroConfigProvider
196
+ apiUrl="https://your-api.com"
197
+ onAuthChange={(user) => console.log('Auth changed:', user)}
198
+ >
199
+ <App />
200
+ </OxyZeroConfigProvider>
63
201
  ```
64
202
 
65
- ## Package Exports
203
+ **Backend**
204
+ ```js
205
+ app.use('/api', createOxyAuth({
206
+ baseURL: 'https://your-oxy-api.com',
207
+ loadUser: true,
208
+ publicPaths: ['/api/health'],
209
+ onError: (error, req, res) => {
210
+ res.status(error.status).json({ error: error.message });
211
+ }
212
+ }));
213
+ ```
66
214
 
67
- The library provides multiple entry points:
215
+ ### Direct API Access
68
216
 
69
- ```typescript
70
- // Core services only (Node.js/Express)
71
- import { OxyServices } from '@oxyhq/services';
217
+ ```jsx
218
+ import { useOxyApi } from '@oxyhq/services/ui';
219
+
220
+ function ProfileForm() {
221
+ const api = useOxyApi();
72
222
 
73
- // UI components only (React/React Native)
74
- import { OxyProvider, Avatar } from '@oxyhq/services/ui';
223
+ const updateProfile = async (data) => {
224
+ const user = await api.updateProfile(data);
225
+ // Token automatically included in request
226
+ };
75
227
 
76
- // Full package (Core + UI)
77
- import { OxyServices, OxyProvider } from '@oxyhq/services/full';
228
+ return <button onClick={() => updateProfile({ name: 'New Name' })}>Update</button>;
229
+ }
78
230
  ```
79
231
 
80
- ## Zero-Config Express Router
232
+ ### Optional Authentication
81
233
 
82
- Quickly mount authentication routes in any Express app:
234
+ ```js
235
+ import { createOptionalOxyAuth } from '@oxyhq/services/node';
83
236
 
84
- ```typescript
85
- import express from 'express';
86
- import { createAuth } from '@oxyhq/services/core';
237
+ // Works with or without authentication
238
+ app.use('/api/content', createOptionalOxyAuth());
87
239
 
88
- const app = express();
89
- app.use('/auth', createAuth({ baseURL: 'http://localhost:3000' }).middleware());
240
+ app.get('/api/content', (req, res) => {
241
+ if (req.user) {
242
+ res.json({ content: 'personalized', user: req.user });
243
+ } else {
244
+ res.json({ content: 'public' });
245
+ }
246
+ });
90
247
  ```
91
248
 
92
- This automatically provides sign-up, login, logout, refresh, and session management endpoints.
249
+ ## Documentation
93
250
 
94
- ## Requirements
251
+ ### Zero-Config Guide
252
+ - **[🚀 Zero-Config Setup Guide](./docs/zero-config.md)** - Complete guide with examples
95
253
 
96
- - **Node.js** 16+ (for backend usage)
97
- - **React** 16.8+ (for React components)
98
- - **React Native** 0.60+ (for mobile components)
99
- - **TypeScript** 4.0+ (optional but recommended)
254
+ ### Advanced Documentation
255
+ - **[📚 Full Documentation](./docs/README.md)** - Complete system documentation
256
+ - **[🚀 Quick Start Guide](./docs/quick-start.md)** - Traditional setup guide
257
+ - **[🔐 Core API Reference](./docs/core-api.md)** - Detailed API documentation
258
+ - **[💼 Integration Examples](./docs/examples/)** - More integration examples
100
259
 
101
- ## Troubleshooting
260
+ ### UI Components
261
+ - **[🎨 UI Components Guide](./docs/ui-components.md)** - React/RN component usage
102
262
 
103
- ### FormData Issues in React Native/Expo
263
+ ## Migration Guide
104
264
 
105
- If you encounter `ReferenceError: Property 'FormData' doesn't exist` when using Expo with Hermes engine:
265
+ ### From Complex Setup
106
266
 
107
- **For file uploads in React Native/Expo:**
108
- - The library handles this automatically - no additional setup required
109
- - File uploads will work with both native FormData (when available) and the polyfilled version
110
- - Ensure you're using the latest version of the package
267
+ **Before (complex setup):**
268
+ ```jsx
269
+ import { OxyProvider, useOxy } from '@oxyhq/services/ui';
270
+ import { OxyServices } from '@oxyhq/services';
111
271
 
112
- ### Additional Dependencies
272
+ const oxy = new OxyServices({ baseURL: 'http://localhost:3001' });
113
273
 
114
- For React Native projects, you may need to install peer dependencies:
274
+ function App() {
275
+ return (
276
+ <OxyProvider oxyServices={oxy}>
277
+ <Dashboard />
278
+ </OxyProvider>
279
+ );
280
+ }
281
+ ```
115
282
 
116
- ```bash
117
- npm install axios jwt-decode invariant
283
+ **After (zero-config):**
284
+ ```jsx
285
+ import { OxyZeroConfigProvider, useOxyZeroConfig } from '@oxyhq/services/ui';
286
+
287
+ function App() {
288
+ return (
289
+ <OxyZeroConfigProvider>
290
+ <Dashboard />
291
+ </OxyZeroConfigProvider>
292
+ );
293
+ }
118
294
  ```
119
295
 
120
- ## Important for React Native Hermes Users
296
+ Just change the provider and hook names - the API is nearly identical!
121
297
 
122
- If you use this package in a React Native app with the Hermes engine, you must add the following import as the very first line of your app's entry file (e.g., App.js or index.js):
298
+ ### Package Exports
123
299
 
124
- ```js
125
- import 'react-native-url-polyfill/auto';
126
- ```
300
+ The library provides multiple entry points for different use cases:
301
+
302
+ ```typescript
303
+ // Zero-config frontend
304
+ import { OxyZeroConfigProvider, useOxyZeroConfig } from '@oxyhq/services/ui';
127
305
 
128
- This ensures that FormData and other web APIs are polyfilled before any dependencies are loaded. If you do not do this, you may see errors like:
306
+ // Zero-config backend
307
+ import { createOxyAuth } from '@oxyhq/services/node';
129
308
 
309
+ // Core services only (traditional)
310
+ import { OxyServices } from '@oxyhq/services';
311
+
312
+ // Full package (Core + UI + Node)
313
+ import { OxyServices, OxyProvider, createOxyAuth } from '@oxyhq/services/full';
130
314
  ```
131
- ReferenceError: Property 'FormData' doesn't exist, js engine: hermes
315
+
316
+ ## Requirements
317
+
318
+ - **Node.js** 16+ (for backend usage)
319
+ - **React** 16.8+ (for React components)
320
+ - **React Native** 0.60+ (for mobile components)
321
+ - **TypeScript** 4.0+ (optional but recommended)
322
+
323
+ ## Troubleshooting
324
+
325
+ ### Common Issues
326
+
327
+ **"useOxyZeroConfig must be used within an OxyZeroConfigProvider"**
328
+ - Make sure your component is wrapped with `<OxyZeroConfigProvider>`
329
+
330
+ **"req.user is undefined"**
331
+ - Ensure the middleware is applied: `app.use('/api', createOxyAuth())`
332
+ - Check that the client sends `Authorization: Bearer <token>` header
333
+
334
+ **FormData Issues in React Native/Expo**
335
+ Add this import as the first line of your app entry file:
336
+ ```js
337
+ import 'react-native-url-polyfill/auto';
132
338
  ```
133
339
 
134
- ---
340
+ ### Getting Help
341
+
342
+ 1. Check the [Zero-Config Guide](./docs/zero-config.md) for complete examples
343
+ 2. Review [Troubleshooting Guide](./docs/troubleshooting.md) for common issues
344
+ 3. Open an issue on [GitHub](https://github.com/oxyhq/services/issues)
135
345
 
136
346
  ## Development
137
347
 
@@ -142,20 +352,17 @@ npm install
142
352
  # Build the library
143
353
  npm run build
144
354
 
145
- # Run tests
355
+ # Run tests
146
356
  npm test
147
-
148
- # Development mode
149
- npm run dev
150
357
  ```
151
358
 
152
359
  ## Integration
153
360
 
154
361
  This library works with:
155
- - **[Oxy API](../oxy-api/)** - The companion authentication server
156
- - **Express.js** - Built-in middleware support
157
- - **React/React Native** - UI components and hooks
158
- - **Next.js** - SSR/SSG authentication
362
+ - **[Oxy API](../api/)** - The companion authentication server
363
+ - **Express.js** - Built-in zero-config middleware support
364
+ - **React/React Native** - Zero-config UI components and hooks
365
+ - **Next.js** - SSR/SSG authentication support
159
366
 
160
367
  ## License
161
368
 
@@ -1396,22 +1396,6 @@ class OxyServices {
1396
1396
  });
1397
1397
  }
1398
1398
 
1399
- // Validate JWT format before attempting to decode
1400
- if (!this.isValidJwtFormat(token)) {
1401
- const error = {
1402
- message: 'Invalid token format',
1403
- code: 'INVALID_TOKEN_FORMAT',
1404
- status: 401
1405
- };
1406
- if (onError) {
1407
- return onError(error);
1408
- }
1409
- return res.status(401).json({
1410
- message: 'Invalid token format',
1411
- code: 'INVALID_TOKEN_FORMAT'
1412
- });
1413
- }
1414
-
1415
1399
  // Create a temporary OxyServices instance with the token to validate it
1416
1400
  const tempOxyServices = new OxyServices({
1417
1401
  baseURL: this.client.defaults.baseURL || ''
@@ -1441,8 +1425,6 @@ class OxyServices {
1441
1425
  const decoded = (0, _jwtDecode.jwtDecode)(token);
1442
1426
  userId = decoded.userId || decoded.id;
1443
1427
  } catch (decodeError) {
1444
- console.error('JWT decode error:', decodeError);
1445
- console.error('Token being decoded:', token.substring(0, 20) + '...');
1446
1428
  const error = {
1447
1429
  message: 'Invalid token payload',
1448
1430
  code: 'INVALID_PAYLOAD',
@@ -1520,14 +1502,6 @@ class OxyServices {
1520
1502
  };
1521
1503
  }
1522
1504
 
1523
- // Validate JWT format before attempting to decode
1524
- if (!this.isValidJwtFormat(token)) {
1525
- return {
1526
- valid: false,
1527
- error: 'Invalid token format'
1528
- };
1529
- }
1530
-
1531
1505
  // Create a temporary OxyServices instance with the token
1532
1506
  const tempOxyServices = new OxyServices({
1533
1507
  baseURL: this.client.defaults.baseURL || ''
@@ -1584,37 +1558,6 @@ class OxyServices {
1584
1558
  }
1585
1559
  }
1586
1560
 
1587
- /**
1588
- * Validate JWT token format
1589
- * @param token - The token to validate
1590
- * @returns Boolean indicating if the token has valid JWT format
1591
- */
1592
- isValidJwtFormat(token) {
1593
- if (!token || typeof token !== 'string') {
1594
- return false;
1595
- }
1596
-
1597
- // JWT tokens should have 3 parts separated by dots
1598
- const parts = token.split('.');
1599
- if (parts.length !== 3) {
1600
- return false;
1601
- }
1602
-
1603
- // Each part should be a valid base64 string
1604
- try {
1605
- parts.forEach(part => {
1606
- if (!part || part.trim() === '') {
1607
- throw new Error('Empty part');
1608
- }
1609
- // Try to decode base64 (this will throw if invalid)
1610
- Buffer.from(part, 'base64');
1611
- });
1612
- return true;
1613
- } catch (error) {
1614
- return false;
1615
- }
1616
- }
1617
-
1618
1561
  /**
1619
1562
  * Centralized error handling
1620
1563
  * @private