@engjts/nexus 0.1.8 → 0.1.10
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/playground.js.map +1 -1
- package/dist/advanced/static/generateDirectoryListing.d.ts +1 -1
- package/dist/advanced/static/generateDirectoryListing.d.ts.map +1 -1
- package/dist/advanced/static/generateDirectoryListing.js +12 -6
- package/dist/advanced/static/generateDirectoryListing.js.map +1 -1
- package/dist/advanced/static/index.d.ts +2 -0
- package/dist/advanced/static/index.d.ts.map +1 -1
- package/dist/advanced/static/index.js +4 -1
- package/dist/advanced/static/index.js.map +1 -1
- package/dist/advanced/static/serveStatic.d.ts.map +1 -1
- package/dist/advanced/static/serveStatic.js +7 -1
- package/dist/advanced/static/serveStatic.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/BENCHMARK_REPORT.md +0 -343
- 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 -1956
- 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 -250
- package/src/advanced/playground/types.ts +0 -49
- 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 -1453
- package/src/core/context-pool.ts +0 -79
- package/src/core/context.ts +0 -856
- package/src/core/index.ts +0 -94
- package/src/core/middleware.ts +0 -272
- 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 -623
- package/src/core/router/index.ts +0 -260
- package/src/core/router/radix-tree.ts +0 -242
- package/src/core/serializer.ts +0 -397
- 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 -616
- 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 -281
- 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,483 +0,0 @@
|
|
|
1
|
-
# Middleware System
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Middleware in Nexus are **composable, type-safe** functions that process requests before they reach the handler. Unlike Express.js, middleware can transform the context and maintain type safety.
|
|
6
|
-
|
|
7
|
-
## Basic Middleware
|
|
8
|
-
|
|
9
|
-
### Simple Middleware
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
const logger = async (ctx, next) => {
|
|
13
|
-
console.log(`${ctx.method} ${ctx.path}`);
|
|
14
|
-
return next(ctx);
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
app.use(logger);
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### Middleware with Logic
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
const timer = async (ctx, next) => {
|
|
24
|
-
const start = Date.now();
|
|
25
|
-
const response = await next(ctx);
|
|
26
|
-
const duration = Date.now() - start;
|
|
27
|
-
|
|
28
|
-
console.log(`Request took ${duration}ms`);
|
|
29
|
-
return response;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
app.use(timer);
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Global Middleware
|
|
36
|
-
|
|
37
|
-
Applied to all routes:
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
app.use(logger());
|
|
41
|
-
app.use(cors());
|
|
42
|
-
app.use(authenticate);
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Route-Specific Middleware
|
|
46
|
-
|
|
47
|
-
Applied to specific routes:
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
app.get('/admin', {
|
|
51
|
-
middlewares: [authenticate, requireAdmin],
|
|
52
|
-
handler: async (ctx) => {
|
|
53
|
-
return { admin: true };
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Built-in Middleware
|
|
59
|
-
|
|
60
|
-
### Logger
|
|
61
|
-
|
|
62
|
-
Logs all requests with timing:
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
import { logger } from './nexus';
|
|
66
|
-
|
|
67
|
-
app.use(logger());
|
|
68
|
-
// Output:
|
|
69
|
-
// --> GET /users
|
|
70
|
-
// <-- GET /users 200 45ms
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### CORS
|
|
74
|
-
|
|
75
|
-
Handle Cross-Origin Resource Sharing:
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { cors } from './nexus';
|
|
79
|
-
|
|
80
|
-
app.use(cors({
|
|
81
|
-
origin: 'https://example.com',
|
|
82
|
-
methods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
83
|
-
credentials: true,
|
|
84
|
-
maxAge: 86400
|
|
85
|
-
}));
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
Default options:
|
|
89
|
-
```typescript
|
|
90
|
-
{
|
|
91
|
-
origin: '*',
|
|
92
|
-
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
|
93
|
-
credentials: false,
|
|
94
|
-
maxAge: 86400
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Custom Middleware
|
|
99
|
-
|
|
100
|
-
### Authentication Middleware
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
const authenticate = async (ctx: any, next: any) => {
|
|
104
|
-
const token = ctx.headers.authorization?.replace('Bearer ', '');
|
|
105
|
-
|
|
106
|
-
if (!token) {
|
|
107
|
-
return ctx.response.status(401).json({
|
|
108
|
-
error: 'Unauthorized',
|
|
109
|
-
message: 'Missing token'
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
const user = await verifyToken(token);
|
|
115
|
-
ctx.user = user; // Add user to context
|
|
116
|
-
return next(ctx);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
return ctx.response.status(401).json({
|
|
119
|
-
error: 'Unauthorized',
|
|
120
|
-
message: 'Invalid token'
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
// Usage
|
|
126
|
-
app.get('/profile', {
|
|
127
|
-
middlewares: [authenticate],
|
|
128
|
-
handler: async (ctx: any) => {
|
|
129
|
-
return { user: ctx.user };
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### Rate Limiting Middleware
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
const rateLimit = (options: { max: number; window: number }) => {
|
|
138
|
-
const requests = new Map<string, number[]>();
|
|
139
|
-
|
|
140
|
-
return async (ctx: any, next: any) => {
|
|
141
|
-
const key = ctx.headers['x-forwarded-for'] || ctx.raw.req.socket.remoteAddress;
|
|
142
|
-
const now = Date.now();
|
|
143
|
-
const windowMs = options.window * 1000;
|
|
144
|
-
|
|
145
|
-
// Get request timestamps for this key
|
|
146
|
-
let timestamps = requests.get(key) || [];
|
|
147
|
-
|
|
148
|
-
// Remove old timestamps outside the window
|
|
149
|
-
timestamps = timestamps.filter(t => now - t < windowMs);
|
|
150
|
-
|
|
151
|
-
if (timestamps.length >= options.max) {
|
|
152
|
-
return ctx.response.status(429).json({
|
|
153
|
-
error: 'Too Many Requests',
|
|
154
|
-
retryAfter: Math.ceil((timestamps[0] + windowMs - now) / 1000)
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Add current timestamp
|
|
159
|
-
timestamps.push(now);
|
|
160
|
-
requests.set(key, timestamps);
|
|
161
|
-
|
|
162
|
-
return next(ctx);
|
|
163
|
-
};
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
// Usage
|
|
167
|
-
app.post('/api/login', {
|
|
168
|
-
middlewares: [rateLimit({ max: 5, window: 60 })],
|
|
169
|
-
handler: async (ctx) => {
|
|
170
|
-
// Max 5 requests per 60 seconds
|
|
171
|
-
return await handleLogin(ctx.body);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Request ID Middleware
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
import { randomUUID } from 'crypto';
|
|
180
|
-
|
|
181
|
-
const requestId = async (ctx: any, next: any) => {
|
|
182
|
-
ctx.requestId = randomUUID();
|
|
183
|
-
const response = await next(ctx);
|
|
184
|
-
response.headers['X-Request-ID'] = ctx.requestId;
|
|
185
|
-
return response;
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
app.use(requestId);
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## Type-Safe Middleware
|
|
192
|
-
|
|
193
|
-
For full type safety, define context types:
|
|
194
|
-
|
|
195
|
-
```typescript
|
|
196
|
-
import { Context, Middleware } from './nexus';
|
|
197
|
-
|
|
198
|
-
interface User {
|
|
199
|
-
id: string;
|
|
200
|
-
name: string;
|
|
201
|
-
role: string;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
interface AuthContext extends Context {
|
|
205
|
-
user: User;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Type-safe middleware
|
|
209
|
-
const authenticate: Middleware<Context, AuthContext> = async (ctx, next) => {
|
|
210
|
-
const token = ctx.headers.authorization;
|
|
211
|
-
const user = await verifyToken(token!);
|
|
212
|
-
|
|
213
|
-
return next({ ...ctx, user });
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
// Type-safe handler
|
|
217
|
-
const profileHandler = async (ctx: AuthContext) => {
|
|
218
|
-
// ctx.user is typed and guaranteed to exist
|
|
219
|
-
return { userId: ctx.user.id, name: ctx.user.name };
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
app.get('/profile', {
|
|
223
|
-
middlewares: [authenticate],
|
|
224
|
-
handler: profileHandler
|
|
225
|
-
});
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
## Middleware Composition
|
|
229
|
-
|
|
230
|
-
Combine multiple middleware into one:
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
const secureRoute = [
|
|
234
|
-
authenticate,
|
|
235
|
-
requireVerifiedEmail,
|
|
236
|
-
rateLimit({ max: 100, window: 60 })
|
|
237
|
-
];
|
|
238
|
-
|
|
239
|
-
app.get('/api/sensitive', {
|
|
240
|
-
middlewares: secureRoute,
|
|
241
|
-
handler: async (ctx) => {
|
|
242
|
-
return { data: 'sensitive' };
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
## Error Handling in Middleware
|
|
248
|
-
|
|
249
|
-
### Try-Catch Pattern
|
|
250
|
-
|
|
251
|
-
```typescript
|
|
252
|
-
const errorHandler = async (ctx: any, next: any) => {
|
|
253
|
-
try {
|
|
254
|
-
return await next(ctx);
|
|
255
|
-
} catch (error) {
|
|
256
|
-
console.error('Middleware error:', error);
|
|
257
|
-
return ctx.response.status(500).json({
|
|
258
|
-
error: 'Internal Server Error'
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
app.use(errorHandler);
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### Using errorHandler Utility
|
|
267
|
-
|
|
268
|
-
```typescript
|
|
269
|
-
import { errorHandler } from './nexus';
|
|
270
|
-
|
|
271
|
-
app.use(errorHandler((error, ctx) => {
|
|
272
|
-
console.error(error);
|
|
273
|
-
return {
|
|
274
|
-
statusCode: 500,
|
|
275
|
-
headers: { 'Content-Type': 'application/json' },
|
|
276
|
-
body: JSON.stringify({ error: error.message })
|
|
277
|
-
};
|
|
278
|
-
}));
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
## Middleware Order
|
|
282
|
-
|
|
283
|
-
The order matters! Middleware executes in the order it's registered:
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
// Good - logger sees all requests
|
|
287
|
-
app.use(logger());
|
|
288
|
-
app.use(authenticate);
|
|
289
|
-
app.use(rateLimit());
|
|
290
|
-
|
|
291
|
-
// Bad - authenticated users bypass rate limit
|
|
292
|
-
app.use(authenticate);
|
|
293
|
-
app.use(rateLimit());
|
|
294
|
-
app.use(logger());
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
## Conditional Middleware
|
|
298
|
-
|
|
299
|
-
Execute middleware based on conditions:
|
|
300
|
-
|
|
301
|
-
```typescript
|
|
302
|
-
const conditionalAuth = async (ctx: any, next: any) => {
|
|
303
|
-
// Skip auth for public routes
|
|
304
|
-
if (ctx.path.startsWith('/public/')) {
|
|
305
|
-
return next(ctx);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Require auth for all other routes
|
|
309
|
-
return authenticate(ctx, next);
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
app.use(conditionalAuth);
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
## Response Modification
|
|
316
|
-
|
|
317
|
-
Middleware can modify responses:
|
|
318
|
-
|
|
319
|
-
```typescript
|
|
320
|
-
const addHeaders = async (ctx: any, next: any) => {
|
|
321
|
-
const response = await next(ctx);
|
|
322
|
-
|
|
323
|
-
// Add custom headers to response
|
|
324
|
-
response.headers['X-Powered-By'] = 'Nexus';
|
|
325
|
-
response.headers['X-Response-Time'] = Date.now().toString();
|
|
326
|
-
|
|
327
|
-
return response;
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
app.use(addHeaders);
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
## Real-World Examples
|
|
334
|
-
|
|
335
|
-
### Complete API Middleware Stack
|
|
336
|
-
|
|
337
|
-
```typescript
|
|
338
|
-
import { createApp, logger, cors } from './nexus';
|
|
339
|
-
|
|
340
|
-
const app = createApp();
|
|
341
|
-
|
|
342
|
-
// 1. CORS - must be first for preflight requests
|
|
343
|
-
app.use(cors({
|
|
344
|
-
origin: process.env.CORS_ORIGIN || '*',
|
|
345
|
-
credentials: true
|
|
346
|
-
}));
|
|
347
|
-
|
|
348
|
-
// 2. Request logging
|
|
349
|
-
app.use(logger());
|
|
350
|
-
|
|
351
|
-
// 3. Request ID for tracing
|
|
352
|
-
app.use(requestId);
|
|
353
|
-
|
|
354
|
-
// 4. Rate limiting
|
|
355
|
-
app.use(rateLimit({ max: 100, window: 60 }));
|
|
356
|
-
|
|
357
|
-
// 5. Error handling wrapper
|
|
358
|
-
app.use(errorHandler(customErrorHandler));
|
|
359
|
-
|
|
360
|
-
// Routes come after all global middleware
|
|
361
|
-
app.get('/api/users', {
|
|
362
|
-
middlewares: [authenticate],
|
|
363
|
-
handler: userHandler
|
|
364
|
-
});
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
### Session Middleware
|
|
368
|
-
|
|
369
|
-
```typescript
|
|
370
|
-
interface SessionData {
|
|
371
|
-
userId?: string;
|
|
372
|
-
createdAt: number;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
const sessions = new Map<string, SessionData>();
|
|
376
|
-
|
|
377
|
-
const session = async (ctx: any, next: any) => {
|
|
378
|
-
const sessionId = ctx.cookies.get('session');
|
|
379
|
-
|
|
380
|
-
if (sessionId && sessions.has(sessionId)) {
|
|
381
|
-
ctx.session = sessions.get(sessionId);
|
|
382
|
-
} else {
|
|
383
|
-
const newSessionId = randomUUID();
|
|
384
|
-
ctx.session = { createdAt: Date.now() };
|
|
385
|
-
sessions.set(newSessionId, ctx.session);
|
|
386
|
-
|
|
387
|
-
ctx.cookies.set('session', newSessionId, {
|
|
388
|
-
httpOnly: true,
|
|
389
|
-
secure: true,
|
|
390
|
-
maxAge: 86400
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const response = await next(ctx);
|
|
395
|
-
|
|
396
|
-
// Save session changes
|
|
397
|
-
if (ctx.cookies.get('session')) {
|
|
398
|
-
sessions.set(ctx.cookies.get('session')!, ctx.session);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
return response;
|
|
402
|
-
};
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
## Best Practices
|
|
406
|
-
|
|
407
|
-
### ✅ DO: Keep middleware focused
|
|
408
|
-
|
|
409
|
-
```typescript
|
|
410
|
-
// Good - single responsibility
|
|
411
|
-
const authenticate = async (ctx, next) => {
|
|
412
|
-
ctx.user = await verifyToken(ctx.headers.authorization);
|
|
413
|
-
return next(ctx);
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
const requireAdmin = async (ctx, next) => {
|
|
417
|
-
if (ctx.user.role !== 'admin') {
|
|
418
|
-
return ctx.response.status(403).json({ error: 'Forbidden' });
|
|
419
|
-
}
|
|
420
|
-
return next(ctx);
|
|
421
|
-
};
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
### ❌ DON'T: Create monolithic middleware
|
|
425
|
-
|
|
426
|
-
```typescript
|
|
427
|
-
// Bad - does too much
|
|
428
|
-
const megaMiddleware = async (ctx, next) => {
|
|
429
|
-
// Authentication
|
|
430
|
-
// Authorization
|
|
431
|
-
// Rate limiting
|
|
432
|
-
// Logging
|
|
433
|
-
// etc...
|
|
434
|
-
};
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
### ✅ DO: Always call next()
|
|
438
|
-
|
|
439
|
-
```typescript
|
|
440
|
-
const middleware = async (ctx, next) => {
|
|
441
|
-
// Do work
|
|
442
|
-
const response = await next(ctx); // Important!
|
|
443
|
-
// Do more work
|
|
444
|
-
return response;
|
|
445
|
-
};
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
### ✅ DO: Handle errors properly
|
|
449
|
-
|
|
450
|
-
```typescript
|
|
451
|
-
const safeMiddleware = async (ctx, next) => {
|
|
452
|
-
try {
|
|
453
|
-
// Risky operation
|
|
454
|
-
ctx.data = await riskyOperation();
|
|
455
|
-
return next(ctx);
|
|
456
|
-
} catch (error) {
|
|
457
|
-
return ctx.response.status(500).json({ error: 'Failed' });
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
## Performance
|
|
463
|
-
|
|
464
|
-
Middleware is optimized through:
|
|
465
|
-
- **JIT Compilation** - Hot middleware paths are compiled
|
|
466
|
-
- **Chain Inlining** - Reduces function call overhead
|
|
467
|
-
- **Context Pooling** - Reuses context objects
|
|
468
|
-
|
|
469
|
-
```typescript
|
|
470
|
-
const app = createApp({
|
|
471
|
-
enableJIT: true // Enable optimization (default)
|
|
472
|
-
});
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
## Next Steps
|
|
476
|
-
|
|
477
|
-
- ✅ [Validation](./05-validation.md) - Validate requests
|
|
478
|
-
- 🔒 [Error Handling](./06-error-handling.md) - Handle errors
|
|
479
|
-
- 📖 [API Reference](./09-api-reference.md) - Complete API docs
|
|
480
|
-
|
|
481
|
-
---
|
|
482
|
-
|
|
483
|
-
[← Routing](./03-routing.md) | [Validation →](./05-validation.md)
|