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,270 @@
1
+ # Production-Level Error Handling System - Quick Reference
2
+
3
+ ## 🎯 Problem Solved
4
+
5
+ ❌ **Before:** Random `res.status(500).json(...)` scattered throughout code
6
+ ✅ **After:** Single centralized error handler with distinguished error types
7
+
8
+ ## 🏗️ System Architecture
9
+
10
+ ```
11
+ Every Request
12
+
13
+ Route Handler (wrapped with asyncHandler)
14
+
15
+ ├─→ Success? → sendSuccess(res, data)
16
+
17
+ └─→ Error thrown ✘
18
+
19
+ Global Error Handler
20
+
21
+ Normalize Error
22
+ ├─→ Is it AppError? Use it
23
+ ├─→ Is it ZodError? Convert to ValidationError
24
+ ├─→ Is it TypeError/ReferenceError/etc? Convert to InternalServerError
25
+
26
+ Classify Error
27
+ ├─→ Operational? (isOperational: true)
28
+ │ ├─ Log as WARN with context
29
+ │ └─ Send full details to client
30
+
31
+ └─→ Programmer Error? (isOperational: false)
32
+ ├─ Log as ERROR with stack trace
33
+ └─ Send generic message in production
34
+
35
+ Send Consistent JSON Response
36
+ ```
37
+
38
+ ## 📦 Error Classes (Use These!)
39
+
40
+ ```javascript
41
+ import {
42
+ AppError, // Base class
43
+ ValidationError, // Input validation failed
44
+ AuthenticationError, // Auth failed (401)
45
+ AuthorizationError, // Permission denied (403)
46
+ NotFoundError, // Resource not found (404)
47
+ ConflictError, // Duplicate/conflict (409)
48
+ BadRequestError, // Malformed request (400)
49
+ InternalServerError, // Unexpected error (500)
50
+ } from "./middlewares/errorHandler.js";
51
+ ```
52
+
53
+ ## 🎬 Quick Start
54
+
55
+ ### 1. Throw Operational Errors
56
+
57
+ ```javascript
58
+ // Validation
59
+ throw new ValidationError("Invalid input", [
60
+ { field: "email", message: "Invalid email", code: "invalid_email" },
61
+ ]);
62
+
63
+ // Not found
64
+ throw new NotFoundError("User", { id: userId });
65
+
66
+ // Duplicate
67
+ throw new ConflictError("Email already exists", { email });
68
+
69
+ // Auth
70
+ throw new AuthenticationError("Invalid credentials");
71
+
72
+ // Permission
73
+ throw new AuthorizationError("Access denied");
74
+
75
+ // Generic operational error
76
+ throw new AppError("Request failed", 400, {
77
+ isOperational: true,
78
+ code: "CUSTOM_ERROR",
79
+ context: { details: "..." },
80
+ });
81
+ ```
82
+
83
+ ### 2. Wrap All Async Handlers
84
+
85
+ ```javascript
86
+ import { asyncHandler } from "./middlewares/errorHandler.js";
87
+
88
+ // ✅ Correct
89
+ router.post(
90
+ "/users",
91
+ asyncHandler(async (req, res) => {
92
+ const user = await User.create(req.body);
93
+ sendSuccess(res, user, 201);
94
+ }),
95
+ );
96
+
97
+ // ❌ Wrong - errors leak!
98
+ router.post("/users", async (req, res) => {
99
+ const user = await User.create(req.body); // Error not caught!
100
+ sendSuccess(res, user, 201);
101
+ });
102
+ ```
103
+
104
+ ### 3. Use Validation Middleware
105
+
106
+ ```javascript
107
+ import { validateRequest } from "./middlewares/validateRequest.js";
108
+ import { z } from "zod";
109
+
110
+ const createUserSchema = z.object({
111
+ body: z.object({
112
+ email: z.string().email("Invalid email"),
113
+ name: z.string().min(1, "Name required"),
114
+ }),
115
+ });
116
+
117
+ router.post(
118
+ "/users",
119
+ validateRequest(createUserSchema),
120
+ asyncHandler(async (req, res) => {
121
+ // req.validatedData.body has been validated
122
+ const user = await User.create(req.validatedData.body);
123
+ sendSuccess(res, user, 201, "User created");
124
+ }),
125
+ );
126
+ ```
127
+
128
+ ## 📊 Logging Behavior
129
+
130
+ | Error Type | Level | Includes Stack | Info Sent to Client |
131
+ | ---------------------- | ----- | -------------- | ---------------------- |
132
+ | ValidationError | WARN | ❌ | ✅ All details |
133
+ | NotFoundError | WARN | ❌ | ✅ All details |
134
+ | AuthenticationError | WARN | ❌ | ✅ All details |
135
+ | TypeError (programmer) | ERROR | ✅ | ❌ Generic only (prod) |
136
+ | Unhandled (programmer) | FATAL | ✅ | ❌ Generic only (prod) |
137
+
138
+ ## 📋 Response Format
139
+
140
+ All responses are consistent JSON:
141
+
142
+ ### Success
143
+
144
+ ```json
145
+ {
146
+ "success": true,
147
+ "message": "User created successfully",
148
+ "data": { "id": "123", "name": "John" },
149
+ "timestamp": "2024-01-19T15:55:30.000Z"
150
+ }
151
+ ```
152
+
153
+ ### Operational Error
154
+
155
+ ```json
156
+ {
157
+ "success": false,
158
+ "message": "User not found",
159
+ "code": "NOT_FOUND",
160
+ "statusCode": 404,
161
+ "context": { "id": "999" },
162
+ "timestamp": "2024-01-19T15:55:30.000Z"
163
+ }
164
+ ```
165
+
166
+ ### Validation Error
167
+
168
+ ```json
169
+ {
170
+ "success": false,
171
+ "message": "Validation failed",
172
+ "code": "VALIDATION_ERROR",
173
+ "statusCode": 422,
174
+ "errors": [
175
+ { "field": "email", "message": "Invalid email", "code": "invalid_email" }
176
+ ],
177
+ "timestamp": "2024-01-19T15:55:30.000Z"
178
+ }
179
+ ```
180
+
181
+ ### Programmer Error (Production)
182
+
183
+ ```json
184
+ {
185
+ "success": false,
186
+ "message": "Internal server error",
187
+ "code": "INTERNAL_SERVER_ERROR",
188
+ "timestamp": "2024-01-19T15:55:30.000Z"
189
+ }
190
+ ```
191
+
192
+ ## 🛡️ Golden Rules
193
+
194
+ 1. **Always use asyncHandler** for async route handlers
195
+
196
+ ```javascript
197
+ router.get("/endpoint", asyncHandler(async (req, res) => { ... }))
198
+ ```
199
+
200
+ 2. **Never use res.status().json()** for errors - throw AppError instead
201
+
202
+ ```javascript
203
+ // ❌ Wrong
204
+ res.status(400).json({ error: "..." });
205
+
206
+ // ✅ Correct
207
+ throw new BadRequestError("Invalid input");
208
+ ```
209
+
210
+ 3. **Validate request early** with validateRequest middleware
211
+
212
+ ```javascript
213
+ router.post("/endpoint", validateRequest(schema), handler);
214
+ ```
215
+
216
+ 4. **Throw, don't catch** - let global handler catch
217
+
218
+ ```javascript
219
+ // ❌ Wrong
220
+ try {
221
+ await someTask();
222
+ } catch (err) {
223
+ res.status(500).json(err);
224
+ }
225
+
226
+ // ✅ Correct
227
+ await someTask(); // Error bubbles up to global handler
228
+ ```
229
+
230
+ 5. **Include context** when throwing errors
231
+ ```javascript
232
+ throw new NotFoundError("User", { id: userId, email: userEmail });
233
+ ```
234
+
235
+ ## 🚀 Features at a Glance
236
+
237
+ | Feature | Status |
238
+ | ------------------------------------------------ | ------ |
239
+ | Centralized error handler | ✅ |
240
+ | Error classification (operational vs programmer) | ✅ |
241
+ | Validation error formatting | ✅ |
242
+ | Async error wrapping | ✅ |
243
+ | Stack trace logging | ✅ |
244
+ | Production sanitization | ✅ |
245
+ | Request logging | ✅ |
246
+ | Graceful shutdown | ✅ |
247
+ | Unhandled exception catching | ✅ |
248
+ | Consistent JSON responses | ✅ |
249
+
250
+ ## 📚 Full Documentation
251
+
252
+ - **[ERROR_HANDLING.md](ERROR_HANDLING.md)** - Comprehensive guide with examples
253
+ - **[IMPLEMENTATION_COMPLETE.md](IMPLEMENTATION_COMPLETE.md)** - Full implementation details
254
+
255
+ ## 🎓 Key Files
256
+
257
+ | File | Purpose |
258
+ | ------------------------------------ | ----------------------------------- |
259
+ | `src/utils/AppError.js` | Error class hierarchy |
260
+ | `src/middlewares/errorHandler.js` | Global error handler + asyncHandler |
261
+ | `src/middlewares/validateRequest.js` | Zod validation middleware |
262
+ | `src/middlewares/requestLogger.js` | Request logging |
263
+ | `src/utils/logger.js` | Structured logging with colors |
264
+ | `src/utils/response.js` | Success response helpers |
265
+
266
+ ---
267
+
268
+ **That's it! Your API now has enterprise-grade error handling.** 🎯
269
+
270
+ Every error flows through one place. Every response is consistent. Errors are properly classified and logged. You're ready for production. 🚀