create-charcole 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 +398 -0
- package/bin/index.js +62 -0
- package/package.json +24 -0
- package/template/.env.example +8 -0
- package/template/ARCHITECTURE_DIAGRAMS.md +283 -0
- package/template/CHECKLIST.md +279 -0
- package/template/COMPLETE.md +405 -0
- package/template/ERROR_HANDLING.md +393 -0
- package/template/IMPLEMENTATION.md +368 -0
- package/template/IMPLEMENTATION_COMPLETE.md +363 -0
- package/template/INDEX.md +290 -0
- package/template/QUICK_REFERENCE.md +270 -0
- package/template/README.md +855 -0
- package/template/package-lock.json +1253 -0
- package/template/package.json +28 -0
- package/template/src/app.js +75 -0
- package/template/src/config/constants.js +20 -0
- package/template/src/config/env.js +26 -0
- package/template/src/middlewares/errorHandler.js +180 -0
- package/template/src/middlewares/requestLogger.js +33 -0
- package/template/src/middlewares/validateRequest.js +42 -0
- package/template/src/modules/health/controller.js +50 -0
- package/template/src/routes.js +17 -0
- package/template/src/server.js +38 -0
- package/template/src/utils/AppError.js +182 -0
- package/template/src/utils/logger.js +73 -0
- package/template/src/utils/response.js +51 -0
- package/template/test-api.js +100 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Production-Level Error Handling - Implementation Complete
|
|
2
|
+
|
|
3
|
+
## ✅ System Architecture
|
|
4
|
+
|
|
5
|
+
Your Express API now has a **true production-grade error handling system** with:
|
|
6
|
+
|
|
7
|
+
### 1. **Centralized Error Handler**
|
|
8
|
+
|
|
9
|
+
- Single middleware catches all errors
|
|
10
|
+
- Consistent JSON response format
|
|
11
|
+
- Global entry point for all error handling
|
|
12
|
+
|
|
13
|
+
### 2. **Error Classification**
|
|
14
|
+
|
|
15
|
+
#### Operational Errors (Expected)
|
|
16
|
+
|
|
17
|
+
- Validation errors (422)
|
|
18
|
+
- Not found (404)
|
|
19
|
+
- Authentication failures (401)
|
|
20
|
+
- Authorization failures (403)
|
|
21
|
+
- Conflict/duplicates (409)
|
|
22
|
+
- Bad requests (400)
|
|
23
|
+
|
|
24
|
+
**All operational errors are:**
|
|
25
|
+
|
|
26
|
+
- ✅ Logged as WARN level
|
|
27
|
+
- ✅ Safe to send to client
|
|
28
|
+
- ✅ Include error codes and context
|
|
29
|
+
|
|
30
|
+
#### Programmer Errors (Bugs)
|
|
31
|
+
|
|
32
|
+
- TypeError, ReferenceError, SyntaxError, RangeError
|
|
33
|
+
- Unhandled exceptions
|
|
34
|
+
- Any thrown error not explicitly handled
|
|
35
|
+
|
|
36
|
+
**All programmer errors are:**
|
|
37
|
+
|
|
38
|
+
- ✅ Logged as ERROR with full stack trace
|
|
39
|
+
- ✅ HIDDEN from client in production
|
|
40
|
+
- ✅ Only generic message sent ("Internal server error")
|
|
41
|
+
|
|
42
|
+
### 3. **Error Class Hierarchy**
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
AppError (base)
|
|
46
|
+
├── ValidationError
|
|
47
|
+
├── AuthenticationError
|
|
48
|
+
├── AuthorizationError
|
|
49
|
+
├── NotFoundError
|
|
50
|
+
├── ConflictError
|
|
51
|
+
├── BadRequestError
|
|
52
|
+
└── InternalServerError
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 4. **Async Error Wrapper**
|
|
56
|
+
|
|
57
|
+
All async routes must use `asyncHandler`:
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
import { asyncHandler } from "./middlewares/errorHandler.js";
|
|
61
|
+
|
|
62
|
+
// ✅ Correct - errors caught
|
|
63
|
+
router.get(
|
|
64
|
+
"/users/:id",
|
|
65
|
+
asyncHandler(async (req, res) => {
|
|
66
|
+
const user = await findUser(req.params.id);
|
|
67
|
+
sendSuccess(res, user);
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// ❌ Wrong - errors NOT caught
|
|
72
|
+
router.get("/users/:id", async (req, res) => {
|
|
73
|
+
const user = await findUser(req.params.id); // If this fails, error not handled
|
|
74
|
+
sendSuccess(res, user);
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 📋 File Structure
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
src/
|
|
82
|
+
├── utils/
|
|
83
|
+
│ ├── AppError.js ← Error classes
|
|
84
|
+
│ ├── logger.js ← Enhanced logger with stacks
|
|
85
|
+
│ └── response.js ← Success response helpers
|
|
86
|
+
├── middlewares/
|
|
87
|
+
│ ├── errorHandler.js ← Global error handler + asyncHandler
|
|
88
|
+
│ ├── validateRequest.js ← Throws ValidationError
|
|
89
|
+
│ └── requestLogger.js ← Logs all requests
|
|
90
|
+
├── modules/
|
|
91
|
+
│ └── health/controller.js ← Example handlers
|
|
92
|
+
├── app.js ← Express setup with error handler
|
|
93
|
+
└── server.js ← Server startup
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 🎯 API Response Examples
|
|
97
|
+
|
|
98
|
+
### ✅ Success Response (200)
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"success": true,
|
|
103
|
+
"message": "Success",
|
|
104
|
+
"data": {
|
|
105
|
+
"status": "healthy",
|
|
106
|
+
"uptime": 42.123,
|
|
107
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
108
|
+
},
|
|
109
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### ✅ Created Response (201)
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"success": true,
|
|
118
|
+
"message": "Item created successfully",
|
|
119
|
+
"data": {
|
|
120
|
+
"id": "abc123",
|
|
121
|
+
"name": "Test Item",
|
|
122
|
+
"description": "A test item",
|
|
123
|
+
"createdAt": "2024-01-19T15:55:30.000Z"
|
|
124
|
+
},
|
|
125
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### ❌ Validation Error (422)
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"success": false,
|
|
134
|
+
"message": "Validation failed",
|
|
135
|
+
"code": "VALIDATION_ERROR",
|
|
136
|
+
"statusCode": 422,
|
|
137
|
+
"errors": [
|
|
138
|
+
{
|
|
139
|
+
"field": "name",
|
|
140
|
+
"message": "Name is required",
|
|
141
|
+
"code": "too_small"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"field": "email",
|
|
145
|
+
"message": "Invalid email address",
|
|
146
|
+
"code": "invalid_string"
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### ❌ Not Found Error (404)
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"success": false,
|
|
158
|
+
"message": "User not found",
|
|
159
|
+
"code": "NOT_FOUND",
|
|
160
|
+
"statusCode": 404,
|
|
161
|
+
"context": {
|
|
162
|
+
"id": "123"
|
|
163
|
+
},
|
|
164
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### ❌ Authentication Error (401)
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"success": false,
|
|
173
|
+
"message": "Invalid credentials",
|
|
174
|
+
"code": "AUTHENTICATION_ERROR",
|
|
175
|
+
"statusCode": 401,
|
|
176
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### ❌ Authorization Error (403)
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"success": false,
|
|
185
|
+
"message": "You don't have permission",
|
|
186
|
+
"code": "AUTHORIZATION_ERROR",
|
|
187
|
+
"statusCode": 403,
|
|
188
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### ❌ Server Error (500) - Production
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"success": false,
|
|
197
|
+
"message": "Internal server error",
|
|
198
|
+
"code": "INTERNAL_SERVER_ERROR",
|
|
199
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### ❌ Server Error (500) - Development
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"success": false,
|
|
208
|
+
"message": "Cannot read property 'name' of undefined",
|
|
209
|
+
"code": "INTERNAL_SERVER_ERROR",
|
|
210
|
+
"statusCode": 500,
|
|
211
|
+
"context": {
|
|
212
|
+
"type": "TypeError"
|
|
213
|
+
},
|
|
214
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## 🪵 Logging Examples
|
|
219
|
+
|
|
220
|
+
### Operational Error Logged (WARN)
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
[2024-01-19T15:55:30.000Z] WARN: Operational Error: NOT_FOUND
|
|
224
|
+
{
|
|
225
|
+
"type": "OPERATIONAL",
|
|
226
|
+
"code": "NOT_FOUND",
|
|
227
|
+
"message": "User not found",
|
|
228
|
+
"statusCode": 404,
|
|
229
|
+
"method": "GET",
|
|
230
|
+
"path": "/api/users/999",
|
|
231
|
+
"query": {},
|
|
232
|
+
"ip": "::1"
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Programmer Error Logged (ERROR with stack)
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
[2024-01-19T15:55:30.000Z] ERROR: Programmer Error: REFERENCE_ERROR
|
|
240
|
+
{
|
|
241
|
+
"type": "PROGRAMMER",
|
|
242
|
+
"code": "REFERENCE_ERROR",
|
|
243
|
+
"message": "user is not defined",
|
|
244
|
+
"statusCode": 500,
|
|
245
|
+
"method": "POST",
|
|
246
|
+
"path": "/api/users",
|
|
247
|
+
"ip": "::1"
|
|
248
|
+
}
|
|
249
|
+
ReferenceError: user is not defined
|
|
250
|
+
at getUserHandler (/app/src/modules/users/controller.js:15:3)
|
|
251
|
+
at processRequest (/app/src/middlewares/errorHandler.js:42:5)
|
|
252
|
+
...
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## 💡 Usage Examples
|
|
256
|
+
|
|
257
|
+
### Creating a User with Validation
|
|
258
|
+
|
|
259
|
+
```javascript
|
|
260
|
+
import { asyncHandler, ConflictError } from "./middlewares/errorHandler.js";
|
|
261
|
+
import { sendSuccess } from "./utils/response.js";
|
|
262
|
+
|
|
263
|
+
export const createUser = asyncHandler(async (req, res) => {
|
|
264
|
+
const { email, name } = req.validatedData.body;
|
|
265
|
+
|
|
266
|
+
// Check for duplicate
|
|
267
|
+
const exists = await User.findOne({ email });
|
|
268
|
+
if (exists) {
|
|
269
|
+
throw new ConflictError("User with this email already exists", { email });
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Create user
|
|
273
|
+
const user = await User.create({ email, name });
|
|
274
|
+
sendSuccess(res, user, 201, "User created successfully");
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Protected Endpoint with Auth
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
export const updateUser = asyncHandler(async (req, res) => {
|
|
282
|
+
const user = await User.findById(req.params.id);
|
|
283
|
+
|
|
284
|
+
if (!user) {
|
|
285
|
+
throw new NotFoundError("User", { id: req.params.id });
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Check authorization
|
|
289
|
+
if (user.id !== req.user.id) {
|
|
290
|
+
throw new AuthorizationError("You can only update your own profile");
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const updated = await user.updateOne(req.validatedData.body);
|
|
294
|
+
sendSuccess(res, updated, 200, "User updated");
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Fetching with Proper Error Handling
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
import { asyncHandler, NotFoundError } from "./middlewares/errorHandler.js";
|
|
302
|
+
|
|
303
|
+
export const getUser = asyncHandler(async (req, res) => {
|
|
304
|
+
const user = await User.findById(req.params.id);
|
|
305
|
+
|
|
306
|
+
if (!user) {
|
|
307
|
+
throw new NotFoundError("User", { id: req.params.id });
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
sendSuccess(res, user);
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## 🚀 Running the Server
|
|
315
|
+
|
|
316
|
+
**Development** (with auto-reload):
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
npm run dev
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Production**:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
npm start
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
The server will start and log:
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
[2024-01-19T15:55:01.329Z] INFO: Express app configured successfully
|
|
332
|
+
[2024-01-19T15:55:01.329Z] INFO: 🔥 Server running in development mode {
|
|
333
|
+
"url": "http://localhost:3000",
|
|
334
|
+
"port": 3000
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## ✅ Key Features
|
|
339
|
+
|
|
340
|
+
- ✅ **No More res.status().json()** - Everything goes through AppError
|
|
341
|
+
- ✅ **Single Error Entrypoint** - Global error handler catches everything
|
|
342
|
+
- ✅ **Operational vs Programmer Errors** - Different handling for each
|
|
343
|
+
- ✅ **Detailed Logging** - Full context logged for debugging
|
|
344
|
+
- ✅ **Production Safe** - Hides sensitive details in production
|
|
345
|
+
- ✅ **Validation Errors** - Field-level error details
|
|
346
|
+
- ✅ **Async Error Wrapper** - asyncHandler prevents promise rejection leaks
|
|
347
|
+
- ✅ **Graceful Shutdown** - Proper cleanup on SIGTERM/SIGINT
|
|
348
|
+
- ✅ **Unhandled Exception Handling** - Catches all edge cases
|
|
349
|
+
|
|
350
|
+
## 📚 Documentation
|
|
351
|
+
|
|
352
|
+
See [ERROR_HANDLING.md](ERROR_HANDLING.md) for comprehensive documentation including:
|
|
353
|
+
|
|
354
|
+
- Architecture overview
|
|
355
|
+
- Error type reference
|
|
356
|
+
- Best practices
|
|
357
|
+
- Testing examples
|
|
358
|
+
- Production checklist
|
|
359
|
+
- Monitoring guidelines
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
**Now your API has enterprise-grade error handling where every error flows through one place with consistent JSON responses.** 🎯
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# 📚 Documentation Index
|
|
2
|
+
|
|
3
|
+
## Quick Navigation
|
|
4
|
+
|
|
5
|
+
### 🚀 Getting Started
|
|
6
|
+
|
|
7
|
+
- **[COMPLETE.md](COMPLETE.md)** - Start here! Final summary with overview
|
|
8
|
+
- **[QUICK_REFERENCE.md](QUICK_REFERENCE.md)** - Quick patterns and golden rules
|
|
9
|
+
|
|
10
|
+
### 📖 Detailed Guides
|
|
11
|
+
|
|
12
|
+
- **[ERROR_HANDLING.md](ERROR_HANDLING.md)** - Comprehensive error handling documentation
|
|
13
|
+
- **[ARCHITECTURE_DIAGRAMS.md](ARCHITECTURE_DIAGRAMS.md)** - Visual architecture & flow diagrams
|
|
14
|
+
- **[IMPLEMENTATION_COMPLETE.md](IMPLEMENTATION_COMPLETE.md)** - Full implementation details & examples
|
|
15
|
+
|
|
16
|
+
### ✅ Reference
|
|
17
|
+
|
|
18
|
+
- **[CHECKLIST.md](CHECKLIST.md)** - Implementation checklist & status
|
|
19
|
+
- **[README.md](README.md)** - Project README
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 📋 What Was Implemented
|
|
24
|
+
|
|
25
|
+
### Problem
|
|
26
|
+
|
|
27
|
+
❌ Random `res.status(500).json(...)` scattered throughout code
|
|
28
|
+
❌ No distinction between operational and programmer errors
|
|
29
|
+
❌ Inconsistent error responses
|
|
30
|
+
❌ Hard to debug
|
|
31
|
+
|
|
32
|
+
### Solution
|
|
33
|
+
|
|
34
|
+
✅ **Centralized error handler** - All errors flow through one place
|
|
35
|
+
✅ **Error classification** - Operational vs Programmer errors
|
|
36
|
+
✅ **Consistent responses** - Standardized JSON format
|
|
37
|
+
✅ **Comprehensive logging** - Full context for debugging
|
|
38
|
+
✅ **Production-safe** - Hides internal details in prod
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🎯 Core Files
|
|
43
|
+
|
|
44
|
+
### Error Classes
|
|
45
|
+
|
|
46
|
+
- `src/utils/AppError.js` - 8 specialized error types
|
|
47
|
+
|
|
48
|
+
### Middleware
|
|
49
|
+
|
|
50
|
+
- `src/middlewares/errorHandler.js` - Global error handler + asyncHandler
|
|
51
|
+
- `src/middlewares/validateRequest.js` - Validation middleware
|
|
52
|
+
- `src/middlewares/requestLogger.js` - Request logging
|
|
53
|
+
|
|
54
|
+
### Utilities
|
|
55
|
+
|
|
56
|
+
- `src/utils/logger.js` - Structured logging
|
|
57
|
+
- `src/utils/response.js` - Success responses
|
|
58
|
+
|
|
59
|
+
### Application
|
|
60
|
+
|
|
61
|
+
- `src/app.js` - Express setup
|
|
62
|
+
- `src/server.js` - Server startup
|
|
63
|
+
- `src/routes.js` - Routes
|
|
64
|
+
- `src/modules/health/controller.js` - Example handlers
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 🔍 How It Works
|
|
69
|
+
|
|
70
|
+
### Error Classes (Use These!)
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
import {
|
|
74
|
+
AppError, // Base class
|
|
75
|
+
ValidationError, // 422 - Input validation
|
|
76
|
+
AuthenticationError, // 401 - Auth failed
|
|
77
|
+
AuthorizationError, // 403 - Permission denied
|
|
78
|
+
NotFoundError, // 404 - Resource not found
|
|
79
|
+
ConflictError, // 409 - Duplicate
|
|
80
|
+
BadRequestError, // 400 - Malformed request
|
|
81
|
+
InternalServerError, // 500 - Unexpected error
|
|
82
|
+
} from "./middlewares/errorHandler.js";
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Error Flow
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
Route throws error
|
|
89
|
+
↓
|
|
90
|
+
asyncHandler catches
|
|
91
|
+
↓
|
|
92
|
+
Global error handler
|
|
93
|
+
↓
|
|
94
|
+
Error normalized & classified
|
|
95
|
+
↓
|
|
96
|
+
Logged (WARN for operational, ERROR for programmer)
|
|
97
|
+
↓
|
|
98
|
+
Consistent JSON response sent
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Usage Pattern
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
// ✅ Wrap async handlers
|
|
105
|
+
router.post(
|
|
106
|
+
"/users",
|
|
107
|
+
asyncHandler(async (req, res) => {
|
|
108
|
+
// ✅ Validate request
|
|
109
|
+
const { email } = req.validatedData.body;
|
|
110
|
+
|
|
111
|
+
// ✅ Throw AppError
|
|
112
|
+
const exists = await User.findOne({ email });
|
|
113
|
+
if (exists) throw new ConflictError("Email already exists");
|
|
114
|
+
|
|
115
|
+
// ✅ Use sendSuccess
|
|
116
|
+
const user = await User.create({ email });
|
|
117
|
+
sendSuccess(res, user, 201, "User created");
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 📊 Response Examples
|
|
125
|
+
|
|
126
|
+
### Success (200)
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"success": true,
|
|
131
|
+
"message": "Success",
|
|
132
|
+
"data": {
|
|
133
|
+
/* ... */
|
|
134
|
+
},
|
|
135
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Validation Error (422)
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"success": false,
|
|
144
|
+
"message": "Validation failed",
|
|
145
|
+
"code": "VALIDATION_ERROR",
|
|
146
|
+
"errors": [
|
|
147
|
+
{ "field": "email", "message": "Invalid email", "code": "invalid_email" }
|
|
148
|
+
],
|
|
149
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Not Found (404)
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"success": false,
|
|
158
|
+
"message": "User not found",
|
|
159
|
+
"code": "NOT_FOUND",
|
|
160
|
+
"context": { "id": "999" },
|
|
161
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Server Error (500) - Production
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"success": false,
|
|
170
|
+
"message": "Internal server error",
|
|
171
|
+
"code": "INTERNAL_SERVER_ERROR",
|
|
172
|
+
"timestamp": "2024-01-19T15:55:30.000Z"
|
|
173
|
+
}
|
|
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
|
+
{ "code": "NOT_FOUND", "message": "User not found", ... }
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Programmer Error (ERROR with stack)
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
[2024-01-19T15:55:30.000Z] ERROR: Programmer Error: REFERENCE_ERROR
|
|
191
|
+
{ "code": "REFERENCE_ERROR", "message": "user is not defined", ... }
|
|
192
|
+
ReferenceError: user is not defined
|
|
193
|
+
at handler.js:15:3
|
|
194
|
+
...
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 🚀 Running
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# Development (auto-reload)
|
|
203
|
+
npm run dev
|
|
204
|
+
|
|
205
|
+
# Production
|
|
206
|
+
npm start
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 📖 Where to Start
|
|
212
|
+
|
|
213
|
+
### I want to...
|
|
214
|
+
|
|
215
|
+
**...understand the system**
|
|
216
|
+
→ Read [COMPLETE.md](COMPLETE.md)
|
|
217
|
+
|
|
218
|
+
**...start using it quickly**
|
|
219
|
+
→ Read [QUICK_REFERENCE.md](QUICK_REFERENCE.md)
|
|
220
|
+
|
|
221
|
+
**...learn in detail**
|
|
222
|
+
→ Read [ERROR_HANDLING.md](ERROR_HANDLING.md)
|
|
223
|
+
|
|
224
|
+
**...see architecture**
|
|
225
|
+
→ Read [ARCHITECTURE_DIAGRAMS.md](ARCHITECTURE_DIAGRAMS.md)
|
|
226
|
+
|
|
227
|
+
**...see examples**
|
|
228
|
+
→ Check [IMPLEMENTATION_COMPLETE.md](IMPLEMENTATION_COMPLETE.md)
|
|
229
|
+
|
|
230
|
+
**...verify completion**
|
|
231
|
+
→ Check [CHECKLIST.md](CHECKLIST.md)
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## ✨ Key Features
|
|
236
|
+
|
|
237
|
+
- ✅ Centralized error handling
|
|
238
|
+
- ✅ Error classification (operational vs programmer)
|
|
239
|
+
- ✅ 8 specialized error classes
|
|
240
|
+
- ✅ Async error wrapper
|
|
241
|
+
- ✅ Validation error formatting
|
|
242
|
+
- ✅ Comprehensive logging with stacks
|
|
243
|
+
- ✅ Production-safe responses
|
|
244
|
+
- ✅ Request logging
|
|
245
|
+
- ✅ Graceful shutdown
|
|
246
|
+
- ✅ Unhandled exception catching
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## 🎓 Golden Rules
|
|
251
|
+
|
|
252
|
+
1. **Always wrap async handlers** with `asyncHandler`
|
|
253
|
+
2. **Always throw AppError** (never use `res.status().json()`)
|
|
254
|
+
3. **Always validate** with `validateRequest`
|
|
255
|
+
4. **Always include context** in errors
|
|
256
|
+
5. **Always use sendSuccess()** for success responses
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## 📞 Support
|
|
261
|
+
|
|
262
|
+
All documentation is included in the repository:
|
|
263
|
+
|
|
264
|
+
| Document | Purpose |
|
|
265
|
+
| -------------------------- | -------------------------- |
|
|
266
|
+
| COMPLETE.md | Overview & getting started |
|
|
267
|
+
| QUICK_REFERENCE.md | Quick patterns & rules |
|
|
268
|
+
| ERROR_HANDLING.md | Comprehensive guide |
|
|
269
|
+
| ARCHITECTURE_DIAGRAMS.md | Visual diagrams |
|
|
270
|
+
| IMPLEMENTATION_COMPLETE.md | Full details & examples |
|
|
271
|
+
| CHECKLIST.md | Status & checklist |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 🎯 Status
|
|
276
|
+
|
|
277
|
+
✅ **COMPLETE AND PRODUCTION-READY**
|
|
278
|
+
|
|
279
|
+
- All error classes implemented
|
|
280
|
+
- Global error handler working
|
|
281
|
+
- Async error wrapper in place
|
|
282
|
+
- Validation integrated
|
|
283
|
+
- Logging configured
|
|
284
|
+
- Documentation complete
|
|
285
|
+
|
|
286
|
+
Your API is ready for enterprise deployment. 🚀
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
**Every error flows through one place. Every response is consistent. That's what engineering looks like.** 🎓
|