@morojs/moro 1.8.10 → 1.8.12
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/README.md +4 -0
- package/dist/core/http/moro-engine-server.d.ts +20 -0
- package/dist/core/http/moro-engine-server.js +114 -1
- package/dist/core/http/moro-engine-server.js.map +1 -1
- package/dist/core/routing/index.d.ts +11 -3
- package/dist/core/routing/index.js +12 -7
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/routing/unified-router.d.ts +28 -3
- package/dist/core/routing/unified-router.js +73 -8
- package/dist/core/routing/unified-router.js.map +1 -1
- package/dist/core/utilities/package-utils.d.ts +8 -3
- package/dist/core/utilities/package-utils.js +1 -0
- package/dist/core/utilities/package-utils.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/moro.d.ts +17 -17
- package/dist/moro.js +37 -7
- package/dist/moro.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ValidationSchema } from '../validation/schema-interface.js';
|
|
2
2
|
import { HttpRequest, HttpResponse } from '../http/index.js';
|
|
3
|
+
import { type StaticBody, type StaticResponse } from './unified-router.js';
|
|
4
|
+
export type { StaticBody, StaticResponse };
|
|
3
5
|
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
|
|
4
6
|
export type RouteHandler<T = any> = (req: HttpRequest, res: HttpResponse) => T | Promise<T>;
|
|
5
7
|
export type Middleware = (req: HttpRequest, res: HttpResponse, next: () => void) => void | Promise<void>;
|
|
@@ -33,7 +35,8 @@ export interface MiddlewarePhases {
|
|
|
33
35
|
export interface RouteSchema {
|
|
34
36
|
method: HttpMethod;
|
|
35
37
|
path: string;
|
|
36
|
-
handler
|
|
38
|
+
/** A function, or the response body itself (see StaticBody / .handler()) */
|
|
39
|
+
handler: RouteHandler | StaticBody;
|
|
37
40
|
validation?: ValidationConfig;
|
|
38
41
|
auth?: AuthConfig;
|
|
39
42
|
rateLimit?: RateLimitConfig;
|
|
@@ -41,6 +44,8 @@ export interface RouteSchema {
|
|
|
41
44
|
middleware?: MiddlewarePhases;
|
|
42
45
|
description?: string;
|
|
43
46
|
tags?: string[];
|
|
47
|
+
/** Fixed reply of a literal handler; see StaticResponse */
|
|
48
|
+
static?: StaticResponse;
|
|
44
49
|
}
|
|
45
50
|
export declare const EXECUTION_PHASES: readonly ["security", "parsing", "rateLimit", "before", "auth", "validation", "transform", "cache", "after", "handler"];
|
|
46
51
|
export type ExecutionPhase = (typeof EXECUTION_PHASES)[number];
|
|
@@ -66,7 +71,10 @@ export interface RouteBuilder {
|
|
|
66
71
|
use(...middleware: Middleware[]): RouteBuilder;
|
|
67
72
|
describe(description: string): RouteBuilder;
|
|
68
73
|
tag(...tags: string[]): RouteBuilder;
|
|
69
|
-
|
|
74
|
+
/** Terminal. A function handles the request; a string or Buffer IS the
|
|
75
|
+
* response body (as res.send would send it), and on a route with nothing
|
|
76
|
+
* else configured Moro's native engine answers it without calling JS. */
|
|
77
|
+
handler<T>(handler: RouteHandler<T> | StaticBody): void;
|
|
70
78
|
}
|
|
71
79
|
export interface CompiledRoute {
|
|
72
80
|
schema: RouteSchema;
|
|
@@ -94,7 +102,7 @@ export declare class IntelligentRouteBuilder implements RouteBuilder {
|
|
|
94
102
|
use(...middleware: Middleware[]): RouteBuilder;
|
|
95
103
|
describe(description: string): RouteBuilder;
|
|
96
104
|
tag(...tags: string[]): RouteBuilder;
|
|
97
|
-
handler<T>(handler: RouteHandler<T>): void;
|
|
105
|
+
handler<T>(handler: RouteHandler<T> | StaticBody): void;
|
|
98
106
|
}
|
|
99
107
|
/**
|
|
100
108
|
* Thin facade implementing CompiledRoute interface
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
// NOTE: This file exports types and thin facades to UnifiedRouter
|
|
5
5
|
// All routing logic has been consolidated in unified-router.ts
|
|
6
|
-
import { UnifiedRouter } from './unified-router.js';
|
|
6
|
+
import { UnifiedRouter, compileStaticRoute, } from './unified-router.js';
|
|
7
7
|
export const EXECUTION_PHASES = [
|
|
8
8
|
'security',
|
|
9
9
|
'parsing',
|
|
@@ -137,13 +137,18 @@ export class IntelligentRouteBuilder {
|
|
|
137
137
|
return this;
|
|
138
138
|
}
|
|
139
139
|
handler(handler) {
|
|
140
|
-
if (
|
|
141
|
-
|
|
140
|
+
if (typeof handler === 'function') {
|
|
141
|
+
// Avoid spread operator - add handler directly
|
|
142
|
+
this.schema.handler = handler;
|
|
143
|
+
// Delegate to UnifiedRouter
|
|
144
|
+
this.router.registerRoute(this.schema);
|
|
145
|
+
return;
|
|
142
146
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
if (typeof handler === 'string' || Buffer.isBuffer(handler)) {
|
|
148
|
+
this.router.registerRoute(compileStaticRoute(this.schema, handler));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
throw new Error('Handler is required: a function, or the response body as a string or Buffer');
|
|
147
152
|
}
|
|
148
153
|
}
|
|
149
154
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/routing/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Intelligent Routing System for Moro Framework\n// Schema-first with automatic middleware ordering and chainable API\n//\n// NOTE: This file exports types and thin facades to UnifiedRouter\n// All routing logic has been consolidated in unified-router.ts\n\nimport { ValidationSchema } from '../validation/schema-interface.js';\nimport { HttpRequest, HttpResponse } from '../http/index.js';\nimport { UnifiedRouter } from './unified-router.js';\n\n// ===== TYPE EXPORTS (Keep all - used by app code) =====\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\nexport type RouteHandler<T = any> = (req: HttpRequest, res: HttpResponse) => T | Promise<T>;\nexport type Middleware = (\n req: HttpRequest,\n res: HttpResponse,\n next: () => void\n) => void | Promise<void>;\n\nexport interface ValidationConfig {\n body?: ValidationSchema;\n query?: ValidationSchema;\n params?: ValidationSchema;\n headers?: ValidationSchema;\n}\n\nexport interface AuthConfig {\n roles?: string[];\n permissions?: string[];\n optional?: boolean;\n}\n\nexport interface RateLimitConfig {\n requests: number;\n window: number;\n skipSuccessfulRequests?: boolean;\n skipFailedRequests?: boolean;\n}\n\nexport interface CacheConfig {\n ttl: number;\n key?: string;\n tags?: string[];\n}\n\nexport interface MiddlewarePhases {\n before?: Middleware[];\n after?: Middleware[];\n transform?: Middleware[];\n}\n\nexport interface RouteSchema {\n method: HttpMethod;\n path: string;\n handler: RouteHandler;\n validation?: ValidationConfig;\n auth?: AuthConfig;\n rateLimit?: RateLimitConfig;\n cache?: CacheConfig;\n middleware?: MiddlewarePhases;\n description?: string;\n tags?: string[];\n}\n\nexport const EXECUTION_PHASES = [\n 'security',\n 'parsing',\n 'rateLimit',\n 'before',\n 'auth',\n 'validation',\n 'transform',\n 'cache',\n 'after',\n 'handler',\n] as const;\n\nexport type ExecutionPhase = (typeof EXECUTION_PHASES)[number];\n\nexport interface ValidatedRequest<T = any> extends HttpRequest {\n validatedBody?: T;\n validatedQuery?: any;\n validatedParams?: any;\n validatedHeaders?: any;\n user?: any;\n}\n\n// ===== ROUTE BUILDER INTERFACE (Public API) =====\n\nexport interface RouteBuilder {\n validate(config: ValidationConfig): RouteBuilder;\n body<T>(schema: ValidationSchema<T>): RouteBuilder;\n query<T>(schema: ValidationSchema<T>): RouteBuilder;\n params<T>(schema: ValidationSchema<T>): RouteBuilder;\n headers<T>(schema: ValidationSchema<T>): RouteBuilder;\n auth(config: AuthConfig): RouteBuilder;\n rateLimit(config: RateLimitConfig): RouteBuilder;\n cache(config: CacheConfig): RouteBuilder;\n before(...middleware: Middleware[]): RouteBuilder;\n after(...middleware: Middleware[]): RouteBuilder;\n transform(...middleware: Middleware[]): RouteBuilder;\n use(...middleware: Middleware[]): RouteBuilder;\n describe(description: string): RouteBuilder;\n tag(...tags: string[]): RouteBuilder;\n handler<T>(handler: RouteHandler<T>): void;\n}\n\n// ===== COMPILED ROUTE INTERFACE (Public API) =====\n\nexport interface CompiledRoute {\n schema: RouteSchema;\n execute(req: HttpRequest, res: HttpResponse): Promise<void>;\n}\n\n// ===== FACADE IMPLEMENTATIONS (Delegate to UnifiedRouter) =====\n\n/**\n * Thin facade to UnifiedRouter.RouteBuilder\n * Maintains backward compatibility while using optimized implementation\n */\nexport class IntelligentRouteBuilder implements RouteBuilder {\n private schema: Partial<RouteSchema>;\n private router = UnifiedRouter.getInstance();\n\n constructor(method: HttpMethod, path: string) {\n this.schema = {\n method,\n path,\n middleware: {} as MiddlewarePhases,\n };\n }\n\n validate(config: ValidationConfig): RouteBuilder {\n // Avoid spread operator - manually merge properties\n if (!this.schema.validation) {\n this.schema.validation = config;\n } else {\n if (config.body !== undefined) this.schema.validation.body = config.body;\n if (config.query !== undefined) this.schema.validation.query = config.query;\n if (config.params !== undefined) this.schema.validation.params = config.params;\n if (config.headers !== undefined) this.schema.validation.headers = config.headers;\n }\n return this;\n }\n\n body<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.body = schema;\n return this;\n }\n\n query<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.query = schema;\n return this;\n }\n\n params<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.params = schema;\n return this;\n }\n\n headers<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.headers = schema;\n return this;\n }\n\n auth(config: AuthConfig): RouteBuilder {\n this.schema.auth = config;\n return this;\n }\n\n rateLimit(config: RateLimitConfig): RouteBuilder {\n this.schema.rateLimit = config;\n return this;\n }\n\n cache(config: CacheConfig): RouteBuilder {\n this.schema.cache = config;\n return this;\n }\n\n before(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.before) phases.before = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.before.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n after(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.after) phases.after = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.after.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n transform(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.transform) phases.transform = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.transform.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n use(...middleware: Middleware[]): RouteBuilder {\n return this.after(...middleware);\n }\n\n describe(description: string): RouteBuilder {\n this.schema.description = description;\n return this;\n }\n\n tag(...tags: string[]): RouteBuilder {\n // Avoid spread, use push for better performance\n if (!this.schema.tags) this.schema.tags = [];\n for (let i = 0; i < tags.length; i++) {\n this.schema.tags.push(tags[i] as string);\n }\n return this;\n }\n\n handler<T>(handler: RouteHandler<T>): void {\n if (!handler) {\n throw new Error('Handler is required');\n }\n\n // Avoid spread operator - add handler directly\n this.schema.handler = handler;\n\n // Delegate to UnifiedRouter\n this.router.registerRoute(this.schema as RouteSchema);\n }\n}\n\n/**\n * Thin facade implementing CompiledRoute interface\n * Just stores schema for documentation purposes\n */\nexport class ExecutableRoute implements CompiledRoute {\n constructor(public readonly schema: RouteSchema) {\n // Register with UnifiedRouter\n UnifiedRouter.getInstance().registerRoute(schema);\n }\n\n async execute(_req: HttpRequest, _res: HttpResponse): Promise<void> {\n // This is never called - UnifiedRouter handles execution\n // But we implement it for interface compatibility\n throw new Error(\n 'ExecutableRoute.execute() should not be called directly - routing handled by UnifiedRouter'\n );\n }\n}\n\n// ===== FACTORY FUNCTIONS (Backward Compatibility) =====\n\nexport function createRoute(method: HttpMethod, path: string): RouteBuilder {\n return new IntelligentRouteBuilder(method, path);\n}\n\nexport function defineRoute(schema: RouteSchema): CompiledRoute {\n return new ExecutableRoute(schema);\n}\n\n// ===== RE-EXPORTS FROM UNIFIED ROUTER =====\n\nexport { UnifiedRouter } from './unified-router.js';\nexport { RouteBuilder as UnifiedRouteBuilder } from './unified-router.js';\nexport { PathMatcher, type CompiledPath, type MatchResult } from './path-matcher.js';\nexport { ObjectPoolManager, getPoolManager } from '../pooling/object-pool-manager.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/routing/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Intelligent Routing System for Moro Framework\n// Schema-first with automatic middleware ordering and chainable API\n//\n// NOTE: This file exports types and thin facades to UnifiedRouter\n// All routing logic has been consolidated in unified-router.ts\n\nimport { ValidationSchema } from '../validation/schema-interface.js';\nimport { HttpRequest, HttpResponse } from '../http/index.js';\nimport {\n UnifiedRouter,\n compileStaticRoute,\n type RouteSchema as UnifiedRouteSchema,\n type StaticBody,\n type StaticResponse,\n} from './unified-router.js';\n\nexport type { StaticBody, StaticResponse };\n\n// ===== TYPE EXPORTS (Keep all - used by app code) =====\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';\nexport type RouteHandler<T = any> = (req: HttpRequest, res: HttpResponse) => T | Promise<T>;\nexport type Middleware = (\n req: HttpRequest,\n res: HttpResponse,\n next: () => void\n) => void | Promise<void>;\n\nexport interface ValidationConfig {\n body?: ValidationSchema;\n query?: ValidationSchema;\n params?: ValidationSchema;\n headers?: ValidationSchema;\n}\n\nexport interface AuthConfig {\n roles?: string[];\n permissions?: string[];\n optional?: boolean;\n}\n\nexport interface RateLimitConfig {\n requests: number;\n window: number;\n skipSuccessfulRequests?: boolean;\n skipFailedRequests?: boolean;\n}\n\nexport interface CacheConfig {\n ttl: number;\n key?: string;\n tags?: string[];\n}\n\nexport interface MiddlewarePhases {\n before?: Middleware[];\n after?: Middleware[];\n transform?: Middleware[];\n}\n\nexport interface RouteSchema {\n method: HttpMethod;\n path: string;\n /** A function, or the response body itself (see StaticBody / .handler()) */\n handler: RouteHandler | StaticBody;\n validation?: ValidationConfig;\n auth?: AuthConfig;\n rateLimit?: RateLimitConfig;\n cache?: CacheConfig;\n middleware?: MiddlewarePhases;\n description?: string;\n tags?: string[];\n /** Fixed reply of a literal handler; see StaticResponse */\n static?: StaticResponse;\n}\n\nexport const EXECUTION_PHASES = [\n 'security',\n 'parsing',\n 'rateLimit',\n 'before',\n 'auth',\n 'validation',\n 'transform',\n 'cache',\n 'after',\n 'handler',\n] as const;\n\nexport type ExecutionPhase = (typeof EXECUTION_PHASES)[number];\n\nexport interface ValidatedRequest<T = any> extends HttpRequest {\n validatedBody?: T;\n validatedQuery?: any;\n validatedParams?: any;\n validatedHeaders?: any;\n user?: any;\n}\n\n// ===== ROUTE BUILDER INTERFACE (Public API) =====\n\nexport interface RouteBuilder {\n validate(config: ValidationConfig): RouteBuilder;\n body<T>(schema: ValidationSchema<T>): RouteBuilder;\n query<T>(schema: ValidationSchema<T>): RouteBuilder;\n params<T>(schema: ValidationSchema<T>): RouteBuilder;\n headers<T>(schema: ValidationSchema<T>): RouteBuilder;\n auth(config: AuthConfig): RouteBuilder;\n rateLimit(config: RateLimitConfig): RouteBuilder;\n cache(config: CacheConfig): RouteBuilder;\n before(...middleware: Middleware[]): RouteBuilder;\n after(...middleware: Middleware[]): RouteBuilder;\n transform(...middleware: Middleware[]): RouteBuilder;\n use(...middleware: Middleware[]): RouteBuilder;\n describe(description: string): RouteBuilder;\n tag(...tags: string[]): RouteBuilder;\n /** Terminal. A function handles the request; a string or Buffer IS the\n * response body (as res.send would send it), and on a route with nothing\n * else configured Moro's native engine answers it without calling JS. */\n handler<T>(handler: RouteHandler<T> | StaticBody): void;\n}\n\n// ===== COMPILED ROUTE INTERFACE (Public API) =====\n\nexport interface CompiledRoute {\n schema: RouteSchema;\n execute(req: HttpRequest, res: HttpResponse): Promise<void>;\n}\n\n// ===== FACADE IMPLEMENTATIONS (Delegate to UnifiedRouter) =====\n\n/**\n * Thin facade to UnifiedRouter.RouteBuilder\n * Maintains backward compatibility while using optimized implementation\n */\nexport class IntelligentRouteBuilder implements RouteBuilder {\n private schema: Partial<RouteSchema>;\n private router = UnifiedRouter.getInstance();\n\n constructor(method: HttpMethod, path: string) {\n this.schema = {\n method,\n path,\n middleware: {} as MiddlewarePhases,\n };\n }\n\n validate(config: ValidationConfig): RouteBuilder {\n // Avoid spread operator - manually merge properties\n if (!this.schema.validation) {\n this.schema.validation = config;\n } else {\n if (config.body !== undefined) this.schema.validation.body = config.body;\n if (config.query !== undefined) this.schema.validation.query = config.query;\n if (config.params !== undefined) this.schema.validation.params = config.params;\n if (config.headers !== undefined) this.schema.validation.headers = config.headers;\n }\n return this;\n }\n\n body<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.body = schema;\n return this;\n }\n\n query<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.query = schema;\n return this;\n }\n\n params<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.params = schema;\n return this;\n }\n\n headers<T>(schema: ValidationSchema<T>): RouteBuilder {\n if (!this.schema.validation) this.schema.validation = {};\n this.schema.validation.headers = schema;\n return this;\n }\n\n auth(config: AuthConfig): RouteBuilder {\n this.schema.auth = config;\n return this;\n }\n\n rateLimit(config: RateLimitConfig): RouteBuilder {\n this.schema.rateLimit = config;\n return this;\n }\n\n cache(config: CacheConfig): RouteBuilder {\n this.schema.cache = config;\n return this;\n }\n\n before(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.before) phases.before = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.before.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n after(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.after) phases.after = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.after.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n transform(...middleware: Middleware[]): RouteBuilder {\n if (!this.schema.middleware) this.schema.middleware = {};\n const phases = this.schema.middleware as MiddlewarePhases;\n // Avoid spread, use push for better performance\n if (!phases.transform) phases.transform = [];\n for (let i = 0; i < middleware.length; i++) {\n phases.transform.push(middleware[i] as Middleware);\n }\n return this;\n }\n\n use(...middleware: Middleware[]): RouteBuilder {\n return this.after(...middleware);\n }\n\n describe(description: string): RouteBuilder {\n this.schema.description = description;\n return this;\n }\n\n tag(...tags: string[]): RouteBuilder {\n // Avoid spread, use push for better performance\n if (!this.schema.tags) this.schema.tags = [];\n for (let i = 0; i < tags.length; i++) {\n this.schema.tags.push(tags[i] as string);\n }\n return this;\n }\n\n handler<T>(handler: RouteHandler<T> | StaticBody): void {\n if (typeof handler === 'function') {\n // Avoid spread operator - add handler directly\n this.schema.handler = handler;\n\n // Delegate to UnifiedRouter\n this.router.registerRoute(this.schema as RouteSchema);\n return;\n }\n if (typeof handler === 'string' || Buffer.isBuffer(handler)) {\n this.router.registerRoute(\n compileStaticRoute(this.schema as Partial<UnifiedRouteSchema>, handler)\n );\n return;\n }\n throw new Error('Handler is required: a function, or the response body as a string or Buffer');\n }\n}\n\n/**\n * Thin facade implementing CompiledRoute interface\n * Just stores schema for documentation purposes\n */\nexport class ExecutableRoute implements CompiledRoute {\n constructor(public readonly schema: RouteSchema) {\n // Register with UnifiedRouter\n UnifiedRouter.getInstance().registerRoute(schema);\n }\n\n async execute(_req: HttpRequest, _res: HttpResponse): Promise<void> {\n // This is never called - UnifiedRouter handles execution\n // But we implement it for interface compatibility\n throw new Error(\n 'ExecutableRoute.execute() should not be called directly - routing handled by UnifiedRouter'\n );\n }\n}\n\n// ===== FACTORY FUNCTIONS (Backward Compatibility) =====\n\nexport function createRoute(method: HttpMethod, path: string): RouteBuilder {\n return new IntelligentRouteBuilder(method, path);\n}\n\nexport function defineRoute(schema: RouteSchema): CompiledRoute {\n return new ExecutableRoute(schema);\n}\n\n// ===== RE-EXPORTS FROM UNIFIED ROUTER =====\n\nexport { UnifiedRouter } from './unified-router.js';\nexport { RouteBuilder as UnifiedRouteBuilder } from './unified-router.js';\nexport { PathMatcher, type CompiledPath, type MatchResult } from './path-matcher.js';\nexport { ObjectPoolManager, getPoolManager } from '../pooling/object-pool-manager.js';\n"]}
|
|
@@ -20,7 +20,8 @@ export interface MiddlewarePhases {
|
|
|
20
20
|
export interface RouteSchema {
|
|
21
21
|
method: HttpMethod;
|
|
22
22
|
path: string;
|
|
23
|
-
|
|
23
|
+
/** A function, or the response body itself (see StaticBody) */
|
|
24
|
+
handler: RouteHandler | StaticBody;
|
|
24
25
|
validation?: ValidationConfig;
|
|
25
26
|
auth?: AuthConfig;
|
|
26
27
|
rateLimit?: RateLimitConfig;
|
|
@@ -28,7 +29,31 @@ export interface RouteSchema {
|
|
|
28
29
|
middleware?: MiddlewarePhases | Middleware[];
|
|
29
30
|
description?: string;
|
|
30
31
|
tags?: string[];
|
|
32
|
+
/** Fixed reply of a literal handler. A server that can answer it
|
|
33
|
+
* natively (MoroEngineServer on @morojs/engine >= 1.1.6) does so without
|
|
34
|
+
* calling into JS; every other server runs `handler`, which sends the
|
|
35
|
+
* same bytes. */
|
|
36
|
+
static?: StaticResponse;
|
|
31
37
|
}
|
|
38
|
+
/** The reply a literal handler sends, in the engine's shape. */
|
|
39
|
+
export interface StaticResponse {
|
|
40
|
+
status: number;
|
|
41
|
+
/** [name, value, name, value, ...], or null for no headers at all */
|
|
42
|
+
headers: string[] | null;
|
|
43
|
+
body: string | Buffer | null;
|
|
44
|
+
}
|
|
45
|
+
/** What .handler() accepts in place of a function: the response body itself. */
|
|
46
|
+
export type StaticBody = string | Buffer;
|
|
47
|
+
/**
|
|
48
|
+
* A literal body in place of a handler: the route answers with exactly that
|
|
49
|
+
* body, as res.send(body) would (status 200, the implied content-type). When
|
|
50
|
+
* nothing else is configured on the route - no auth, validation, rate limit,
|
|
51
|
+
* cache or middleware, and a literal path - the schema also carries `static`,
|
|
52
|
+
* so a server that can answer it natively does so without calling into JS.
|
|
53
|
+
* Anything configured keeps the route on the normal pipeline, where the
|
|
54
|
+
* handler sends the same bytes after that configuration has run.
|
|
55
|
+
*/
|
|
56
|
+
export declare function compileStaticRoute(schema: Partial<RouteSchema>, body: StaticBody): RouteSchema;
|
|
32
57
|
export declare class RouteBuilder {
|
|
33
58
|
private schema;
|
|
34
59
|
private router;
|
|
@@ -47,7 +72,7 @@ export declare class RouteBuilder {
|
|
|
47
72
|
use(...middleware: Middleware[]): this;
|
|
48
73
|
describe(description: string): this;
|
|
49
74
|
tag(...tags: string[]): this;
|
|
50
|
-
handler<T>(handler: RouteHandler<T>): void;
|
|
75
|
+
handler<T>(handler: RouteHandler<T> | StaticBody): void;
|
|
51
76
|
}
|
|
52
77
|
export declare class UnifiedRouter {
|
|
53
78
|
private static instance;
|
|
@@ -105,7 +130,7 @@ export declare class UnifiedRouter {
|
|
|
105
130
|
/**
|
|
106
131
|
* Direct API (for backward compatibility)
|
|
107
132
|
*/
|
|
108
|
-
addRoute(method: HttpMethod, path: string, handler: RouteHandler, middleware?: Middleware[]): void;
|
|
133
|
+
addRoute(method: HttpMethod, path: string, handler: RouteHandler | StaticBody, middleware?: Middleware[]): void;
|
|
109
134
|
/**
|
|
110
135
|
* Find a matching route for the request - HYBRID OPTIMIZED
|
|
111
136
|
* Returns boolean (sync) for fast-path routes, Promise<boolean> for others
|
|
@@ -13,6 +13,51 @@ const logger = createFrameworkLogger('UnifiedRouter');
|
|
|
13
13
|
const rateLimitCore = new RateLimitCore();
|
|
14
14
|
const cacheCore = new CacheCore();
|
|
15
15
|
const validationCore = new ValidationCore();
|
|
16
|
+
// The content-type res.send() implies for a body it was given no header for:
|
|
17
|
+
// the same three cases MoroEngineServer's send() picks a template by, spelled
|
|
18
|
+
// out here so an engine-answered reply carries the bytes send() would have.
|
|
19
|
+
const STATIC_JSON_START = /^\s*[{[]/;
|
|
20
|
+
function impliedContentType(body) {
|
|
21
|
+
if (typeof body !== 'string')
|
|
22
|
+
return 'application/octet-stream';
|
|
23
|
+
return STATIC_JSON_START.test(body)
|
|
24
|
+
? 'application/json; charset=utf-8'
|
|
25
|
+
: 'text/plain; charset=utf-8';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A literal body in place of a handler: the route answers with exactly that
|
|
29
|
+
* body, as res.send(body) would (status 200, the implied content-type). When
|
|
30
|
+
* nothing else is configured on the route - no auth, validation, rate limit,
|
|
31
|
+
* cache or middleware, and a literal path - the schema also carries `static`,
|
|
32
|
+
* so a server that can answer it natively does so without calling into JS.
|
|
33
|
+
* Anything configured keeps the route on the normal pipeline, where the
|
|
34
|
+
* handler sends the same bytes after that configuration has run.
|
|
35
|
+
*/
|
|
36
|
+
export function compileStaticRoute(schema, body) {
|
|
37
|
+
schema.handler = (_req, res) => {
|
|
38
|
+
res.send(body);
|
|
39
|
+
};
|
|
40
|
+
const path = schema.path ?? '';
|
|
41
|
+
const mw = schema.middleware;
|
|
42
|
+
const hasMiddleware = Array.isArray(mw)
|
|
43
|
+
? mw.length > 0
|
|
44
|
+
: mw !== undefined &&
|
|
45
|
+
Object.keys(mw).some(phase => {
|
|
46
|
+
const list = mw[phase];
|
|
47
|
+
return Array.isArray(list) && list.length > 0;
|
|
48
|
+
});
|
|
49
|
+
const bare = !path.includes(':') &&
|
|
50
|
+
!path.includes('*') &&
|
|
51
|
+
!schema.auth &&
|
|
52
|
+
!schema.validation &&
|
|
53
|
+
!schema.rateLimit &&
|
|
54
|
+
!schema.cache &&
|
|
55
|
+
!hasMiddleware;
|
|
56
|
+
if (bare) {
|
|
57
|
+
schema.static = { status: 200, headers: ['content-type', impliedContentType(body)], body };
|
|
58
|
+
}
|
|
59
|
+
return schema;
|
|
60
|
+
}
|
|
16
61
|
// Canonical uppercase methods - lets dispatch skip toUpperCase for the
|
|
17
62
|
// interned method strings every adapter hands over
|
|
18
63
|
const UPPERCASE_METHODS = new Set(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']);
|
|
@@ -143,14 +188,20 @@ export class RouteBuilder {
|
|
|
143
188
|
}
|
|
144
189
|
return this;
|
|
145
190
|
}
|
|
146
|
-
// Terminal method
|
|
191
|
+
// Terminal method: a function, or the response body itself (see
|
|
192
|
+
// compileStaticRoute for what a literal body means).
|
|
147
193
|
handler(handler) {
|
|
148
|
-
if (
|
|
149
|
-
|
|
194
|
+
if (typeof handler === 'function') {
|
|
195
|
+
// Avoid spread operator - add handler directly
|
|
196
|
+
this.schema.handler = handler;
|
|
197
|
+
this.router.registerRoute(this.schema);
|
|
198
|
+
return;
|
|
150
199
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
200
|
+
if (typeof handler === 'string' || Buffer.isBuffer(handler)) {
|
|
201
|
+
this.router.registerRoute(compileStaticRoute(this.schema, handler));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
throw new Error('Handler is required: a function, or the response body as a string or Buffer');
|
|
154
205
|
}
|
|
155
206
|
}
|
|
156
207
|
// ===== Unified Router =====
|
|
@@ -278,6 +329,20 @@ export class UnifiedRouter {
|
|
|
278
329
|
* Register a route (internal method) - OPTIMIZED
|
|
279
330
|
*/
|
|
280
331
|
registerRoute(schema) {
|
|
332
|
+
// A literal body in place of a handler (see compileStaticRoute). Every
|
|
333
|
+
// entry point lands here - the builder, app.get(path, body), route(schema)
|
|
334
|
+
// - so this is where the body becomes a handler and, on a bare route, a
|
|
335
|
+
// reply the native engine can answer itself.
|
|
336
|
+
if (typeof schema.handler !== 'function') {
|
|
337
|
+
const body = schema.handler;
|
|
338
|
+
if (typeof body !== 'string' && !Buffer.isBuffer(body)) {
|
|
339
|
+
throw new Error(`Handler for ${schema.method} ${schema.path} must be a function, ` +
|
|
340
|
+
'or the response body as a string or Buffer');
|
|
341
|
+
}
|
|
342
|
+
compileStaticRoute(schema, body);
|
|
343
|
+
}
|
|
344
|
+
// From here on the handler is a function, whichever form was registered.
|
|
345
|
+
const registered = schema;
|
|
281
346
|
// OPTIMIZATION: Skip PathMatcher.compile for better performance
|
|
282
347
|
// Determine if static route (optimized check)
|
|
283
348
|
const pathLen = schema.path.length;
|
|
@@ -296,9 +361,9 @@ export class UnifiedRouter {
|
|
|
296
361
|
// OPTIMIZATION: Lazy auth middleware creation (only create when needed, not during registration)
|
|
297
362
|
// This speeds up route registration significantly
|
|
298
363
|
const route = {
|
|
299
|
-
schema,
|
|
364
|
+
schema: registered,
|
|
300
365
|
compiledPath: null, // Will be set lazily if needed
|
|
301
|
-
handler:
|
|
366
|
+
handler: registered.handler,
|
|
302
367
|
isFastPath,
|
|
303
368
|
executionOrder,
|
|
304
369
|
rateLimitConfig: schema.rateLimit,
|