@oxyhq/services 5.7.3 → 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 (37) hide show
  1. package/README.md +287 -80
  2. package/lib/commonjs/node/index.js +49 -2
  3. package/lib/commonjs/node/index.js.map +1 -1
  4. package/lib/commonjs/node/middleware.js +227 -0
  5. package/lib/commonjs/node/middleware.js.map +1 -0
  6. package/lib/commonjs/ui/index.js +16 -1
  7. package/lib/commonjs/ui/index.js.map +1 -1
  8. package/lib/commonjs/ui/zero-config/index.js +25 -0
  9. package/lib/commonjs/ui/zero-config/index.js.map +1 -0
  10. package/lib/commonjs/ui/zero-config/provider.js +278 -0
  11. package/lib/commonjs/ui/zero-config/provider.js.map +1 -0
  12. package/lib/module/node/index.js +11 -1
  13. package/lib/module/node/index.js.map +1 -1
  14. package/lib/module/node/middleware.js +199 -0
  15. package/lib/module/node/middleware.js.map +1 -0
  16. package/lib/module/ui/index.js +16 -1
  17. package/lib/module/ui/index.js.map +1 -1
  18. package/lib/module/ui/zero-config/index.js +8 -0
  19. package/lib/module/ui/zero-config/index.js.map +1 -0
  20. package/lib/module/ui/zero-config/provider.js +270 -0
  21. package/lib/module/ui/zero-config/provider.js.map +1 -0
  22. package/lib/typescript/node/index.d.ts +7 -1
  23. package/lib/typescript/node/index.d.ts.map +1 -1
  24. package/lib/typescript/node/middleware.d.ts +92 -0
  25. package/lib/typescript/node/middleware.d.ts.map +1 -0
  26. package/lib/typescript/ui/index.d.ts +2 -1
  27. package/lib/typescript/ui/index.d.ts.map +1 -1
  28. package/lib/typescript/ui/zero-config/index.d.ts +5 -0
  29. package/lib/typescript/ui/zero-config/index.d.ts.map +1 -0
  30. package/lib/typescript/ui/zero-config/provider.d.ts +84 -0
  31. package/lib/typescript/ui/zero-config/provider.d.ts.map +1 -0
  32. package/package.json +6 -1
  33. package/src/node/index.ts +17 -1
  34. package/src/node/middleware.ts +234 -0
  35. package/src/ui/index.ts +19 -1
  36. package/src/ui/zero-config/index.ts +11 -0
  37. package/src/ui/zero-config/provider.tsx +310 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Zero-config Express middleware for OxyHQ Services authentication
