ryauth 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example ADDED
@@ -0,0 +1,7 @@
1
+ # RyAuth Configuration
2
+
3
+ # Access Token Secret (minimum 32 characters)
4
+ ACCESS_TOKEN_SECRET=your_32+_character_access_token_secret_here
5
+
6
+ # Refresh Token Secret (minimum 32 characters)
7
+ REFRESH_TOKEN_SECRET=your_32+_character_refresh_token_secret_here
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Your Name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,232 @@
1
+ # RyAuth
2
+
3
+ [![npm version](https://badge.fury.io/js/ryauth.svg)](https://badge.fury.io/js/ryauth)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen)](https://nodejs.org/)
6
+ [![Test Coverage](https://img.shields.io/badge/coverage-94%25-green)](https://github.com/ryanpereira49/RyAuth)
7
+ [![GitHub Issues](https://img.shields.io/github/issues/ryanpereira49/RyAuth)](https://github.com/ryanpereira49/RyAuth/issues)
8
+
9
+ A modern, secure, and database-agnostic authentication library for Node.js. Built with JWT tokens, Argon2 password hashing, and role-based access control (RBAC).
10
+
11
+ ## โœจ Features
12
+
13
+ - ๐Ÿ” **Secure Authentication** - JWT-based authentication with access and refresh tokens
14
+ - ๐Ÿ›ก๏ธ **Password Security** - Argon2 password hashing (winner of the 2015 Password Hashing Competition)
15
+ - ๐Ÿ”„ **Token Rotation** - Automatic refresh token rotation for enhanced security
16
+ - ๐Ÿ‘ฅ **Role-Based Access Control** - Fine-grained permissions and user roles
17
+ - ๐Ÿ—„๏ธ **Database Agnostic** - Adapter pattern supports any database (PostgreSQL, MongoDB, MySQL, etc.)
18
+ - ๐Ÿš€ **Modern JavaScript** - ES modules, async/await, and TypeScript-ready
19
+ - โœ… **Runtime Validation** - Zod schemas for input validation and type safety
20
+ - ๐Ÿงช **Comprehensive Testing** - 66 tests with 94% code coverage
21
+ - ๐Ÿ“š **Full Documentation** - Complete API reference and examples
22
+
23
+ ## ๐Ÿ“ฆ Installation
24
+
25
+ ```bash
26
+ npm install ryauth
27
+ # or
28
+ yarn add ryauth
29
+ # or
30
+ pnpm add ryauth
31
+ ```
32
+
33
+ ## ๐Ÿš€ Quick Start
34
+
35
+ ```javascript
36
+ import express from 'express';
37
+ import { createAuthMiddleware, AuthService, MemoryAdapter } from 'ryauth';
38
+
39
+ const app = express();
40
+ app.use(express.json());
41
+
42
+ // Initialize authentication
43
+ const adapter = new MemoryAdapter();
44
+ const authService = new AuthService(adapter);
45
+
46
+ // Create middleware
47
+ const authMiddleware = createAuthMiddleware({
48
+ accessTokenSecret: process.env.ACCESS_TOKEN_SECRET,
49
+ refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET
50
+ });
51
+
52
+ // Register endpoint
53
+ app.post('/auth/register', async (req, res) => {
54
+ try {
55
+ const { email, password } = req.body;
56
+ const result = await authService.register(email, password);
57
+ res.json(result);
58
+ } catch (error) {
59
+ res.status(400).json({ error: error.message });
60
+ }
61
+ });
62
+
63
+ // Login endpoint
64
+ app.post('/auth/login', async (req, res) => {
65
+ try {
66
+ const { email, password } = req.body;
67
+ const result = await authService.login(email, password);
68
+ res.json(result);
69
+ } catch (error) {
70
+ res.status(401).json({ error: error.message });
71
+ }
72
+ });
73
+
74
+ // Protected route
75
+ app.get('/api/profile', authMiddleware.authenticate, (req, res) => {
76
+ res.json({ user: req.user });
77
+ });
78
+
79
+ // Admin-only route
80
+ app.get('/api/admin', authMiddleware.authenticate, authMiddleware.authorize('admin'), (req, res) => {
81
+ res.json({ message: 'Welcome, admin!' });
82
+ });
83
+
84
+ app.listen(3000, () => {
85
+ console.log('Server running on port 3000');
86
+ });
87
+ ```
88
+
89
+ ## ๐Ÿ”ง Environment Setup
90
+
91
+ Create a `.env` file in your project root:
92
+
93
+ ```env
94
+ # Access Token Secret (minimum 32 characters)
95
+ ACCESS_TOKEN_SECRET=your_32+_character_access_token_secret_here
96
+
97
+ # Refresh Token Secret (minimum 32 characters)
98
+ REFRESH_TOKEN_SECRET=your_32+_character_refresh_token_secret_here
99
+ ```
100
+
101
+ ## ๐Ÿ—๏ธ Architecture
102
+
103
+ RyAuth uses a modular architecture designed for security and flexibility:
104
+
105
+ ```
106
+ src/
107
+ โ”œโ”€โ”€ core/
108
+ โ”‚ โ””โ”€โ”€ crypto.js # Argon2 & JOSE JWT operations
109
+ โ”œโ”€โ”€ adapters/
110
+ โ”‚ โ”œโ”€โ”€ base.js # Abstract database adapter interface
111
+ โ”‚ โ””โ”€โ”€ memory.js # In-memory adapter for testing
112
+ โ”œโ”€โ”€ middleware/
113
+ โ”‚ โ””โ”€โ”€ auth.js # Express middleware for JWT validation
114
+ โ””โ”€โ”€ services/
115
+ โ””โ”€โ”€ auth-service.js # Core authentication business logic
116
+ ```
117
+
118
+ ## ๐Ÿ“š API Overview
119
+
120
+ ### AuthService
121
+
122
+ The main service class that orchestrates authentication flows.
123
+
124
+ ```javascript
125
+ const authService = new AuthService(adapter);
126
+
127
+ // User management
128
+ await authService.register('user@example.com', 'password123');
129
+ await authService.login('user@example.com', 'password123');
130
+ await authService.refresh(refreshToken);
131
+ await authService.revokeRefreshToken(refreshToken);
132
+ ```
133
+
134
+ ### Middleware
135
+
136
+ Express.js middleware for authentication and authorization.
137
+
138
+ ```javascript
139
+ const authMiddleware = createAuthMiddleware(config);
140
+
141
+ // Authentication
142
+ app.get('/protected', authMiddleware.authenticate, handler);
143
+
144
+ // Authorization
145
+ app.get('/admin', authMiddleware.authenticate, authMiddleware.authorize('admin'), handler);
146
+ ```
147
+
148
+ ### Adapters
149
+
150
+ Database abstraction layer supporting multiple databases.
151
+
152
+ ```javascript
153
+ // Built-in MemoryAdapter for testing
154
+ const adapter = new MemoryAdapter();
155
+
156
+ // Custom adapter for PostgreSQL
157
+ class PostgreSQLAdapter extends BaseAdapter {
158
+ async findUserByEmail(email) { /* implementation */ }
159
+ async createUser(userData) { /* implementation */ }
160
+ // ... other required methods
161
+ }
162
+ ```
163
+
164
+ ## ๐Ÿงช Testing
165
+
166
+ ```bash
167
+ npm test
168
+ ```
169
+
170
+ RyAuth includes comprehensive test coverage:
171
+ - **66 tests** covering all functionality
172
+ - **94% code coverage**
173
+ - Unit tests for all core modules
174
+ - Integration tests for complete flows
175
+
176
+ ## ๐Ÿ“– Documentation
177
+
178
+ - **[API Reference](docs/api-reference.md)** - Complete API documentation
179
+ - **[Examples](docs/examples.md)** - Practical code examples and integrations
180
+ - **[Contributing Guide](CONTRIBUTING.md)** - Guidelines for contributors
181
+
182
+ ## ๐Ÿ”’ Security Features
183
+
184
+ - **Argon2 Password Hashing** - Memory-hard algorithm resistant to brute force attacks
185
+ - **JWT Token Rotation** - Automatic refresh token rotation prevents token theft
186
+ - **Session Management** - Ability to revoke refresh tokens
187
+ - **Input Validation** - Runtime validation with Zod schemas
188
+ - **Timing-Safe Comparison** - Prevents timing attacks during authentication
189
+ - **Secure Defaults** - 15-minute access tokens, 7-day refresh tokens
190
+
191
+ ## ๐Ÿค Contributing
192
+
193
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
194
+
195
+ ### Development Setup
196
+
197
+ ```bash
198
+ # Clone the repository
199
+ git clone https://github.com/ryanpereira49/RyAuth.git
200
+ cd RyAuth
201
+
202
+ # Install dependencies
203
+ npm install
204
+
205
+ # Copy environment template
206
+ cp .env.example .env
207
+
208
+ # Run tests
209
+ npm test
210
+ ```
211
+
212
+ ## ๐Ÿ“„ License
213
+
214
+ MIT License - see the [LICENSE](LICENSE) file for details.
215
+
216
+ ## ๐Ÿ™ Acknowledgments
217
+
218
+ - Built with [JOSE](https://github.com/panva/jose) for JWT operations
219
+ - Password hashing powered by [Argon2](https://github.com/ranisalt/node-argon2)
220
+ - Runtime validation with [Zod](https://github.com/colinhacks/zod)
221
+
222
+ ## ๐Ÿ“ž Support
223
+
224
+ - ๐Ÿ› [Issues](https://github.com/ryanpereira49/RyAuth/issues)
225
+ - ๐Ÿ’ฌ [Discussions](https://github.com/ryanpereira49/RyAuth/discussions)
226
+ - ๐Ÿ“ง Contact: ryanpereira499@gmail.com
227
+
228
+ ---
229
+
230
+ **Made with โค๏ธ for secure Node.js applications**
231
+
232
+ *RyAuth - Modern Authentication, Simplified.*
@@ -0,0 +1,203 @@
1
+ # API Reference
2
+
3
+ Complete API documentation for RyAuth authentication library.
4
+
5
+ ## AuthService
6
+
7
+ The main service class that orchestrates authentication flows.
8
+
9
+ ### Constructor
10
+
11
+ ```javascript
12
+ new AuthService(adapter)
13
+ ```
14
+
15
+ **Parameters:**
16
+ - `adapter` (BaseAdapter): Database adapter instance
17
+
18
+ ### Methods
19
+
20
+ #### `register(email, password)`
21
+
22
+ Register a new user account.
23
+
24
+ ```javascript
25
+ const result = await authService.register('user@example.com', 'password123');
26
+ ```
27
+
28
+ **Parameters:**
29
+ - `email` (string): User's email address
30
+ - `password` (string): User's password (minimum 8 characters)
31
+
32
+ **Returns:** `Promise<{success: boolean, userId: string}>`
33
+
34
+ **Throws:** Error for validation failures or duplicate users
35
+
36
+ #### `login(email, password)`
37
+
38
+ Authenticate a user and return tokens.
39
+
40
+ ```javascript
41
+ const result = await authService.login('user@example.com', 'password123');
42
+ ```
43
+
44
+ **Parameters:**
45
+ - `email` (string): User's email address
46
+ - `password` (string): User's password
47
+
48
+ **Returns:** `Promise<{success: boolean, accessToken: string, refreshToken: string, user: object}>`
49
+
50
+ **Throws:** Error for invalid credentials
51
+
52
+ #### `refresh(refreshToken)`
53
+
54
+ Refresh access and refresh tokens.
55
+
56
+ ```javascript
57
+ const result = await authService.refresh('refresh_token_here');
58
+ ```
59
+
60
+ **Parameters:**
61
+ - `refreshToken` (string): Valid refresh token
62
+
63
+ **Returns:** `Promise<{success: boolean, accessToken: string, refreshToken: string}>`
64
+
65
+ **Throws:** Error for invalid or expired tokens
66
+
67
+ #### `revokeRefreshToken(refreshToken)`
68
+
69
+ Revoke a refresh token (logout).
70
+
71
+ ```javascript
72
+ await authService.revokeRefreshToken('refresh_token_here');
73
+ ```
74
+
75
+ **Parameters:**
76
+ - `refreshToken` (string): Refresh token to revoke
77
+
78
+ **Returns:** `Promise<void>`
79
+
80
+ ## Middleware
81
+
82
+ Express.js middleware for JWT authentication and authorization.
83
+
84
+ ### `createAuthMiddleware(config)`
85
+
86
+ Create an authentication middleware instance.
87
+
88
+ ```javascript
89
+ const authMiddleware = createAuthMiddleware({
90
+ accessTokenSecret: process.env.ACCESS_TOKEN_SECRET,
91
+ refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET
92
+ });
93
+ ```
94
+
95
+ **Parameters:**
96
+ - `config` (object):
97
+ - `accessTokenSecret` (string): Secret for access tokens (min 32 chars)
98
+ - `refreshTokenSecret` (string): Secret for refresh tokens (min 32 chars)
99
+
100
+ **Returns:** AuthMiddleware instance with `authenticate` and `authorize` methods
101
+
102
+ ### `authenticate`
103
+
104
+ Middleware to verify JWT access tokens.
105
+
106
+ ```javascript
107
+ app.get('/protected', authMiddleware.authenticate, (req, res) => {
108
+ res.json({ user: req.user });
109
+ });
110
+ ```
111
+
112
+ Attaches `req.user` with user payload if token is valid.
113
+
114
+ ### `authorize(...roles)`
115
+
116
+ Middleware for role-based access control.
117
+
118
+ ```javascript
119
+ app.get('/admin', authMiddleware.authenticate, authMiddleware.authorize('admin'), (req, res) => {
120
+ res.json({ message: 'Admin access granted' });
121
+ });
122
+ ```
123
+
124
+ **Parameters:**
125
+ - `...roles` (string[]): Allowed roles
126
+
127
+ ## Adapters
128
+
129
+ Database abstraction layer using the adapter pattern.
130
+
131
+ ### BaseAdapter
132
+
133
+ Abstract base class for database adapters.
134
+
135
+ **Required Methods:**
136
+ - `findUserByEmail(email)`: Find user by email
137
+ - `createUser(userData)`: Create new user
138
+ - `saveRefreshToken(userId, token, expiresAt)`: Save refresh token
139
+ - `findRefreshToken(token)`: Find refresh token
140
+ - `revokeRefreshToken(token)`: Revoke refresh token
141
+ - `isRefreshTokenRevoked(token)`: Check if token is revoked
142
+
143
+ ### MemoryAdapter
144
+
145
+ In-memory adapter for development and testing.
146
+
147
+ ```javascript
148
+ import { MemoryAdapter } from 'ryauth';
149
+
150
+ const adapter = new MemoryAdapter();
151
+ ```
152
+
153
+ ## Crypto Utilities
154
+
155
+ Low-level cryptographic functions (advanced usage).
156
+
157
+ ### `hashPassword(plain)`
158
+
159
+ Hash a password with Argon2.
160
+
161
+ ```javascript
162
+ const hash = await hashPassword('password123');
163
+ ```
164
+
165
+ ### `verifyPassword(hash, plain)`
166
+
167
+ Verify a password against its hash.
168
+
169
+ ```javascript
170
+ const isValid = await verifyPassword(hash, 'password123');
171
+ ```
172
+
173
+ ### `signAccessToken(payload)`
174
+
175
+ Sign an access token (15-minute expiry).
176
+
177
+ ### `signRefreshToken(payload)`
178
+
179
+ Sign a refresh token (7-day expiry).
180
+
181
+ ### `verifyJWT(token, secret)`
182
+
183
+ Verify and decode a JWT token.
184
+
185
+ ## Error Handling
186
+
187
+ RyAuth throws descriptive errors for various failure conditions:
188
+
189
+ - **Validation Errors**: Invalid input data
190
+ - **Authentication Errors**: Invalid credentials, expired tokens
191
+ - **Authorization Errors**: Insufficient permissions
192
+ - **Adapter Errors**: Database operation failures
193
+
194
+ Always wrap operations in try-catch blocks:
195
+
196
+ ```javascript
197
+ try {
198
+ const result = await authService.login(email, password);
199
+ res.json(result);
200
+ } catch (error) {
201
+ res.status(400).json({ error: error.message });
202
+ }
203
+ ```
@@ -0,0 +1,225 @@
1
+ # Examples
2
+
3
+ Practical examples for integrating RyAuth into your applications.
4
+
5
+ ## Basic Express.js Setup
6
+
7
+ ```javascript
8
+ import express from 'express';
9
+ import { createAuthMiddleware, AuthService, MemoryAdapter } from 'ryauth';
10
+
11
+ const app = express();
12
+ app.use(express.json());
13
+
14
+ // Initialize
15
+ const adapter = new MemoryAdapter();
16
+ const authService = new AuthService(adapter);
17
+ const authMiddleware = createAuthMiddleware({
18
+ accessTokenSecret: process.env.ACCESS_TOKEN_SECRET,
19
+ refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET
20
+ });
21
+
22
+ // Routes
23
+ app.post('/auth/register', async (req, res) => {
24
+ try {
25
+ const { email, password } = req.body;
26
+ const result = await authService.register(email, password);
27
+ res.json(result);
28
+ } catch (error) {
29
+ res.status(400).json({ error: error.message });
30
+ }
31
+ });
32
+
33
+ app.post('/auth/login', async (req, res) => {
34
+ try {
35
+ const { email, password } = req.body;
36
+ const result = await authService.login(email, password);
37
+ res.json(result);
38
+ } catch (error) {
39
+ res.status(401).json({ error: error.message });
40
+ }
41
+ });
42
+
43
+ app.get('/api/profile', authMiddleware.authenticate, (req, res) => {
44
+ res.json({ user: req.user });
45
+ });
46
+
47
+ app.listen(3000);
48
+ ```
49
+
50
+ ## Role-Based Access Control
51
+
52
+ ```javascript
53
+ // Admin-only route
54
+ app.get('/api/admin/users',
55
+ authMiddleware.authenticate,
56
+ authMiddleware.authorize('admin'),
57
+ (req, res) => {
58
+ res.json({ users: [] }); // Return user list
59
+ }
60
+ );
61
+
62
+ // Multiple roles allowed
63
+ app.get('/api/content',
64
+ authMiddleware.authenticate,
65
+ authMiddleware.authorize('user', 'editor', 'admin'),
66
+ (req, res) => {
67
+ res.json({ content: 'Protected content' });
68
+ }
69
+ );
70
+ ```
71
+
72
+ ## Token Refresh
73
+
74
+ ```javascript
75
+ app.post('/auth/refresh', async (req, res) => {
76
+ try {
77
+ const { refreshToken } = req.body;
78
+ const result = await authService.refresh(refreshToken);
79
+ res.json(result);
80
+ } catch (error) {
81
+ res.status(401).json({ error: error.message });
82
+ }
83
+ });
84
+ ```
85
+
86
+ ## Logout (Token Revocation)
87
+
88
+ ```javascript
89
+ app.post('/auth/logout', authMiddleware.authenticate, async (req, res) => {
90
+ try {
91
+ // Get refresh token from request (could be in body, cookie, etc.)
92
+ const { refreshToken } = req.body;
93
+ await authService.revokeRefreshToken(refreshToken);
94
+ res.json({ success: true });
95
+ } catch (error) {
96
+ res.status(400).json({ error: error.message });
97
+ }
98
+ });
99
+ ```
100
+
101
+ ## Custom Database Adapter
102
+
103
+ ```javascript
104
+ import { BaseAdapter } from 'ryauth';
105
+
106
+ export class PostgreSQLAdapter extends BaseAdapter {
107
+ constructor(db) {
108
+ super();
109
+ this.db = db; // Your database connection
110
+ }
111
+
112
+ async findUserByEmail(email) {
113
+ const result = await this.db.query(
114
+ 'SELECT id, email, hashed_password, role FROM users WHERE email = $1',
115
+ [email]
116
+ );
117
+ return result.rows[0] || null;
118
+ }
119
+
120
+ async createUser(userData) {
121
+ const result = await this.db.query(
122
+ 'INSERT INTO users (email, hashed_password, role) VALUES ($1, $2, $3) RETURNING *',
123
+ [userData.email, userData.hashedPassword, userData.role]
124
+ );
125
+ return result.rows[0];
126
+ }
127
+
128
+ async saveRefreshToken(userId, token, expiresAt) {
129
+ await this.db.query(
130
+ 'INSERT INTO refresh_tokens (user_id, token, expires_at) VALUES ($1, $2, $3)',
131
+ [userId, token, expiresAt]
132
+ );
133
+ }
134
+
135
+ async findRefreshToken(token) {
136
+ const result = await this.db.query(
137
+ 'SELECT * FROM refresh_tokens WHERE token = $1 AND expires_at > NOW()',
138
+ [token]
139
+ );
140
+ return result.rows[0] || null;
141
+ }
142
+
143
+ async revokeRefreshToken(token) {
144
+ await this.db.query(
145
+ 'DELETE FROM refresh_tokens WHERE token = $1',
146
+ [token]
147
+ );
148
+ }
149
+
150
+ async isRefreshTokenRevoked(token) {
151
+ const result = await this.db.query(
152
+ 'SELECT 1 FROM refresh_tokens WHERE token = $1',
153
+ [token]
154
+ );
155
+ return result.rows.length === 0;
156
+ }
157
+ }
158
+ ```
159
+
160
+ ## Testing with RyAuth
161
+
162
+ ```javascript
163
+ import { AuthService, MemoryAdapter } from 'ryauth';
164
+
165
+ describe('Authentication', () => {
166
+ let authService;
167
+ let adapter;
168
+
169
+ beforeEach(() => {
170
+ adapter = new MemoryAdapter();
171
+ authService = new AuthService(adapter);
172
+ });
173
+
174
+ it('should register a new user', async () => {
175
+ const result = await authService.register('test@example.com', 'password123');
176
+ expect(result.success).toBe(true);
177
+ expect(result.userId).toBeDefined();
178
+ });
179
+
180
+ it('should login with correct credentials', async () => {
181
+ await authService.register('test@example.com', 'password123');
182
+ const result = await authService.login('test@example.com', 'password123');
183
+
184
+ expect(result.success).toBe(true);
185
+ expect(result.accessToken).toBeDefined();
186
+ expect(result.refreshToken).toBeDefined();
187
+ });
188
+ });
189
+ ```
190
+
191
+ ## Environment Configuration
192
+
193
+ ```javascript
194
+ // .env
195
+ ACCESS_TOKEN_SECRET=your_super_secret_access_token_key_here_minimum_32_chars
196
+ REFRESH_TOKEN_SECRET=your_super_secret_refresh_token_key_here_minimum_32_chars
197
+
198
+ // Generate secure secrets
199
+ node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
200
+ ```
201
+
202
+ ## Error Handling
203
+
204
+ ```javascript
205
+ // Always wrap auth operations in try-catch
206
+ app.post('/auth/register', async (req, res) => {
207
+ try {
208
+ const result = await authService.register(req.body.email, req.body.password);
209
+ res.json(result);
210
+ } catch (error) {
211
+ // Handle validation errors, duplicate users, etc.
212
+ res.status(400).json({ error: error.message });
213
+ }
214
+ });
215
+
216
+ app.post('/auth/login', async (req, res) => {
217
+ try {
218
+ const result = await authService.login(req.body.email, req.body.password);
219
+ res.json(result);
220
+ } catch (error) {
221
+ // Handle invalid credentials
222
+ res.status(401).json({ error: error.message });
223
+ }
224
+ });
225
+ ```
package/index.js ADDED
@@ -0,0 +1,15 @@
1
+ // RyAuth - Modern Authentication Library for Node.js
2
+ // Main entry point exporting all public APIs
3
+
4
+ // Core services
5
+ export { AuthService } from './src/services/auth-service.js';
6
+
7
+ // Middleware
8
+ export { createAuthMiddleware } from './src/middleware/auth.js';
9
+
10
+ // Adapters
11
+ export { BaseAdapter } from './src/adapters/base.js';
12
+ export { MemoryAdapter } from './src/adapters/memory.js';
13
+
14
+ // Core utilities (for advanced users)
15
+ export { hashPassword, verifyPassword, signAccessToken, signRefreshToken, verifyJWT } from './src/core/crypto.js';