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.
@@ -0,0 +1,368 @@
1
+ #!/usr/bin/env node
2
+
3
+ /\*\*
4
+
5
+ - ╔═════════════════════════════════════════════════════════════════════════╗
6
+ - ║ ║
7
+ - ║ ✅ PRODUCTION-LEVEL ERROR HANDLING - IMPLEMENTATION SUMMARY ║
8
+ - ║ ║
9
+ - ╚═════════════════════════════════════════════════════════════════════════╝
10
+ -
11
+ - PROBLEM SOLVED:
12
+ - ❌ No more random res.status(500).json(...) scattered throughout code
13
+ - ❌ No distinction between operational and programmer errors
14
+ - ❌ Inconsistent error response formats
15
+ - ❌ No centralized error handling
16
+ -
17
+ - SOLUTION PROVIDED:
18
+ - ✅ Centralized error handler - ALL errors flow through one place
19
+ - ✅ Error classification - Operational vs Programmer errors
20
+ - ✅ Consistent responses - Standardized JSON format everywhere
21
+ - ✅ Comprehensive logging - Full context for debugging
22
+ - ✅ Production-safe - Hides internal details in production
23
+ -
24
+ - ═════════════════════════════════════════════════════════════════════════
25
+ -
26
+ - ERROR CLASS HIERARCHY (Use these, never res.status().json()!)
27
+ - ═════════════════════════════════════════════════════════════════════════
28
+ -
29
+ - AppError (base - isOperational, code, context, cause, timestamp)
30
+ - │
31
+ - ├─ ValidationError (422) → Input validation failed
32
+ - ├─ BadRequestError (400) → Malformed request
33
+ - ├─ AuthenticationError (401) → Auth credentials invalid
34
+ - ├─ AuthorizationError (403) → Permission denied
35
+ - ├─ NotFoundError (404) → Resource doesn't exist
36
+ - ├─ ConflictError (409) → Duplicate/conflict
37
+ - └─ InternalServerError (500) → Unexpected error (programmer bug)
38
+ -
39
+ - ═════════════════════════════════════════════════════════════════════════
40
+ -
41
+ - ERROR FLOW (How every error is handled)
42
+ - ═════════════════════════════════════════════════════════════════════════
43
+ -
44
+ - Request arrives
45
+ - ↓
46
+ - Route handler (MUST wrap with asyncHandler)
47
+ - ├─ Success? → sendSuccess(res, data) → Response sent ✓
48
+ - │
49
+ - └─ Error thrown ✘
50
+ - ↓
51
+ - asyncHandler catches it
52
+ - ↓
53
+ - Global error handler middleware (MUST be last)
54
+ - ↓
55
+ - Error normalized
56
+ - ├─ AppError? → Use as is
57
+ - ├─ ZodError? → Convert to ValidationError
58
+ - ├─ TypeError? → Convert to InternalServerError
59
+ - ├─ ReferenceError? → Convert to InternalServerError
60
+ - └─ Unknown? → Wrap in InternalServerError
61
+ - ↓
62
+ - Error classified
63
+ - ├─ Operational (isOperational: true)
64
+ - │ └─ Log as WARN, send full details to client
65
+ - │
66
+ - └─ Programmer (isOperational: false)
67
+ - ├─ Log as ERROR with full stack trace
68
+ - └─ Send generic message in production
69
+ - ↓
70
+ - Consistent JSON response sent
71
+ -
72
+ - ═════════════════════════════════════════════════════════════════════════
73
+ -
74
+ - RESPONSE FORMAT (Always consistent)
75
+ - ═════════════════════════════════════════════════════════════════════════
76
+ -
77
+ - SUCCESS (200, 201, etc.)
78
+ - {
79
+ - "success": true,
80
+ - "message": "User created successfully",
81
+ - "data": { ... },
82
+ - "timestamp": "2024-01-19T15:55:30.000Z"
83
+ - }
84
+ -
85
+ - OPERATIONAL ERROR (400, 401, 403, 404, 409, 422)
86
+ - {
87
+ - "success": false,
88
+ - "message": "User not found",
89
+ - "code": "NOT_FOUND",
90
+ - "statusCode": 404,
91
+ - "context": { "id": "999" },
92
+ - "timestamp": "2024-01-19T15:55:30.000Z"
93
+ - }
94
+ -
95
+ - VALIDATION ERROR (422)
96
+ - {
97
+ - "success": false,
98
+ - "message": "Validation failed",
99
+ - "code": "VALIDATION_ERROR",
100
+ - "statusCode": 422,
101
+ - "errors": [
102
+ - { "field": "email", "message": "Invalid email", "code": "invalid_email" }
103
+ - ],
104
+ - "timestamp": "2024-01-19T15:55:30.000Z"
105
+ - }
106
+ -
107
+ - PROGRAMMER ERROR (500) - PRODUCTION
108
+ - {
109
+ - "success": false,
110
+ - "message": "Internal server error",
111
+ - "code": "INTERNAL_SERVER_ERROR",
112
+ - "timestamp": "2024-01-19T15:55:30.000Z"
113
+ - }
114
+ - (Details hidden in production)
115
+ -
116
+ - ═════════════════════════════════════════════════════════════════════════
117
+ -
118
+ - HOW TO USE (4 Golden Rules)
119
+ - ═════════════════════════════════════════════════════════════════════════
120
+ -
121
+ - 1. WRAP ASYNC HANDLERS WITH asyncHandler
122
+ - ✅ router.post("/users", asyncHandler(async (req, res) => {
123
+ - const user = await createUser(...);
124
+ - sendSuccess(res, user, 201, "Created");
125
+ - }));
126
+ - ❌ router.post("/users", async (req, res) => { ... }); // Error leaks!
127
+ -
128
+ - 2. THROW AppError (Never use res.status().json()!)
129
+ - ✅ if (!user) throw new NotFoundError("User", { id });
130
+ - ✅ if (exists) throw new ConflictError("Email already exists");
131
+ - ❌ res.status(404).json({ error: "User not found" }); // WRONG!
132
+ -
133
+ - 3. VALIDATE WITH validateRequest MIDDLEWARE
134
+ - ✅ router.post("/users", validateRequest(schema), handler);
135
+ - ❌ Just accept raw data without validation
136
+ -
137
+ - 4. SEND SUCCESS WITH sendSuccess HELPER
138
+ - ✅ sendSuccess(res, data, 200, "Success message");
139
+ - ❌ res.json(data); // Inconsistent format
140
+ -
141
+ - ═════════════════════════════════════════════════════════════════════════
142
+ -
143
+ - LOGGING BEHAVIOR
144
+ - ═════════════════════════════════════════════════════════════════════════
145
+ -
146
+ - OPERATIONAL ERROR (WARN level - expected, can be handled)
147
+ - [2024-01-19T15:55:30.000Z] WARN: Operational Error: NOT_FOUND
148
+ - {
149
+ - "type": "OPERATIONAL",
150
+ - "code": "NOT_FOUND",
151
+ - "message": "User not found",
152
+ - "statusCode": 404,
153
+ - "method": "GET",
154
+ - "path": "/api/users/999"
155
+ - }
156
+ -
157
+ - PROGRAMMER ERROR (ERROR level - unexpected, needs fixing)
158
+ - [2024-01-19T15:55:30.000Z] ERROR: Programmer Error: REFERENCE_ERROR
159
+ - {
160
+ - "type": "PROGRAMMER",
161
+ - "code": "REFERENCE_ERROR",
162
+ - "message": "user is not defined",
163
+ - "statusCode": 500,
164
+ - "method": "GET",
165
+ - "path": "/api/users/123"
166
+ - }
167
+ - ReferenceError: user is not defined
168
+ - at getUserHandler (/app/src/modules/users/controller.js:15:3)
169
+ - at processRequest (/app/src/middlewares/errorHandler.js:42:5)
170
+ - ...
171
+ -
172
+ - ═════════════════════════════════════════════════════════════════════════
173
+ -
174
+ - FILES CREATED
175
+ - ═════════════════════════════════════════════════════════════════════════
176
+ -
177
+ - NEW CORE FILES:
178
+ - • src/utils/AppError.js (8 specialized error classes)
179
+ -
180
+ - DOCUMENTATION:
181
+ - • INDEX.md (Start here!)
182
+ - • QUICK_REFERENCE.md (Quick patterns)
183
+ - • ERROR_HANDLING.md (Comprehensive guide)
184
+ - • ARCHITECTURE_DIAGRAMS.md (Visual architecture)
185
+ - • IMPLEMENTATION_COMPLETE.md (Full details)
186
+ - • COMPLETE.md (Final summary)
187
+ - • CHECKLIST.md (Status checklist)
188
+ -
189
+ - ═════════════════════════════════════════════════════════════════════════
190
+ -
191
+ - FILES UPDATED
192
+ - ═════════════════════════════════════════════════════════════════════════
193
+ -
194
+ - CORE SYSTEM:
195
+ - • src/middlewares/errorHandler.js (REWRITTEN - Global error handler)
196
+ - • src/middlewares/validateRequest.js (Updated to throw ValidationError)
197
+ - • src/middlewares/requestLogger.js (Enhanced logging)
198
+ - • src/utils/logger.js (Added stack trace support)
199
+ - • src/utils/response.js (Added documentation)
200
+ - • src/app.js (Integrated error handler)
201
+ - • src/server.js (Enhanced shutdown)
202
+ - • src/routes.js (Updated routes)
203
+ - • src/modules/health/controller.js (Updated handlers)
204
+ -
205
+ - ═════════════════════════════════════════════════════════════════════════
206
+ -
207
+ - RUNNING THE SERVER
208
+ - ═════════════════════════════════════════════════════════════════════════
209
+ -
210
+ - DEVELOPMENT (with auto-reload):
211
+ - $ npm run dev
212
+ -
213
+ - PRODUCTION:
214
+ - $ npm start
215
+ -
216
+ - SERVER STARTS WITH:
217
+ - [2024-01-19T15:55:01.329Z] INFO: Express app configured successfully
218
+ - [2024-01-19T15:55:01.329Z] INFO: 🔥 Server running in development mode {
219
+ - "url": "http://localhost:3000",
220
+ - "port": 3000
221
+ - }
222
+ -
223
+ - ═════════════════════════════════════════════════════════════════════════
224
+ -
225
+ - EXAMPLE: CREATE USER ENDPOINT
226
+ - ═════════════════════════════════════════════════════════════════════════
227
+ -
228
+ - import { asyncHandler, ConflictError } from "./middlewares/errorHandler.js";
229
+ - import { sendSuccess } from "./utils/response.js";
230
+ - import { validateRequest } from "./middlewares/validateRequest.js";
231
+ - import { z } from "zod";
232
+ -
233
+ - // 1. Define validation schema
234
+ - const createUserSchema = z.object({
235
+ - body: z.object({
236
+ - email: z.string().email("Invalid email"),
237
+ - name: z.string().min(1, "Name required"),
238
+ - }),
239
+ - });
240
+ -
241
+ - // 2. Define handler (wrapped with asyncHandler)
242
+ - export const createUser = asyncHandler(async (req, res) => {
243
+ - const { email, name } = req.validatedData.body;
244
+ -
245
+ - // Check for duplicate (throw operational error)
246
+ - const exists = await User.findOne({ email });
247
+ - if (exists) {
248
+ - throw new ConflictError("Email already exists", { email });
249
+ - }
250
+ -
251
+ - // Create user (any error thrown here is caught by global handler)
252
+ - const user = await User.create({ email, name });
253
+ -
254
+ - // Send success response
255
+ - sendSuccess(res, user, 201, "User created successfully");
256
+ - });
257
+ -
258
+ - // 3. Use in routes
259
+ - router.post("/users", validateRequest(createUserSchema), createUser);
260
+ -
261
+ - RESULT:
262
+ - ✅ Validation error (422) → Field-level details
263
+ - ✅ Duplicate email (409) → Conflict error
264
+ - ✅ Database error (500) → Stack trace logged, generic message sent
265
+ - ✅ Success (201) → Consistent success response
266
+ -
267
+ - ═════════════════════════════════════════════════════════════════════════
268
+ -
269
+ - KEY FEATURES
270
+ - ═════════════════════════════════════════════════════════════════════════
271
+ -
272
+ - ✅ Centralized error handling - All errors flow through one place
273
+ - ✅ Error classification - Operational vs Programmer errors
274
+ - ✅ 8 specialized error classes - For every common scenario
275
+ - ✅ Async error wrapper - Prevents promise rejection leaks
276
+ - ✅ Validation formatting - Field-level error details
277
+ - ✅ Comprehensive logging - Full context for debugging
278
+ - ✅ Stack trace logging - For programmer error investigation
279
+ - ✅ Production-safe responses - Hides internal details in prod
280
+ - ✅ Request logging - Method, path, status, duration
281
+ - ✅ Graceful shutdown - Proper cleanup on signals
282
+ - ✅ Unhandled exception catching - Catches all edge cases
283
+ - ✅ Consistent JSON format - All responses standardized
284
+ -
285
+ - ═════════════════════════════════════════════════════════════════════════
286
+ -
287
+ - DOCUMENTATION
288
+ - ═════════════════════════════════════════════════════════════════════════
289
+ -
290
+ - START HERE:
291
+ - INDEX.md - Navigation and overview
292
+ -
293
+ - QUICK START:
294
+ - QUICK_REFERENCE.md - Patterns and golden rules
295
+ -
296
+ - COMPREHENSIVE GUIDE:
297
+ - ERROR_HANDLING.md - Full documentation with examples
298
+ -
299
+ - ARCHITECTURE:
300
+ - ARCHITECTURE_DIAGRAMS.md - Visual flow and diagrams
301
+ -
302
+ - DETAILS:
303
+ - IMPLEMENTATION_COMPLETE.md - Full implementation details
304
+ - COMPLETE.md - Final summary
305
+ - CHECKLIST.md - Status and checklist
306
+ -
307
+ - ═════════════════════════════════════════════════════════════════════════
308
+ -
309
+ - STATUS: ✅ PRODUCTION-READY
310
+ -
311
+ - Your API now has enterprise-grade error handling.
312
+ - Every error flows through one place.
313
+ - Every response is consistent.
314
+ - This is where engineering starts.
315
+ -
316
+ - ═════════════════════════════════════════════════════════════════════════
317
+ \*/
318
+
319
+ console.log(`╔═════════════════════════════════════════════════════════════════════════╗
320
+ ║ ║
321
+ ║ ✅ PRODUCTION-LEVEL ERROR HANDLING - IMPLEMENTATION COMPLETE ║
322
+ ║ ║
323
+ ║ 🎯 SOLVED: ║
324
+ ║ No more res.status(500).json(...) scattered everywhere! ║
325
+ ║ ║
326
+ ║ ✨ FEATURES: ║
327
+ ║ ✅ Centralized error handler ║
328
+ ║ ✅ Error classification (operational vs programmer) ║
329
+ ║ ✅ 8 specialized error classes ║
330
+ ║ ✅ Async error wrapper ║
331
+ ║ ✅ Validation error formatting ║
332
+ ║ ✅ Comprehensive logging with stacks ║
333
+ ║ ✅ Production-safe responses ║
334
+ ║ ✅ Consistent JSON format ║
335
+ ║ ✅ Request logging ║
336
+ ║ ✅ Graceful shutdown ║
337
+ ║ ║
338
+ ║ 🚀 QUICK START: ║
339
+ ║ ║
340
+ ║ 1. Wrap async handlers: ║
341
+ ║ router.get("/users/:id", asyncHandler(async (req, res) => {})) ║
342
+ ║ ║
343
+ ║ 2. Throw AppError: ║
344
+ ║ throw new NotFoundError("User", { id }); ║
345
+ ║ ║
346
+ ║ 3. Validate requests: ║
347
+ ║ router.post("/users", validateRequest(schema), handler) ║
348
+ ║ ║
349
+ ║ 4. Send success: ║
350
+ ║ sendSuccess(res, data, 201, "Created"); ║
351
+ ║ ║
352
+ ║ 📚 DOCUMENTATION: ║
353
+ ║ • INDEX.md - Start here! ║
354
+ ║ • QUICK_REFERENCE.md - Patterns & rules ║
355
+ ║ • ERROR_HANDLING.md - Comprehensive guide ║
356
+ ║ • ARCHITECTURE_DIAGRAMS.md - Visual diagrams ║
357
+ ║ ║
358
+ ║ 🚀 RUNNING: ║
359
+ ║ npm run dev (development with auto-reload) ║
360
+ ║ npm start (production) ║
361
+ ║ ║
362
+ ║ ✅ STATUS: PRODUCTION-READY ║
363
+ ║ ║
364
+ ║ Every error flows through one place. ║
365
+ ║ Every response is consistent. ║
366
+ ║ This is where engineering starts. 🎯 ║
367
+ ║ ║
368
+ ╚═════════════════════════════════════════════════════════════════════════╝`);