3
+ *
4
+ * This provides a simple, one-line solution for adding authentication to Express apps.
5
+ * Simply import and use: app.use('/api', createOxyAuth())
6
+ */
7
+ import { ApiError } from '../models/interfaces';
8
+ export interface OxyAuthConfig {
9
+ /** Base URL of your Oxy API server */
10
+ baseURL?: string;
11
+ /** Whether to load full user data (default: true) */
12
+ loadUser?: boolean;
13
+ /** Routes that don't require authentication */
14
+ publicPaths?: string[];
15
+ /** Custom error handler */
16
+ onError?: (error: ApiError, req: any, res: any) => void;
17
+ }
18
+ export interface AuthenticatedRequest {
19
+ user?: any;
20
+ userId?: string;
21
+ accessToken?: string;
22
+ }
23
+ /**
24
+ * Creates zero-config authentication middleware for Express.js
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import express from 'express';
29
+ * import { createOxyAuth } from '@oxyhq/services/node';
30
+ *
31
+ * const app = express();
32
+ *
33
+ * // Zero-config auth for all /api routes
34
+ * app.use('/api', createOxyAuth());
35
+ *
36
+ * // Now all routes under /api automatically have req.user available
37
+ * app.get('/api/profile', (req, res) => {
38
+ * res.json({ user: req.user }); // req.user is automatically available
39
+ * });
40
+ * ```
41
+ */
42
+ export declare function createOxyAuth(config?: OxyAuthConfig): (req: any, res: any, next: any) => Promise<any>;
43
+ /**
44
+ * Creates optional authentication middleware
45
+ * This middleware will attach user data if a valid token is present, but won't fail if missing
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * import { createOptionalOxyAuth } from '@oxyhq/services/node';
50
+ *
51
+ * app.use('/api', createOptionalOxyAuth());
52
+ *
53
+ * app.get('/api/content', (req, res) => {
54
+ * if (req.user) {
55
+ * // User is authenticated, show personalized content
56
+ * res.json({ content: 'personalized', user: req.user });
57
+ * } else {
58
+ * // Anonymous user, show public content
59
+ * res.json({ content: 'public' });
60
+ * }
61
+ * });
62
+ * ```
63
+ */
64
+ export declare function createOptionalOxyAuth(config?: OxyAuthConfig): (req: any, res: any, next: any) => Promise<any>;
65
+ /**
66
+ * Utility function to quickly set up a complete Express app with authentication
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * import { createOxyExpressApp } from '@oxyhq/services/node';
71
+ *
72
+ * const app = createOxyExpressApp();
73
+ *
74
+ * // All routes automatically have authentication and req.user available
75
+ * app.get('/api/profile', (req, res) => {
76
+ * res.json({ user: req.user });
77
+ * });
78
+ *
79
+ * app.listen(3000);
80
+ * ```
81
+ */
82
+ export declare function createOxyExpressApp(config?: OxyAuthConfig & {
83
+ /** Express app configuration */
84
+ cors?: boolean;
85
+ /** JSON body parser limit */
86
+ jsonLimit?: string;
87
+ /** Additional middleware to apply */
88
+ middleware?: any[];
89
+ }): void;
90
+ export { OxyServices } from '../core';
91
+ export * from '../models/interfaces';
92
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../src/node/middleware.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,aAAkB,IAUxC,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,kBA+E5C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,GAAE,aAAkB,IAQhD,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,kBAgC5C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,aAAa,GAAG;IAC1D,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;CACf,QAKL;AAGD,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,cAAc,sBAAsB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  declare let OxyProvider: any, OxySignInButton: any, OxyLogo: any, Avatar: any, FollowButton: any, OxyPayButton: any, FontLoader: any, setupFonts: any, OxyIcon: any, useOxy: any, OxyContextProvider: any, OxyContextState: any, OxyContextProviderProps: any, useFollow: any, ProfileScreen: any, OxyRouter: any, useAuthStore: any, fontFamilies: any, fontStyles: any, toast: any;
2
- export { OxyProvider, OxySignInButton, OxyLogo, Avatar, FollowButton, OxyPayButton, FontLoader, setupFonts, OxyIcon, useOxy, OxyContextProvider, OxyContextState, OxyContextProviderProps, useFollow, ProfileScreen, OxyRouter, useAuthStore, fontFamilies, fontStyles, toast };
2
+ declare let OxyZeroConfigProvider: any, useOxyZeroConfig: any, useOxyApi: any;
3
+ export { OxyProvider, OxySignInButton, OxyLogo, Avatar, FollowButton, OxyPayButton, FontLoader, setupFonts, OxyIcon, useOxy, OxyContextProvider, OxyContextState, OxyContextProviderProps, useFollow, ProfileScreen, OxyRouter, useAuthStore, fontFamilies, fontStyles, toast, OxyZeroConfigProvider, useOxyZeroConfig, useOxyApi };
3
4
  export { OxyServices } from '../core';
