@morojs/moro 1.7.28 → 1.7.30
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/schema.js +3 -1
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/framework.d.ts +1 -1
- package/dist/core/framework.js +42 -28
- package/dist/core/framework.js.map +1 -1
- package/dist/core/http/http-server.d.ts +116 -12
- package/dist/core/http/http-server.js +1171 -862
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/uws-http-server.d.ts +72 -5
- package/dist/core/http/uws-http-server.js +718 -150
- package/dist/core/http/uws-http-server.js.map +1 -1
- package/dist/core/logger/logger.d.ts +2 -0
- package/dist/core/logger/logger.js +32 -6
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/middleware/built-in/compression/core.js +47 -29
- package/dist/core/middleware/built-in/compression/core.js.map +1 -1
- package/dist/core/middleware/built-in/error-tracker/middleware.d.ts +5 -2
- package/dist/core/middleware/built-in/error-tracker/middleware.js +13 -11
- package/dist/core/middleware/built-in/error-tracker/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/index.d.ts +3 -3
- package/dist/core/middleware/built-in/performance-monitor/middleware.d.ts +2 -1
- package/dist/core/middleware/built-in/performance-monitor/middleware.js +7 -6
- package/dist/core/middleware/built-in/performance-monitor/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/request-logger/middleware.d.ts +2 -1
- package/dist/core/middleware/built-in/request-logger/middleware.js +5 -5
- package/dist/core/middleware/built-in/request-logger/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/validation/core.js +61 -27
- package/dist/core/middleware/built-in/validation/core.js.map +1 -1
- package/dist/core/routing/radix-tree.d.ts +1 -0
- package/dist/core/routing/radix-tree.js +48 -10
- package/dist/core/routing/radix-tree.js.map +1 -1
- package/dist/core/routing/unified-router.d.ts +16 -0
- package/dist/core/routing/unified-router.js +39 -12
- package/dist/core/routing/unified-router.js.map +1 -1
- package/dist/core/utilities/hooks.d.ts +2 -0
- package/dist/core/utilities/hooks.js +12 -0
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/moro.d.ts +1 -0
- package/dist/moro.js +44 -68
- package/dist/moro.js.map +1 -1
- package/package.json +1 -1
|
@@ -53,7 +53,7 @@ export declare const builtInMiddleware: {
|
|
|
53
53
|
range: typeof import("./range/middleware.js").createRangeMiddleware;
|
|
54
54
|
};
|
|
55
55
|
export declare const simpleMiddleware: {
|
|
56
|
-
requestLogger: (
|
|
57
|
-
performanceMonitor: (
|
|
58
|
-
errorTracker: (
|
|
56
|
+
requestLogger: (req: import("../../http/index.js").HttpRequest, res: import("../../http/index.js").HttpResponse, next: () => void) => void;
|
|
57
|
+
performanceMonitor: (req: import("../../http/index.js").HttpRequest, res: import("../../http/index.js").HttpResponse, next: () => void) => void;
|
|
58
|
+
errorTracker: (err: Error, req: import("../../http/index.js").HttpRequest, _res: import("../../http/index.js").HttpResponse, next: (err?: Error) => void) => void;
|
|
59
59
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HttpRequest, HttpResponse } from '../../../../types/http.js';
|
|
1
2
|
/**
|
|
2
3
|
* Performance monitoring middleware
|
|
3
4
|
* Tracks request duration and logs warnings for slow requests
|
|
@@ -9,4 +10,4 @@
|
|
|
9
10
|
* app.use(performanceMonitor);
|
|
10
11
|
* ```
|
|
11
12
|
*/
|
|
12
|
-
export declare const performanceMonitor: (
|
|
13
|
+
export declare const performanceMonitor: (req: HttpRequest, res: HttpResponse, next: () => void) => void;
|
|
@@ -12,18 +12,19 @@ const logger = createFrameworkLogger('PerformanceMonitor');
|
|
|
12
12
|
* app.use(performanceMonitor);
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
|
-
export const performanceMonitor =
|
|
15
|
+
export const performanceMonitor = (req, res, next) => {
|
|
16
16
|
const startTime = Date.now();
|
|
17
|
-
|
|
17
|
+
res.on('finish', () => {
|
|
18
18
|
const duration = Date.now() - startTime;
|
|
19
19
|
// Log slow requests
|
|
20
20
|
if (duration > 1000) {
|
|
21
|
-
logger.warn(`Slow request detected: ${
|
|
22
|
-
path:
|
|
23
|
-
method:
|
|
21
|
+
logger.warn(`Slow request detected: ${req.path} took ${duration}ms`, 'SlowRequest', {
|
|
22
|
+
path: req.path,
|
|
23
|
+
method: req.method,
|
|
24
24
|
duration,
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
-
};
|
|
27
|
+
});
|
|
28
|
+
next();
|
|
28
29
|
};
|
|
29
30
|
//# sourceMappingURL=middleware.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../../../src/core/middleware/built-in/performance-monitor/middleware.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../../../src/core/middleware/built-in/performance-monitor/middleware.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,MAAM,MAAM,GAAG,qBAAqB,CAAC,oBAAoB,CAAC,CAAC;AAE3D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAgB,EAAE,GAAiB,EAAE,IAAgB,EAAQ,EAAE;IAChG,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QAExC,oBAAoB;QACpB,IAAI,QAAQ,GAAG,IAAI,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,0BAA0B,GAAG,CAAC,IAAI,SAAS,QAAQ,IAAI,EAAE,aAAa,EAAE;gBAClF,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,EAAE,CAAC;AACT,CAAC,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HttpRequest, HttpResponse } from '../../../../types/http.js';
|
|
1
2
|
/**
|
|
2
3
|
* Simple request logging middleware
|
|
3
4
|
* Logs incoming requests and their completion time
|
|
@@ -9,4 +10,4 @@
|
|
|
9
10
|
* app.use(requestLogger);
|
|
10
11
|
* ```
|
|
11
12
|
*/
|
|
12
|
-
export declare const requestLogger: (
|
|
13
|
+
export declare const requestLogger: (req: HttpRequest, res: HttpResponse, next: () => void) => void;
|
|
@@ -12,13 +12,13 @@ const logger = createFrameworkLogger('RequestLogger');
|
|
|
12
12
|
* app.use(requestLogger);
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
|
-
export const requestLogger =
|
|
15
|
+
export const requestLogger = (req, res, next) => {
|
|
16
16
|
const startTime = Date.now();
|
|
17
|
-
logger.info(`${
|
|
18
|
-
|
|
19
|
-
context.onComplete = () => {
|
|
17
|
+
logger.info(`${req.method} ${req.path}`, 'RequestLogger');
|
|
18
|
+
res.on('finish', () => {
|
|
20
19
|
const duration = Date.now() - startTime;
|
|
21
20
|
logger.info(`Request completed in ${duration}ms`, 'RequestLogger');
|
|
22
|
-
};
|
|
21
|
+
});
|
|
22
|
+
next();
|
|
23
23
|
};
|
|
24
24
|
//# sourceMappingURL=middleware.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../../../src/core/middleware/built-in/request-logger/middleware.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../../../src/core/middleware/built-in/request-logger/middleware.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGjE,MAAM,MAAM,GAAG,qBAAqB,CAAC,eAAe,CAAC,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAgB,EAAE,GAAiB,EAAE,IAAgB,EAAQ,EAAE;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,eAAe,CAAC,CAAC;IAE1D,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,wBAAwB,QAAQ,IAAI,EAAE,eAAe,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,IAAI,EAAE,CAAC;AACT,CAAC,CAAC"}
|
|
@@ -4,6 +4,29 @@ import { normalizeValidationError, } from '../../../validation/schema-interface.
|
|
|
4
4
|
import { handleValidationError, normalizeErrors } from '../../../validation/error-handler.js';
|
|
5
5
|
import { getGlobalConfig } from '../../../config/index.js';
|
|
6
6
|
const logger = createFrameworkLogger('ValidationCore');
|
|
7
|
+
// Schemas that threw from safeParse (async refinements) - always use parseAsync for these
|
|
8
|
+
const asyncOnlySchemas = new WeakSet();
|
|
9
|
+
/**
|
|
10
|
+
* Run a schema against data, preferring the synchronous safeParse fast path
|
|
11
|
+
* (no promise, no exception-based control flow) when the library supports it.
|
|
12
|
+
* Falls back to parseAsync for libraries without safeParse (Joi/Yup adapters)
|
|
13
|
+
* and for schemas with async refinements.
|
|
14
|
+
*/
|
|
15
|
+
function runSchema(schema, data) {
|
|
16
|
+
const s = schema;
|
|
17
|
+
if (typeof s.safeParse === 'function' && !asyncOnlySchemas.has(s)) {
|
|
18
|
+
try {
|
|
19
|
+
const r = s.safeParse(data);
|
|
20
|
+
return r.success ? { success: true, data: r.data } : { success: false, error: r.error };
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// safeParse throws (rather than failing) only when the schema requires
|
|
24
|
+
// async parsing (e.g. zod async refinements) - remember and fall through
|
|
25
|
+
asyncOnlySchemas.add(s);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return s.parseAsync(data).then((d) => ({ success: true, data: d }), (e) => ({ success: false, error: e }));
|
|
29
|
+
}
|
|
7
30
|
// ===== Core Logic =====
|
|
8
31
|
/**
|
|
9
32
|
* ValidationCore - Core validation logic
|
|
@@ -16,16 +39,6 @@ export class ValidationCore {
|
|
|
16
39
|
if (res.headersSent) {
|
|
17
40
|
return false;
|
|
18
41
|
}
|
|
19
|
-
// Get global validation config
|
|
20
|
-
let globalHandler;
|
|
21
|
-
try {
|
|
22
|
-
const globalConfig = getGlobalConfig();
|
|
23
|
-
globalHandler = globalConfig.modules.validation.onError;
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// Config not initialized yet, use default handler
|
|
27
|
-
globalHandler = undefined;
|
|
28
|
-
}
|
|
29
42
|
try {
|
|
30
43
|
// Order by likelihood and cost: params > query > body > headers
|
|
31
44
|
// Params are fastest (already parsed, small) and most common in REST APIs
|
|
@@ -38,12 +51,15 @@ export class ValidationCore {
|
|
|
38
51
|
break;
|
|
39
52
|
}
|
|
40
53
|
if (hasParams) {
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
let result = runSchema(config.params, req.params);
|
|
55
|
+
if (typeof result.then === 'function')
|
|
56
|
+
result = await result;
|
|
57
|
+
if (result.success) {
|
|
58
|
+
req.validatedParams = result.data;
|
|
43
59
|
req.params = req.validatedParams;
|
|
44
60
|
}
|
|
45
|
-
|
|
46
|
-
this.handleValidationError(error, 'params', req, res, config.onValidationError
|
|
61
|
+
else {
|
|
62
|
+
this.handleValidationError(result.error, 'params', req, res, config.onValidationError);
|
|
47
63
|
return false;
|
|
48
64
|
}
|
|
49
65
|
}
|
|
@@ -58,34 +74,43 @@ export class ValidationCore {
|
|
|
58
74
|
break;
|
|
59
75
|
}
|
|
60
76
|
if (hasQuery) {
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
let result = runSchema(config.query, req.query);
|
|
78
|
+
if (typeof result.then === 'function')
|
|
79
|
+
result = await result;
|
|
80
|
+
if (result.success) {
|
|
81
|
+
req.validatedQuery = result.data;
|
|
63
82
|
req.query = req.validatedQuery;
|
|
64
83
|
}
|
|
65
|
-
|
|
66
|
-
this.handleValidationError(error, 'query', req, res, config.onValidationError
|
|
84
|
+
else {
|
|
85
|
+
this.handleValidationError(result.error, 'query', req, res, config.onValidationError);
|
|
67
86
|
return false;
|
|
68
87
|
}
|
|
69
88
|
}
|
|
70
89
|
}
|
|
71
90
|
// Body is expensive (POST/PUT/PATCH only, requires parsing)
|
|
72
91
|
if (config.body !== undefined && req.body !== undefined) {
|
|
73
|
-
|
|
74
|
-
|
|
92
|
+
let result = runSchema(config.body, req.body);
|
|
93
|
+
if (typeof result.then === 'function')
|
|
94
|
+
result = await result;
|
|
95
|
+
if (result.success) {
|
|
96
|
+
req.validatedBody = result.data;
|
|
75
97
|
req.body = req.validatedBody;
|
|
76
98
|
}
|
|
77
|
-
|
|
78
|
-
this.handleValidationError(error, 'body', req, res, config.onValidationError
|
|
99
|
+
else {
|
|
100
|
+
this.handleValidationError(result.error, 'body', req, res, config.onValidationError);
|
|
79
101
|
return false;
|
|
80
102
|
}
|
|
81
103
|
}
|
|
82
104
|
// Headers are rarely validated
|
|
83
105
|
if (config.headers !== undefined && req.headers !== undefined) {
|
|
84
|
-
|
|
85
|
-
|
|
106
|
+
let result = runSchema(config.headers, req.headers);
|
|
107
|
+
if (typeof result.then === 'function')
|
|
108
|
+
result = await result;
|
|
109
|
+
if (result.success) {
|
|
110
|
+
req.validatedHeaders = result.data;
|
|
86
111
|
}
|
|
87
|
-
|
|
88
|
-
this.handleValidationError(error, 'headers', req, res, config.onValidationError
|
|
112
|
+
else {
|
|
113
|
+
this.handleValidationError(result.error, 'headers', req, res, config.onValidationError);
|
|
89
114
|
return false;
|
|
90
115
|
}
|
|
91
116
|
}
|
|
@@ -105,11 +130,20 @@ export class ValidationCore {
|
|
|
105
130
|
return false;
|
|
106
131
|
}
|
|
107
132
|
}
|
|
108
|
-
handleValidationError(error, field, req, res, customHandler
|
|
133
|
+
handleValidationError(error, field, req, res, customHandler) {
|
|
109
134
|
// Don't send error if headers already sent
|
|
110
135
|
if (res.headersSent) {
|
|
111
136
|
return;
|
|
112
137
|
}
|
|
138
|
+
// Resolve the global handler on the error path only - the success path
|
|
139
|
+
// (the overwhelming majority of requests) never touches config
|
|
140
|
+
let globalHandler;
|
|
141
|
+
try {
|
|
142
|
+
globalHandler = getGlobalConfig().modules.validation.onError;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
globalHandler = undefined;
|
|
146
|
+
}
|
|
113
147
|
const normalizedError = normalizeValidationError(error);
|
|
114
148
|
const errors = normalizeErrors(normalizedError.issues, field);
|
|
115
149
|
handleValidationError(errors, field, req, res, customHandler, globalHandler);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../../../src/core/middleware/built-in/validation/core.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EAEL,wBAAwB,GACzB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAC9F,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAG3D,MAAM,MAAM,GAAG,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../../../src/core/middleware/built-in/validation/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,25 @@ function fastHash(str) {
|
|
|
9
9
|
}
|
|
10
10
|
return hash;
|
|
11
11
|
}
|
|
12
|
+
// Same hash computed over a path slice without allocating the substring
|
|
13
|
+
function fastHashRange(path, start, end) {
|
|
14
|
+
let hash = 0x811c9dc5;
|
|
15
|
+
for (let i = start; i < end; i++) {
|
|
16
|
+
hash ^= path.charCodeAt(i);
|
|
17
|
+
hash = (hash * 0x01000193) >>> 0;
|
|
18
|
+
}
|
|
19
|
+
return hash;
|
|
20
|
+
}
|
|
21
|
+
// Compare a stored segment against a path slice without allocating
|
|
22
|
+
function segmentEqualsRange(segment, path, start, end) {
|
|
23
|
+
if (segment.length !== end - start)
|
|
24
|
+
return false;
|
|
25
|
+
for (let i = start; i < end; i++) {
|
|
26
|
+
if (segment.charCodeAt(i - start) !== path.charCodeAt(i))
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
12
31
|
export class RadixTree {
|
|
13
32
|
root;
|
|
14
33
|
constructor() {
|
|
@@ -20,6 +39,7 @@ export class RadixTree {
|
|
|
20
39
|
paramName: null,
|
|
21
40
|
handler: null,
|
|
22
41
|
paramPath: null,
|
|
42
|
+
collisionNext: null,
|
|
23
43
|
};
|
|
24
44
|
}
|
|
25
45
|
/**
|
|
@@ -60,6 +80,7 @@ export class RadixTree {
|
|
|
60
80
|
paramName: paramName,
|
|
61
81
|
handler: null,
|
|
62
82
|
paramPath: null,
|
|
83
|
+
collisionNext: null,
|
|
63
84
|
};
|
|
64
85
|
}
|
|
65
86
|
node = node.paramChild;
|
|
@@ -87,6 +108,7 @@ export class RadixTree {
|
|
|
87
108
|
paramName: null,
|
|
88
109
|
handler: null,
|
|
89
110
|
paramPath: null,
|
|
111
|
+
collisionNext: null,
|
|
90
112
|
};
|
|
91
113
|
node.staticChildren.set(segmentHash, child);
|
|
92
114
|
node = child;
|
|
@@ -102,15 +124,27 @@ export class RadixTree {
|
|
|
102
124
|
paramName: null,
|
|
103
125
|
handler: null,
|
|
104
126
|
paramPath: null,
|
|
127
|
+
collisionNext: null,
|
|
105
128
|
};
|
|
106
129
|
node.staticChildren.set(segmentHash, child);
|
|
107
130
|
}
|
|
108
131
|
else {
|
|
109
|
-
//
|
|
110
|
-
if
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
132
|
+
// FNV hash collision: walk the sibling chain for a true segment match,
|
|
133
|
+
// appending a new node if this exact segment isn't chained yet
|
|
134
|
+
while (child.segment !== segment) {
|
|
135
|
+
if (!child.collisionNext) {
|
|
136
|
+
child.collisionNext = {
|
|
137
|
+
segmentHash,
|
|
138
|
+
segment,
|
|
139
|
+
staticChildren: null,
|
|
140
|
+
paramChild: null,
|
|
141
|
+
paramName: null,
|
|
142
|
+
handler: null,
|
|
143
|
+
paramPath: null,
|
|
144
|
+
collisionNext: null,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
child = child.collisionNext;
|
|
114
148
|
}
|
|
115
149
|
}
|
|
116
150
|
node = child;
|
|
@@ -157,11 +191,14 @@ export class RadixTree {
|
|
|
157
191
|
while (segEnd < len && path.charCodeAt(segEnd) !== slashCode) {
|
|
158
192
|
segEnd++;
|
|
159
193
|
}
|
|
160
|
-
|
|
161
|
-
const segmentHash =
|
|
162
|
-
// Direct hash lookup (O(1))
|
|
163
|
-
|
|
164
|
-
|
|
194
|
+
// Hash and compare in place - no substring allocation per segment
|
|
195
|
+
const segmentHash = fastHashRange(path, idx, segEnd);
|
|
196
|
+
// Direct hash lookup (O(1)), walking the collision chain if needed
|
|
197
|
+
let child = node.staticChildren.get(segmentHash);
|
|
198
|
+
while (child && !segmentEqualsRange(child.segment, path, idx, segEnd)) {
|
|
199
|
+
child = child.collisionNext;
|
|
200
|
+
}
|
|
201
|
+
if (child) {
|
|
165
202
|
const result = this.searchNode(child, path, segEnd, paramValues);
|
|
166
203
|
if (result) {
|
|
167
204
|
return result;
|
|
@@ -201,6 +238,7 @@ export class RadixTree {
|
|
|
201
238
|
paramName: null,
|
|
202
239
|
handler: null,
|
|
203
240
|
paramPath: null,
|
|
241
|
+
collisionNext: null,
|
|
204
242
|
};
|
|
205
243
|
}
|
|
206
244
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radix-tree.js","sourceRoot":"","sources":["../../../src/core/routing/radix-tree.ts"],"names":[],"mappings":"AAAA,yDAAyD;
|
|
1
|
+
{"version":3,"file":"radix-tree.js","sourceRoot":"","sources":["../../../src/core/routing/radix-tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -115,6 +115,22 @@ export declare class UnifiedRouter {
|
|
|
115
115
|
private isFastPathRoute;
|
|
116
116
|
private buildExecutionOrder;
|
|
117
117
|
getAllRoutes(): RouteSchema[];
|
|
118
|
+
/**
|
|
119
|
+
* Fast-path routes (no middleware/auth/validation/rateLimit/cache) in a shape
|
|
120
|
+
* suitable for registering directly on a native server router (e.g. uWS).
|
|
121
|
+
*/
|
|
122
|
+
getNativeFastPathRoutes(): Array<{
|
|
123
|
+
method: string;
|
|
124
|
+
path: string;
|
|
125
|
+
paramNames: string[] | null;
|
|
126
|
+
handler: (req: HttpRequest, res: HttpResponse) => any;
|
|
127
|
+
}>;
|
|
128
|
+
/**
|
|
129
|
+
* Public wrapper around the registered error handler so native fast paths
|
|
130
|
+
* share the exact same error semantics as router-dispatched routes.
|
|
131
|
+
* Returns true if the handler produced a response.
|
|
132
|
+
*/
|
|
133
|
+
handleRouteError(err: any, req: HttpRequest, res: HttpResponse): Promise<boolean>;
|
|
118
134
|
getRouteCount(): number;
|
|
119
135
|
getStats(): {
|
|
120
136
|
totalRoutes: number;
|
|
@@ -528,12 +528,10 @@ export class UnifiedRouter {
|
|
|
528
528
|
}
|
|
529
529
|
// ===== Route Execution =====
|
|
530
530
|
async executeRoute(route, req, res, matchResult) {
|
|
531
|
-
//
|
|
532
|
-
req
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
req.params[key] = params[key];
|
|
536
|
-
}
|
|
531
|
+
// The matcher already built a fresh params object - use it directly.
|
|
532
|
+
// (No pooling: handlers may retain req past the response, so recycling
|
|
533
|
+
// the object would alias params across requests.)
|
|
534
|
+
req.params = matchResult.params;
|
|
537
535
|
try {
|
|
538
536
|
// Performance: Skip empty executionOrder array iteration
|
|
539
537
|
// Most routes have empty or very short executionOrder
|
|
@@ -572,12 +570,6 @@ export class UnifiedRouter {
|
|
|
572
570
|
});
|
|
573
571
|
}
|
|
574
572
|
}
|
|
575
|
-
finally {
|
|
576
|
-
// Release params back to pool
|
|
577
|
-
if (req.params) {
|
|
578
|
-
this.poolManager.releaseParams(req.params);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
573
|
}
|
|
582
574
|
async executePhase(phase, route, req, res) {
|
|
583
575
|
const schema = route.schema;
|
|
@@ -749,6 +741,41 @@ export class UnifiedRouter {
|
|
|
749
741
|
getAllRoutes() {
|
|
750
742
|
return this.allRoutes.map(r => r.schema);
|
|
751
743
|
}
|
|
744
|
+
/**
|
|
745
|
+
* Fast-path routes (no middleware/auth/validation/rateLimit/cache) in a shape
|
|
746
|
+
* suitable for registering directly on a native server router (e.g. uWS).
|
|
747
|
+
*/
|
|
748
|
+
getNativeFastPathRoutes() {
|
|
749
|
+
const result = [];
|
|
750
|
+
for (const route of this.allRoutes) {
|
|
751
|
+
if (!route.isFastPath)
|
|
752
|
+
continue;
|
|
753
|
+
const path = route.schema.path;
|
|
754
|
+
let paramNames = null;
|
|
755
|
+
if (path.indexOf(':') !== -1) {
|
|
756
|
+
paramNames = [];
|
|
757
|
+
for (const seg of path.split('/')) {
|
|
758
|
+
if (seg.charCodeAt(0) === 58)
|
|
759
|
+
paramNames.push(seg.slice(1));
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
result.push({
|
|
763
|
+
method: route.schema.method,
|
|
764
|
+
path,
|
|
765
|
+
paramNames,
|
|
766
|
+
handler: route.schema.handler,
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
return result;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Public wrapper around the registered error handler so native fast paths
|
|
773
|
+
* share the exact same error semantics as router-dispatched routes.
|
|
774
|
+
* Returns true if the handler produced a response.
|
|
775
|
+
*/
|
|
776
|
+
handleRouteError(err, req, res) {
|
|
777
|
+
return this.invokeErrorHandler(err, req, res);
|
|
778
|
+
}
|
|
752
779
|
getRouteCount() {
|
|
753
780
|
return this.stats.totalRoutes;
|
|
754
781
|
}
|