my-async-handler 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/LICENSE +21 -0
- package/README.md +123 -0
- package/index.js +14 -0
- package/package.json +25 -0
- package/test.js +54 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Krishna Karale
|
|
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,123 @@
|
|
|
1
|
+
# my_async_handler ๐
|
|
2
|
+
|
|
3
|
+
A lightweight, zero-dependency utility for **Express.js** to eliminate `try-catch` boilerplate and handle async errors gracefully.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ๐ด The Problem
|
|
8
|
+
|
|
9
|
+
In **Express 4**, when you use `async/await` in your route handlers, any error thrown or any rejected promise is **not automatically caught by Express**.
|
|
10
|
+
|
|
11
|
+
This leads to:
|
|
12
|
+
|
|
13
|
+
1. **Unhandled Promise Rejections**
|
|
14
|
+
Your Node.js process might crash or behave unpredictably.
|
|
15
|
+
|
|
16
|
+
2. **Repetitive Code**
|
|
17
|
+
You end up writing `try-catch` blocks in every single controller, making your code messy and hard to maintain.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## ๐ข The Solution
|
|
22
|
+
|
|
23
|
+
`my_async_handler` is a higher-order function that wraps your async middleware. It ensures that if an error occurs, it is automatically caught and passed to the Express `next(err)` function, forwarding it to your global error-handling middleware.
|
|
24
|
+
|
|
25
|
+
### โ
Features
|
|
26
|
+
|
|
27
|
+
- **Clean** โ Removes the need for `try-catch` in every route.
|
|
28
|
+
- **Safe** โ Prevents unhandled promise rejections.
|
|
29
|
+
- **Lightweight** โ Zero dependencies.
|
|
30
|
+
- **Modern** โ Fully supports ES Modules (`import/export`).
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## ๐ Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install my-async-handler
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## ๐ Usage
|
|
43
|
+
|
|
44
|
+
### 1๏ธโฃ Basic Async Route
|
|
45
|
+
|
|
46
|
+
Instead of wrapping your logic in a `try...catch` block, wrap the entire function in `asyncHandler`.
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import asyncHandler from 'my_async_handler';
|
|
50
|
+
|
|
51
|
+
// No try-catch needed!
|
|
52
|
+
export const getData = asyncHandler(async (req, res, next) => {
|
|
53
|
+
// If find() fails, the error is automatically passed to next()
|
|
54
|
+
const data = await MyModel.find();
|
|
55
|
+
res.status(200).json({ success: true, data });
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### 2๏ธโฃ Handling Custom Errors
|
|
62
|
+
|
|
63
|
+
You can throw errors directly inside your logic, and `asyncHandler` will catch them and send them to your error middleware.
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
export const getUser = asyncHandler(async (req, res, next) => {
|
|
67
|
+
const user = await User.findById(req.params.id);
|
|
68
|
+
|
|
69
|
+
if (!user) {
|
|
70
|
+
const error = new Error("User not found");
|
|
71
|
+
error.status = 404;
|
|
72
|
+
throw error; // This goes straight to your global error handler
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
res.json(user);
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### 3๏ธโฃ Setup Global Error Middleware
|
|
82
|
+
|
|
83
|
+
For this utility to work, ensure you have an error handler at the end of your `app.js` file (after all routes).
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// This MUST be after all your routes
|
|
87
|
+
app.use((err, req, res, next) => {
|
|
88
|
+
const statusCode = err.status || 500;
|
|
89
|
+
|
|
90
|
+
res.status(statusCode).json({
|
|
91
|
+
success: false,
|
|
92
|
+
message: err.message || "Internal Server Error"
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## ๐งช Testing
|
|
100
|
+
|
|
101
|
+
This package includes a simple test script to verify functionality without needing a database.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm test
|
|
105
|
+
```
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## โ ๏ธ Disclaimer: Use At Your Own Risk
|
|
109
|
+
|
|
110
|
+
This software is provided **"as is"**, without any warranties or guarantees of any kind.
|
|
111
|
+
|
|
112
|
+
By using this package, you agree that:
|
|
113
|
+
|
|
114
|
+
- You are responsible for testing and validating it before deploying to production.
|
|
115
|
+
- The author is **not liable** for any issues arising from its use.
|
|
116
|
+
- This includes, but is not limited to:
|
|
117
|
+
- Server downtime
|
|
118
|
+
- Data loss
|
|
119
|
+
- Security vulnerabilities
|
|
120
|
+
- Unexpected behavior
|
|
121
|
+
- Production failures
|
|
122
|
+
|
|
123
|
+
Always verify and test thoroughly in a **development environment** before using it in a live system.
|
package/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wraps async Express middleware to catch errors and pass them to next().
|
|
3
|
+
* @param {Function} fn - The async function to wrap.
|
|
4
|
+
*/
|
|
5
|
+
const asyncHandler = (fn) => {
|
|
6
|
+
if (typeof fn !== "function") {
|
|
7
|
+
throw new TypeError("asyncHandler expects a function");
|
|
8
|
+
}
|
|
9
|
+
return (req, res, next) => {
|
|
10
|
+
Promise.resolve(fn(req, res, next)).catch(next);
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default asyncHandler;
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-async-handler",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight wrapper for Express async routes to eliminate try-catch boilerplate.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"express",
|
|
7
|
+
"express-middleware",
|
|
8
|
+
"async",
|
|
9
|
+
"async-handler",
|
|
10
|
+
"error-handling",
|
|
11
|
+
"middleware",
|
|
12
|
+
"nodejs"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": "Krishna Karale",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "index.js",
|
|
18
|
+
"exports": "./index.js",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=14"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"test": "node test.js"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/test.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import asyncHandler from './index.js';
|
|
2
|
+
|
|
3
|
+
// --- Test Utilities ---
|
|
4
|
+
const mockReq = {};
|
|
5
|
+
const mockRes = {
|
|
6
|
+
status: function(code) { this.statusCode = code; return this; },
|
|
7
|
+
json: function(data) { this.body = data; return this; }
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const runTest = async (name, testFn) => {
|
|
11
|
+
try {
|
|
12
|
+
await testFn();
|
|
13
|
+
console.log(`โ
Passed: ${name}`);
|
|
14
|
+
} catch (err) {
|
|
15
|
+
console.error(`โ Failed: ${name}`);
|
|
16
|
+
console.error(err);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// --- Test Cases ---
|
|
22
|
+
|
|
23
|
+
// 1. Verify it returns a function
|
|
24
|
+
runTest("Returns a middleware function", () => {
|
|
25
|
+
const middleware = asyncHandler(async () => {});
|
|
26
|
+
if (typeof middleware !== 'function') throw new Error("Should return a function");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// 2. Verify it catches errors and calls next(err)
|
|
30
|
+
runTest("Catches async errors and calls next()", async () => {
|
|
31
|
+
let errorPassedToNext = null;
|
|
32
|
+
const next = (err) => { errorPassedToNext = err; };
|
|
33
|
+
|
|
34
|
+
const error = new Error("Async Failure");
|
|
35
|
+
const handler = async () => { throw error; };
|
|
36
|
+
|
|
37
|
+
const middleware = asyncHandler(handler);
|
|
38
|
+
await middleware(mockReq, mockRes, next);
|
|
39
|
+
|
|
40
|
+
if (errorPassedToNext !== error) {
|
|
41
|
+
throw new Error("The error was not passed to the next() function!");
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// 3. Verify it works with normal (non-async) functions
|
|
46
|
+
runTest("Works with synchronous functions", async () => {
|
|
47
|
+
let called = false;
|
|
48
|
+
const next = () => { called = true; };
|
|
49
|
+
|
|
50
|
+
const middleware = asyncHandler((req, res, next) => { next(); });
|
|
51
|
+
await middleware(mockReq, mockRes, next);
|
|
52
|
+
|
|
53
|
+
if (!called) throw new Error("next() was not called in sync mode");
|
|
54
|
+
});
|