4
5
  export type { User, LoginResponse, ApiError } from '../models/interfaces';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/index.ts"],"names":[],"mappings":"AASA,QAAA,IAAI,WAAW,KAAA,EAAE,eAAe,KAAA,EAAE,OAAO,KAAA,EAAE,MAAM,KAAA,EAAE,YAAY,KAAA,EAAE,YAAY,KAAA,EAAE,UAAU,KAAA,EAAE,UAAU,KAAA,EAAE,OAAO,KAAA,EAAE,MAAM,KAAA,EAA8H,kBAAkB,KAAA,EAAE,eAAe,KAAA,EAAE,uBAAuB,KAAA,EAAE,SAAS,KAAA,EAAE,aAAa,KAAA,EAAE,SAAS,KAAA,EAAE,YAAY,KAAA,EAAE,YAAY,KAAA,EAAE,UAAU,KAAA,EAAE,KAAK,KAAA,CAAC;AAiDrY,OAAO,EACL,WAAW,EACX,eAAe,EACf,OAAO,EACP,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,EACV,OAAO,EACP,MAAM,EACN,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,SAAS,EACT,aAAa,EACb,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,KAAK,EACN,CAAC;AAGF,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/index.ts"],"names":[],"mappings":"AASA,QAAA,IAAI,WAAW,KAAA,EAAE,eAAe,KAAA,EAAE,OAAO,KAAA,EAAE,MAAM,KAAA,EAAE,YAAY,KAAA,EAAE,YAAY,KAAA,EAAE,UAAU,KAAA,EAAE,UAAU,KAAA,EAAE,OAAO,KAAA,EAAE,MAAM,KAAA,EAA8H,kBAAkB,KAAA,EAAE,eAAe,KAAA,EAAE,uBAAuB,KAAA,EAAE,SAAS,KAAA,EAAE,aAAa,KAAA,EAAE,SAAS,KAAA,EAAE,YAAY,KAAA,EAAE,YAAY,KAAA,EAAE,UAAU,KAAA,EAAE,KAAK,KAAA,CAAC;AAGrY,QAAA,IAAI,qBAAqB,KAAA,EAAE,gBAAgB,KAAA,EAAE,SAAS,KAAA,CAAC;AA2DvD,OAAO,EACL,WAAW,EACX,eAAe,EACf,OAAO,EACP,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,EACV,OAAO,EACP,MAAM,EACN,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,SAAS,EACT,aAAa,EACb,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,KAAK,EAGL,qBAAqB,EACrB,gBAAgB,EAChB,SAAS,EACV,CAAC;AAGF,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Zero-config exports for OxyHQ Services
3
+ */
4
+ export { OxyZeroConfigProvider, useOxyZeroConfig, useOxyApi, type OxyZeroConfigState, type OxyZeroConfigProviderProps } from './provider';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/zero-config/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,SAAS,EACT,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAChC,MAAM,YAAY,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Zero-config OxyHQ Provider and Hook for React/React Native
3
+ *
4
+ * This provides a simplified, one-line setup for frontend authentication
5
+ * with automatic token management and API integration.
6
+ */
7
+ import React, { ReactNode } from 'react';
8
+ import { OxyServices } from '../../core';
9
+ import { User } from '../../models/interfaces';
10
+ export interface OxyZeroConfigState {
11
+ user: User | null;
12
+ isAuthenticated: boolean;
13
+ isLoading: boolean;
14
+ error: string | null;
15
+ login: (username: string, password: string) => Promise<User>;
16
+ logout: () => Promise<void>;
17
+ register: (username: string, email: string, password: string) => Promise<User>;
18
+ api: OxyServices;
19
+ }
20
+ export interface OxyZeroConfigProviderProps {
21
+ children: ReactNode;
22
+ /** Base URL of your Oxy API server (defaults to process.env.REACT_APP_OXY_API_URL or http://localhost:3001) */
23
+ apiUrl?: string;
24
+ /** Called when authentication state changes */
25
+ onAuthChange?: (user: User | null) => void;
26
+ /** Storage key prefix (default: 'oxy_zero') */
27
+ storagePrefix?: string;
28
+ }
29
+ /**
30
+ * Zero-config provider for OxyHQ Services
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * import { OxyZeroConfigProvider } from '@oxyhq/services/ui';
35
+ *
36
+ * function App() {
37
+ * return (
38
+ * <OxyZeroConfigProvider>
39
+ * <MyApp />
40
+ * </OxyZeroConfigProvider>
41
+ * );
42
+ * }
43
+ * ```
44
+ */
45
+ export declare const OxyZeroConfigProvider: React.FC<OxyZeroConfigProviderProps>;
46
+ /**
47
+ * Zero-config hook for OxyHQ Services
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * function MyComponent() {
52
+ * const { user, login, logout, isAuthenticated } = useOxyZeroConfig();
53
+ *
54
+ * const handleLogin = () => {
55
+ * login('username', 'password');
56
+ * };
57
+ *
58
+ * if (isAuthenticated) {
59
+ * return <div>Welcome, {user?.username}!</div>;
60
+ * }
61
+ *
62
+ * return <button onClick={handleLogin}>Login</button>;
63
+ * }
64
+ * ```
65
+ */
66
+ export declare const useOxyZeroConfig: () => OxyZeroConfigState;
67
+ /**
68
+ * Hook for automatic API client with authentication
69
+ * This automatically includes the auth token in requests
70
+ *
71
+ * @example
72
+ * ```tsx
73
+ * function ProfileComponent() {
74
+ * const api = useOxyApi();
75
+ *
76
+ * const updateProfile = async (data) => {
77
+ * const user = await api.updateProfile(data);
78
+ * // Token is automatically included
79
+ * };
80
+ * }
81
+ * ```
82
+ */
83
+ export declare const useOxyApi: () => OxyServices;
84
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../src/ui/zero-config/provider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,EAAkD,SAAS,EAAe,MAAM,OAAO,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,IAAI,EAAiB,MAAM,yBAAyB,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IAEjC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAGrB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAG/E,GAAG,EAAE,WAAW,CAAC;CAClB;AAID,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,SAAS,CAAC;IACpB,+GAA+G;IAC/G,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CA6MtE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,gBAAgB,QAAO,kBAMnC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,SAAS,QAAO,WAG5B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/services",
3
- "version": "5.7.3",
3
+ "version": "5.7.4",
4
4
  "description": "Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -23,6 +23,11 @@
