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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Request, Response } from "express";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { sendSuccess } from "../../utils/response.
|
|
4
|
-
import { asyncHandler } from "../../middlewares/errorHandler.
|
|
5
|
-
import { validateRequest } from "../../middlewares/validateRequest.
|
|
3
|
+
import { sendSuccess } from "../../utils/response.ts";
|
|
4
|
+
import { asyncHandler } from "../../middlewares/errorHandler.ts";
|
|
5
|
+
import { validateRequest } from "../../middlewares/validateRequest.ts";
|
|
6
6
|
|
|
7
7
|
const healthCheckSchema = z.object({
|
|
8
8
|
query: z.object({}),
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
import type { User } from "../modules/auth/auth.schemas.ts";
|
|
3
|
+
|
|
4
|
+
const users: User[] = [];
|
|
5
|
+
|
|
6
|
+
type CreateUserData = {
|
|
7
|
+
email: string;
|
|
8
|
+
name: string;
|
|
9
|
+
passwordHash: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const userRepo = {
|
|
13
|
+
async findByEmail(email: string): Promise<User | undefined> {
|
|
14
|
+
return users.find((u) => u.email === email);
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
async create(data: CreateUserData): Promise<User> {
|
|
18
|
+
const user: User = {
|
|
19
|
+
id: randomUUID(),
|
|
20
|
+
email: data.email,
|
|
21
|
+
name: data.name,
|
|
22
|
+
passwordHash: data.passwordHash,
|
|
23
|
+
role: "user",
|
|
24
|
+
provider: "credentials",
|
|
25
|
+
isEmailVerified: false,
|
|
26
|
+
createdAt: new Date(),
|
|
27
|
+
updatedAt: new Date(),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
users.push(user);
|
|
31
|
+
return user;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import {
|
|
3
|
+
getHealth,
|
|
4
|
+
createItem,
|
|
5
|
+
createItemSchema,
|
|
6
|
+
} from "../modules/health/controller.ts";
|
|
7
|
+
import { validateRequest } from "../middlewares/validateRequest.ts";
|
|
8
|
+
import protectedRoutes from "./protected.ts";
|
|
9
|
+
import authRoutes from "../modules/auth/auth.routes.ts";
|
|
10
|
+
const router = Router();
|
|
11
|
+
|
|
12
|
+
// Health check
|
|
13
|
+
router.get("/health", getHealth);
|
|
14
|
+
|
|
15
|
+
// Example: Create item with validation
|
|
16
|
+
router.post("/items", validateRequest(createItemSchema), createItem);
|
|
17
|
+
|
|
18
|
+
// 🔐 Auth routes
|
|
19
|
+
router.use("/auth", authRoutes);
|
|
20
|
+
|
|
21
|
+
// 🔐 Protected routes (REQUIRED BEARER TOKEN FOR THEM)
|
|
22
|
+
router.use("/protected", protectedRoutes);
|
|
23
|
+
|
|
24
|
+
export default router;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { requireAuth } from "../modules/auth/auth.middlewares.ts";
|
|
3
|
+
|
|
4
|
+
const router = Router();
|
|
5
|
+
|
|
6
|
+
router.get("/me", requireAuth, (req, res) => {
|
|
7
|
+
res.json({
|
|
8
|
+
message: "You are authenticated",
|
|
9
|
+
user: req.user,
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export default router;
|
|
@@ -2,18 +2,25 @@
|
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES2020",
|
|
4
4
|
"module": "ESNext",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"rootDir": "./src",
|
|
7
|
+
"outDir": "./dist",
|
|
7
8
|
"strict": true,
|
|
8
9
|
"esModuleInterop": true,
|
|
9
10
|
"forceConsistentCasingInFileNames": true,
|
|
10
11
|
"skipLibCheck": true,
|
|
11
|
-
"moduleResolution": "node",
|
|
12
12
|
"resolveJsonModule": true,
|
|
13
13
|
"allowJs": false,
|
|
14
|
-
"noEmitOnError":
|
|
15
|
-
"sourceMap": true
|
|
14
|
+
"noEmitOnError": false,
|
|
15
|
+
"sourceMap": true,
|
|
16
|
+
"declaration": false,
|
|
17
|
+
"allowImportingTsExtensions": true,
|
|
18
|
+
"noEmit": true
|
|
16
19
|
},
|
|
17
|
-
"include": ["src
|
|
18
|
-
"exclude": ["node_modules", "dist"]
|
|
20
|
+
"include": ["src/**/*"],
|
|
21
|
+
"exclude": ["node_modules", "dist"],
|
|
22
|
+
"ts-node": {
|
|
23
|
+
"esm": true,
|
|
24
|
+
"experimentalSpecifierResolution": "node"
|
|
25
|
+
}
|
|
19
26
|
}
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
# Error Handling Architecture Diagram
|
|
2
|
-
|
|
3
|
-
## Complete Error Flow
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
7
|
-
│ HTTP REQUEST │
|
|
8
|
-
└──────────────────────────────────────┬──────────────────────────────┘
|
|
9
|
-
│
|
|
10
|
-
▼
|
|
11
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
12
|
-
│ CORS & BODY PARSING MIDDLEWARE │
|
|
13
|
-
└──────────────────────────────────────┬──────────────────────────────┘
|
|
14
|
-
│
|
|
15
|
-
▼
|
|
16
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
17
|
-
│ REQUEST LOGGER MIDDLEWARE │
|
|
18
|
-
│ (Logs: method, path, query, IP, user-agent) │
|
|
19
|
-
└──────────────────────────────────────┬──────────────────────────────┘
|
|
20
|
-
│
|
|
21
|
-
▼
|
|
22
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
23
|
-
│ VALIDATION MIDDLEWARE (optional) │
|
|
24
|
-
│ │
|
|
25
|
-
│ Validates with Zod schema → throws ValidationError if fails │
|
|
26
|
-
└──────────────────────────────────────┬──────────────────────────────┘
|
|
27
|
-
│
|
|
28
|
-
▼
|
|
29
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
30
|
-
│ ROUTE HANDLER (wrapped with asyncHandler) │
|
|
31
|
-
│ │
|
|
32
|
-
│ ┌────────────────────────────────────────────────────────────────┐ │
|
|
33
|
-
│ │ asyncHandler(async (req, res) => { │ │
|
|
34
|
-
│ │ // Your handler code │ │
|
|
35
|
-
│ │ const user = await User.findById(req.params.id); │ │
|
|
36
|
-
│ │ │ │
|
|
37
|
-
│ │ if (!user) { │ │
|
|
38
|
-
│ │ throw new NotFoundError("User", { id: req.params.id }); │ │
|
|
39
|
-
│ │ } │ │
|
|
40
|
-
│ │ │ │
|
|
41
|
-
│ │ sendSuccess(res, user); │ │
|
|
42
|
-
│ │ }) │ │
|
|
43
|
-
│ └────────────────────────────────────────────────────────────────┘ │
|
|
44
|
-
└────────┬────────────────────────────────────────────────────────────┘
|
|
45
|
-
│
|
|
46
|
-
├──→ Success? ──→ sendSuccess() ──→ [END: Response sent]
|
|
47
|
-
│
|
|
48
|
-
└──→ Error thrown ✘ ──→ [Continue below]
|
|
49
|
-
│
|
|
50
|
-
▼
|
|
51
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
52
|
-
│ GLOBAL ERROR HANDLER MIDDLEWARE │
|
|
53
|
-
│ (This is where ALL errors flow!) │
|
|
54
|
-
└────┬────────────────────────────────────────────────────────────────┘
|
|
55
|
-
│
|
|
56
|
-
▼
|
|
57
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
58
|
-
│ ERROR NORMALIZATION │
|
|
59
|
-
│ │
|
|
60
|
-
│ if (err instanceof AppError) → Use as is │
|
|
61
|
-
│ if (err instanceof ZodError) → Convert to ValidationError │
|
|
62
|
-
│ if (err instanceof TypeError) → Convert to InternalServerError │
|
|
63
|
-
│ if (err instanceof ReferenceError)→ Convert to InternalServerError │
|
|
64
|
-
│ if (err instanceof SyntaxError) → Convert to InternalServerError │
|
|
65
|
-
│ if (err instanceof RangeError) → Convert to InternalServerError │
|
|
66
|
-
│ else → Wrap in InternalServerError │
|
|
67
|
-
└────┬────────────────────────────────────────────────────────────────┘
|
|
68
|
-
│
|
|
69
|
-
▼
|
|
70
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
71
|
-
│ ERROR CLASSIFICATION │
|
|
72
|
-
│ │
|
|
73
|
-
│ ┌─ Operational Error (isOperational: true) │
|
|
74
|
-
│ │ ├─ ValidationError (422) │
|
|
75
|
-
│ │ ├─ NotFoundError (404) │
|
|
76
|
-
│ │ ├─ AuthenticationError (401) │
|
|
77
|
-
│ │ ├─ AuthorizationError (403) │
|
|
78
|
-
│ │ ├─ ConflictError (409) │
|
|
79
|
-
│ │ └─ BadRequestError (400) │
|
|
80
|
-
│ │ │
|
|
81
|
-
│ └─ Programmer Error (isOperational: false) │
|
|
82
|
-
│ └─ TypeError, ReferenceError, SyntaxError, etc. │
|
|
83
|
-
└────┬────────────────────────────────────────────────────────────────┘
|
|
84
|
-
│
|
|
85
|
-
▼
|
|
86
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
87
|
-
│ ERROR LOGGING │
|
|
88
|
-
│ │
|
|
89
|
-
│ If Operational Error: │
|
|
90
|
-
│ ├─ Log as WARN level │
|
|
91
|
-
│ ├─ Include: code, message, statusCode, method, path, IP │
|
|
92
|
-
│ └─ NO stack trace (expected error) │
|
|
93
|
-
│ │
|
|
94
|
-
│ If Programmer Error: │
|
|
95
|
-
│ ├─ Log as ERROR level │
|
|
96
|
-
│ ├─ Include: code, message, statusCode, method, path, IP, stack │
|
|
97
|
-
│ └─ YES full stack trace (for debugging) │
|
|
98
|
-
└────┬────────────────────────────────────────────────────────────────┘
|
|
99
|
-
│
|
|
100
|
-
▼
|
|
101
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
102
|
-
│ SEND ERROR RESPONSE │
|
|
103
|
-
│ │
|
|
104
|
-
│ If Production & Programmer Error: │
|
|
105
|
-
│ ├─ { │
|
|
106
|
-
│ │ success: false, │
|
|
107
|
-
│ │ message: "Internal server error", │
|
|
108
|
-
│ │ code: "INTERNAL_SERVER_ERROR", │
|
|
109
|
-
│ │ timestamp: "..." │
|
|
110
|
-
│ │ } │
|
|
111
|
-
│ │ │
|
|
112
|
-
│ └─ (Details hidden from client) │
|
|
113
|
-
│ │
|
|
114
|
-
│ If Development OR Operational Error: │
|
|
115
|
-
│ ├─ { │
|
|
116
|
-
│ │ success: false, │
|
|
117
|
-
│ │ message: "Full error message", │
|
|
118
|
-
│ │ code: "ERROR_CODE", │
|
|
119
|
-
│ │ statusCode: 422, │
|
|
120
|
-
│ │ context: { ... }, │
|
|
121
|
-
│ │ errors: [ ... ], // for validation errors │
|
|
122
|
-
│ │ timestamp: "..." │
|
|
123
|
-
│ │ } │
|
|
124
|
-
│ │ │
|
|
125
|
-
│ └─ (Full details sent) │
|
|
126
|
-
└────┬────────────────────────────────────────────────────────────────┘
|
|
127
|
-
│
|
|
128
|
-
▼
|
|
129
|
-
┌─────────────────────────────────────────────────────────────────────┐
|
|
130
|
-
│ HTTP RESPONSE SENT TO CLIENT │
|
|
131
|
-
│ │
|
|
132
|
-
│ Status Code: 400, 401, 403, 404, 409, 422, 500, etc. │
|
|
133
|
-
│ Body: Consistent JSON error format │
|
|
134
|
-
└─────────────────────────────────────────────────────────────────────┘
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## Error Class Hierarchy
|
|
138
|
-
|
|
139
|
-
```
|
|
140
|
-
Error (JavaScript)
|
|
141
|
-
│
|
|
142
|
-
└── AppError (Base class)
|
|
143
|
-
│
|
|
144
|
-
├── ValidationError (422 - Input validation failed)
|
|
145
|
-
├── BadRequestError (400 - Malformed request)
|
|
146
|
-
├── AuthenticationError (401 - Auth failed)
|
|
147
|
-
├── AuthorizationError (403 - Permission denied)
|
|
148
|
-
├── NotFoundError (404 - Resource not found)
|
|
149
|
-
├── ConflictError (409 - Duplicate/conflict)
|
|
150
|
-
└── InternalServerError (500 - Unexpected error)
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Middleware Stack Order
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
Express App
|
|
157
|
-
│
|
|
158
|
-
├─ Trust Proxy
|
|
159
|
-
├─ CORS
|
|
160
|
-
├─ JSON Body Parser
|
|
161
|
-
├─ URL Encoded Parser
|
|
162
|
-
├─ Request Timeout Handler
|
|
163
|
-
│
|
|
164
|
-
├─ requestLogger (logs all requests)
|
|
165
|
-
│
|
|
166
|
-
├─ Routes:
|
|
167
|
-
│ │
|
|
168
|
-
│ ├─ validateRequest (optional, per route)
|
|
169
|
-
│ │
|
|
170
|
-
│ └─ Route Handler (MUST wrap with asyncHandler)
|
|
171
|
-
│
|
|
172
|
-
└─ errorHandler (MUST BE LAST)
|
|
173
|
-
└─ Catches all errors and sends JSON response
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Error Classification Decision Tree
|
|
177
|
-
|
|
178
|
-
```
|
|
179
|
-
Error Thrown
|
|
180
|
-
│
|
|
181
|
-
┌───────────┴───────────┐
|
|
182
|
-
│ │
|
|
183
|
-
Is AppError? Is ZodError?
|
|
184
|
-
│ │
|
|
185
|
-
YES YES
|
|
186
|
-
│ │
|
|
187
|
-
┌───────▼────────┐ ┌──────▼──────────┐
|
|
188
|
-
│ Use as is │ │ Convert to │
|
|
189
|
-
│ (already has │ │ ValidationError │
|
|
190
|
-
│ isOperational)│ │ (422) │
|
|
191
|
-
└─────────────────┘ └─────────────────┘
|
|
192
|
-
│
|
|
193
|
-
┌───────────────────────┴───────────────────────┐
|
|
194
|
-
│ │
|
|
195
|
-
Is Operational? Is Programmer Error?
|
|
196
|
-
(isOperational: true) (Syntax, Type, Ref, Range)
|
|
197
|
-
│ │
|
|
198
|
-
YES YES
|
|
199
|
-
│ │
|
|
200
|
-
┌──────────▼──────────┐ ┌──────────▼──────────┐
|
|
201
|
-
│ Send full error │ │ Convert to │
|
|
202
|
-
│ details to client │ │ InternalServerError │
|
|
203
|
-
│ with code & context │ │ (500) │
|
|
204
|
-
│ │ │ isOperational: false│
|
|
205
|
-
│ Log as WARN │ │ │
|
|
206
|
-
│ (no stack) │ │ Log as ERROR │
|
|
207
|
-
│ │ │ WITH FULL STACK │
|
|
208
|
-
└─────────────────────┘ │ │
|
|
209
|
-
│ Hide details in │
|
|
210
|
-
│ production │
|
|
211
|
-
└─────────────────────┘
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
## Request-to-Response Timeline
|
|
215
|
-
|
|
216
|
-
```
|
|
217
|
-
TIME LAYER ACTION
|
|
218
|
-
════ ═════════════════════ ════════════════════════════════════════
|
|
219
|
-
|
|
220
|
-
T0 Network Request arrives at server
|
|
221
|
-
|
|
222
|
-
T1 Express Middleware CORS, Body Parser, Request Logger
|
|
223
|
-
|
|
224
|
-
T2 Route Handler validateRequest() - validates input
|
|
225
|
-
|
|
226
|
-
T3 Route Handler Handler executes (wrapped with asyncHandler)
|
|
227
|
-
├─ Success: sendSuccess() → Response sent → T6
|
|
228
|
-
└─ Error: Thrown → T4
|
|
229
|
-
|
|
230
|
-
T4 asyncHandler Catches error, passes to next(error)
|
|
231
|
-
|
|
232
|
-
T5 Error Handler Mw Normalizes error
|
|
233
|
-
Classifies (operational vs programmer)
|
|
234
|
-
Logs error with context
|
|
235
|
-
Sanitizes response (production)
|
|
236
|
-
Sends JSON response
|
|
237
|
-
|
|
238
|
-
T6 Network Response sent to client
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
## Environment Behavior
|
|
242
|
-
|
|
243
|
-
```
|
|
244
|
-
┌──────────────────────┐ ┌──────────────────────┐
|
|
245
|
-
│ DEVELOPMENT │ │ PRODUCTION │
|
|
246
|
-
│ NODE_ENV=development│ │ NODE_ENV=production │
|
|
247
|
-
└──────────┬───────────┘ └──────────┬───────────┘
|
|
248
|
-
│ │
|
|
249
|
-
│ Programmer Error: │ Programmer Error:
|
|
250
|
-
│ ┌────────────────────────┐ │ ┌────────────────────────┐
|
|
251
|
-
│ │ { │ │ │ { │
|
|
252
|
-
│ │ success: false, │ │ │ success: false, │
|
|
253
|
-
│ │ message: "TypeError: │ │ │ message: "Internal │
|
|
254
|
-
│ │ x is undefined", │ │ │ server error", │
|
|
255
|
-
│ │ code: "INTERNAL...", │ │ │ code: "INTERNAL...", │
|
|
256
|
-
│ │ stack: "TypeError... │ │ │ timestamp: "..." │
|
|
257
|
-
│ │ at handler.js:15..." │ │ │ } │
|
|
258
|
-
│ │ } │ │ │ │
|
|
259
|
-
│ └────────────────────────┘ │ └────────────────────────┘
|
|
260
|
-
│ │
|
|
261
|
-
│ Operational Error: │ Operational Error:
|
|
262
|
-
│ (sent fully in both) │ (sent fully in both)
|
|
263
|
-
│ ┌────────────────────────┐ │ ┌────────────────────────┐
|
|
264
|
-
│ │ { │ │ │ { │
|
|
265
|
-
│ │ success: false, │ │ │ success: false, │
|
|
266
|
-
│ │ message: "User not │ │ │ message: "User not │
|
|
267
|
-
│ │ found", │ │ │ found", │
|
|
268
|
-
│ │ code: "NOT_FOUND", │ │ │ code: "NOT_FOUND", │
|
|
269
|
-
│ │ context: {...} │ │ │ context: {...} │
|
|
270
|
-
│ │ } │ │ │ } │
|
|
271
|
-
│ └────────────────────────┘ │ └────────────────────────┘
|
|
272
|
-
│ │
|
|
273
|
-
│ Logging: │ Logging:
|
|
274
|
-
│ Full details + stack │ Full details + stack
|
|
275
|
-
│ (for development) │ (server-side only)
|
|
276
|
-
│ │
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
---
|
|
280
|
-
|
|
281
|
-
This architecture ensures that **every single error in your application flows through one place, gets properly classified, logged with full context, and returns a consistent JSON response to the client.**
|
|
282
|
-
|
|
283
|
-
That's production-grade error handling. 🎯
|