devdad-express-utils 1.5.0 → 1.7.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/README.md +88 -8
- package/dist/DatabaseConnection.d.ts +10 -1
- package/dist/DatabaseConnection.js +39 -10
- package/dist/responseFormatter.d.ts +37 -2
- package/dist/responseFormatter.js +48 -3
- package/package.json +1 -1
- package/dist/AppError.1.d.ts +0 -0
- package/dist/AppError.1.js +0 -1
- package/dist/AppError.2.d.ts +0 -0
- package/dist/AppError.2.js +0 -1
- package/dist/authWrapper.d.ts +0 -17
- package/dist/authWrapper.js +0 -48
- package/dist/validateRequest.d.ts +0 -9
- package/dist/validateRequest.js +0 -19
package/README.md
CHANGED
|
@@ -54,10 +54,10 @@ throw new AppError("Validation failed", 400, ["Email is required"]);
|
|
|
54
54
|
|
|
55
55
|
### Response Formatting
|
|
56
56
|
|
|
57
|
-
Standardize API responses with consistent JSON structure.
|
|
57
|
+
Standardize API responses with consistent JSON structure and automatic response sending.
|
|
58
58
|
|
|
59
59
|
```typescript
|
|
60
|
-
import { sendSuccess, sendError
|
|
60
|
+
import { sendSuccess, sendError } from "devdad-express-utils";
|
|
61
61
|
|
|
62
62
|
// Success response
|
|
63
63
|
sendSuccess(res, { id: 1, name: "John" }, "User fetched", 200);
|
|
@@ -66,26 +66,86 @@ sendSuccess(res, { id: 1, name: "John" }, "User fetched", 200);
|
|
|
66
66
|
sendSuccess(res, { id: 1, name: "John" })
|
|
67
67
|
.cookie("session", "abc123")
|
|
68
68
|
.setHeader("X-Custom", "value");
|
|
69
|
+
// Response sent automatically! 🎉
|
|
69
70
|
|
|
70
71
|
// Error response
|
|
71
72
|
sendError(res, "User not found", 404);
|
|
72
73
|
```
|
|
73
74
|
|
|
75
|
+
#### Response Format
|
|
76
|
+
|
|
77
|
+
All responses include a `success` field by default:
|
|
78
|
+
|
|
79
|
+
**Success Response:**
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"status": "success",
|
|
84
|
+
"success": true,
|
|
85
|
+
"message": "User fetched",
|
|
86
|
+
"data": { "id": 1, "name": "John" }
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Error Response:**
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"status": "error",
|
|
95
|
+
"success": false,
|
|
96
|
+
"message": "User not found"
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Method Chaining
|
|
101
|
+
|
|
102
|
+
`sendSuccess` returns the Express response object, allowing you to chain any Express response methods:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
sendSuccess(res, { token: "abc123" }, "Login successful", 200)
|
|
106
|
+
.cookie("authToken", "abc123", { httpOnly: true, secure: true })
|
|
107
|
+
.header("X-Rate-Limit-Remaining", "99")
|
|
108
|
+
.status(200); // Can even override status
|
|
109
|
+
// Response automatically sent after chaining completes
|
|
110
|
+
```
|
|
111
|
+
|
|
74
112
|
### Database Connection
|
|
75
113
|
|
|
76
|
-
MongoDB connection utility with automatic reconnection and retry logic.
|
|
114
|
+
MongoDB connection utility with automatic reconnection, exponential backoff, and configurable retry logic.
|
|
77
115
|
|
|
78
116
|
```typescript
|
|
79
|
-
import {
|
|
117
|
+
import {
|
|
118
|
+
connectDB,
|
|
119
|
+
getDBStatus,
|
|
120
|
+
resetDBConnection,
|
|
121
|
+
} from "devdad-express-utils";
|
|
80
122
|
|
|
81
123
|
// Connect to MongoDB (ensure MONGO_URI is set in environment)
|
|
82
124
|
await connectDB();
|
|
83
125
|
|
|
84
126
|
// Check connection status
|
|
85
127
|
const status = getDBStatus();
|
|
86
|
-
console.log(status); // { isConnected: true, readyState: 1, host: '...', name: '...' }
|
|
128
|
+
console.log(status); // { isConnected: true, readyState: 1, host: '...', name: '...', retryCount: 0 }
|
|
129
|
+
|
|
130
|
+
// Manually reset and retry (useful after Docker container restarts)
|
|
131
|
+
await resetDBConnection();
|
|
87
132
|
```
|
|
88
133
|
|
|
134
|
+
#### Environment Variables
|
|
135
|
+
|
|
136
|
+
- **MONGO_URI**: MongoDB connection string (required)
|
|
137
|
+
- **DB_MAX_RETRIES**: Maximum connection retry attempts (default: 10)
|
|
138
|
+
- **DB_RETRY_INTERVAL**: Initial retry interval in milliseconds (default: 3000)
|
|
139
|
+
- **NODE_ENV**: Set to 'production' to exit after max retries, 'development' to keep process alive
|
|
140
|
+
|
|
141
|
+
#### Retry Behavior
|
|
142
|
+
|
|
143
|
+
- **Exponential backoff**: Retry intervals increase exponentially (3s → 6s → 12s → 24s → 30s max)
|
|
144
|
+
- **Random jitter**: Adds up to 1 second of random delay to prevent thundering herd
|
|
145
|
+
- **Docker-friendly**: Higher default retry count (10) accommodates container startup times
|
|
146
|
+
- **Development mode**: Process stays alive after max retries for manual recovery
|
|
147
|
+
- **Production mode**: Process exits after max retries to allow container restart
|
|
148
|
+
|
|
89
149
|
### Logging
|
|
90
150
|
|
|
91
151
|
Winston-based logger with configurable service name and environment-aware transports.
|
|
@@ -197,20 +257,32 @@ errorHandler(err: any, req: Request, res: Response, next: NextFunction) => void
|
|
|
197
257
|
|
|
198
258
|
### sendSuccess
|
|
199
259
|
|
|
200
|
-
Sends a standardized success response. Returns the Response object for
|
|
260
|
+
Sends a standardized success response with automatic sending after method chaining. Returns the Response object for chaining Express response methods like `.cookie()`, `.header()`, etc.
|
|
201
261
|
|
|
202
262
|
```typescript
|
|
203
263
|
sendSuccess(res: Response, data: any, message?: string, statusCode?: number) => Response
|
|
204
264
|
```
|
|
205
265
|
|
|
266
|
+
**Features:**
|
|
267
|
+
|
|
268
|
+
- Includes `success: true` field by default
|
|
269
|
+
- Automatically sends response after chaining completes
|
|
270
|
+
- Supports all Express response method chaining
|
|
271
|
+
- No extra `.send()` call needed
|
|
272
|
+
|
|
206
273
|
### sendError
|
|
207
274
|
|
|
208
|
-
Sends a standardized error response.
|
|
275
|
+
Sends a standardized error response immediately.
|
|
209
276
|
|
|
210
277
|
```typescript
|
|
211
278
|
sendError(res: Response, message: string, statusCode?: number, data?: any) => void
|
|
212
279
|
```
|
|
213
280
|
|
|
281
|
+
**Features:**
|
|
282
|
+
|
|
283
|
+
- Includes `success: false` field by default
|
|
284
|
+
- Sends response immediately (no chaining needed for errors)
|
|
285
|
+
|
|
214
286
|
### connectDB
|
|
215
287
|
|
|
216
288
|
Connects to MongoDB with retry logic and automatic reconnection.
|
|
@@ -224,7 +296,15 @@ connectDB() => Promise<void>
|
|
|
224
296
|
Gets the current MongoDB connection status.
|
|
225
297
|
|
|
226
298
|
```typescript
|
|
227
|
-
getDBStatus() => { isConnected: boolean; readyState: number; host: string; name: string; }
|
|
299
|
+
getDBStatus() => { isConnected: boolean; readyState: number; host: string; name: string; retryCount: number; }
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### resetDBConnection
|
|
303
|
+
|
|
304
|
+
Manually resets retry count and attempts reconnection. Useful for recovering from Docker container restarts.
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
resetDBConnection() => Promise<void>
|
|
228
308
|
```
|
|
229
309
|
|
|
230
310
|
### logger
|
|
@@ -17,11 +17,12 @@ declare class DatabaseConnection {
|
|
|
17
17
|
connect(): Promise<void>;
|
|
18
18
|
/**
|
|
19
19
|
* Handles connection errors by retrying the connection up to MAX_RETRIES times.
|
|
20
|
-
*
|
|
20
|
+
* Uses exponential backoff for retry intervals.
|
|
21
21
|
*/
|
|
22
22
|
private handleConnectionError;
|
|
23
23
|
/**
|
|
24
24
|
* Handles disconnection events by attempting to reconnect if not already connected.
|
|
25
|
+
* Resets retry count for fresh reconnection attempts.
|
|
25
26
|
*/
|
|
26
27
|
private handleDisconnection;
|
|
27
28
|
/**
|
|
@@ -37,7 +38,13 @@ declare class DatabaseConnection {
|
|
|
37
38
|
readyState: number;
|
|
38
39
|
host: string;
|
|
39
40
|
name: string;
|
|
41
|
+
retryCount: number;
|
|
40
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* Manually reset retry count and attempt reconnection
|
|
45
|
+
* Useful for recovering from Docker container restarts
|
|
46
|
+
*/
|
|
47
|
+
resetAndRetry(): Promise<void>;
|
|
41
48
|
}
|
|
42
49
|
declare const _default: () => Promise<void>;
|
|
43
50
|
export default _default;
|
|
@@ -46,5 +53,7 @@ export declare const getDBStatus: () => {
|
|
|
46
53
|
readyState: number;
|
|
47
54
|
host: string;
|
|
48
55
|
name: string;
|
|
56
|
+
retryCount: number;
|
|
49
57
|
};
|
|
58
|
+
export declare const resetDBConnection: () => Promise<void>;
|
|
50
59
|
export { DatabaseConnection };
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import mongoose from "mongoose";
|
|
2
2
|
/**
|
|
3
3
|
* Maximum number of connection retry attempts
|
|
4
|
+
* Can be overridden with DB_MAX_RETRIES environment variable
|
|
4
5
|
*/
|
|
5
|
-
const MAX_RETRIES =
|
|
6
|
+
const MAX_RETRIES = parseInt(process.env.DB_MAX_RETRIES || '10');
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
+
* Initial interval between retry attempts in milliseconds
|
|
9
|
+
* Can be overridden with DB_RETRY_INTERVAL environment variable
|
|
8
10
|
*/
|
|
9
|
-
const
|
|
11
|
+
const INITIAL_RETRY_INTERVAL = parseInt(process.env.DB_RETRY_INTERVAL || '3000'); // 3 seconds
|
|
12
|
+
/**
|
|
13
|
+
* Maximum retry interval (caps exponential backoff)
|
|
14
|
+
*/
|
|
15
|
+
const MAX_RETRY_INTERVAL = 30000; // 30 seconds
|
|
10
16
|
/**
|
|
11
17
|
* Database connection class for MongoDB using Mongoose.
|
|
12
18
|
* Provides automatic reconnection, retry logic, and connection status monitoring.
|
|
@@ -69,27 +75,39 @@ class DatabaseConnection {
|
|
|
69
75
|
}
|
|
70
76
|
/**
|
|
71
77
|
* Handles connection errors by retrying the connection up to MAX_RETRIES times.
|
|
72
|
-
*
|
|
78
|
+
* Uses exponential backoff for retry intervals.
|
|
73
79
|
*/
|
|
74
80
|
async handleConnectionError() {
|
|
75
81
|
if (this.retryCount < MAX_RETRIES) {
|
|
76
82
|
this.retryCount++;
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
// Calculate exponential backoff with jitter
|
|
84
|
+
const exponentialDelay = Math.min(INITIAL_RETRY_INTERVAL * Math.pow(2, this.retryCount - 1), MAX_RETRY_INTERVAL);
|
|
85
|
+
const jitter = Math.random() * 1000; // Add up to 1 second of random jitter
|
|
86
|
+
const delay = exponentialDelay + jitter;
|
|
87
|
+
console.log(`Retrying connection... Attempt ${this.retryCount} of ${MAX_RETRIES} (waiting ${Math.round(delay)}ms)`);
|
|
88
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
79
89
|
return this.connect();
|
|
80
90
|
}
|
|
81
91
|
else {
|
|
82
|
-
console.error(`Failed to connect to MongoDB after ${MAX_RETRIES} attempts`);
|
|
83
|
-
|
|
92
|
+
console.error(`Failed to connect to MongoDB after ${MAX_RETRIES} attempts. Please check:`, `1. Docker container is running: docker ps`, `2. MongoDB is accessible: ${process.env.MONGO_URI}`, `3. Network connectivity between containers`, `4. Environment variables are correctly set`);
|
|
93
|
+
// Only exit in production, allow recovery in development
|
|
94
|
+
if (process.env.NODE_ENV === 'production') {
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
console.log('Development mode: keeping process alive for manual retry');
|
|
99
|
+
}
|
|
84
100
|
}
|
|
85
101
|
}
|
|
86
102
|
/**
|
|
87
103
|
* Handles disconnection events by attempting to reconnect if not already connected.
|
|
104
|
+
* Resets retry count for fresh reconnection attempts.
|
|
88
105
|
*/
|
|
89
|
-
handleDisconnection() {
|
|
106
|
+
async handleDisconnection() {
|
|
90
107
|
if (!this.isConnected) {
|
|
91
108
|
console.log("Attempting to reconnect to MongoDB...");
|
|
92
|
-
this.
|
|
109
|
+
this.retryCount = 0; // Reset retry count for reconnection attempts
|
|
110
|
+
await this.connect();
|
|
93
111
|
}
|
|
94
112
|
}
|
|
95
113
|
/**
|
|
@@ -116,12 +134,23 @@ class DatabaseConnection {
|
|
|
116
134
|
readyState: mongoose.connection.readyState,
|
|
117
135
|
host: mongoose.connection.host,
|
|
118
136
|
name: mongoose.connection.name,
|
|
137
|
+
retryCount: this.retryCount,
|
|
119
138
|
};
|
|
120
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Manually reset retry count and attempt reconnection
|
|
142
|
+
* Useful for recovering from Docker container restarts
|
|
143
|
+
*/
|
|
144
|
+
async resetAndRetry() {
|
|
145
|
+
console.log('Resetting connection state and retrying...');
|
|
146
|
+
this.retryCount = 0;
|
|
147
|
+
await this.connect();
|
|
148
|
+
}
|
|
121
149
|
}
|
|
122
150
|
// Create a singleton instance
|
|
123
151
|
const dbConnection = new DatabaseConnection();
|
|
124
152
|
// Export the connect function and the instance
|
|
125
153
|
export default dbConnection.connect.bind(dbConnection);
|
|
126
154
|
export const getDBStatus = dbConnection.getConnectionStatus.bind(dbConnection);
|
|
155
|
+
export const resetDBConnection = dbConnection.resetAndRetry.bind(dbConnection);
|
|
127
156
|
export { DatabaseConnection };
|
|
@@ -1,18 +1,53 @@
|
|
|
1
1
|
import { Response } from "express";
|
|
2
2
|
/**
|
|
3
|
-
* Sends a success response.
|
|
3
|
+
* Sends a success response and returns the response object for chaining.
|
|
4
|
+
* Automatically sends the response after chaining operations complete - no extra .send() needed!
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Includes success: true field by default
|
|
8
|
+
* - Supports method chaining (.cookie(), .header(), etc.)
|
|
9
|
+
* - Automatically sends response after chaining completes
|
|
10
|
+
* - Returns Express response object for chaining
|
|
11
|
+
*
|
|
4
12
|
* @param {Response} res - Express response object.
|
|
5
13
|
* @param {any} data - Response data.
|
|
6
14
|
* @param {string} [message='Success'] - Response message.
|
|
7
15
|
* @param {number} [statusCode=200] - HTTP status code.
|
|
8
16
|
* @returns {Response} The Express response object for chaining.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Basic usage
|
|
20
|
+
* sendSuccess(res, { userId: 123 }, "Login successful");
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Chain methods without calling .send()
|
|
24
|
+
* sendSuccess(res, { userId: 123 }, "Login successful", 200)
|
|
25
|
+
* .cookie("authToken", "xyz789", { httpOnly: true })
|
|
26
|
+
* .header("X-Custom", "value");
|
|
27
|
+
* // Response sent automatically!
|
|
9
28
|
*/
|
|
10
29
|
export declare const sendSuccess: (res: Response, data: any, message?: string, statusCode?: number) => Response;
|
|
11
30
|
/**
|
|
12
|
-
* Sends an error response.
|
|
31
|
+
* Sends an error response immediately.
|
|
32
|
+
*
|
|
33
|
+
* Features:
|
|
34
|
+
* - Includes success: false field by default
|
|
35
|
+
* - Sends response immediately (no chaining needed)
|
|
36
|
+
* - Supports optional error data
|
|
37
|
+
*
|
|
13
38
|
* @param {Response} res - Express response object.
|
|
14
39
|
* @param {string} message - Error message.
|
|
15
40
|
* @param {number} [statusCode=400] - HTTP status code.
|
|
16
41
|
* @param {any} [data] - Additional error data.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // Basic error
|
|
45
|
+
* sendError(res, "User not found", 404);
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // Error with additional data
|
|
49
|
+
* sendError(res, "Validation failed", 400, {
|
|
50
|
+
* errors: ["Email is required", "Password too short"]
|
|
51
|
+
* });
|
|
17
52
|
*/
|
|
18
53
|
export declare const sendError: (res: Response, message: string, statusCode?: number, data?: any) => void;
|
|
@@ -1,29 +1,74 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sends a success response.
|
|
2
|
+
* Sends a success response and returns the response object for chaining.
|
|
3
|
+
* Automatically sends the response after chaining operations complete - no extra .send() needed!
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Includes success: true field by default
|
|
7
|
+
* - Supports method chaining (.cookie(), .header(), etc.)
|
|
8
|
+
* - Automatically sends response after chaining completes
|
|
9
|
+
* - Returns Express response object for chaining
|
|
10
|
+
*
|
|
3
11
|
* @param {Response} res - Express response object.
|
|
4
12
|
* @param {any} data - Response data.
|
|
5
13
|
* @param {string} [message='Success'] - Response message.
|
|
6
14
|
* @param {number} [statusCode=200] - HTTP status code.
|
|
7
15
|
* @returns {Response} The Express response object for chaining.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Basic usage
|
|
19
|
+
* sendSuccess(res, { userId: 123 }, "Login successful");
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Chain methods without calling .send()
|
|
23
|
+
* sendSuccess(res, { userId: 123 }, "Login successful", 200)
|
|
24
|
+
* .cookie("authToken", "xyz789", { httpOnly: true })
|
|
25
|
+
* .header("X-Custom", "value");
|
|
26
|
+
* // Response sent automatically!
|
|
8
27
|
*/
|
|
9
28
|
export const sendSuccess = (res, data, message = "Success", statusCode = 200) => {
|
|
10
29
|
const response = {
|
|
11
30
|
status: "success",
|
|
31
|
+
success: true,
|
|
12
32
|
message,
|
|
13
33
|
data,
|
|
14
34
|
};
|
|
15
|
-
|
|
35
|
+
res.status(statusCode);
|
|
36
|
+
// Use setImmediate to send response after current execution stack
|
|
37
|
+
setImmediate(() => {
|
|
38
|
+
if (!res._responseSent) {
|
|
39
|
+
res._responseSent = true;
|
|
40
|
+
res.json(response);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return res;
|
|
16
44
|
};
|
|
17
45
|
/**
|
|
18
|
-
* Sends an error response.
|
|
46
|
+
* Sends an error response immediately.
|
|
47
|
+
*
|
|
48
|
+
* Features:
|
|
49
|
+
* - Includes success: false field by default
|
|
50
|
+
* - Sends response immediately (no chaining needed)
|
|
51
|
+
* - Supports optional error data
|
|
52
|
+
*
|
|
19
53
|
* @param {Response} res - Express response object.
|
|
20
54
|
* @param {string} message - Error message.
|
|
21
55
|
* @param {number} [statusCode=400] - HTTP status code.
|
|
22
56
|
* @param {any} [data] - Additional error data.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Basic error
|
|
60
|
+
* sendError(res, "User not found", 404);
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Error with additional data
|
|
64
|
+
* sendError(res, "Validation failed", 400, {
|
|
65
|
+
* errors: ["Email is required", "Password too short"]
|
|
66
|
+
* });
|
|
23
67
|
*/
|
|
24
68
|
export const sendError = (res, message, statusCode = 400, data) => {
|
|
25
69
|
const response = {
|
|
26
70
|
status: "error",
|
|
71
|
+
success: false,
|
|
27
72
|
message,
|
|
28
73
|
...(data && { data }),
|
|
29
74
|
};
|
package/package.json
CHANGED
package/dist/AppError.1.d.ts
DELETED
|
File without changes
|
package/dist/AppError.1.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
package/dist/AppError.2.d.ts
DELETED
|
File without changes
|
package/dist/AppError.2.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
package/dist/authWrapper.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { JwtPayload, Algorithm } from "jsonwebtoken";
|
|
2
|
-
import { Request, Response, NextFunction } from "express";
|
|
3
|
-
interface AuthOptions {
|
|
4
|
-
secret: string;
|
|
5
|
-
algorithms?: Algorithm[];
|
|
6
|
-
}
|
|
7
|
-
interface AuthenticatedRequest extends Request {
|
|
8
|
-
user?: JwtPayload | string;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Middleware to require JWT authentication.
|
|
12
|
-
* Verifies the JWT token from Authorization header and attaches decoded payload to req.user.
|
|
13
|
-
* @param {AuthOptions} options - JWT verification options.
|
|
14
|
-
* @returns {(req: Request, res: Response, next: NextFunction) => void} - Middleware function.
|
|
15
|
-
*/
|
|
16
|
-
export declare const requireAuth: (options: AuthOptions) => (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
17
|
-
export {};
|
package/dist/authWrapper.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import jwt, { JsonWebTokenError, TokenExpiredError, } from "jsonwebtoken";
|
|
2
|
-
import { AppError } from "./AppError.js";
|
|
3
|
-
const defaultAlgorithms = ["HS256"];
|
|
4
|
-
/**
|
|
5
|
-
* Middleware to require JWT authentication.
|
|
6
|
-
* Verifies the JWT token from Authorization header and attaches decoded payload to req.user.
|
|
7
|
-
* @param {AuthOptions} options - JWT verification options.
|
|
8
|
-
* @returns {(req: Request, res: Response, next: NextFunction) => void} - Middleware function.
|
|
9
|
-
*/
|
|
10
|
-
export const requireAuth = (options) => {
|
|
11
|
-
return (req, res, next) => {
|
|
12
|
-
const authHeader = req.headers.authorization;
|
|
13
|
-
if (!authHeader) {
|
|
14
|
-
throw new AppError("Access denied. No token provided.", 401);
|
|
15
|
-
}
|
|
16
|
-
if (!authHeader.startsWith("Bearer ")) {
|
|
17
|
-
throw new AppError("Malformed authorization header.", 401);
|
|
18
|
-
}
|
|
19
|
-
const token = authHeader.substring(7);
|
|
20
|
-
if (!token) {
|
|
21
|
-
throw new AppError("Access denied. No token provided.", 401);
|
|
22
|
-
}
|
|
23
|
-
try {
|
|
24
|
-
let decoded;
|
|
25
|
-
if (options.algorithms) {
|
|
26
|
-
decoded = jwt.verify(token, options.secret, {
|
|
27
|
-
algorithms: options.algorithms,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
decoded = jwt.verify(token, options.secret);
|
|
32
|
-
}
|
|
33
|
-
req.user = decoded;
|
|
34
|
-
next();
|
|
35
|
-
}
|
|
36
|
-
catch (error) {
|
|
37
|
-
if (error instanceof JsonWebTokenError) {
|
|
38
|
-
throw new AppError("Invalid token.", 401);
|
|
39
|
-
}
|
|
40
|
-
else if (error instanceof TokenExpiredError) {
|
|
41
|
-
throw new AppError("Token expired.", 401);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
throw new AppError("Authentication failed.", 401);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ValidationChain } from 'express-validator';
|
|
2
|
-
import { Request, Response, NextFunction } from 'express';
|
|
3
|
-
/**
|
|
4
|
-
* Middleware wrapper for express-validator validations.
|
|
5
|
-
* Runs the provided validations and throws AppError if any fail.
|
|
6
|
-
* @param {ValidationChain[]} validations - Array of express-validator validation chains.
|
|
7
|
-
* @returns {(req: Request, res: Response, next: NextFunction) => Promise<void>} - Middleware function.
|
|
8
|
-
*/
|
|
9
|
-
export declare const validateRequest: (validations: ValidationChain[]) => (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
package/dist/validateRequest.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { validationResult } from 'express-validator';
|
|
2
|
-
import { AppError } from './AppError.js';
|
|
3
|
-
/**
|
|
4
|
-
* Middleware wrapper for express-validator validations.
|
|
5
|
-
* Runs the provided validations and throws AppError if any fail.
|
|
6
|
-
* @param {ValidationChain[]} validations - Array of express-validator validation chains.
|
|
7
|
-
* @returns {(req: Request, res: Response, next: NextFunction) => Promise<void>} - Middleware function.
|
|
8
|
-
*/
|
|
9
|
-
export const validateRequest = (validations) => {
|
|
10
|
-
return async (req, res, next) => {
|
|
11
|
-
await Promise.all(validations.map(validation => validation.run(req)));
|
|
12
|
-
const errors = validationResult(req);
|
|
13
|
-
if (!errors.isEmpty()) {
|
|
14
|
-
const errorMessages = errors.array().map(err => err.msg);
|
|
15
|
-
throw new AppError('Validation failed', 400, errorMessages);
|
|
16
|
-
}
|
|
17
|
-
next();
|
|
18
|
-
};
|
|
19
|
-
};
|