@morojs/moro 1.6.0 → 1.6.2
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/core/config/config-sources.js +4 -0
- package/dist/core/config/config-sources.js.map +1 -1
- package/dist/core/config/config-validator.js +3 -0
- package/dist/core/config/config-validator.js.map +1 -1
- package/dist/core/config/file-loader.js +3 -1
- package/dist/core/config/file-loader.js.map +1 -1
- package/dist/core/config/schema.js +4 -1
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/events/event-bus.js +1 -1
- package/dist/core/events/event-bus.js.map +1 -1
- package/dist/core/framework.d.ts +1 -1
- package/dist/core/framework.js +13 -7
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +55 -15
- package/dist/core/http/http-server.js +70 -146
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/index.d.ts +1 -1
- package/dist/core/http/index.js +1 -1
- package/dist/core/http/index.js.map +1 -1
- package/dist/core/http/uws-http-server.d.ts +4 -22
- package/dist/core/http/uws-http-server.js +43 -208
- package/dist/core/http/uws-http-server.js.map +1 -1
- package/dist/core/networking/adapters/uws-adapter.d.ts +1 -1
- package/dist/core/networking/adapters/uws-adapter.js +1 -1
- package/dist/core/pooling/object-pool-manager.d.ts +140 -0
- package/dist/core/pooling/object-pool-manager.js +502 -0
- package/dist/core/pooling/object-pool-manager.js.map +1 -0
- package/dist/core/routing/app-integration.d.ts +12 -10
- package/dist/core/routing/app-integration.js +43 -74
- package/dist/core/routing/app-integration.js.map +1 -1
- package/dist/core/routing/index.d.ts +15 -29
- package/dist/core/routing/index.js +43 -390
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/routing/path-matcher.d.ts +67 -0
- package/dist/core/routing/path-matcher.js +182 -0
- package/dist/core/routing/path-matcher.js.map +1 -0
- package/dist/core/{http → routing}/router.d.ts +21 -9
- package/dist/core/routing/router.js +68 -0
- package/dist/core/routing/router.js.map +1 -0
- package/dist/core/routing/unified-router.d.ts +148 -0
- package/dist/core/routing/unified-router.js +684 -0
- package/dist/core/routing/unified-router.js.map +1 -0
- package/dist/moro.d.ts +10 -7
- package/dist/moro.js +90 -41
- package/dist/moro.js.map +1 -1
- package/dist/types/config.d.ts +3 -0
- package/package.json +1 -1
- package/src/core/config/config-sources.ts +4 -0
- package/src/core/config/config-validator.ts +3 -0
- package/src/core/config/file-loader.ts +4 -1
- package/src/core/config/schema.ts +4 -1
- package/src/core/events/event-bus.ts +1 -1
- package/src/core/framework.ts +14 -9
- package/src/core/http/http-server.ts +76 -161
- package/src/core/http/index.ts +1 -1
- package/src/core/http/uws-http-server.ts +43 -246
- package/src/core/networking/adapters/uws-adapter.ts +1 -1
- package/src/core/pooling/object-pool-manager.ts +630 -0
- package/src/core/routing/app-integration.ts +57 -109
- package/src/core/routing/index.ts +62 -473
- package/src/core/routing/path-matcher.ts +222 -0
- package/src/core/routing/router.ts +97 -0
- package/src/core/routing/unified-router.ts +870 -0
- package/src/moro.ts +107 -57
- package/src/types/config.ts +3 -0
- package/dist/core/http/router.js +0 -183
- package/dist/core/http/router.js.map +0 -1
- package/src/core/http/router.ts +0 -230
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
// Intelligent Routing System for Moro Framework
|
|
2
2
|
// Schema-first with automatic middleware ordering and chainable API
|
|
3
|
+
//
|
|
4
|
+
// NOTE: This file exports types and thin facades to UnifiedRouter
|
|
5
|
+
// All routing logic has been consolidated in unified-router.ts
|
|
3
6
|
|
|
4
7
|
import { ValidationSchema } from '../validation/schema-interface.js';
|
|
5
8
|
import { HttpRequest, HttpResponse } from '../http/index.js';
|
|
6
|
-
import {
|
|
9
|
+
import { UnifiedRouter } from './unified-router.js';
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
// ===== TYPE EXPORTS (Keep all - used by app code) =====
|
|
9
12
|
|
|
10
|
-
// Core types
|
|
11
13
|
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
|
|
12
14
|
export type RouteHandler<T = any> = (req: HttpRequest, res: HttpResponse) => T | Promise<T>;
|
|
13
15
|
export type Middleware = (
|
|
@@ -16,7 +18,6 @@ export type Middleware = (
|
|
|
16
18
|
next: () => void
|
|
17
19
|
) => void | Promise<void>;
|
|
18
20
|
|
|
19
|
-
// Configuration interfaces
|
|
20
21
|
export interface ValidationConfig {
|
|
21
22
|
body?: ValidationSchema;
|
|
22
23
|
query?: ValidationSchema;
|
|
@@ -42,107 +43,93 @@ export interface CacheConfig {
|
|
|
42
43
|
tags?: string[];
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
// Middleware phases for intelligent ordering
|
|
46
46
|
export interface MiddlewarePhases {
|
|
47
|
-
before?: Middleware[];
|
|
48
|
-
after?: Middleware[];
|
|
49
|
-
transform?: Middleware[];
|
|
47
|
+
before?: Middleware[];
|
|
48
|
+
after?: Middleware[];
|
|
49
|
+
transform?: Middleware[];
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
// Core route schema
|
|
53
52
|
export interface RouteSchema {
|
|
54
53
|
method: HttpMethod;
|
|
55
54
|
path: string;
|
|
56
55
|
handler: RouteHandler;
|
|
57
|
-
|
|
58
|
-
// Framework-managed (order-independent)
|
|
59
56
|
validation?: ValidationConfig;
|
|
60
57
|
auth?: AuthConfig;
|
|
61
58
|
rateLimit?: RateLimitConfig;
|
|
62
59
|
cache?: CacheConfig;
|
|
63
|
-
|
|
64
|
-
// Custom middleware with phase hints
|
|
65
60
|
middleware?: MiddlewarePhases;
|
|
66
|
-
|
|
67
|
-
// Metadata
|
|
68
61
|
description?: string;
|
|
69
62
|
tags?: string[];
|
|
70
63
|
}
|
|
71
64
|
|
|
72
|
-
// Execution phases in optimal order
|
|
73
65
|
export const EXECUTION_PHASES = [
|
|
74
|
-
'security',
|
|
75
|
-
'parsing',
|
|
76
|
-
'rateLimit',
|
|
77
|
-
'before',
|
|
78
|
-
'auth',
|
|
79
|
-
'validation',
|
|
80
|
-
'transform',
|
|
81
|
-
'cache',
|
|
82
|
-
'after',
|
|
83
|
-
'handler',
|
|
66
|
+
'security',
|
|
67
|
+
'parsing',
|
|
68
|
+
'rateLimit',
|
|
69
|
+
'before',
|
|
70
|
+
'auth',
|
|
71
|
+
'validation',
|
|
72
|
+
'transform',
|
|
73
|
+
'cache',
|
|
74
|
+
'after',
|
|
75
|
+
'handler',
|
|
84
76
|
] as const;
|
|
85
77
|
|
|
86
78
|
export type ExecutionPhase = (typeof EXECUTION_PHASES)[number];
|
|
87
79
|
|
|
88
|
-
// Enhanced request with validation results
|
|
89
80
|
export interface ValidatedRequest<T = any> extends HttpRequest {
|
|
90
81
|
validatedBody?: T;
|
|
91
82
|
validatedQuery?: any;
|
|
92
83
|
validatedParams?: any;
|
|
93
84
|
validatedHeaders?: any;
|
|
94
|
-
user?: any;
|
|
85
|
+
user?: any;
|
|
95
86
|
}
|
|
96
87
|
|
|
97
|
-
//
|
|
88
|
+
// ===== ROUTE BUILDER INTERFACE (Public API) =====
|
|
89
|
+
|
|
98
90
|
export interface RouteBuilder {
|
|
99
|
-
// Validation methods
|
|
100
91
|
validate(config: ValidationConfig): RouteBuilder;
|
|
101
92
|
body<T>(schema: ValidationSchema<T>): RouteBuilder;
|
|
102
93
|
query<T>(schema: ValidationSchema<T>): RouteBuilder;
|
|
103
94
|
params<T>(schema: ValidationSchema<T>): RouteBuilder;
|
|
104
95
|
headers<T>(schema: ValidationSchema<T>): RouteBuilder;
|
|
105
|
-
|
|
106
|
-
// Security/Auth methods
|
|
107
96
|
auth(config: AuthConfig): RouteBuilder;
|
|
108
97
|
rateLimit(config: RateLimitConfig): RouteBuilder;
|
|
109
|
-
|
|
110
|
-
// Caching
|
|
111
98
|
cache(config: CacheConfig): RouteBuilder;
|
|
112
|
-
|
|
113
|
-
// Custom middleware with phase control
|
|
114
99
|
before(...middleware: Middleware[]): RouteBuilder;
|
|
115
100
|
after(...middleware: Middleware[]): RouteBuilder;
|
|
116
101
|
transform(...middleware: Middleware[]): RouteBuilder;
|
|
117
|
-
use(...middleware: Middleware[]): RouteBuilder;
|
|
118
|
-
|
|
119
|
-
// Metadata
|
|
102
|
+
use(...middleware: Middleware[]): RouteBuilder;
|
|
120
103
|
describe(description: string): RouteBuilder;
|
|
121
104
|
tag(...tags: string[]): RouteBuilder;
|
|
122
|
-
|
|
123
|
-
// Terminal method
|
|
124
|
-
handler<T>(handler: RouteHandler<T>): CompiledRoute;
|
|
105
|
+
handler<T>(handler: RouteHandler<T>): void;
|
|
125
106
|
}
|
|
126
107
|
|
|
127
|
-
//
|
|
108
|
+
// ===== COMPILED ROUTE INTERFACE (Public API) =====
|
|
109
|
+
|
|
128
110
|
export interface CompiledRoute {
|
|
129
111
|
schema: RouteSchema;
|
|
130
112
|
execute(req: HttpRequest, res: HttpResponse): Promise<void>;
|
|
131
113
|
}
|
|
132
114
|
|
|
133
|
-
//
|
|
115
|
+
// ===== FACADE IMPLEMENTATIONS (Delegate to UnifiedRouter) =====
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Thin facade to UnifiedRouter.RouteBuilder
|
|
119
|
+
* Maintains backward compatibility while using optimized implementation
|
|
120
|
+
*/
|
|
134
121
|
export class IntelligentRouteBuilder implements RouteBuilder {
|
|
135
122
|
private schema: Partial<RouteSchema>;
|
|
123
|
+
private router = UnifiedRouter.getInstance();
|
|
136
124
|
|
|
137
125
|
constructor(method: HttpMethod, path: string) {
|
|
138
126
|
this.schema = {
|
|
139
127
|
method,
|
|
140
128
|
path,
|
|
141
|
-
middleware: {},
|
|
129
|
+
middleware: {} as MiddlewarePhases,
|
|
142
130
|
};
|
|
143
131
|
}
|
|
144
132
|
|
|
145
|
-
// Validation methods
|
|
146
133
|
validate(config: ValidationConfig): RouteBuilder {
|
|
147
134
|
this.schema.validation = { ...this.schema.validation, ...config };
|
|
148
135
|
return this;
|
|
@@ -172,7 +159,6 @@ export class IntelligentRouteBuilder implements RouteBuilder {
|
|
|
172
159
|
return this;
|
|
173
160
|
}
|
|
174
161
|
|
|
175
|
-
// Security methods
|
|
176
162
|
auth(config: AuthConfig): RouteBuilder {
|
|
177
163
|
this.schema.auth = config;
|
|
178
164
|
return this;
|
|
@@ -183,28 +169,29 @@ export class IntelligentRouteBuilder implements RouteBuilder {
|
|
|
183
169
|
return this;
|
|
184
170
|
}
|
|
185
171
|
|
|
186
|
-
// Caching
|
|
187
172
|
cache(config: CacheConfig): RouteBuilder {
|
|
188
173
|
this.schema.cache = config;
|
|
189
174
|
return this;
|
|
190
175
|
}
|
|
191
176
|
|
|
192
|
-
// Custom middleware
|
|
193
177
|
before(...middleware: Middleware[]): RouteBuilder {
|
|
194
178
|
if (!this.schema.middleware) this.schema.middleware = {};
|
|
195
|
-
|
|
179
|
+
const phases = this.schema.middleware as MiddlewarePhases;
|
|
180
|
+
phases.before = [...(phases.before || []), ...middleware];
|
|
196
181
|
return this;
|
|
197
182
|
}
|
|
198
183
|
|
|
199
184
|
after(...middleware: Middleware[]): RouteBuilder {
|
|
200
185
|
if (!this.schema.middleware) this.schema.middleware = {};
|
|
201
|
-
|
|
186
|
+
const phases = this.schema.middleware as MiddlewarePhases;
|
|
187
|
+
phases.after = [...(phases.after || []), ...middleware];
|
|
202
188
|
return this;
|
|
203
189
|
}
|
|
204
190
|
|
|
205
191
|
transform(...middleware: Middleware[]): RouteBuilder {
|
|
206
192
|
if (!this.schema.middleware) this.schema.middleware = {};
|
|
207
|
-
|
|
193
|
+
const phases = this.schema.middleware as MiddlewarePhases;
|
|
194
|
+
phases.transform = [...(phases.transform || []), ...middleware];
|
|
208
195
|
return this;
|
|
209
196
|
}
|
|
210
197
|
|
|
@@ -212,7 +199,6 @@ export class IntelligentRouteBuilder implements RouteBuilder {
|
|
|
212
199
|
return this.after(...middleware);
|
|
213
200
|
}
|
|
214
201
|
|
|
215
|
-
// Metadata
|
|
216
202
|
describe(description: string): RouteBuilder {
|
|
217
203
|
this.schema.description = description;
|
|
218
204
|
return this;
|
|
@@ -223,8 +209,7 @@ export class IntelligentRouteBuilder implements RouteBuilder {
|
|
|
223
209
|
return this;
|
|
224
210
|
}
|
|
225
211
|
|
|
226
|
-
|
|
227
|
-
handler<T>(handler: RouteHandler<T>): CompiledRoute {
|
|
212
|
+
handler<T>(handler: RouteHandler<T>): void {
|
|
228
213
|
if (!handler) {
|
|
229
214
|
throw new Error('Handler is required');
|
|
230
215
|
}
|
|
@@ -234,439 +219,43 @@ export class IntelligentRouteBuilder implements RouteBuilder {
|
|
|
234
219
|
handler,
|
|
235
220
|
};
|
|
236
221
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
'RouteCompilation',
|
|
240
|
-
{
|
|
241
|
-
hasValidation: !!completeSchema.validation,
|
|
242
|
-
hasAuth: !!completeSchema.auth,
|
|
243
|
-
hasRateLimit: !!completeSchema.rateLimit,
|
|
244
|
-
hasCache: !!completeSchema.cache,
|
|
245
|
-
customMiddleware: {
|
|
246
|
-
before: completeSchema.middleware?.before?.length || 0,
|
|
247
|
-
after: completeSchema.middleware?.after?.length || 0,
|
|
248
|
-
transform: completeSchema.middleware?.transform?.length || 0,
|
|
249
|
-
},
|
|
250
|
-
}
|
|
251
|
-
);
|
|
252
|
-
|
|
253
|
-
return new ExecutableRoute(completeSchema);
|
|
222
|
+
// Delegate to UnifiedRouter
|
|
223
|
+
this.router.registerRoute(completeSchema);
|
|
254
224
|
}
|
|
255
225
|
}
|
|
256
226
|
|
|
257
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Thin facade implementing CompiledRoute interface
|
|
229
|
+
* Just stores schema for documentation purposes
|
|
230
|
+
*/
|
|
258
231
|
export class ExecutableRoute implements CompiledRoute {
|
|
259
|
-
// PERFORMANCE OPTIMIZATION: Pre-analyze route requirements
|
|
260
|
-
private readonly requiresAuth: boolean;
|
|
261
|
-
private readonly requiresValidation: boolean;
|
|
262
|
-
private readonly requiresRateLimit: boolean;
|
|
263
|
-
private readonly requiresCache: boolean;
|
|
264
|
-
private readonly hasBeforeMiddleware: boolean;
|
|
265
|
-
private readonly hasAfterMiddleware: boolean;
|
|
266
|
-
private readonly hasTransformMiddleware: boolean;
|
|
267
|
-
private readonly isFastPath: boolean;
|
|
268
|
-
|
|
269
232
|
constructor(public readonly schema: RouteSchema) {
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
this.requiresValidation = !!this.schema.validation;
|
|
273
|
-
this.requiresRateLimit = !!this.schema.rateLimit;
|
|
274
|
-
this.requiresCache = !!this.schema.cache;
|
|
275
|
-
this.hasBeforeMiddleware = !!this.schema.middleware?.before?.length;
|
|
276
|
-
this.hasAfterMiddleware = !!this.schema.middleware?.after?.length;
|
|
277
|
-
this.hasTransformMiddleware = !!this.schema.middleware?.transform?.length;
|
|
278
|
-
|
|
279
|
-
// Fast path: no middleware, no auth, no validation, no rate limiting
|
|
280
|
-
this.isFastPath =
|
|
281
|
-
!this.requiresAuth &&
|
|
282
|
-
!this.requiresValidation &&
|
|
283
|
-
!this.requiresRateLimit &&
|
|
284
|
-
!this.requiresCache &&
|
|
285
|
-
!this.hasBeforeMiddleware &&
|
|
286
|
-
!this.hasAfterMiddleware &&
|
|
287
|
-
!this.hasTransformMiddleware;
|
|
288
|
-
|
|
289
|
-
// Log fast path routes for monitoring
|
|
290
|
-
if (this.isFastPath) {
|
|
291
|
-
logger.debug(`Fast path route: ${this.schema.method} ${this.schema.path}`, 'FastPath');
|
|
292
|
-
}
|
|
233
|
+
// Register with UnifiedRouter
|
|
234
|
+
UnifiedRouter.getInstance().registerRoute(schema);
|
|
293
235
|
}
|
|
294
236
|
|
|
295
237
|
async execute(req: HttpRequest, res: HttpResponse): Promise<void> {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
// Skip all middleware - execute handler directly
|
|
302
|
-
const result = await this.schema.handler(validatedReq, res);
|
|
303
|
-
if (result !== undefined && !res.headersSent) {
|
|
304
|
-
res.json(result);
|
|
305
|
-
}
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// Optimized middleware execution - only run what's needed
|
|
310
|
-
if (this.hasBeforeMiddleware) {
|
|
311
|
-
await this.executePhase('before', validatedReq, res);
|
|
312
|
-
if (res.headersSent) return;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (this.requiresRateLimit) {
|
|
316
|
-
await this.executePhase('rateLimit', validatedReq, res);
|
|
317
|
-
if (res.headersSent) return;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (this.requiresAuth) {
|
|
321
|
-
await this.executePhase('auth', validatedReq, res);
|
|
322
|
-
if (res.headersSent) return;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (this.requiresValidation) {
|
|
326
|
-
await this.executePhase('validation', validatedReq, res);
|
|
327
|
-
if (res.headersSent) return;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (this.hasTransformMiddleware) {
|
|
331
|
-
await this.executePhase('transform', validatedReq, res);
|
|
332
|
-
if (res.headersSent) return;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if (this.requiresCache) {
|
|
336
|
-
await this.executePhase('cache', validatedReq, res);
|
|
337
|
-
if (res.headersSent) return;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (this.hasAfterMiddleware) {
|
|
341
|
-
await this.executePhase('after', validatedReq, res);
|
|
342
|
-
if (res.headersSent) return;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Execute handler last
|
|
346
|
-
if (!res.headersSent) {
|
|
347
|
-
await this.executePhase('handler', validatedReq, res);
|
|
348
|
-
}
|
|
349
|
-
} catch (error) {
|
|
350
|
-
logger.error('Route execution error', 'RouteExecution', {
|
|
351
|
-
error: error instanceof Error ? error.message : String(error),
|
|
352
|
-
route: `${this.schema.method} ${this.schema.path}`,
|
|
353
|
-
requestId: req.requestId,
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
if (!res.headersSent) {
|
|
357
|
-
res.status(500).json({
|
|
358
|
-
success: false,
|
|
359
|
-
error: 'Internal server error',
|
|
360
|
-
requestId: req.requestId,
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
private async executePhase(
|
|
367
|
-
phase: ExecutionPhase,
|
|
368
|
-
req: ValidatedRequest,
|
|
369
|
-
res: HttpResponse
|
|
370
|
-
): Promise<void> {
|
|
371
|
-
switch (phase) {
|
|
372
|
-
case 'before':
|
|
373
|
-
if (this.schema.middleware?.before) {
|
|
374
|
-
for (const middleware of this.schema.middleware.before) {
|
|
375
|
-
await this.executeMiddleware(middleware, req, res);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
break;
|
|
379
|
-
|
|
380
|
-
case 'rateLimit':
|
|
381
|
-
if (this.schema.rateLimit) {
|
|
382
|
-
await this.executeRateLimit(req, res);
|
|
383
|
-
}
|
|
384
|
-
break;
|
|
385
|
-
|
|
386
|
-
case 'auth':
|
|
387
|
-
if (this.schema.auth) {
|
|
388
|
-
await this.executeAuth(req, res);
|
|
389
|
-
}
|
|
390
|
-
break;
|
|
391
|
-
|
|
392
|
-
case 'validation':
|
|
393
|
-
if (this.schema.validation) {
|
|
394
|
-
await this.executeValidation(req, res);
|
|
395
|
-
}
|
|
396
|
-
break;
|
|
397
|
-
|
|
398
|
-
case 'transform':
|
|
399
|
-
if (this.schema.middleware?.transform) {
|
|
400
|
-
for (const middleware of this.schema.middleware.transform) {
|
|
401
|
-
await this.executeMiddleware(middleware, req, res);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
break;
|
|
405
|
-
|
|
406
|
-
case 'cache':
|
|
407
|
-
if (this.schema.cache) {
|
|
408
|
-
await this.executeCache(req, res);
|
|
409
|
-
}
|
|
410
|
-
break;
|
|
411
|
-
|
|
412
|
-
case 'after':
|
|
413
|
-
if (this.schema.middleware?.after) {
|
|
414
|
-
for (const middleware of this.schema.middleware.after) {
|
|
415
|
-
await this.executeMiddleware(middleware, req, res);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
break;
|
|
419
|
-
|
|
420
|
-
case 'handler': {
|
|
421
|
-
const result = await this.schema.handler(req, res);
|
|
422
|
-
if (result !== undefined && !res.headersSent) {
|
|
423
|
-
res.json(result);
|
|
424
|
-
}
|
|
425
|
-
break;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
private async executeMiddleware(
|
|
431
|
-
middleware: Middleware,
|
|
432
|
-
req: HttpRequest,
|
|
433
|
-
res: HttpResponse
|
|
434
|
-
): Promise<void> {
|
|
435
|
-
// PERFORMANCE OPTIMIZATION: Reduce Promise overhead
|
|
436
|
-
return new Promise((resolve, reject) => {
|
|
437
|
-
let resolved = false;
|
|
438
|
-
|
|
439
|
-
const next = () => {
|
|
440
|
-
if (!resolved) {
|
|
441
|
-
resolved = true;
|
|
442
|
-
resolve();
|
|
443
|
-
}
|
|
444
|
-
};
|
|
445
|
-
|
|
446
|
-
try {
|
|
447
|
-
const result = middleware(req, res, next);
|
|
448
|
-
if (result instanceof Promise) {
|
|
449
|
-
result.then(() => !resolved && next()).catch(reject);
|
|
450
|
-
} else {
|
|
451
|
-
// Synchronous middleware - call next immediately if not called
|
|
452
|
-
if (!resolved) {
|
|
453
|
-
next();
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
} catch (error) {
|
|
457
|
-
if (!resolved) {
|
|
458
|
-
resolved = true;
|
|
459
|
-
reject(error);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
private async executeRateLimit(req: HttpRequest, res: HttpResponse): Promise<void> {
|
|
466
|
-
// Rate limiting implementation will be added
|
|
467
|
-
logger.debug('Rate limit check', 'RateLimit', {
|
|
468
|
-
config: this.schema.rateLimit,
|
|
469
|
-
ip: req.ip,
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
private async executeAuth(req: ValidatedRequest, res: HttpResponse): Promise<void> {
|
|
474
|
-
const authConfig = this.schema.auth;
|
|
475
|
-
const auth = req.auth;
|
|
476
|
-
|
|
477
|
-
// This should never happen since executeAuth is only called when auth config exists
|
|
478
|
-
if (!authConfig) {
|
|
479
|
-
logger.error('executeAuth called without auth config', 'Auth');
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
logger.debug('Auth check', 'Auth', {
|
|
484
|
-
config: authConfig,
|
|
485
|
-
isAuthenticated: auth?.isAuthenticated,
|
|
486
|
-
userRoles: auth?.user?.roles,
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
// Check if auth middleware ran
|
|
490
|
-
if (!auth) {
|
|
491
|
-
res.status(500);
|
|
492
|
-
res.json({
|
|
493
|
-
success: false,
|
|
494
|
-
error: 'Authentication middleware not configured',
|
|
495
|
-
message: 'Auth middleware must be installed before using route-level auth',
|
|
496
|
-
});
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
// Check authentication requirement (default is required unless optional: true)
|
|
501
|
-
if (!authConfig.optional && !auth.isAuthenticated) {
|
|
502
|
-
res.status(401);
|
|
503
|
-
res.json({
|
|
504
|
-
success: false,
|
|
505
|
-
error: 'Authentication required',
|
|
506
|
-
message: 'You must be logged in to access this resource',
|
|
507
|
-
});
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// Skip further checks if not authenticated but optional
|
|
512
|
-
if (!auth.isAuthenticated && authConfig.optional) {
|
|
513
|
-
return; // Continue to handler
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// Only check roles/permissions if user is authenticated
|
|
517
|
-
if (auth.isAuthenticated) {
|
|
518
|
-
const user = auth.user;
|
|
519
|
-
|
|
520
|
-
// Check roles if specified
|
|
521
|
-
if (authConfig.roles && authConfig.roles.length > 0) {
|
|
522
|
-
const userRoles = user?.roles || [];
|
|
523
|
-
const hasRole = authConfig.roles.some((role: string) => userRoles.includes(role));
|
|
524
|
-
|
|
525
|
-
if (!hasRole) {
|
|
526
|
-
res.status(403);
|
|
527
|
-
res.json({
|
|
528
|
-
success: false,
|
|
529
|
-
error: 'Insufficient permissions',
|
|
530
|
-
message: `Required roles: ${authConfig.roles.join(', ')}`,
|
|
531
|
-
userRoles,
|
|
532
|
-
});
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// Check permissions if specified
|
|
538
|
-
if (authConfig.permissions && authConfig.permissions.length > 0) {
|
|
539
|
-
const userPermissions = user?.permissions || [];
|
|
540
|
-
const hasPermission = authConfig.permissions.every((permission: string) =>
|
|
541
|
-
userPermissions.includes(permission)
|
|
542
|
-
);
|
|
543
|
-
|
|
544
|
-
if (!hasPermission) {
|
|
545
|
-
res.status(403);
|
|
546
|
-
res.json({
|
|
547
|
-
success: false,
|
|
548
|
-
error: 'Insufficient permissions',
|
|
549
|
-
message: `Required permissions: ${authConfig.permissions.join(', ')}`,
|
|
550
|
-
userPermissions,
|
|
551
|
-
});
|
|
552
|
-
return;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
// All auth checks passed
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
private async executeValidation(req: ValidatedRequest, res: HttpResponse): Promise<void> {
|
|
561
|
-
if (!this.schema.validation) return;
|
|
562
|
-
|
|
563
|
-
const { body, query, params, headers } = this.schema.validation;
|
|
564
|
-
|
|
565
|
-
// Validate body
|
|
566
|
-
if (body && req.body !== undefined) {
|
|
567
|
-
try {
|
|
568
|
-
req.validatedBody = await body.parseAsync(req.body);
|
|
569
|
-
req.body = req.validatedBody; // Update original for compatibility
|
|
570
|
-
} catch (error: any) {
|
|
571
|
-
this.sendValidationError(res, error, 'body', req.requestId);
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
// Validate query
|
|
577
|
-
if (query && req.query !== undefined) {
|
|
578
|
-
try {
|
|
579
|
-
req.validatedQuery = await query.parseAsync(req.query);
|
|
580
|
-
req.query = req.validatedQuery; // Update original for compatibility
|
|
581
|
-
} catch (error: any) {
|
|
582
|
-
this.sendValidationError(res, error, 'query', req.requestId);
|
|
583
|
-
return;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// Validate params
|
|
588
|
-
if (params && req.params !== undefined) {
|
|
589
|
-
try {
|
|
590
|
-
req.validatedParams = await params.parseAsync(req.params);
|
|
591
|
-
req.params = req.validatedParams; // Update original for compatibility
|
|
592
|
-
} catch (error: any) {
|
|
593
|
-
this.sendValidationError(res, error, 'params', req.requestId);
|
|
594
|
-
return;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// Validate headers
|
|
599
|
-
if (headers && req.headers !== undefined) {
|
|
600
|
-
try {
|
|
601
|
-
req.validatedHeaders = await headers.parseAsync(req.headers);
|
|
602
|
-
} catch (error: any) {
|
|
603
|
-
this.sendValidationError(res, error, 'headers', req.requestId);
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
logger.debug('Validation passed', 'Validation', {
|
|
609
|
-
route: `${this.schema.method} ${this.schema.path}`,
|
|
610
|
-
validatedFields: Object.keys(this.schema.validation),
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
private sendValidationError(
|
|
615
|
-
res: HttpResponse,
|
|
616
|
-
error: any,
|
|
617
|
-
field: string,
|
|
618
|
-
requestId?: string
|
|
619
|
-
): void {
|
|
620
|
-
if (error.issues) {
|
|
621
|
-
res.status(400).json({
|
|
622
|
-
success: false,
|
|
623
|
-
error: `Validation failed for ${field}`,
|
|
624
|
-
details: error.issues.map((issue: any) => ({
|
|
625
|
-
field: issue.path.length > 0 ? issue.path.join('.') : field,
|
|
626
|
-
message: issue.message,
|
|
627
|
-
code: issue.code,
|
|
628
|
-
})),
|
|
629
|
-
requestId,
|
|
630
|
-
});
|
|
631
|
-
} else {
|
|
632
|
-
res.status(400).json({
|
|
633
|
-
success: false,
|
|
634
|
-
error: `Validation failed for ${field}`,
|
|
635
|
-
requestId,
|
|
636
|
-
});
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
private async executeCache(req: HttpRequest, res: HttpResponse): Promise<void> {
|
|
641
|
-
// Caching implementation will be added
|
|
642
|
-
logger.debug('Cache check', 'Cache', {
|
|
643
|
-
config: this.schema.cache,
|
|
644
|
-
});
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// Performance monitoring
|
|
648
|
-
getPerformanceInfo() {
|
|
649
|
-
return {
|
|
650
|
-
path: this.schema.path,
|
|
651
|
-
method: this.schema.method,
|
|
652
|
-
isFastPath: this.isFastPath,
|
|
653
|
-
requiresAuth: this.requiresAuth,
|
|
654
|
-
requiresValidation: this.requiresValidation,
|
|
655
|
-
requiresRateLimit: this.requiresRateLimit,
|
|
656
|
-
requiresCache: this.requiresCache,
|
|
657
|
-
hasBeforeMiddleware: this.hasBeforeMiddleware,
|
|
658
|
-
hasAfterMiddleware: this.hasAfterMiddleware,
|
|
659
|
-
hasTransformMiddleware: this.hasTransformMiddleware,
|
|
660
|
-
};
|
|
238
|
+
// This is never called - UnifiedRouter handles execution
|
|
239
|
+
// But we implement it for interface compatibility
|
|
240
|
+
throw new Error(
|
|
241
|
+
'ExecutableRoute.execute() should not be called directly - routing handled by UnifiedRouter'
|
|
242
|
+
);
|
|
661
243
|
}
|
|
662
244
|
}
|
|
663
245
|
|
|
664
|
-
//
|
|
246
|
+
// ===== FACTORY FUNCTIONS (Backward Compatibility) =====
|
|
247
|
+
|
|
665
248
|
export function createRoute(method: HttpMethod, path: string): RouteBuilder {
|
|
666
249
|
return new IntelligentRouteBuilder(method, path);
|
|
667
250
|
}
|
|
668
251
|
|
|
669
|
-
// Schema-first route creation
|
|
670
252
|
export function defineRoute(schema: RouteSchema): CompiledRoute {
|
|
671
253
|
return new ExecutableRoute(schema);
|
|
672
254
|
}
|
|
255
|
+
|
|
256
|
+
// ===== RE-EXPORTS FROM UNIFIED ROUTER =====
|
|
257
|
+
|
|
258
|
+
export { UnifiedRouter } from './unified-router.js';
|
|
259
|
+
export { RouteBuilder as UnifiedRouteBuilder } from './unified-router.js';
|
|
260
|
+
export { PathMatcher, type CompiledPath, type MatchResult } from './path-matcher.js';
|
|
261
|
+
export { ObjectPoolManager, getPoolManager } from '../pooling/object-pool-manager.js';
|