@engjts/nexus 0.1.7 → 0.1.9
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/dist/advanced/playground/generatePlaygroundHTML.d.ts.map +1 -1
- package/dist/advanced/playground/generatePlaygroundHTML.js +107 -0
- package/dist/advanced/playground/generatePlaygroundHTML.js.map +1 -1
- package/dist/advanced/playground/playground.d.ts +19 -0
- package/dist/advanced/playground/playground.d.ts.map +1 -1
- package/dist/advanced/playground/playground.js +70 -0
- package/dist/advanced/playground/playground.js.map +1 -1
- package/dist/advanced/playground/types.d.ts +20 -0
- package/dist/advanced/playground/types.d.ts.map +1 -1
- package/dist/core/application.d.ts +14 -0
- package/dist/core/application.d.ts.map +1 -1
- package/dist/core/application.js +173 -71
- package/dist/core/application.js.map +1 -1
- package/dist/core/context-pool.d.ts +2 -13
- package/dist/core/context-pool.d.ts.map +1 -1
- package/dist/core/context-pool.js +7 -45
- package/dist/core/context-pool.js.map +1 -1
- package/dist/core/context.d.ts +108 -5
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +449 -53
- package/dist/core/context.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +9 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/middleware.d.ts +6 -0
- package/dist/core/middleware.d.ts.map +1 -1
- package/dist/core/middleware.js +83 -84
- package/dist/core/middleware.js.map +1 -1
- package/dist/core/performance/fast-json.d.ts +149 -0
- package/dist/core/performance/fast-json.d.ts.map +1 -0
- package/dist/core/performance/fast-json.js +473 -0
- package/dist/core/performance/fast-json.js.map +1 -0
- package/dist/core/router/file-router.d.ts +20 -7
- package/dist/core/router/file-router.d.ts.map +1 -1
- package/dist/core/router/file-router.js +41 -13
- package/dist/core/router/file-router.js.map +1 -1
- package/dist/core/router/index.d.ts +6 -0
- package/dist/core/router/index.d.ts.map +1 -1
- package/dist/core/router/index.js +33 -6
- package/dist/core/router/index.js.map +1 -1
- package/dist/core/router/radix-tree.d.ts +4 -1
- package/dist/core/router/radix-tree.d.ts.map +1 -1
- package/dist/core/router/radix-tree.js +7 -3
- package/dist/core/router/radix-tree.js.map +1 -1
- package/dist/core/serializer.d.ts +251 -0
- package/dist/core/serializer.d.ts.map +1 -0
- package/dist/core/serializer.js +290 -0
- package/dist/core/serializer.js.map +1 -0
- package/dist/core/types.d.ts +39 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/documentation/01-getting-started.md +0 -240
- package/documentation/02-context.md +0 -335
- package/documentation/03-routing.md +0 -397
- package/documentation/04-middleware.md +0 -483
- package/documentation/05-validation.md +0 -514
- package/documentation/06-error-handling.md +0 -465
- package/documentation/07-performance.md +0 -364
- package/documentation/08-adapters.md +0 -470
- package/documentation/09-api-reference.md +0 -548
- package/documentation/10-examples.md +0 -582
- package/documentation/11-deployment.md +0 -477
- package/documentation/12-sentry.md +0 -620
- package/documentation/13-sentry-data-storage.md +0 -996
- package/documentation/14-sentry-data-reference.md +0 -457
- package/documentation/15-sentry-summary.md +0 -409
- package/documentation/16-alerts-system.md +0 -745
- package/documentation/17-alert-adapters.md +0 -696
- package/documentation/18-alerts-implementation-summary.md +0 -385
- package/documentation/19-class-based-routing.md +0 -840
- package/documentation/20-websocket-realtime.md +0 -813
- package/documentation/21-cache-system.md +0 -510
- package/documentation/22-job-queue.md +0 -772
- package/documentation/23-sentry-plugin.md +0 -551
- package/documentation/24-testing-utilities.md +0 -1287
- package/documentation/25-api-versioning.md +0 -533
- package/documentation/26-context-store.md +0 -607
- package/documentation/27-dependency-injection.md +0 -329
- package/documentation/28-lifecycle-hooks.md +0 -521
- package/documentation/29-package-structure.md +0 -196
- package/documentation/30-plugin-system.md +0 -414
- package/documentation/31-jwt-authentication.md +0 -597
- package/documentation/32-cli.md +0 -268
- package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
- package/documentation/ALERTS-INDEX.md +0 -330
- package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
- package/documentation/README.md +0 -178
- package/documentation/index.html +0 -34
- package/modern_framework_paper.md +0 -1870
- package/public/css/style.css +0 -87
- package/public/index.html +0 -34
- package/public/js/app.js +0 -27
- package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
- package/src/advanced/cache/MultiTierCache.ts +0 -194
- package/src/advanced/cache/RedisCacheStore.ts +0 -341
- package/src/advanced/cache/index.ts +0 -5
- package/src/advanced/cache/types.ts +0 -40
- package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
- package/src/advanced/graphql/index.ts +0 -22
- package/src/advanced/graphql/server.ts +0 -252
- package/src/advanced/graphql/types.ts +0 -42
- package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
- package/src/advanced/jobs/JobQueue.ts +0 -556
- package/src/advanced/jobs/RedisQueueStore.ts +0 -367
- package/src/advanced/jobs/index.ts +0 -5
- package/src/advanced/jobs/types.ts +0 -70
- package/src/advanced/observability/APMManager.ts +0 -163
- package/src/advanced/observability/AlertManager.ts +0 -109
- package/src/advanced/observability/MetricRegistry.ts +0 -151
- package/src/advanced/observability/ObservabilityCenter.ts +0 -304
- package/src/advanced/observability/StructuredLogger.ts +0 -154
- package/src/advanced/observability/TracingManager.ts +0 -117
- package/src/advanced/observability/adapters.ts +0 -304
- package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
- package/src/advanced/observability/index.ts +0 -11
- package/src/advanced/observability/types.ts +0 -174
- package/src/advanced/playground/extractPathParams.ts +0 -6
- package/src/advanced/playground/generateFieldExample.ts +0 -31
- package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1849
- package/src/advanced/playground/generateSummary.ts +0 -19
- package/src/advanced/playground/getTagFromPath.ts +0 -9
- package/src/advanced/playground/index.ts +0 -8
- package/src/advanced/playground/playground.ts +0 -170
- package/src/advanced/playground/types.ts +0 -20
- package/src/advanced/playground/zodToExample.ts +0 -16
- package/src/advanced/playground/zodToParams.ts +0 -15
- package/src/advanced/postman/buildAuth.ts +0 -31
- package/src/advanced/postman/buildBody.ts +0 -15
- package/src/advanced/postman/buildQueryParams.ts +0 -27
- package/src/advanced/postman/buildRequestItem.ts +0 -36
- package/src/advanced/postman/buildResponses.ts +0 -11
- package/src/advanced/postman/buildUrl.ts +0 -33
- package/src/advanced/postman/capitalize.ts +0 -4
- package/src/advanced/postman/generateCollection.ts +0 -59
- package/src/advanced/postman/generateEnvironment.ts +0 -34
- package/src/advanced/postman/generateExampleFromZod.ts +0 -21
- package/src/advanced/postman/generateFieldExample.ts +0 -45
- package/src/advanced/postman/generateName.ts +0 -20
- package/src/advanced/postman/generateUUID.ts +0 -11
- package/src/advanced/postman/getTagFromPath.ts +0 -10
- package/src/advanced/postman/index.ts +0 -28
- package/src/advanced/postman/postman.ts +0 -156
- package/src/advanced/postman/slugify.ts +0 -7
- package/src/advanced/postman/types.ts +0 -140
- package/src/advanced/realtime/index.ts +0 -18
- package/src/advanced/realtime/websocket.ts +0 -231
- package/src/advanced/sentry/index.ts +0 -1236
- package/src/advanced/sentry/types.ts +0 -355
- package/src/advanced/static/generateDirectoryListing.ts +0 -47
- package/src/advanced/static/generateETag.ts +0 -7
- package/src/advanced/static/getMimeType.ts +0 -9
- package/src/advanced/static/index.ts +0 -32
- package/src/advanced/static/isSafePath.ts +0 -13
- package/src/advanced/static/publicDir.ts +0 -21
- package/src/advanced/static/serveStatic.ts +0 -225
- package/src/advanced/static/spa.ts +0 -24
- package/src/advanced/static/types.ts +0 -159
- package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
- package/src/advanced/swagger/buildOperation.ts +0 -61
- package/src/advanced/swagger/buildParameters.ts +0 -61
- package/src/advanced/swagger/buildRequestBody.ts +0 -21
- package/src/advanced/swagger/buildResponses.ts +0 -54
- package/src/advanced/swagger/capitalize.ts +0 -5
- package/src/advanced/swagger/convertPath.ts +0 -9
- package/src/advanced/swagger/createSwagger.ts +0 -12
- package/src/advanced/swagger/generateOperationId.ts +0 -21
- package/src/advanced/swagger/generateSpec.ts +0 -105
- package/src/advanced/swagger/generateSummary.ts +0 -24
- package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
- package/src/advanced/swagger/generateThemeCss.ts +0 -53
- package/src/advanced/swagger/index.ts +0 -25
- package/src/advanced/swagger/swagger.ts +0 -237
- package/src/advanced/swagger/types.ts +0 -206
- package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
- package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
- package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
- package/src/advanced/testing/factory.ts +0 -509
- package/src/advanced/testing/harness.ts +0 -612
- package/src/advanced/testing/index.ts +0 -430
- package/src/advanced/testing/load-test.ts +0 -618
- package/src/advanced/testing/mock-server.ts +0 -498
- package/src/advanced/testing/mock.ts +0 -670
- package/src/cli/bin.ts +0 -9
- package/src/cli/cli.ts +0 -158
- package/src/cli/commands/add.ts +0 -178
- package/src/cli/commands/build.ts +0 -73
- package/src/cli/commands/create.ts +0 -166
- package/src/cli/commands/dev.ts +0 -85
- package/src/cli/commands/generate.ts +0 -99
- package/src/cli/commands/help.ts +0 -95
- package/src/cli/commands/init.ts +0 -91
- package/src/cli/commands/version.ts +0 -38
- package/src/cli/index.ts +0 -6
- package/src/cli/templates/generators.ts +0 -359
- package/src/cli/templates/index.ts +0 -680
- package/src/cli/utils/exec.ts +0 -52
- package/src/cli/utils/file-system.ts +0 -78
- package/src/cli/utils/logger.ts +0 -111
- package/src/core/adapter.ts +0 -88
- package/src/core/application.ts +0 -1335
- package/src/core/context-pool.ts +0 -127
- package/src/core/context.ts +0 -412
- package/src/core/index.ts +0 -80
- package/src/core/middleware.ts +0 -262
- package/src/core/performance/buffer-pool.ts +0 -108
- package/src/core/performance/middleware-optimizer.ts +0 -162
- package/src/core/plugin/PluginManager.ts +0 -435
- package/src/core/plugin/builder.ts +0 -358
- package/src/core/plugin/index.ts +0 -50
- package/src/core/plugin/types.ts +0 -214
- package/src/core/router/file-router.ts +0 -594
- package/src/core/router/index.ts +0 -227
- package/src/core/router/radix-tree.ts +0 -226
- package/src/core/store/index.ts +0 -30
- package/src/core/store/registry.ts +0 -178
- package/src/core/store/request-store.ts +0 -240
- package/src/core/store/types.ts +0 -233
- package/src/core/types.ts +0 -574
- package/src/database/adapter.ts +0 -35
- package/src/database/adapters/index.ts +0 -1
- package/src/database/adapters/mysql.ts +0 -669
- package/src/database/database.ts +0 -70
- package/src/database/dialect.ts +0 -388
- package/src/database/index.ts +0 -12
- package/src/database/migrations.ts +0 -86
- package/src/database/optimizer.ts +0 -125
- package/src/database/query-builder.ts +0 -404
- package/src/database/realtime.ts +0 -53
- package/src/database/schema.ts +0 -71
- package/src/database/transactions.ts +0 -56
- package/src/database/types.ts +0 -87
- package/src/deployment/cluster.ts +0 -471
- package/src/deployment/config.ts +0 -454
- package/src/deployment/docker.ts +0 -599
- package/src/deployment/graceful-shutdown.ts +0 -373
- package/src/deployment/index.ts +0 -56
- package/src/index.ts +0 -264
- package/src/security/adapter.ts +0 -318
- package/src/security/auth/JWTPlugin.ts +0 -234
- package/src/security/auth/JWTProvider.ts +0 -316
- package/src/security/auth/adapter.ts +0 -12
- package/src/security/auth/jwt.ts +0 -234
- package/src/security/auth/middleware.ts +0 -188
- package/src/security/csrf.ts +0 -220
- package/src/security/headers.ts +0 -108
- package/src/security/index.ts +0 -60
- package/src/security/rate-limit/adapter.ts +0 -7
- package/src/security/rate-limit/memory.ts +0 -108
- package/src/security/rate-limit/middleware.ts +0 -181
- package/src/security/sanitization.ts +0 -75
- package/src/security/types.ts +0 -240
- package/src/security/utils.ts +0 -52
- package/tsconfig.json +0 -39
|
@@ -1,465 +0,0 @@
|
|
|
1
|
-
# Error Handling
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Nexus provides **automatic error handling** for all async handlers. You don't need to wrap everything in try-catch or call `next(error)` like in Express.js.
|
|
6
|
-
|
|
7
|
-
## Automatic Error Handling
|
|
8
|
-
|
|
9
|
-
### Basic Example
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
app.get('/user/:id', async (ctx) => {
|
|
13
|
-
// Any error thrown here is automatically caught
|
|
14
|
-
const user = await database.getUser(ctx.params.id);
|
|
15
|
-
|
|
16
|
-
if (!user) {
|
|
17
|
-
throw new Error('User not found');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return { user };
|
|
21
|
-
});
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
The framework catches the error and returns:
|
|
25
|
-
|
|
26
|
-
```json
|
|
27
|
-
{
|
|
28
|
-
"error": "Internal Server Error",
|
|
29
|
-
"message": "User not found" // Only in development
|
|
30
|
-
}
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Custom Error Handler
|
|
34
|
-
|
|
35
|
-
### Global Error Handler
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
app.onError((error, ctx) => {
|
|
39
|
-
// Log the error
|
|
40
|
-
console.error('Error:', error.message);
|
|
41
|
-
console.error('Path:', ctx.path);
|
|
42
|
-
console.error('Stack:', error.stack);
|
|
43
|
-
|
|
44
|
-
// Return custom response
|
|
45
|
-
return {
|
|
46
|
-
statusCode: 500,
|
|
47
|
-
headers: { 'Content-Type': 'application/json' },
|
|
48
|
-
body: JSON.stringify({
|
|
49
|
-
error: 'Something went wrong',
|
|
50
|
-
requestId: ctx.requestId
|
|
51
|
-
})
|
|
52
|
-
};
|
|
53
|
-
});
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### Environment-Aware Errors
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
app.onError((error, ctx) => {
|
|
60
|
-
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
61
|
-
|
|
62
|
-
return ctx.response.status(500).json({
|
|
63
|
-
error: 'Internal Server Error',
|
|
64
|
-
message: isDevelopment ? error.message : undefined,
|
|
65
|
-
stack: isDevelopment ? error.stack : undefined,
|
|
66
|
-
path: ctx.path
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Custom Error Classes
|
|
72
|
-
|
|
73
|
-
### Define Custom Errors
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
class AppError extends Error {
|
|
77
|
-
statusCode: number;
|
|
78
|
-
isOperational: boolean;
|
|
79
|
-
|
|
80
|
-
constructor(message: string, statusCode: number = 500) {
|
|
81
|
-
super(message);
|
|
82
|
-
this.statusCode = statusCode;
|
|
83
|
-
this.isOperational = true;
|
|
84
|
-
Error.captureStackTrace(this, this.constructor);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
class NotFoundError extends AppError {
|
|
89
|
-
constructor(resource: string) {
|
|
90
|
-
super(`${resource} not found`, 404);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
class ValidationError extends AppError {
|
|
95
|
-
constructor(message: string) {
|
|
96
|
-
super(message, 400);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
class UnauthorizedError extends AppError {
|
|
101
|
-
constructor(message: string = 'Unauthorized') {
|
|
102
|
-
super(message, 401);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
class ForbiddenError extends AppError {
|
|
107
|
-
constructor(message: string = 'Forbidden') {
|
|
108
|
-
super(message, 403);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Use Custom Errors
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
app.get('/users/:id', async (ctx) => {
|
|
117
|
-
const user = await database.getUser(ctx.params.id);
|
|
118
|
-
|
|
119
|
-
if (!user) {
|
|
120
|
-
throw new NotFoundError('User');
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return { user };
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
app.post('/admin/users', async (ctx) => {
|
|
127
|
-
if (!ctx.user?.isAdmin) {
|
|
128
|
-
throw new ForbiddenError('Admin access required');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return await createUser(ctx.body);
|
|
132
|
-
});
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Handle Custom Errors
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
app.onError((error, ctx) => {
|
|
139
|
-
// Handle custom app errors
|
|
140
|
-
if (error instanceof AppError) {
|
|
141
|
-
return ctx.response.status(error.statusCode).json({
|
|
142
|
-
error: error.message,
|
|
143
|
-
statusCode: error.statusCode
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Handle unexpected errors
|
|
148
|
-
console.error('Unexpected error:', error);
|
|
149
|
-
return ctx.response.status(500).json({
|
|
150
|
-
error: 'Internal Server Error'
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## Validation Errors
|
|
156
|
-
|
|
157
|
-
Validation errors are automatically handled:
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
app.post('/users', {
|
|
161
|
-
schema: {
|
|
162
|
-
body: z.object({
|
|
163
|
-
email: z.string().email()
|
|
164
|
-
})
|
|
165
|
-
},
|
|
166
|
-
handler: async (ctx) => {
|
|
167
|
-
return await createUser(ctx.body);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// Invalid request returns:
|
|
172
|
-
// {
|
|
173
|
-
// "error": "Validation failed",
|
|
174
|
-
// "details": [...]
|
|
175
|
-
// }
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Error Middleware
|
|
179
|
-
|
|
180
|
-
### Wrap Routes in Error Handler
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
import { errorHandler } from './nexus';
|
|
184
|
-
|
|
185
|
-
const safErrorHandler = errorHandler((error, ctx) => {
|
|
186
|
-
// Custom error handling
|
|
187
|
-
if (error.name === 'DatabaseError') {
|
|
188
|
-
return ctx.response.status(503).json({
|
|
189
|
-
error: 'Service Unavailable',
|
|
190
|
-
message: 'Database connection failed'
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return ctx.response.status(500).json({
|
|
195
|
-
error: 'Internal Server Error'
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
app.use(safeErrorHandler);
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
## Async Error Handling
|
|
203
|
-
|
|
204
|
-
### Promises
|
|
205
|
-
|
|
206
|
-
```typescript
|
|
207
|
-
app.get('/data', async (ctx) => {
|
|
208
|
-
// Errors in promises are automatically caught
|
|
209
|
-
const data = await fetchData();
|
|
210
|
-
const processed = await processData(data);
|
|
211
|
-
return { processed };
|
|
212
|
-
});
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Parallel Operations
|
|
216
|
-
|
|
217
|
-
```typescript
|
|
218
|
-
app.get('/dashboard', async (ctx) => {
|
|
219
|
-
// Errors in Promise.all are caught
|
|
220
|
-
const [users, posts, comments] = await Promise.all([
|
|
221
|
-
getUsers(),
|
|
222
|
-
getPosts(),
|
|
223
|
-
getComments()
|
|
224
|
-
]);
|
|
225
|
-
|
|
226
|
-
return { users, posts, comments };
|
|
227
|
-
});
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
## HTTP Status Codes
|
|
231
|
-
|
|
232
|
-
### Common Error Responses
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
app.get('/users/:id', async (ctx) => {
|
|
236
|
-
const user = await getUser(ctx.params.id);
|
|
237
|
-
|
|
238
|
-
if (!user) {
|
|
239
|
-
// 404 Not Found
|
|
240
|
-
return ctx.response.status(404).json({
|
|
241
|
-
error: 'Not Found',
|
|
242
|
-
message: 'User not found'
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return { user };
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
app.post('/admin/action', async (ctx) => {
|
|
250
|
-
if (!ctx.headers.authorization) {
|
|
251
|
-
// 401 Unauthorized
|
|
252
|
-
return ctx.response.status(401).json({
|
|
253
|
-
error: 'Unauthorized',
|
|
254
|
-
message: 'Authentication required'
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
if (!ctx.user.isAdmin) {
|
|
259
|
-
// 403 Forbidden
|
|
260
|
-
return ctx.response.status(403).json({
|
|
261
|
-
error: 'Forbidden',
|
|
262
|
-
message: 'Admin access required'
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
return await performAction();
|
|
267
|
-
});
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
## Error Logging
|
|
271
|
-
|
|
272
|
-
### Structured Logging
|
|
273
|
-
|
|
274
|
-
```typescript
|
|
275
|
-
app.onError((error, ctx) => {
|
|
276
|
-
const logData = {
|
|
277
|
-
timestamp: new Date().toISOString(),
|
|
278
|
-
level: 'error',
|
|
279
|
-
message: error.message,
|
|
280
|
-
stack: error.stack,
|
|
281
|
-
context: {
|
|
282
|
-
method: ctx.method,
|
|
283
|
-
path: ctx.path,
|
|
284
|
-
query: ctx.query,
|
|
285
|
-
headers: ctx.headers,
|
|
286
|
-
user: ctx.user?.id
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
console.error(JSON.stringify(logData));
|
|
291
|
-
|
|
292
|
-
return ctx.response.status(500).json({
|
|
293
|
-
error: 'Internal Server Error'
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
### Integration with Logging Services
|
|
299
|
-
|
|
300
|
-
```typescript
|
|
301
|
-
import * as Sentry from '@sentry/node';
|
|
302
|
-
|
|
303
|
-
app.onError((error, ctx) => {
|
|
304
|
-
// Send to Sentry
|
|
305
|
-
Sentry.captureException(error, {
|
|
306
|
-
tags: {
|
|
307
|
-
path: ctx.path,
|
|
308
|
-
method: ctx.method
|
|
309
|
-
},
|
|
310
|
-
user: ctx.user ? { id: ctx.user.id } : undefined
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
return ctx.response.status(500).json({
|
|
314
|
-
error: 'Internal Server Error',
|
|
315
|
-
errorId: Sentry.lastEventId()
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
## Real-World Examples
|
|
321
|
-
|
|
322
|
-
### Complete Error Handling Setup
|
|
323
|
-
|
|
324
|
-
```typescript
|
|
325
|
-
import { createApp } from './nexus';
|
|
326
|
-
|
|
327
|
-
// Custom errors
|
|
328
|
-
class AppError extends Error {
|
|
329
|
-
statusCode: number;
|
|
330
|
-
constructor(message: string, statusCode: number) {
|
|
331
|
-
super(message);
|
|
332
|
-
this.statusCode = statusCode;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
// Create app
|
|
337
|
-
const app = createApp();
|
|
338
|
-
|
|
339
|
-
// Global error handler
|
|
340
|
-
app.onError((error, ctx) => {
|
|
341
|
-
// Log error
|
|
342
|
-
console.error({
|
|
343
|
-
error: error.message,
|
|
344
|
-
stack: error.stack,
|
|
345
|
-
path: ctx.path,
|
|
346
|
-
method: ctx.method
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
// App errors (known)
|
|
350
|
-
if (error instanceof AppError) {
|
|
351
|
-
return ctx.response.status(error.statusCode).json({
|
|
352
|
-
error: error.message,
|
|
353
|
-
path: ctx.path
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// Validation errors
|
|
358
|
-
if (error.name === 'ZodError') {
|
|
359
|
-
return ctx.response.status(400).json({
|
|
360
|
-
error: 'Validation failed',
|
|
361
|
-
details: error.errors
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Database errors
|
|
366
|
-
if (error.name === 'SequelizeConnectionError') {
|
|
367
|
-
return ctx.response.status(503).json({
|
|
368
|
-
error: 'Service Unavailable'
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Unknown errors
|
|
373
|
-
return ctx.response.status(500).json({
|
|
374
|
-
error: 'Internal Server Error',
|
|
375
|
-
message: process.env.NODE_ENV === 'development' ? error.message : undefined
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
// Routes
|
|
380
|
-
app.get('/users/:id', async (ctx) => {
|
|
381
|
-
const user = await getUser(ctx.params.id);
|
|
382
|
-
if (!user) throw new AppError('User not found', 404);
|
|
383
|
-
return { user };
|
|
384
|
-
});
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
### Database Error Handling
|
|
388
|
-
|
|
389
|
-
```typescript
|
|
390
|
-
app.get('/users', async (ctx) => {
|
|
391
|
-
try {
|
|
392
|
-
const users = await database.query('SELECT * FROM users');
|
|
393
|
-
return { users };
|
|
394
|
-
} catch (error) {
|
|
395
|
-
if (error.code === 'ECONNREFUSED') {
|
|
396
|
-
throw new AppError('Database connection failed', 503);
|
|
397
|
-
}
|
|
398
|
-
throw error; // Re-throw for global handler
|
|
399
|
-
}
|
|
400
|
-
});
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
## Best Practices
|
|
404
|
-
|
|
405
|
-
### ✅ DO: Use custom error classes
|
|
406
|
-
|
|
407
|
-
```typescript
|
|
408
|
-
throw new NotFoundError('User');
|
|
409
|
-
throw new ValidationError('Invalid email format');
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
### ✅ DO: Log errors properly
|
|
413
|
-
|
|
414
|
-
```typescript
|
|
415
|
-
app.onError((error, ctx) => {
|
|
416
|
-
console.error({
|
|
417
|
-
message: error.message,
|
|
418
|
-
stack: error.stack,
|
|
419
|
-
path: ctx.path
|
|
420
|
-
});
|
|
421
|
-
// Return response
|
|
422
|
-
});
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
### ✅ DO: Return appropriate status codes
|
|
426
|
-
|
|
427
|
-
```typescript
|
|
428
|
-
// 400 - Bad Request (validation)
|
|
429
|
-
// 401 - Unauthorized (authentication)
|
|
430
|
-
// 403 - Forbidden (authorization)
|
|
431
|
-
// 404 - Not Found
|
|
432
|
-
// 500 - Internal Server Error
|
|
433
|
-
// 503 - Service Unavailable
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
### ❌ DON'T: Expose sensitive information
|
|
437
|
-
|
|
438
|
-
```typescript
|
|
439
|
-
// Bad
|
|
440
|
-
return { error: error.stack };
|
|
441
|
-
|
|
442
|
-
// Good
|
|
443
|
-
return {
|
|
444
|
-
error: 'Internal Server Error',
|
|
445
|
-
errorId: generateErrorId()
|
|
446
|
-
};
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
### ✅ DO: Provide helpful error messages in development
|
|
450
|
-
|
|
451
|
-
```typescript
|
|
452
|
-
const message = process.env.NODE_ENV === 'development'
|
|
453
|
-
? error.message
|
|
454
|
-
: 'Something went wrong';
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
## Next Steps
|
|
458
|
-
|
|
459
|
-
- ⚡ [Performance](./07-performance.md) - Optimize your application
|
|
460
|
-
- 🔌 [Adapters](./08-adapters.md) - Extend with adapters
|
|
461
|
-
- 📖 [API Reference](./09-api-reference.md) - Complete API docs
|
|
462
|
-
|
|
463
|
-
---
|
|
464
|
-
|
|
465
|
-
[← Validation](./05-validation.md) | [Performance →](./07-performance.md)
|