create-charcole 1.0.0 → 2.0.1

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.
Files changed (73) hide show
  1. package/.github/workflows/release.yml +26 -0
  2. package/CHANGELOG.md +25 -0
  3. package/README.md +11 -1
  4. package/bin/index.js +94 -49
  5. package/bin/lib/pkgManager.js +66 -0
  6. package/bin/lib/templateHandler.js +70 -0
  7. package/package.json +4 -1
  8. package/template/js/basePackage.json +28 -0
  9. package/template/{package-lock.json → js/package-lock.json} +1253 -1253
  10. package/template/{package.json → js/package.json} +28 -28
  11. package/template/ts/.env.example +8 -0
  12. package/template/ts/ARCHITECTURE_DIAGRAMS.md +283 -0
  13. package/template/ts/CHECKLIST.md +279 -0
  14. package/template/ts/COMPLETE.md +405 -0
  15. package/template/ts/ERROR_HANDLING.md +393 -0
  16. package/template/ts/IMPLEMENTATION.md +368 -0
  17. package/template/ts/IMPLEMENTATION_COMPLETE.md +363 -0
  18. package/template/ts/INDEX.md +290 -0
  19. package/template/ts/QUICK_REFERENCE.md +270 -0
  20. package/template/ts/README.md +855 -0
  21. package/template/ts/basePackage.json +36 -0
  22. package/template/ts/package-lock.json +2428 -0
  23. package/template/ts/package.json +32 -0
  24. package/template/ts/src/app.js +75 -0
  25. package/template/ts/src/app.ts +66 -0
  26. package/template/ts/src/config/constants.js +20 -0
  27. package/template/ts/src/config/constants.ts +27 -0
  28. package/template/ts/src/config/env.js +26 -0
  29. package/template/ts/src/config/env.ts +40 -0
  30. package/template/ts/src/middlewares/errorHandler.js +180 -0
  31. package/template/ts/src/middlewares/errorHandler.ts +209 -0
  32. package/template/ts/src/middlewares/requestLogger.js +33 -0
  33. package/template/ts/src/middlewares/requestLogger.ts +38 -0
  34. package/template/ts/src/middlewares/validateRequest.js +42 -0
  35. package/template/ts/src/middlewares/validateRequest.ts +46 -0
  36. package/template/ts/src/modules/health/controller.js +50 -0
  37. package/template/ts/src/modules/health/controller.ts +64 -0
  38. package/template/ts/src/routes.js +17 -0
  39. package/template/ts/src/routes.ts +16 -0
  40. package/template/ts/src/server.js +38 -0
  41. package/template/ts/src/server.ts +42 -0
  42. package/template/ts/src/types/express.d.ts +9 -0
  43. package/template/ts/src/utils/AppError.js +182 -0
  44. package/template/ts/src/utils/AppError.ts +220 -0
  45. package/template/ts/src/utils/logger.js +73 -0
  46. package/template/ts/src/utils/logger.ts +55 -0
  47. package/template/ts/src/utils/response.js +51 -0
  48. package/template/ts/src/utils/response.ts +100 -0
  49. package/template/ts/test-api.js +100 -0
  50. package/template/ts/tsconfig.json +19 -0
  51. /package/template/{.env.example → js/.env.example} +0 -0
  52. /package/template/{ARCHITECTURE_DIAGRAMS.md → js/ARCHITECTURE_DIAGRAMS.md} +0 -0
  53. /package/template/{CHECKLIST.md → js/CHECKLIST.md} +0 -0
  54. /package/template/{COMPLETE.md → js/COMPLETE.md} +0 -0
  55. /package/template/{ERROR_HANDLING.md → js/ERROR_HANDLING.md} +0 -0
  56. /package/template/{IMPLEMENTATION.md → js/IMPLEMENTATION.md} +0 -0
  57. /package/template/{IMPLEMENTATION_COMPLETE.md → js/IMPLEMENTATION_COMPLETE.md} +0 -0
  58. /package/template/{INDEX.md → js/INDEX.md} +0 -0
  59. /package/template/{QUICK_REFERENCE.md → js/QUICK_REFERENCE.md} +0 -0
  60. /package/template/{README.md → js/README.md} +0 -0
  61. /package/template/{src → js/src}/app.js +0 -0
  62. /package/template/{src → js/src}/config/constants.js +0 -0
  63. /package/template/{src → js/src}/config/env.js +0 -0
  64. /package/template/{src → js/src}/middlewares/errorHandler.js +0 -0
  65. /package/template/{src → js/src}/middlewares/requestLogger.js +0 -0
  66. /package/template/{src → js/src}/middlewares/validateRequest.js +0 -0
  67. /package/template/{src → js/src}/modules/health/controller.js +0 -0
  68. /package/template/{src → js/src}/routes.js +0 -0
  69. /package/template/{src → js/src}/server.js +0 -0
  70. /package/template/{src → js/src}/utils/AppError.js +0 -0
  71. /package/template/{src → js/src}/utils/logger.js +0 -0
  72. /package/template/{src → js/src}/utils/response.js +0 -0
  73. /package/template/{test-api.js → js/test-api.js} +0 -0
@@ -0,0 +1,405 @@
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. 🎯