create-charcole 2.0.4 → 2.1.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/CHANGELOG.md +200 -14
- package/README.md +137 -332
- package/bin/index.js +236 -55
- package/bin/lib/pkgManager.js +8 -25
- package/bin/lib/templateHandler.js +5 -42
- package/package.json +2 -2
- package/plans/V2_1_PLAN.md +20 -0
- package/template/js/.env.example +8 -0
- package/template/js/basePackage.json +11 -13
- package/template/js/src/app.js +4 -1
- package/template/js/src/modules/auth/auth.constants.js +3 -0
- package/template/js/src/modules/auth/auth.controller.js +29 -0
- package/template/js/src/modules/auth/auth.middlewares.js +19 -0
- package/template/js/src/modules/auth/auth.routes.js +9 -0
- package/template/js/src/modules/auth/auth.schemas.js +60 -0
- package/template/js/src/modules/auth/auth.service.js +67 -0
- package/template/js/src/modules/auth/package.json +6 -0
- package/template/js/src/repositories/user.repo.js +19 -0
- package/template/js/src/routes/index.js +25 -0
- package/template/js/src/routes/protected.js +13 -0
- package/template/ts/.env.example +8 -0
- package/template/ts/basePackage.json +19 -15
- package/template/ts/build.js +46 -0
- package/template/ts/src/app.ts +5 -4
- package/template/ts/src/middlewares/errorHandler.ts +15 -23
- package/template/ts/src/middlewares/requestLogger.ts +1 -1
- package/template/ts/src/middlewares/validateRequest.ts +1 -1
- package/template/ts/src/modules/auth/auth.constants.ts +6 -0
- package/template/ts/src/modules/auth/auth.controller.ts +32 -0
- package/template/ts/src/modules/auth/auth.middlewares.ts +46 -0
- package/template/ts/src/modules/auth/auth.routes.ts +9 -0
- package/template/ts/src/modules/auth/auth.schemas.ts +73 -0
- package/template/ts/src/modules/auth/auth.service.ts +106 -0
- package/template/ts/src/modules/auth/package.json +10 -0
- package/template/ts/src/modules/health/controller.ts +3 -3
- package/template/ts/src/repositories/user.repo.ts +33 -0
- package/template/ts/src/routes/index.ts +24 -0
- package/template/ts/src/routes/protected.ts +13 -0
- package/template/ts/src/server.ts +0 -1
- package/template/ts/src/utils/logger.ts +1 -1
- package/template/ts/tsconfig.json +14 -7
- package/template/js/ARCHITECTURE_DIAGRAMS.md +0 -283
- package/template/js/CHECKLIST.md +0 -279
- package/template/js/COMPLETE.md +0 -405
- package/template/js/ERROR_HANDLING.md +0 -393
- package/template/js/IMPLEMENTATION.md +0 -368
- package/template/js/IMPLEMENTATION_COMPLETE.md +0 -363
- package/template/js/INDEX.md +0 -290
- package/template/js/QUICK_REFERENCE.md +0 -270
- package/template/js/package.json +0 -28
- package/template/js/src/routes.js +0 -17
- package/template/js/test-api.js +0 -100
- package/template/ts/ARCHITECTURE_DIAGRAMS.md +0 -283
- package/template/ts/CHECKLIST.md +0 -279
- package/template/ts/COMPLETE.md +0 -405
- package/template/ts/ERROR_HANDLING.md +0 -393
- package/template/ts/IMPLEMENTATION.md +0 -368
- package/template/ts/IMPLEMENTATION_COMPLETE.md +0 -363
- package/template/ts/INDEX.md +0 -290
- package/template/ts/QUICK_REFERENCE.md +0 -270
- package/template/ts/package.json +0 -32
- package/template/ts/src/app.js +0 -75
- package/template/ts/src/config/constants.js +0 -20
- package/template/ts/src/config/env.js +0 -26
- package/template/ts/src/middlewares/errorHandler.js +0 -180
- package/template/ts/src/middlewares/requestLogger.js +0 -33
- package/template/ts/src/middlewares/validateRequest.js +0 -42
- package/template/ts/src/modules/health/controller.js +0 -50
- package/template/ts/src/routes.js +0 -17
- package/template/ts/src/routes.ts +0 -16
- package/template/ts/src/server.js +0 -38
- package/template/ts/src/utils/AppError.js +0 -182
- package/template/ts/src/utils/logger.js +0 -73
- package/template/ts/src/utils/response.js +0 -51
- package/template/ts/test-api.js +0 -100
package/template/js/CHECKLIST.md
DELETED
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
# Implementation Checklist - Production Error Handling System
|
|
2
|
-
|
|
3
|
-
## ✅ Files Created
|
|
4
|
-
|
|
5
|
-
- [x] `src/utils/AppError.js` - Error class hierarchy (8 error types)
|
|
6
|
-
- [x] `ERROR_HANDLING.md` - Comprehensive documentation
|
|
7
|
-
- [x] `QUICK_REFERENCE.md` - Quick start guide
|
|
8
|
-
- [x] `ARCHITECTURE_DIAGRAMS.md` - Visual architecture diagrams
|
|
9
|
-
- [x] `IMPLEMENTATION_COMPLETE.md` - Implementation details & examples
|
|
10
|
-
- [x] `COMPLETE.md` - Final summary document
|
|
11
|
-
- [x] `test-api.js` - API testing script
|
|
12
|
-
|
|
13
|
-
## ✅ Files Updated
|
|
14
|
-
|
|
15
|
-
### Core System
|
|
16
|
-
|
|
17
|
-
- [x] `src/utils/logger.js` - Added stack trace support + fatal() method
|
|
18
|
-
- [x] `src/utils/response.js` - Added documentation, kept for backward compatibility
|
|
19
|
-
- [x] `src/middlewares/errorHandler.js` - **Complete rewrite**
|
|
20
|
-
- Global error handler with normalization
|
|
21
|
-
- asyncHandler wrapper for async routes
|
|
22
|
-
- Error classification (operational vs programmer)
|
|
23
|
-
- Intelligent logging based on error type
|
|
24
|
-
- Production-safe responses
|
|
25
|
-
- [x] `src/middlewares/validateRequest.js` - Updated to throw ValidationError
|
|
26
|
-
- [x] `src/middlewares/requestLogger.js` - Enhanced with error detection
|
|
27
|
-
- [x] `src/app.js` - Updated to use new error system
|
|
28
|
-
- [x] `src/server.js` - Enhanced with graceful shutdown
|
|
29
|
-
- [x] `src/routes.js` - Updated with example routes
|
|
30
|
-
- [x] `src/modules/health/controller.js` - Updated with asyncHandler & new error classes
|
|
31
|
-
- [x] `package.json` - Already had Zod, no changes needed
|
|
32
|
-
- [x] `.env` - Already configured
|
|
33
|
-
- [x] `.env.example` - Already configured
|
|
34
|
-
- [x] `README.md` - Already configured
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## 🎯 Core Components
|
|
39
|
-
|
|
40
|
-
### 1. AppError Class Hierarchy
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
AppError (base) - isOperational, code, context, cause, timestamp
|
|
44
|
-
├── ValidationError (422)
|
|
45
|
-
├── BadRequestError (400)
|
|
46
|
-
├── AuthenticationError (401)
|
|
47
|
-
├── AuthorizationError (403)
|
|
48
|
-
├── NotFoundError (404)
|
|
49
|
-
├── ConflictError (409)
|
|
50
|
-
└── InternalServerError (500)
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**Methods:**
|
|
54
|
-
|
|
55
|
-
- `toJSON()` - Convert to response format
|
|
56
|
-
- `getFullDetails()` - Get full error info for logging
|
|
57
|
-
|
|
58
|
-
### 2. Global Error Handler
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
errorHandler(err, req, res, next)
|
|
62
|
-
├── normalizeError() - Convert any error type to AppError
|
|
63
|
-
├── logError() - Log with appropriate level + context
|
|
64
|
-
└── sendErrorResponse() - Send client response
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 3. Async Error Wrapper
|
|
68
|
-
|
|
69
|
-
```
|
|
70
|
-
asyncHandler(fn) - Wraps async handlers to catch errors
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
**Usage:**
|
|
74
|
-
|
|
75
|
-
```javascript
|
|
76
|
-
router.get(
|
|
77
|
-
"/endpoint",
|
|
78
|
-
asyncHandler(async (req, res) => {
|
|
79
|
-
// Error thrown here is caught and passed to global handler
|
|
80
|
-
}),
|
|
81
|
-
);
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### 4. Validation Middleware
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
validateRequest(schema) - Validates body, query, params
|
|
88
|
-
├── Throws ValidationError if fails
|
|
89
|
-
└── Attaches req.validatedData if succeeds
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### 5. Enhanced Logger
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
logger.debug(msg, data)
|
|
96
|
-
logger.info(msg, data)
|
|
97
|
-
logger.warn(msg, data)
|
|
98
|
-
logger.error(msg, data, stack)
|
|
99
|
-
logger.fatal(msg, data, stack)
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
**Features:**
|
|
103
|
-
|
|
104
|
-
- Color-coded output
|
|
105
|
-
- Configurable levels
|
|
106
|
-
- Stack trace support
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## 🔄 Error Flow Summary
|
|
111
|
-
|
|
112
|
-
1. **Request arrives**
|
|
113
|
-
2. **Middleware chain** (CORS, body parser, request logger)
|
|
114
|
-
3. **Validation middleware** (optional, throws ValidationError)
|
|
115
|
-
4. **Route handler** (wrapped with asyncHandler)
|
|
116
|
-
- Success → `sendSuccess(res, data)` → Response sent
|
|
117
|
-
- Error → `throw new ErrorType(...)` → Step 5
|
|
118
|
-
5. **asyncHandler catches** error → passes to next(error)
|
|
119
|
-
6. **Global error handler** catches error
|
|
120
|
-
- Normalizes: ZodError → ValidationError, TypeError → InternalServerError, etc.
|
|
121
|
-
- Classifies: operational vs programmer
|
|
122
|
-
- Logs: WARN for operational, ERROR with stack for programmer
|
|
123
|
-
- Sanitizes: hides details in production
|
|
124
|
-
- Sends: consistent JSON response
|
|
125
|
-
7. **Client receives** structured error response
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## 📊 Error Classification
|
|
130
|
-
|
|
131
|
-
### Operational Errors (isOperational: true)
|
|
132
|
-
|
|
133
|
-
**Expected errors that can be handled gracefully**
|
|
134
|
-
|
|
135
|
-
- ValidationError (422) - Input validation failed
|
|
136
|
-
- BadRequestError (400) - Malformed request
|
|
137
|
-
- AuthenticationError (401) - Invalid credentials
|
|
138
|
-
- AuthorizationError (403) - Permission denied
|
|
139
|
-
- NotFoundError (404) - Resource doesn't exist
|
|
140
|
-
- ConflictError (409) - Duplicate/conflict
|
|
141
|
-
|
|
142
|
-
**Behavior:**
|
|
143
|
-
|
|
144
|
-
- ✅ Logged as WARN
|
|
145
|
-
- ✅ Full details sent to client
|
|
146
|
-
- ✅ NO stack trace logged
|
|
147
|
-
- ✅ Code included for client handling
|
|
148
|
-
|
|
149
|
-
### Programmer Errors (isOperational: false)
|
|
150
|
-
|
|
151
|
-
**Unexpected errors that indicate bugs**
|
|
152
|
-
|
|
153
|
-
- TypeError
|
|
154
|
-
- ReferenceError
|
|
155
|
-
- SyntaxError
|
|
156
|
-
- RangeError
|
|
157
|
-
- Unhandled exceptions
|
|
158
|
-
- Any error not explicitly thrown as AppError
|
|
159
|
-
|
|
160
|
-
**Behavior:**
|
|
161
|
-
|
|
162
|
-
- ✅ Logged as ERROR
|
|
163
|
-
- ✅ FULL stack trace logged
|
|
164
|
-
- ✅ Generic message sent to client in production
|
|
165
|
-
- ✅ Full details shown in development
|
|
166
|
-
|
|
167
|
-
---
|
|
168
|
-
|
|
169
|
-
## 🎓 Golden Rules
|
|
170
|
-
|
|
171
|
-
1. ✅ **Always wrap async handlers** with asyncHandler
|
|
172
|
-
2. ✅ **Always throw AppError** (not res.status().json())
|
|
173
|
-
3. ✅ **Always validate** with validateRequest middleware
|
|
174
|
-
4. ✅ **Always include context** when throwing errors
|
|
175
|
-
5. ✅ **Always use sendSuccess()** for success responses
|
|
176
|
-
6. ❌ **Never use res.status().json()** for errors
|
|
177
|
-
7. ❌ **Never catch errors silently**
|
|
178
|
-
8. ❌ **Never mix error handling styles**
|
|
179
|
-
|
|
180
|
-
---
|
|
181
|
-
|
|
182
|
-
## 🔍 Testing the System
|
|
183
|
-
|
|
184
|
-
### Manual Test Cases
|
|
185
|
-
|
|
186
|
-
1. **Valid request** → 200 with data
|
|
187
|
-
2. **Invalid input** → 422 with field errors
|
|
188
|
-
3. **Not found** → 404 with context
|
|
189
|
-
4. **Duplicate** → 409 with message
|
|
190
|
-
5. **Unauthorized** → 401 with message
|
|
191
|
-
6. **Forbidden** → 403 with message
|
|
192
|
-
7. **Programmer error** → 500 (generic in prod, detailed in dev)
|
|
193
|
-
8. **Unhandled error** → Caught and logged
|
|
194
|
-
|
|
195
|
-
### Run API Tests
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
node test-api.js
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## 📈 Production Readiness
|
|
204
|
-
|
|
205
|
-
### Before Deploying
|
|
206
|
-
|
|
207
|
-
- [ ] Set `NODE_ENV=production` in .env
|
|
208
|
-
- [ ] Configure `CORS_ORIGIN` for your domain
|
|
209
|
-
- [ ] Set `LOG_LEVEL` appropriately
|
|
210
|
-
- [ ] Test all endpoints with error cases
|
|
211
|
-
- [ ] Verify error responses don't leak secrets
|
|
212
|
-
- [ ] Set up error monitoring (e.g., Sentry)
|
|
213
|
-
- [ ] Configure structured logging sink
|
|
214
|
-
- [ ] Test graceful shutdown behavior
|
|
215
|
-
|
|
216
|
-
### Error Monitoring
|
|
217
|
-
|
|
218
|
-
Monitor these metrics:
|
|
219
|
-
|
|
220
|
-
- 4xx error rate (client errors)
|
|
221
|
-
- 5xx error rate (server errors)
|
|
222
|
-
- Error rate by endpoint
|
|
223
|
-
- Error rate by error code
|
|
224
|
-
- Response time percentiles
|
|
225
|
-
- Unhandled exception rate
|
|
226
|
-
|
|
227
|
-
---
|
|
228
|
-
|
|
229
|
-
## 📚 Documentation Files
|
|
230
|
-
|
|
231
|
-
| File | Purpose | Audience |
|
|
232
|
-
| -------------------------------------------------------- | -------------- | ---------- |
|
|
233
|
-
| [COMPLETE.md](COMPLETE.md) | Final summary | Everyone |
|
|
234
|
-
| [QUICK_REFERENCE.md](QUICK_REFERENCE.md) | Quick start | Developers |
|
|
235
|
-
| [ERROR_HANDLING.md](ERROR_HANDLING.md) | Full guide | Architects |
|
|
236
|
-
| [ARCHITECTURE_DIAGRAMS.md](ARCHITECTURE_DIAGRAMS.md) | Visual arch | Architects |
|
|
237
|
-
| [IMPLEMENTATION_COMPLETE.md](IMPLEMENTATION_COMPLETE.md) | Implementation | DevOps |
|
|
238
|
-
|
|
239
|
-
---
|
|
240
|
-
|
|
241
|
-
## 🚀 Starting the Server
|
|
242
|
-
|
|
243
|
-
```bash
|
|
244
|
-
# Development
|
|
245
|
-
npm run dev
|
|
246
|
-
|
|
247
|
-
# Production
|
|
248
|
-
npm start
|
|
249
|
-
|
|
250
|
-
# Testing
|
|
251
|
-
node test-api.js
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
## ✨ What You Get
|
|
257
|
-
|
|
258
|
-
✅ Centralized error handling
|
|
259
|
-
✅ Proper error classification
|
|
260
|
-
✅ Comprehensive logging
|
|
261
|
-
✅ Secure error responses
|
|
262
|
-
✅ Development-friendly output
|
|
263
|
-
✅ Production-safe responses
|
|
264
|
-
✅ Consistent JSON format
|
|
265
|
-
✅ Full stack traces (in dev)
|
|
266
|
-
✅ Error context tracking
|
|
267
|
-
✅ Request logging
|
|
268
|
-
✅ Async error catching
|
|
269
|
-
✅ Graceful shutdown
|
|
270
|
-
|
|
271
|
-
---
|
|
272
|
-
|
|
273
|
-
## 🎯 Status: COMPLETE ✅
|
|
274
|
-
|
|
275
|
-
All components implemented. All files created. All documentation written.
|
|
276
|
-
|
|
277
|
-
**Your production-grade error handling system is ready to deploy.** 🚀
|
|
278
|
-
|
|
279
|
-
Every error flows through one place. Every response is consistent. This is where engineering starts. 🎓
|
package/template/js/COMPLETE.md
DELETED
|
@@ -1,405 +0,0 @@
|
|
|
1
|
-
# ✅ PRODUCTION-LEVEL ERROR HANDLING - COMPLETE
|
|
2
|
-
|
|
3
|
-
## 🎯 Mission Accomplished
|
|
4
|
-
|
|
5
|
-
**No more random `res.status(500).json(...)`**
|
|
6
|
-
|
|
7
|
-
Your Express backend now has an **enterprise-grade, centralized error handling system** that distinguishes between operational and programmer errors, with comprehensive logging and consistent JSON responses.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## 📂 What Was Built
|
|
12
|
-
|
|
13
|
-
### Core Error System
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
src/
|
|
17
|
-
├── utils/
|
|
18
|
-
│ ├── AppError.js [NEW] Error class hierarchy
|
|
19
|
-
│ │ ├── AppError (base)
|
|
20
|
-
│ │ ├── ValidationError (422)
|
|
21
|
-
│ │ ├── AuthenticationError (401)
|
|
22
|
-
│ │ ├── AuthorizationError (403)
|
|
23
|
-
│ │ ├── NotFoundError (404)
|
|
24
|
-
│ │ ├── ConflictError (409)
|
|
25
|
-
│ │ ├── BadRequestError (400)
|
|
26
|
-
│ │ └── InternalServerError (500)
|
|
27
|
-
│ │
|
|
28
|
-
│ ├── logger.js [ENHANCED] Color-coded logging with stacks
|
|
29
|
-
│ │ ├── debug(), info(), warn(), error()
|
|
30
|
-
│ │ └── fatal() for unhandled errors
|
|
31
|
-
│ │
|
|
32
|
-
│ └── response.js [MAINTAINED] Success response helpers
|
|
33
|
-
│
|
|
34
|
-
├── middlewares/
|
|
35
|
-
│ ├── errorHandler.js [REWRITTEN] Global error handler
|
|
36
|
-
│ │ ├── errorHandler() - Global middleware (MUST BE LAST)
|
|
37
|
-
│ │ ├── asyncHandler() - Wrapper for async routes
|
|
38
|
-
│ │ ├── normalizeError() - Error type conversion
|
|
39
|
-
│ │ ├── logError() - Contextual logging
|
|
40
|
-
│ │ └── sendErrorResponse() - Client response
|
|
41
|
-
│ │
|
|
42
|
-
│ ├── validateRequest.js [UPDATED] Validation middleware
|
|
43
|
-
│ │ └── Throws ValidationError on failure
|
|
44
|
-
│ │
|
|
45
|
-
│ └── requestLogger.js [IMPROVED] Request logging
|
|
46
|
-
│ └── Logs all requests with context
|
|
47
|
-
│
|
|
48
|
-
├── config/
|
|
49
|
-
│ ├── env.js [MAINTAINED] Environment validation
|
|
50
|
-
│ └── constants.js [MAINTAINED] Status codes & messages
|
|
51
|
-
│
|
|
52
|
-
├── app.js [UPDATED] Express setup
|
|
53
|
-
│ └── errorHandler as last middleware
|
|
54
|
-
│
|
|
55
|
-
├── server.js [UPDATED] Graceful shutdown
|
|
56
|
-
│ └── Proper cleanup on SIGTERM/SIGINT
|
|
57
|
-
│
|
|
58
|
-
├── routes.js [UPDATED] Example routes
|
|
59
|
-
│ └── Using new error classes
|
|
60
|
-
│
|
|
61
|
-
└── modules/health/controller.js [UPDATED] Example handlers
|
|
62
|
-
└── Using asyncHandler & errors
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
## 🎓 How to Use
|
|
68
|
-
|
|
69
|
-
### 1️⃣ Throw Errors (Never use res.status().json!)
|
|
70
|
-
|
|
71
|
-
```javascript
|
|
72
|
-
// ✅ Correct - Throw AppError
|
|
73
|
-
throw new NotFoundError("User", { id: userId });
|
|
74
|
-
throw new ValidationError("Invalid email", errors);
|
|
75
|
-
throw new AuthenticationError("Invalid credentials");
|
|
76
|
-
throw new ConflictError("Email already exists");
|
|
77
|
-
|
|
78
|
-
// ❌ Wrong - Never use res.status()
|
|
79
|
-
res.status(404).json({ error: "User not found" });
|
|
80
|
-
res.status(500).json({ error: "Something went wrong" });
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### 2️⃣ Wrap Async Handlers
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
86
|
-
// ✅ Correct
|
|
87
|
-
import { asyncHandler } from "./middlewares/errorHandler.js";
|
|
88
|
-
|
|
89
|
-
router.get(
|
|
90
|
-
"/users/:id",
|
|
91
|
-
asyncHandler(async (req, res) => {
|
|
92
|
-
const user = await User.findById(req.params.id);
|
|
93
|
-
if (!user) throw new NotFoundError("User");
|
|
94
|
-
sendSuccess(res, user);
|
|
95
|
-
}),
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
// ❌ Wrong
|
|
99
|
-
router.get("/users/:id", async (req, res) => {
|
|
100
|
-
const user = await User.findById(req.params.id); // Error leaks!
|
|
101
|
-
sendSuccess(res, user);
|
|
102
|
-
});
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### 3️⃣ Validate Requests
|
|
106
|
-
|
|
107
|
-
```javascript
|
|
108
|
-
import { validateRequest } from "./middlewares/validateRequest.js";
|
|
109
|
-
import { z } from "zod";
|
|
110
|
-
|
|
111
|
-
const schema = z.object({
|
|
112
|
-
body: z.object({
|
|
113
|
-
email: z.string().email(),
|
|
114
|
-
name: z.string().min(1),
|
|
115
|
-
}),
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
router.post(
|
|
119
|
-
"/users",
|
|
120
|
-
validateRequest(schema),
|
|
121
|
-
asyncHandler(async (req, res) => {
|
|
122
|
-
// req.validatedData.body is already validated
|
|
123
|
-
const user = await User.create(req.validatedData.body);
|
|
124
|
-
sendSuccess(res, user, 201, "User created");
|
|
125
|
-
}),
|
|
126
|
-
);
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### 4️⃣ Always Send Success Responses Using Helper
|
|
130
|
-
|
|
131
|
-
```javascript
|
|
132
|
-
import { sendSuccess } from "./utils/response.js";
|
|
133
|
-
|
|
134
|
-
// ✅ Correct
|
|
135
|
-
router.get(
|
|
136
|
-
"/users",
|
|
137
|
-
asyncHandler(async (req, res) => {
|
|
138
|
-
const users = await User.find();
|
|
139
|
-
sendSuccess(res, users, 200, "Users fetched successfully");
|
|
140
|
-
}),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
// ❌ Wrong
|
|
144
|
-
router.get("/users", async (req, res) => {
|
|
145
|
-
const users = await User.find();
|
|
146
|
-
res.json(users); // Inconsistent format
|
|
147
|
-
});
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## 🔍 What Happens When An Error Occurs
|
|
153
|
-
|
|
154
|
-
```
|
|
155
|
-
Request comes in
|
|
156
|
-
↓
|
|
157
|
-
Route Handler throws error (intentional or accidental)
|
|
158
|
-
↓
|
|
159
|
-
asyncHandler catches it
|
|
160
|
-
↓
|
|
161
|
-
Global errorHandler middleware (last in chain)
|
|
162
|
-
↓
|
|
163
|
-
Error normalized to AppError
|
|
164
|
-
↓
|
|
165
|
-
Error classified:
|
|
166
|
-
├─ Operational? (expected error)
|
|
167
|
-
│ └─ Log as WARN, send full details to client
|
|
168
|
-
│
|
|
169
|
-
└─ Programmer? (unexpected bug)
|
|
170
|
-
├─ Log as ERROR with full stack trace
|
|
171
|
-
└─ Send generic message in production
|
|
172
|
-
↓
|
|
173
|
-
Consistent JSON response sent to client
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
## 📊 Logging Examples
|
|
179
|
-
|
|
180
|
-
### Operational Error (WARN)
|
|
181
|
-
|
|
182
|
-
```
|
|
183
|
-
[2024-01-19T15:55:30.000Z] WARN: Operational Error: NOT_FOUND
|
|
184
|
-
{
|
|
185
|
-
"type": "OPERATIONAL",
|
|
186
|
-
"code": "NOT_FOUND",
|
|
187
|
-
"message": "User not found",
|
|
188
|
-
"statusCode": 404,
|
|
189
|
-
"method": "GET",
|
|
190
|
-
"path": "/api/users/999"
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Programmer Error (ERROR with stack)
|
|
195
|
-
|
|
196
|
-
```
|
|
197
|
-
[2024-01-19T15:55:30.000Z] ERROR: Programmer Error: REFERENCE_ERROR
|
|
198
|
-
{
|
|
199
|
-
"type": "PROGRAMMER",
|
|
200
|
-
"code": "REFERENCE_ERROR",
|
|
201
|
-
"message": "user is not defined",
|
|
202
|
-
"statusCode": 500,
|
|
203
|
-
"method": "GET",
|
|
204
|
-
"path": "/api/users/123"
|
|
205
|
-
}
|
|
206
|
-
ReferenceError: user is not defined
|
|
207
|
-
at getUserHandler (/app/src/modules/users/controller.js:15:3)
|
|
208
|
-
at processRequest (/app/src/middlewares/errorHandler.js:42:5)
|
|
209
|
-
...
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## 📝 Response Formats
|
|
215
|
-
|
|
216
|
-
### ✅ Success (200, 201, etc.)
|
|
217
|
-
|
|
218
|
-
```json
|
|
219
|
-
{
|
|
220
|
-
"success": true,
|
|
221
|
-
"message": "User created successfully",
|
|
222
|
-
"data": { "id": "123", "name": "John" },
|
|
223
|
-
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### ❌ Validation Error (422)
|
|
228
|
-
|
|
229
|
-
```json
|
|
230
|
-
{
|
|
231
|
-
"success": false,
|
|
232
|
-
"message": "Validation failed",
|
|
233
|
-
"code": "VALIDATION_ERROR",
|
|
234
|
-
"statusCode": 422,
|
|
235
|
-
"errors": [
|
|
236
|
-
{ "field": "email", "message": "Invalid email", "code": "invalid_email" }
|
|
237
|
-
],
|
|
238
|
-
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
239
|
-
}
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### ❌ Not Found (404)
|
|
243
|
-
|
|
244
|
-
```json
|
|
245
|
-
{
|
|
246
|
-
"success": false,
|
|
247
|
-
"message": "User not found",
|
|
248
|
-
"code": "NOT_FOUND",
|
|
249
|
-
"statusCode": 404,
|
|
250
|
-
"context": { "id": "999" },
|
|
251
|
-
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### ❌ Programmer Error (Production)
|
|
256
|
-
|
|
257
|
-
```json
|
|
258
|
-
{
|
|
259
|
-
"success": false,
|
|
260
|
-
"message": "Internal server error",
|
|
261
|
-
"code": "INTERNAL_SERVER_ERROR",
|
|
262
|
-
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
263
|
-
}
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## 📚 Documentation Files
|
|
269
|
-
|
|
270
|
-
| File | Purpose |
|
|
271
|
-
| -------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|
272
|
-
| [ERROR_HANDLING.md](ERROR_HANDLING.md) | **Comprehensive guide** - Architecture, usage, best practices, examples |
|
|
273
|
-
| [QUICK_REFERENCE.md](QUICK_REFERENCE.md) | **Quick start** - Error classes, usage patterns, golden rules |
|
|
274
|
-
| [ARCHITECTURE_DIAGRAMS.md](ARCHITECTURE_DIAGRAMS.md) | **Visual diagrams** - Error flow, middleware stack, decision trees |
|
|
275
|
-
| [IMPLEMENTATION_COMPLETE.md](IMPLEMENTATION_COMPLETE.md) | **Implementation details** - Full API response examples |
|
|
276
|
-
|
|
277
|
-
---
|
|
278
|
-
|
|
279
|
-
## ✨ Key Features Implemented
|
|
280
|
-
|
|
281
|
-
| Feature | Status | Details |
|
|
282
|
-
| ------------------------- | ------ | ------------------------------------- |
|
|
283
|
-
| Centralized Error Handler | ✅ | All errors flow through one place |
|
|
284
|
-
| Error Classification | ✅ | Operational vs Programmer errors |
|
|
285
|
-
| Error Classes | ✅ | 8 specialized error types |
|
|
286
|
-
| Async Error Wrapping | ✅ | asyncHandler prevents promise leaks |
|
|
287
|
-
| Zod Integration | ✅ | Automatic validation error formatting |
|
|
288
|
-
| Request Validation Mw | ✅ | Validates body, query, params |
|
|
289
|
-
| Structured Logging | ✅ | Color-coded with levels & context |
|
|
290
|
-
| Stack Trace Logging | ✅ | Full traces for programmer errors |
|
|
291
|
-
| Production Sanitization | ✅ | Hides details in production |
|
|
292
|
-
| Graceful Shutdown | ✅ | Proper cleanup on signals |
|
|
293
|
-
| Consistent JSON Format | ✅ | All responses standardized |
|
|
294
|
-
| Request Logging | ✅ | Logs method, path, status, duration |
|
|
295
|
-
| Unhandled Exceptions | ✅ | Caught and logged at exit |
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## 🚀 Running Your API
|
|
300
|
-
|
|
301
|
-
```bash
|
|
302
|
-
# Development (with auto-reload)
|
|
303
|
-
npm run dev
|
|
304
|
-
|
|
305
|
-
# Production
|
|
306
|
-
npm start
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
Output:
|
|
310
|
-
|
|
311
|
-
```
|
|
312
|
-
[2024-01-19T15:55:01.329Z] INFO: Express app configured successfully
|
|
313
|
-
[2024-01-19T15:55:01.329Z] INFO: 🔥 Server running in development mode {
|
|
314
|
-
"url": "http://localhost:3000",
|
|
315
|
-
"port": 3000
|
|
316
|
-
}
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
---
|
|
320
|
-
|
|
321
|
-
## 🎯 Next Steps
|
|
322
|
-
|
|
323
|
-
1. **Read [QUICK_REFERENCE.md](QUICK_REFERENCE.md)** for quick start patterns
|
|
324
|
-
2. **Check [ERROR_HANDLING.md](ERROR_HANDLING.md)** for comprehensive guide
|
|
325
|
-
3. **Start building endpoints** using the patterns shown
|
|
326
|
-
4. **Deploy with confidence** - your error handling is production-ready
|
|
327
|
-
|
|
328
|
-
---
|
|
329
|
-
|
|
330
|
-
## 💡 Example: Creating a User Endpoint
|
|
331
|
-
|
|
332
|
-
```javascript
|
|
333
|
-
import {
|
|
334
|
-
asyncHandler,
|
|
335
|
-
ConflictError,
|
|
336
|
-
ValidationError,
|
|
337
|
-
} from "./middlewares/errorHandler.js";
|
|
338
|
-
import { validateRequest } from "./middlewares/validateRequest.js";
|
|
339
|
-
import { sendSuccess } from "./utils/response.js";
|
|
340
|
-
import { z } from "zod";
|
|
341
|
-
|
|
342
|
-
// 1. Define validation schema
|
|
343
|
-
const createUserSchema = z.object({
|
|
344
|
-
body: z.object({
|
|
345
|
-
email: z.string().email("Invalid email"),
|
|
346
|
-
name: z.string().min(1, "Name required").max(100),
|
|
347
|
-
password: z.string().min(8, "Min 8 chars"),
|
|
348
|
-
}),
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
// 2. Export handler wrapped with asyncHandler
|
|
352
|
-
export const createUser = asyncHandler(async (req, res) => {
|
|
353
|
-
const { email, name, password } = req.validatedData.body;
|
|
354
|
-
|
|
355
|
-
// Check for duplicate (operational error)
|
|
356
|
-
const exists = await User.findOne({ email });
|
|
357
|
-
if (exists) {
|
|
358
|
-
throw new ConflictError("User with this email already exists", { email });
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// Create user
|
|
362
|
-
const user = await User.create({ email, name, password });
|
|
363
|
-
|
|
364
|
-
// Send success response
|
|
365
|
-
sendSuccess(res, user, 201, "User created successfully");
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
// 3. Use in routes
|
|
369
|
-
router.post("/users", validateRequest(createUserSchema), createUser);
|
|
370
|
-
|
|
371
|
-
// That's it! Errors are automatically caught and handled:
|
|
372
|
-
// ✅ Validation errors → 422 with field details
|
|
373
|
-
// ✅ Duplicate email → 409 Conflict
|
|
374
|
-
// ✅ Database error → 500 with stack trace (dev only)
|
|
375
|
-
// ✅ Any unexpected error → 500 with full logging
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
---
|
|
379
|
-
|
|
380
|
-
## 🏆 You Now Have
|
|
381
|
-
|
|
382
|
-
✅ **A complete, production-grade error handling system**
|
|
383
|
-
✅ **Every error flows through one centralized handler**
|
|
384
|
-
✅ **Operational vs Programmer errors are distinguished**
|
|
385
|
-
✅ **Comprehensive logging with context**
|
|
386
|
-
✅ **Consistent JSON response format**
|
|
387
|
-
✅ **Security: Production sanitization of errors**
|
|
388
|
-
✅ **Development debugging: Full stack traces**
|
|
389
|
-
✅ **Enterprise-ready error management**
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
|
-
## 📞 Support
|
|
394
|
-
|
|
395
|
-
For detailed examples and patterns, see:
|
|
396
|
-
|
|
397
|
-
- **[ERROR_HANDLING.md](ERROR_HANDLING.md)** - Full documentation with examples
|
|
398
|
-
- **[QUICK_REFERENCE.md](QUICK_REFERENCE.md)** - Quick patterns and golden rules
|
|
399
|
-
- **[ARCHITECTURE_DIAGRAMS.md](ARCHITECTURE_DIAGRAMS.md)** - Visual architecture
|
|
400
|
-
|
|
401
|
-
---
|
|
402
|
-
|
|
403
|
-
**Your API is now ready for production.** 🚀
|
|
404
|
-
|
|
405
|
-
Every error goes through one place. Every response is consistent. Every issue is properly logged. That's what engineering looks like. 🎯
|