devdad-express-utils 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/README.md +160 -0
- package/dist/AppError.1.d.ts +0 -0
- package/dist/AppError.1.js +1 -0
- package/dist/AppError.2.d.ts +0 -0
- package/dist/AppError.2.js +1 -0
- package/dist/AppError.d.ts +7 -0
- package/dist/AppError.js +15 -0
- package/dist/catchAsync.d.ts +2 -0
- package/dist/catchAsync.js +5 -0
- package/dist/errorHandler.d.ts +3 -0
- package/dist/errorHandler.js +47 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Express Utils
|
|
2
|
+
|
|
3
|
+
A collection of reusable utilities for Express.js applications, including error handling, async route wrapping, and custom error classes.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install express-utils
|
|
9
|
+
# or
|
|
10
|
+
yarn add express-utils
|
|
11
|
+
# or
|
|
12
|
+
pnpm add express-utils
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Error Handling
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import express from "express";
|
|
21
|
+
import { errorHandler, AppError } from "express-utils";
|
|
22
|
+
|
|
23
|
+
const app = express();
|
|
24
|
+
|
|
25
|
+
// Your routes here
|
|
26
|
+
|
|
27
|
+
// Use the error handler as the last middleware
|
|
28
|
+
app.use(errorHandler);
|
|
29
|
+
|
|
30
|
+
// In your controllers, throw AppError for operational errors
|
|
31
|
+
throw new AppError("Something went wrong", 400);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Async Route Wrapping
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { catchAsync } from "express-utils";
|
|
38
|
+
|
|
39
|
+
const getUsers = catchAsync(async (req, res, next) => {
|
|
40
|
+
const users = await User.find();
|
|
41
|
+
res.json(users);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
app.get("/users", getUsers);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Custom Error Class
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { AppError } from "express-utils";
|
|
51
|
+
|
|
52
|
+
throw new AppError("Validation failed", 400, ["Email is required"]);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### JavaScript Usage
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const { AppError, catchAsync, errorHandler } = require("express-utils");
|
|
59
|
+
|
|
60
|
+
// Or with ES modules
|
|
61
|
+
import { AppError, catchAsync, errorHandler } from "express-utils";
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Error Handling Patterns
|
|
65
|
+
|
|
66
|
+
### Using AppError
|
|
67
|
+
|
|
68
|
+
**For operational errors (expected errors like validation):**
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// In controllers wrapped with catchAsync
|
|
72
|
+
const createUser = catchAsync(async (req, res, next) => {
|
|
73
|
+
// Validation fails
|
|
74
|
+
return next(new AppError("Email is required", 400));
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Or for unexpected errors
|
|
78
|
+
throw new AppError("Database connection failed", 500);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Why `next(new AppError())` over `throw`?**
|
|
82
|
+
|
|
83
|
+
- `next()` passes the error to your error handler middleware
|
|
84
|
+
- Allows centralized error handling and formatting
|
|
85
|
+
- Better for Express middleware pattern
|
|
86
|
+
- `throw` is more for unexpected errors that bubble up
|
|
87
|
+
|
|
88
|
+
### Complete Example
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
const express = require("express");
|
|
92
|
+
const { AppError, catchAsync, errorHandler } = require("express-utils");
|
|
93
|
+
|
|
94
|
+
const app = express();
|
|
95
|
+
|
|
96
|
+
const getUser = catchAsync(async (req, res, next) => {
|
|
97
|
+
const user = await User.findById(req.params.id);
|
|
98
|
+
if (!user) {
|
|
99
|
+
return next(new AppError("User not found", 404));
|
|
100
|
+
}
|
|
101
|
+
res.json(user);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
app.get("/users/:id", getUser);
|
|
105
|
+
|
|
106
|
+
// Error handler should be last
|
|
107
|
+
app.use(errorHandler);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### JavaScript Usage
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
const { AppError, catchAsync, errorHandler } = require("express-utils");
|
|
114
|
+
|
|
115
|
+
// Or with ES modules
|
|
116
|
+
import { AppError, catchAsync, errorHandler } from "express-utils";
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## API
|
|
120
|
+
|
|
121
|
+
### AppError
|
|
122
|
+
|
|
123
|
+
Custom error class for operational errors.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
new AppError(message: string, statusCode: number, errors?: string[])
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### catchAsync
|
|
130
|
+
|
|
131
|
+
Higher-order function to wrap async route handlers and catch errors.
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
catchAsync(fn: (req, res, next) => Promise<any>) => (req, res, next) => void
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### errorHandler
|
|
138
|
+
|
|
139
|
+
Express error handling middleware with detailed logging in development.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
errorHandler(err: any, req: Request, res: Response, next: NextFunction) => void
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Install dependencies
|
|
149
|
+
pnpm install
|
|
150
|
+
|
|
151
|
+
# Build the package
|
|
152
|
+
pnpm run build
|
|
153
|
+
|
|
154
|
+
# Publish to npm
|
|
155
|
+
npm publish
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
ISC
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
package/dist/AppError.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class AppError extends Error {
|
|
2
|
+
statusCode;
|
|
3
|
+
status;
|
|
4
|
+
isOperational;
|
|
5
|
+
errors;
|
|
6
|
+
constructor(message, statusCode, errors = []) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.statusCode = statusCode;
|
|
9
|
+
this.status = statusCode.toString().startsWith("4") ? "fail" : "error";
|
|
10
|
+
this.isOperational = true;
|
|
11
|
+
this.errors = errors.length > 0 ? errors : undefined;
|
|
12
|
+
// Maintain proper stack trace
|
|
13
|
+
Error.captureStackTrace(this, this.constructor);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AppError } from "./AppError.js";
|
|
2
|
+
const sendErrorDev = (err, res) => {
|
|
3
|
+
res.status(err.statusCode || 500).json({
|
|
4
|
+
status: err.status || "error",
|
|
5
|
+
message: err.message,
|
|
6
|
+
error: err,
|
|
7
|
+
errors: err.errors || [],
|
|
8
|
+
stack: err.stack,
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
const sendErrorProd = (err, res) => {
|
|
12
|
+
// Operational, trusted error → send to client
|
|
13
|
+
if (err.isOperational) {
|
|
14
|
+
res.status(err.statusCode).json({
|
|
15
|
+
status: err.status,
|
|
16
|
+
message: err.message,
|
|
17
|
+
...(err.errors && err.errors.length > 0 && { errors: err.errors }),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// Unknown error → hide details
|
|
22
|
+
console.error("ERROR", err);
|
|
23
|
+
res.status(500).json({
|
|
24
|
+
status: "error",
|
|
25
|
+
message: "Something went wrong!",
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const errorHandler = (err, req, res, next) => {
|
|
30
|
+
err.statusCode = err.statusCode || 500;
|
|
31
|
+
err.status = err.status || "error";
|
|
32
|
+
// Add this for Extra In-Depth Error Logging
|
|
33
|
+
console.error("Error details:", {
|
|
34
|
+
message: err.message,
|
|
35
|
+
statusCode: err.statusCode,
|
|
36
|
+
errors: err.errors,
|
|
37
|
+
stack: err.stack,
|
|
38
|
+
fullError: err,
|
|
39
|
+
});
|
|
40
|
+
if (process.env.NODE_ENV === "development") {
|
|
41
|
+
sendErrorDev(err, res);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
sendErrorProd(err instanceof AppError ? err : new AppError(err.message, 500), res);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
export { errorHandler };
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devdad-express-utils",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Reusable Express.js utilities for error handling, async wrapping, and more",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"prepublishOnly": "npm run build"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"express",
|
|
15
|
+
"utilities",
|
|
16
|
+
"error-handling",
|
|
17
|
+
"typescript"
|
|
18
|
+
],
|
|
19
|
+
"author": "Oliver Metz",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"express": "^5.1.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/express": "^5.0.5",
|
|
26
|
+
"typescript": "^5.9.3"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
]
|
|
31
|
+
}
|