23
23
  "require": "./lib/commonjs/ui/index.js",
24
24
  "types": "./lib/typescript/ui/index.d.ts"
25
25
  },
26
+ "./node": {
27
+ "import": "./lib/module/node/index.js",
28
+ "require": "./lib/commonjs/node/index.js",
29
+ "types": "./lib/typescript/node/index.d.ts"
30
+ },
26
31
  "./full": {
27
32
  "import": "./lib/module/index.js",
28
33
  "require": "./lib/commonjs/index.js",
package/src/node/index.ts CHANGED
@@ -1,7 +1,19 @@
1
1
  /**
2
- * OxyHQServices Node.js Entry Point
2
+ * Node.js-specific exports for OxyHQ Services
3
+ *
4
+ * This module provides zero-config Express.js middleware and utilities
5
+ * for backend integration with OxyHQ Services.
3
6
  */
4
7
 
8
+ // Export the zero-config middleware
9
+ export {
10
+ createOxyAuth,
11
+ createOptionalOxyAuth,
12
+ createOxyExpressApp,
13
+ type OxyAuthConfig,
14
+ type AuthenticatedRequest
15
+ } from './middleware';
16
+
5
17
  // ------------- Core Imports -------------
6
18
  import { OxyServices, OXY_CLOUD_URL } from '../core'; // Adjusted path
7
19
  import { createAuth } from './createAuth';
@@ -16,6 +28,10 @@ export { createAuth };
16
28
  // ------------- Model Exports -------------
17
29
  export { Models }; // Export all models as a namespace
18
30
  export * from '../models/interfaces'; // Export all models directly
31
+ export * from '../models/secureSession';
32
+
33
+ // Re-export utilities
34
+ export { DeviceManager } from '../utils/deviceManager';
19
35
 
20
36
  // Default export for consistency or specific use cases if needed
21
37
  export default OxyServices;
@@ -0,0 +1,234 @@
1
+ /**
2
+ * Zero-config Express middleware for OxyHQ Services authentication
3
+ *
4
+ * This provides a simple, one-line solution for adding authentication to Express apps.
5
+ * Simply import and use: app.use('/api', createOxyAuth())
6
+ */
7
+
8
+ import { OxyServices } from '../core';
9
+ import { ApiError } from '../models/interfaces';
10
+
11
+ export interface OxyAuthConfig {
12
+ /** Base URL of your Oxy API server */
13
+ baseURL?: string;
14
+ /** Whether to load full user data (default: true) */
15
+ loadUser?: boolean;
16
+ /** Routes that don't require authentication */
17
+ publicPaths?: string[];
18
+ /** Custom error handler */
19
+ onError?: (error: ApiError, req: any, res: any) => void;
20
+ }
21
+
22
+ export interface AuthenticatedRequest {
23
+ user?: any;
24
+ userId?: string;
25
+ accessToken?: string;
26
+ }
27
+
28
+ /**
29
+ * Creates zero-config authentication middleware for Express.js
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * import express from 'express';
34
+ * import { createOxyAuth } from '@oxyhq/services/node';
35
+ *
36
+ * const app = express();
37
+ *
38
+ * // Zero-config auth for all /api routes
39
+ * app.use('/api', createOxyAuth());
40
+ *
41
+ * // Now all routes under /api automatically have req.user available
42
+ * app.get('/api/profile', (req, res) => {
43
+ * res.json({ user: req.user }); // req.user is automatically available
44
+ * });
45
+ * ```
46
+ */
47
+ export function createOxyAuth(config: OxyAuthConfig = {}) {
48
+ const {
49
+ baseURL = process.env.OXY_API_URL || 'http://localhost:3001',
50
+ loadUser = true,
51
+ publicPaths = [],
52
+ onError
53
+ } = config;
54
+
55
+ const oxy = new OxyServices({ baseURL });
56
+
57
+ return async (req: any, res: any, next: any) => {
58
+ // Check if this is a public path
59
+ const isPublicPath = publicPaths.some(path =>
60
+ req.path === path || req.path.startsWith(path + '/')
61
+ );
62
+
63
+ if (isPublicPath) {
64
+ return next();
65
+ }
66
+
67
+ try {
68
+ const authHeader = req.headers['authorization'];
69
+ const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
70
+
71
+ if (!token) {
72
+ const error: ApiError = {
73
+ message: 'Access token required',
74
+ code: 'MISSING_TOKEN',
75
+ status: 401
76
+ };
77
+
78
+ if (onError) {
79
+ return onError(error, req, res);
80
+ }
81
+
82
+ return res.status(401).json({
83
+ error: 'Access token required',
84
+ code: 'MISSING_TOKEN'
85
+ });
86
+ }
87
+
88
+ // Validate token using the OxyServices client
89
+ const authResult = await oxy.authenticateToken(token);
90
+
91
+ if (!authResult.valid) {
92
+ const error: ApiError = {
93
+ message: authResult.error || 'Invalid token',
94
+ code: 'INVALID_TOKEN',
95
+ status: 403
96
+ };
97
+
98
+ if (onError) {
99
+ return onError(error, req, res);
100
+ }
101
+
102
+ return res.status(403).json({
103
+ error: authResult.error || 'Invalid token',
104
+ code: 'INVALID_TOKEN'
105
+ });
106
+ }
107
+
108
+ // Attach user data to request
109
+ req.userId = authResult.userId;
110
+ req.accessToken = token;
111
+
112
+ if (loadUser && authResult.user) {
113
+ req.user = authResult.user;
114
+ } else {
115
+ req.user = { id: authResult.userId };
116
+ }
117
+
118
+ next();
119
+ } catch (error: any) {
120
+ const apiError: ApiError = {
121
+ message: error.message || 'Authentication failed',
122
+ code: error.code || 'AUTH_ERROR',
123
+ status: error.status || 500
124
+ };
125
+
126
+ if (onError) {
127
+ return onError(apiError, req, res);
128
+ }
129
+
130
+ res.status(apiError.status).json({
131
+ error: apiError.message,
132
+ code: apiError.code
133
+ });
134
+ }
135
+ };
136
+ }
137
+
138
+ /**
139
+ * Creates optional authentication middleware
140
+ * This middleware will attach user data if a valid token is present, but won't fail if missing
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * import { createOptionalOxyAuth } from '@oxyhq/services/node';
145
+ *
146
+ * app.use('/api', createOptionalOxyAuth());
147
+ *
148
+ * app.get('/api/content', (req, res) => {
149
+ * if (req.user) {
150
+ * // User is authenticated, show personalized content
151
+ * res.json({ content: 'personalized', user: req.user });
152
+ * } else {
153
+ * // Anonymous user, show public content
154
+ * res.json({ content: 'public' });
155
+ * }
156
+ * });
157
+ * ```
158
+ */
159
+ export function createOptionalOxyAuth(config: OxyAuthConfig = {}) {
160
+ const {
161
+ baseURL = process.env.OXY_API_URL || 'http://localhost:3001',
162
+ loadUser = true
163
+ } = config;
164
+
165
+ const oxy = new OxyServices({ baseURL });
166
+
167
+ return async (req: any, res: any, next: any) => {
168
+ try {
169
+ const authHeader = req.headers['authorization'];
170
+ const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
171
+
172
+ if (!token) {
173
+ // No token provided, continue without authentication
174
+ return next();
175
+ }
176
+
177
+ // Validate token using the OxyServices client
178
+ const authResult = await oxy.authenticateToken(token);
179
+
180
+ if (authResult.valid) {
181
+ // Attach user data to request if token is valid
182
+ req.userId = authResult.userId;
183
+ req.accessToken = token;
184
+
185
+ if (loadUser && authResult.user) {
186
+ req.user = authResult.user;
187
+ } else {
188
+ req.user = { id: authResult.userId };
189
+ }
190
+ }
191
+
192
+ next();
193
+ } catch (error) {
194
+ // If there's an error, continue without authentication
195
+ // This makes the middleware truly optional
196
+ next();
197
+ }
198
+ };
199
+ }
200
+
201
+ /**
202
+ * Utility function to quickly set up a complete Express app with authentication
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * import { createOxyExpressApp } from '@oxyhq/services/node';
207
+ *
208
+ * const app = createOxyExpressApp();
209
+ *
210
+ * // All routes automatically have authentication and req.user available
211
+ * app.get('/api/profile', (req, res) => {
212
+ * res.json({ user: req.user });
213
+ * });
214
+ *
215
+ * app.listen(3000);
216
+ * ```
217
+ */
218
+ export function createOxyExpressApp(config: OxyAuthConfig & {
219
+ /** Express app configuration */
220
+ cors?: boolean;
221
+ /** JSON body parser limit */
222
+ jsonLimit?: string;
223
+ /** Additional middleware to apply */
224
+ middleware?: any[];
225
+ } = {}) {
226
+ // This is a lightweight helper - users should import express themselves
227
+ // We'll provide the middleware setup instructions instead
228
+
229
+ throw new Error('createOxyExpressApp is not implemented yet. Please use createOxyAuth() middleware with your existing Express app.');
230
+ }
231
+
232
+ // Re-export for convenience
233
+ export { OxyServices } from '../core';
234
+ export * from '../models/interfaces';
package/src/ui/index.ts CHANGED
@@ -9,6 +9,9 @@ import isFrontend from './isFrontend';
9
9
  // Real UI exports
10
10
  let OxyProvider, OxySignInButton, OxyLogo, Avatar, FollowButton, OxyPayButton, FontLoader, setupFonts, OxyIcon, useOxy, useOxyAuth, useOxyUser, useOxyKarma, useOxyPayments, useOxyDevices, useOxyNotifications, useOxySocket, useOxyQR, useOxyIAP, OxyContextProvider, OxyContextState, OxyContextProviderProps, useFollow, ProfileScreen, OxyRouter, useAuthStore, fontFamilies, fontStyles, toast;
11
11
 
12
+ // Zero-config exports
13
+ let OxyZeroConfigProvider, useOxyZeroConfig, useOxyApi;
14
+
12
15
  if (isFrontend) {
13
16
  OxyProvider = require('./components/OxyProvider').default;
14
17
  OxySignInButton = require('./components/OxySignInButton').default;
@@ -30,6 +33,11 @@ if (isFrontend) {
30
33
  fontFamilies = require('./styles/fonts').fontFamilies;
31
34
  fontStyles = require('./styles/fonts').fontStyles;
32
35
  toast = require('../lib/sonner').toast;
36
+
37
+ // Zero-config components
38
+ OxyZeroConfigProvider = require('./zero-config').OxyZeroConfigProvider;
39
+ useOxyZeroConfig = require('./zero-config').useOxyZeroConfig;
40
+ useOxyApi = require('./zero-config').useOxyApi;
33
41
  } else {
34
42
  // Backend: no-op fallbacks
35
43
  const noopComponent = () => null;
@@ -54,6 +62,11 @@ if (isFrontend) {
54
62
  fontFamilies = {};
55
63
  fontStyles = {};
56
64
  toast = () => {};
65
+
66
+ // Zero-config no-ops
67
+ OxyZeroConfigProvider = noopComponent;
68
+ useOxyZeroConfig = noopHook;
69
+ useOxyApi = () => ({});
57
70
  }
58
71
 
59
72
  export {
@@ -76,7 +89,12 @@ export {
76
89
  useAuthStore,
77
90
  fontFamilies,
78
91
  fontStyles,
79
- toast
92
+ toast,
93
+
94
+ // Zero-config exports
95
+ OxyZeroConfigProvider,
96
+ useOxyZeroConfig,
97
+ useOxyApi
80
98
  };
81
99
 
82
100
  // Re-export core services for convenience in UI context
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Zero-config exports for OxyHQ Services
3
+ */
4
+
5
+ export {
6
+ OxyZeroConfigProvider,
7
+ useOxyZeroConfig,
8
+ useOxyApi,
9
+ type OxyZeroConfigState,
10
+ type OxyZeroConfigProviderProps
11
+ } from './provider';