@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
package/src/core/http/router.ts
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
// src/core/router.ts
|
|
2
|
-
import {
|
|
3
|
-
HttpRequest,
|
|
4
|
-
HttpResponse,
|
|
5
|
-
HttpHandler,
|
|
6
|
-
Middleware,
|
|
7
|
-
RouteDefinition,
|
|
8
|
-
} from '../../types/http.js';
|
|
9
|
-
import { createFrameworkLogger } from '../logger/index.js';
|
|
10
|
-
|
|
11
|
-
export class Router {
|
|
12
|
-
private routes: RouteDefinition[] = [];
|
|
13
|
-
private logger = createFrameworkLogger('Router');
|
|
14
|
-
|
|
15
|
-
// Performance optimizations - O(1) static route lookup
|
|
16
|
-
private staticRoutes = new Map<string, RouteDefinition>(); // "GET:/api/users" -> route
|
|
17
|
-
private dynamicRoutes: RouteDefinition[] = []; // Routes with parameters
|
|
18
|
-
|
|
19
|
-
// Object pooling for parameters to reduce GC pressure
|
|
20
|
-
private paramObjectPool: Record<string, string>[] = [];
|
|
21
|
-
private readonly maxPoolSize = 50;
|
|
22
|
-
|
|
23
|
-
get(path: string, ...handlers: (Middleware | HttpHandler)[]): void {
|
|
24
|
-
this.addRoute('GET', path, handlers);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
post(path: string, ...handlers: (Middleware | HttpHandler)[]): void {
|
|
28
|
-
this.addRoute('POST', path, handlers);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
put(path: string, ...handlers: (Middleware | HttpHandler)[]): void {
|
|
32
|
-
this.addRoute('PUT', path, handlers);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
delete(path: string, ...handlers: (Middleware | HttpHandler)[]): void {
|
|
36
|
-
this.addRoute('DELETE', path, handlers);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
patch(path: string, ...handlers: (Middleware | HttpHandler)[]): void {
|
|
40
|
-
this.addRoute('PATCH', path, handlers);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
private addRoute(method: string, path: string, handlers: (Middleware | HttpHandler)[]): void {
|
|
44
|
-
const { pattern, paramNames } = this.pathToRegex(path);
|
|
45
|
-
const handler = handlers.pop() as HttpHandler;
|
|
46
|
-
const middleware = handlers as Middleware[];
|
|
47
|
-
|
|
48
|
-
const route: RouteDefinition = {
|
|
49
|
-
method,
|
|
50
|
-
path,
|
|
51
|
-
pattern,
|
|
52
|
-
paramNames,
|
|
53
|
-
handler,
|
|
54
|
-
middleware,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Add to routes array (maintain compatibility)
|
|
58
|
-
this.routes.push(route);
|
|
59
|
-
|
|
60
|
-
// Performance optimization: separate static and dynamic routes
|
|
61
|
-
const isStatic = !path.includes(':') && !path.includes('*');
|
|
62
|
-
if (isStatic && middleware.length === 0) {
|
|
63
|
-
// Static route with no middleware - use O(1) lookup
|
|
64
|
-
const routeKey = `${method}:${path}`;
|
|
65
|
-
this.staticRoutes.set(routeKey, route);
|
|
66
|
-
this.logger.debug(`Added static route: ${routeKey}`, 'FastRoute');
|
|
67
|
-
} else {
|
|
68
|
-
// Dynamic route or has middleware - needs regex matching
|
|
69
|
-
this.dynamicRoutes.push(route);
|
|
70
|
-
this.logger.debug(`Added dynamic route: ${method} ${path}`, 'DynamicRoute');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Initialize object pool on first route
|
|
74
|
-
if (this.paramObjectPool.length === 0) {
|
|
75
|
-
for (let i = 0; i < this.maxPoolSize; i++) {
|
|
76
|
-
this.paramObjectPool.push({});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private pathToRegex(path: string): { pattern: RegExp; paramNames: string[] } {
|
|
82
|
-
const paramNames: string[] = [];
|
|
83
|
-
|
|
84
|
-
// Convert parameterized routes to regex
|
|
85
|
-
const regexPattern = path
|
|
86
|
-
.replace(/\/:([^/]+)/g, (match, paramName) => {
|
|
87
|
-
paramNames.push(paramName);
|
|
88
|
-
return '/([^/]+)';
|
|
89
|
-
})
|
|
90
|
-
.replace(/\//g, '\\/');
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
pattern: new RegExp(`^${regexPattern}$`),
|
|
94
|
-
paramNames,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async handle(req: HttpRequest, res: HttpResponse, basePath: string = ''): Promise<boolean> {
|
|
99
|
-
let path = req.path.startsWith(basePath) ? req.path.substring(basePath.length) : req.path;
|
|
100
|
-
|
|
101
|
-
// If removing basePath results in empty string, default to '/'
|
|
102
|
-
if (path === '' || path === undefined) {
|
|
103
|
-
path = '/';
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
this.logger.debug(
|
|
107
|
-
`Router processing: originalPath="${req.path}", basePath="${basePath}", processedPath="${path}"`,
|
|
108
|
-
'Processing'
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
// PERFORMANCE OPTIMIZATION: Fast path - O(1) static route lookup first
|
|
112
|
-
const routeKey = `${req.method}:${path}`;
|
|
113
|
-
const staticRoute = this.staticRoutes.get(routeKey);
|
|
114
|
-
|
|
115
|
-
if (staticRoute) {
|
|
116
|
-
this.logger.debug(`Fast route match: ${routeKey}`, 'FastRoute');
|
|
117
|
-
|
|
118
|
-
// Static route with no middleware - execute handler directly
|
|
119
|
-
req.params = {}; // No params for static routes
|
|
120
|
-
const result = await staticRoute.handler(req, res);
|
|
121
|
-
|
|
122
|
-
// If handler returns data and response hasn't been sent, send it
|
|
123
|
-
if (result !== undefined && result !== null && !res.headersSent) {
|
|
124
|
-
res.json(result);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Fallback: Dynamic route matching (with middleware support)
|
|
131
|
-
const route = this.dynamicRoutes.find(r => r.method === req.method && r.pattern.test(path));
|
|
132
|
-
|
|
133
|
-
this.logger.debug(
|
|
134
|
-
`Found dynamic route: ${!!route}${route ? ` ${route.method} ${route.path}` : ' none'}`,
|
|
135
|
-
'RouteMatch'
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
if (!route) {
|
|
139
|
-
return false; // Route not found
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Extract path parameters using object pooling
|
|
143
|
-
const matches = path.match(route.pattern);
|
|
144
|
-
if (matches) {
|
|
145
|
-
req.params = this.acquireParamObject();
|
|
146
|
-
route.paramNames.forEach((name, index) => {
|
|
147
|
-
req.params[name] = matches[index + 1];
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
// Execute middleware
|
|
153
|
-
for (const mw of route.middleware) {
|
|
154
|
-
await new Promise<void>((resolve, reject) => {
|
|
155
|
-
let nextCalled = false;
|
|
156
|
-
|
|
157
|
-
const next = () => {
|
|
158
|
-
if (nextCalled) return;
|
|
159
|
-
nextCalled = true;
|
|
160
|
-
resolve();
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
const result = mw(req, res, next);
|
|
165
|
-
|
|
166
|
-
if (result instanceof Promise) {
|
|
167
|
-
result
|
|
168
|
-
.then(() => {
|
|
169
|
-
if (!nextCalled) next();
|
|
170
|
-
})
|
|
171
|
-
.catch(reject);
|
|
172
|
-
}
|
|
173
|
-
} catch (error) {
|
|
174
|
-
reject(error);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
if (res.headersSent) break; // Early exit if response sent
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Execute handler
|
|
182
|
-
const result = await route.handler(req, res);
|
|
183
|
-
|
|
184
|
-
// If handler returns data and response hasn't been sent, send it
|
|
185
|
-
if (result !== undefined && result !== null && !res.headersSent) {
|
|
186
|
-
res.json(result);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return true;
|
|
190
|
-
} finally {
|
|
191
|
-
// Release parameter object back to pool
|
|
192
|
-
if (req.params && matches) {
|
|
193
|
-
this.releaseParamObject(req.params);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
getRoutes(): RouteDefinition[] {
|
|
199
|
-
return [...this.routes];
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Object pooling methods for performance optimization
|
|
203
|
-
private acquireParamObject(): Record<string, string> {
|
|
204
|
-
const obj = this.paramObjectPool.pop();
|
|
205
|
-
if (obj) {
|
|
206
|
-
// Clear the object
|
|
207
|
-
for (const key in obj) {
|
|
208
|
-
delete obj[key];
|
|
209
|
-
}
|
|
210
|
-
return obj;
|
|
211
|
-
}
|
|
212
|
-
return {};
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private releaseParamObject(obj: Record<string, string>): void {
|
|
216
|
-
if (this.paramObjectPool.length < this.maxPoolSize) {
|
|
217
|
-
this.paramObjectPool.push(obj);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Performance statistics for monitoring
|
|
222
|
-
getPerformanceStats() {
|
|
223
|
-
return {
|
|
224
|
-
totalRoutes: this.routes.length,
|
|
225
|
-
staticRoutes: this.staticRoutes.size,
|
|
226
|
-
dynamicRoutes: this.dynamicRoutes.length,
|
|
227
|
-
paramObjectPoolSize: this.paramObjectPool.length,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
}
|