@webpieces/http-server 0.2.15 → 0.2.17
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/package.json +4 -5
- package/src/WebpiecesFactory.d.ts +23 -4
- package/src/WebpiecesFactory.js +25 -8
- package/src/WebpiecesFactory.js.map +1 -1
- package/src/WebpiecesMiddleware.d.ts +75 -0
- package/src/WebpiecesMiddleware.js +218 -0
- package/src/WebpiecesMiddleware.js.map +1 -0
- package/src/WebpiecesServer.d.ts +42 -5
- package/src/WebpiecesServer.js.map +1 -1
- package/src/WebpiecesServerImpl.d.ts +57 -28
- package/src/WebpiecesServerImpl.js +136 -135
- package/src/WebpiecesServerImpl.js.map +1 -1
- package/src/filters/ContextFilter.d.ts +1 -1
- package/src/filters/ContextFilter.js.map +1 -1
- package/src/filters/LogApiFilter.d.ts +40 -0
- package/src/filters/LogApiFilter.js +92 -0
- package/src/filters/LogApiFilter.js.map +1 -0
- package/src/index.d.ts +3 -4
- package/src/index.js +13 -15
- package/src/index.js.map +1 -1
- package/src/FilterMatcher.d.ts +0 -39
- package/src/FilterMatcher.js +0 -69
- package/src/FilterMatcher.js.map +0 -1
- package/src/MethodMeta.d.ts +0 -42
- package/src/MethodMeta.js +0 -40
- package/src/MethodMeta.js.map +0 -1
- package/src/RouteBuilderImpl.d.ts +0 -90
- package/src/RouteBuilderImpl.js +0 -141
- package/src/RouteBuilderImpl.js.map +0 -1
- package/src/RouteHandler.d.ts +0 -22
- package/src/RouteHandler.js +0 -20
- package/src/RouteHandler.js.map +0 -1
- package/src/filters/JsonFilter.d.ts +0 -62
- package/src/filters/JsonFilter.js +0 -146
- package/src/filters/JsonFilter.js.map +0 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { MethodMeta } from '@webpieces/http-routing';
|
|
2
|
+
import { Filter, WpResponse, Service } from '@webpieces/http-filters';
|
|
3
|
+
/**
|
|
4
|
+
* LogApiFilter - Structured API logging for all requests/responses.
|
|
5
|
+
* Priority: 130 (just below ContextFilter at 140, with gap for custom context filters)
|
|
6
|
+
*
|
|
7
|
+
* Logging patterns:
|
|
8
|
+
* - [API-SVR-req] 'Class.method / url' request=jsonStringOfRequest
|
|
9
|
+
* - [API-SVR-resp-SUCCESS] 'Class.method / url' response=jsonStringOfResponse
|
|
10
|
+
* - [API-SVR-resp-FAIL] 'Class.method / url' error=... (server errors: 500, 502, 504)
|
|
11
|
+
* - [API-SVR-resp-OTHER] 'Class.method / url' errorType=... (user errors: 400, 401, 403, 404, 266)
|
|
12
|
+
*
|
|
13
|
+
* User errors (HttpBadRequestError, etc.) are logged as OTHER, not FAIL,
|
|
14
|
+
* because they are expected behavior from the server's perspective.
|
|
15
|
+
*/
|
|
16
|
+
export declare class LogApiFilter extends Filter<MethodMeta, WpResponse<unknown>> {
|
|
17
|
+
filter(meta: MethodMeta, nextFilter: Service<MethodMeta, WpResponse<unknown>>): Promise<WpResponse<unknown>>;
|
|
18
|
+
/**
|
|
19
|
+
* Get formatted class.method string for logging.
|
|
20
|
+
*/
|
|
21
|
+
private getClassMethod;
|
|
22
|
+
/**
|
|
23
|
+
* Log incoming request.
|
|
24
|
+
*/
|
|
25
|
+
private logRequest;
|
|
26
|
+
/**
|
|
27
|
+
* Log successful response.
|
|
28
|
+
*/
|
|
29
|
+
private logSuccessResponse;
|
|
30
|
+
/**
|
|
31
|
+
* Log exception based on error type.
|
|
32
|
+
* User errors get OTHER (no stack trace), server errors get FAIL.
|
|
33
|
+
*/
|
|
34
|
+
private logException;
|
|
35
|
+
/**
|
|
36
|
+
* Check if error is a user error (expected behavior from server perspective).
|
|
37
|
+
* These are NOT failures - just users making mistakes or validation issues.
|
|
38
|
+
*/
|
|
39
|
+
private isUserError;
|
|
40
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LogApiFilter = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const inversify_1 = require("inversify");
|
|
6
|
+
const http_routing_1 = require("@webpieces/http-routing");
|
|
7
|
+
const http_filters_1 = require("@webpieces/http-filters");
|
|
8
|
+
const http_api_1 = require("@webpieces/http-api");
|
|
9
|
+
/**
|
|
10
|
+
* LogApiFilter - Structured API logging for all requests/responses.
|
|
11
|
+
* Priority: 130 (just below ContextFilter at 140, with gap for custom context filters)
|
|
12
|
+
*
|
|
13
|
+
* Logging patterns:
|
|
14
|
+
* - [API-SVR-req] 'Class.method / url' request=jsonStringOfRequest
|
|
15
|
+
* - [API-SVR-resp-SUCCESS] 'Class.method / url' response=jsonStringOfResponse
|
|
16
|
+
* - [API-SVR-resp-FAIL] 'Class.method / url' error=... (server errors: 500, 502, 504)
|
|
17
|
+
* - [API-SVR-resp-OTHER] 'Class.method / url' errorType=... (user errors: 400, 401, 403, 404, 266)
|
|
18
|
+
*
|
|
19
|
+
* User errors (HttpBadRequestError, etc.) are logged as OTHER, not FAIL,
|
|
20
|
+
* because they are expected behavior from the server's perspective.
|
|
21
|
+
*/
|
|
22
|
+
let LogApiFilter = class LogApiFilter extends http_filters_1.Filter {
|
|
23
|
+
async filter(meta, nextFilter) {
|
|
24
|
+
const classMethod = this.getClassMethod(meta);
|
|
25
|
+
const url = meta.path;
|
|
26
|
+
// Log request
|
|
27
|
+
this.logRequest(classMethod, url, meta.requestDto);
|
|
28
|
+
try {
|
|
29
|
+
const response = await nextFilter.invoke(meta);
|
|
30
|
+
// Log success response
|
|
31
|
+
this.logSuccessResponse(classMethod, url, response);
|
|
32
|
+
return response;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
// Log error and re-throw (jsonTranslator will handle serialization)
|
|
36
|
+
this.logException(classMethod, url, error);
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get formatted class.method string for logging.
|
|
42
|
+
*/
|
|
43
|
+
getClassMethod(meta) {
|
|
44
|
+
const className = meta.routeMeta.controllerClassName ?? 'Unknown';
|
|
45
|
+
return `${className}.${meta.methodName}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Log incoming request.
|
|
49
|
+
*/
|
|
50
|
+
logRequest(classMethod, url, request) {
|
|
51
|
+
console.log(`[API-SVR-req] '${classMethod} ${url}' request=${JSON.stringify(request)}`);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Log successful response.
|
|
55
|
+
*/
|
|
56
|
+
logSuccessResponse(classMethod, url, response) {
|
|
57
|
+
console.log(`[API-SVR-resp-SUCCESS] '${classMethod} ${url}' response=${JSON.stringify(response.response)}`);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Log exception based on error type.
|
|
61
|
+
* User errors get OTHER (no stack trace), server errors get FAIL.
|
|
62
|
+
*/
|
|
63
|
+
logException(classMethod, url, error) {
|
|
64
|
+
if (this.isUserError(error)) {
|
|
65
|
+
// User errors (400, 401, 403, 404, 266) - no stack trace needed
|
|
66
|
+
const errorType = error?.constructor.name ?? 'UnknownError';
|
|
67
|
+
console.log(`[API-SVR-resp-OTHER] '${classMethod} ${url}' errorType=${errorType}`);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Server errors (500, 502, etc.) - log full details
|
|
71
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
72
|
+
console.error(`[API-SVR-resp-FAIL] '${classMethod} ${url}' error=${errorMessage}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if error is a user error (expected behavior from server perspective).
|
|
77
|
+
* These are NOT failures - just users making mistakes or validation issues.
|
|
78
|
+
*/
|
|
79
|
+
isUserError(error) {
|
|
80
|
+
return (error instanceof http_api_1.HttpBadRequestError ||
|
|
81
|
+
error instanceof http_api_1.HttpUnauthorizedError ||
|
|
82
|
+
error instanceof http_api_1.HttpForbiddenError ||
|
|
83
|
+
error instanceof http_api_1.HttpNotFoundError ||
|
|
84
|
+
error instanceof http_api_1.HttpUserError);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
exports.LogApiFilter = LogApiFilter;
|
|
88
|
+
exports.LogApiFilter = LogApiFilter = tslib_1.__decorate([
|
|
89
|
+
(0, http_routing_1.provideSingleton)(),
|
|
90
|
+
(0, inversify_1.injectable)()
|
|
91
|
+
], LogApiFilter);
|
|
92
|
+
//# sourceMappingURL=LogApiFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogApiFilter.js","sourceRoot":"","sources":["../../../../../../packages/http/http-server/src/filters/LogApiFilter.ts"],"names":[],"mappings":";;;;AAAA,yCAAuC;AACvC,0DAAuE;AACvE,0DAAsE;AACtE,kDAM6B;AAE7B;;;;;;;;;;;;GAYG;AAGI,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,qBAAuC;IACrE,KAAK,CAAC,MAAM,CACR,IAAgB,EAChB,UAAoD;QAEpD,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;QAEtB,cAAc;QACd,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAEnD,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAE/C,uBAAuB;YACvB,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;YAEpD,OAAO,QAAQ,CAAC;QACpB,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACtB,oEAAoE;YACpE,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;YAC3C,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,IAAgB;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,mBAAmB,IAAI,SAAS,CAAC;QAClE,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;IAC7C,CAAC;IAED;;OAEG;IACK,UAAU,CAAC,WAAmB,EAAE,GAAW,EAAE,OAAgB;QACjE,OAAO,CAAC,GAAG,CAAC,kBAAkB,WAAW,IAAI,GAAG,aAAa,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED;;OAEG;IACK,kBAAkB,CAAC,WAAmB,EAAE,GAAW,EAAE,QAA6B;QACtF,OAAO,CAAC,GAAG,CACP,2BAA2B,WAAW,IAAI,GAAG,cAAc,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CACjG,CAAC;IACN,CAAC;IAED;;;OAGG;IACK,YAAY,CAAC,WAAmB,EAAE,GAAW,EAAE,KAAc;QACjE,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,gEAAgE;YAChE,MAAM,SAAS,GAAI,KAAe,EAAE,WAAW,CAAC,IAAI,IAAI,cAAc,CAAC;YACvE,OAAO,CAAC,GAAG,CAAC,yBAAyB,WAAW,IAAI,GAAG,eAAe,SAAS,EAAE,CAAC,CAAC;QACvF,CAAC;aAAM,CAAC;YACJ,oDAAoD;YACpD,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,OAAO,CAAC,KAAK,CAAC,wBAAwB,WAAW,IAAI,GAAG,WAAW,YAAY,EAAE,CAAC,CAAC;QACvF,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,WAAW,CAAC,KAAc;QAC9B,OAAO,CACH,KAAK,YAAY,8BAAmB;YACpC,KAAK,YAAY,gCAAqB;YACtC,KAAK,YAAY,6BAAkB;YACnC,KAAK,YAAY,4BAAiB;YAClC,KAAK,YAAY,wBAAa,CACjC,CAAC;IACN,CAAC;CACJ,CAAA;AA9EY,oCAAY;uBAAZ,YAAY;IAFxB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;GACA,YAAY,CA8ExB","sourcesContent":["import { injectable } from 'inversify';\nimport { provideSingleton, MethodMeta } from '@webpieces/http-routing';\nimport { Filter, WpResponse, Service } from '@webpieces/http-filters';\nimport {\n HttpBadRequestError,\n HttpUnauthorizedError,\n HttpForbiddenError,\n HttpNotFoundError,\n HttpUserError,\n} from '@webpieces/http-api';\n\n/**\n * LogApiFilter - Structured API logging for all requests/responses.\n * Priority: 130 (just below ContextFilter at 140, with gap for custom context filters)\n *\n * Logging patterns:\n * - [API-SVR-req] 'Class.method / url' request=jsonStringOfRequest\n * - [API-SVR-resp-SUCCESS] 'Class.method / url' response=jsonStringOfResponse\n * - [API-SVR-resp-FAIL] 'Class.method / url' error=... (server errors: 500, 502, 504)\n * - [API-SVR-resp-OTHER] 'Class.method / url' errorType=... (user errors: 400, 401, 403, 404, 266)\n *\n * User errors (HttpBadRequestError, etc.) are logged as OTHER, not FAIL,\n * because they are expected behavior from the server's perspective.\n */\n@provideSingleton()\n@injectable()\nexport class LogApiFilter extends Filter<MethodMeta, WpResponse<unknown>> {\n async filter(\n meta: MethodMeta,\n nextFilter: Service<MethodMeta, WpResponse<unknown>>,\n ): Promise<WpResponse<unknown>> {\n const classMethod = this.getClassMethod(meta);\n const url = meta.path;\n\n // Log request\n this.logRequest(classMethod, url, meta.requestDto);\n\n try {\n const response = await nextFilter.invoke(meta);\n\n // Log success response\n this.logSuccessResponse(classMethod, url, response);\n\n return response;\n } catch (error: unknown) {\n // Log error and re-throw (jsonTranslator will handle serialization)\n this.logException(classMethod, url, error);\n throw error;\n }\n }\n\n /**\n * Get formatted class.method string for logging.\n */\n private getClassMethod(meta: MethodMeta): string {\n const className = meta.routeMeta.controllerClassName ?? 'Unknown';\n return `${className}.${meta.methodName}`;\n }\n\n /**\n * Log incoming request.\n */\n private logRequest(classMethod: string, url: string, request: unknown): void {\n console.log(`[API-SVR-req] '${classMethod} ${url}' request=${JSON.stringify(request)}`);\n }\n\n /**\n * Log successful response.\n */\n private logSuccessResponse(classMethod: string, url: string, response: WpResponse<unknown>): void {\n console.log(\n `[API-SVR-resp-SUCCESS] '${classMethod} ${url}' response=${JSON.stringify(response.response)}`,\n );\n }\n\n /**\n * Log exception based on error type.\n * User errors get OTHER (no stack trace), server errors get FAIL.\n */\n private logException(classMethod: string, url: string, error: unknown): void {\n if (this.isUserError(error)) {\n // User errors (400, 401, 403, 404, 266) - no stack trace needed\n const errorType = (error as Error)?.constructor.name ?? 'UnknownError';\n console.log(`[API-SVR-resp-OTHER] '${classMethod} ${url}' errorType=${errorType}`);\n } else {\n // Server errors (500, 502, etc.) - log full details\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(`[API-SVR-resp-FAIL] '${classMethod} ${url}' error=${errorMessage}`);\n }\n }\n\n /**\n * Check if error is a user error (expected behavior from server perspective).\n * These are NOT failures - just users making mistakes or validation issues.\n */\n private isUserError(error: unknown): boolean {\n return (\n error instanceof HttpBadRequestError ||\n error instanceof HttpUnauthorizedError ||\n error instanceof HttpForbiddenError ||\n error instanceof HttpNotFoundError ||\n error instanceof HttpUserError\n );\n }\n}\n"]}
|
package/src/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { WebpiecesServer } from './WebpiecesServer';
|
|
2
2
|
export { WebpiecesFactory } from './WebpiecesFactory';
|
|
3
|
-
export {
|
|
4
|
-
export { RouteHandler } from './RouteHandler';
|
|
5
|
-
export { MethodMeta } from './MethodMeta';
|
|
3
|
+
export { WebpiecesMiddleware } from './WebpiecesMiddleware';
|
|
6
4
|
export { ContextFilter } from './filters/ContextFilter';
|
|
7
|
-
export {
|
|
5
|
+
export { LogApiFilter } from './filters/LogApiFilter';
|
|
6
|
+
export { RouteHandler, ExpressRouteHandler, MethodMeta, RouteBuilderImpl, RouteHandlerWithMeta, FilterWithMeta, HttpFilter, FilterMatcher, } from '@webpieces/http-routing';
|
package/src/index.js
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.FilterMatcher = exports.FilterWithMeta = exports.RouteHandlerWithMeta = exports.RouteBuilderImpl = exports.MethodMeta = exports.RouteHandler = exports.LogApiFilter = exports.ContextFilter = exports.WebpiecesMiddleware = exports.WebpiecesFactory = void 0;
|
|
4
4
|
var WebpiecesFactory_1 = require("./WebpiecesFactory");
|
|
5
5
|
Object.defineProperty(exports, "WebpiecesFactory", { enumerable: true, get: function () { return WebpiecesFactory_1.WebpiecesFactory; } });
|
|
6
|
-
var
|
|
7
|
-
Object.defineProperty(exports, "
|
|
8
|
-
Object.defineProperty(exports, "RouteHandlerWithMeta", { enumerable: true, get: function () { return RouteBuilderImpl_1.RouteHandlerWithMeta; } });
|
|
9
|
-
Object.defineProperty(exports, "FilterWithMeta", { enumerable: true, get: function () { return RouteBuilderImpl_1.FilterWithMeta; } });
|
|
10
|
-
var RouteHandler_1 = require("./RouteHandler");
|
|
11
|
-
Object.defineProperty(exports, "RouteHandler", { enumerable: true, get: function () { return RouteHandler_1.RouteHandler; } });
|
|
12
|
-
var MethodMeta_1 = require("./MethodMeta");
|
|
13
|
-
Object.defineProperty(exports, "MethodMeta", { enumerable: true, get: function () { return MethodMeta_1.MethodMeta; } });
|
|
6
|
+
var WebpiecesMiddleware_1 = require("./WebpiecesMiddleware");
|
|
7
|
+
Object.defineProperty(exports, "WebpiecesMiddleware", { enumerable: true, get: function () { return WebpiecesMiddleware_1.WebpiecesMiddleware; } });
|
|
14
8
|
var ContextFilter_1 = require("./filters/ContextFilter");
|
|
15
9
|
Object.defineProperty(exports, "ContextFilter", { enumerable: true, get: function () { return ContextFilter_1.ContextFilter; } });
|
|
16
|
-
var
|
|
17
|
-
Object.defineProperty(exports, "
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Object.defineProperty(exports, "
|
|
21
|
-
Object.defineProperty(exports, "
|
|
10
|
+
var LogApiFilter_1 = require("./filters/LogApiFilter");
|
|
11
|
+
Object.defineProperty(exports, "LogApiFilter", { enumerable: true, get: function () { return LogApiFilter_1.LogApiFilter; } });
|
|
12
|
+
// Re-export from http-routing for backward compatibility
|
|
13
|
+
var http_routing_1 = require("@webpieces/http-routing");
|
|
14
|
+
Object.defineProperty(exports, "RouteHandler", { enumerable: true, get: function () { return http_routing_1.RouteHandler; } });
|
|
15
|
+
Object.defineProperty(exports, "MethodMeta", { enumerable: true, get: function () { return http_routing_1.MethodMeta; } });
|
|
16
|
+
Object.defineProperty(exports, "RouteBuilderImpl", { enumerable: true, get: function () { return http_routing_1.RouteBuilderImpl; } });
|
|
17
|
+
Object.defineProperty(exports, "RouteHandlerWithMeta", { enumerable: true, get: function () { return http_routing_1.RouteHandlerWithMeta; } });
|
|
18
|
+
Object.defineProperty(exports, "FilterWithMeta", { enumerable: true, get: function () { return http_routing_1.FilterWithMeta; } });
|
|
19
|
+
Object.defineProperty(exports, "FilterMatcher", { enumerable: true, get: function () { return http_routing_1.FilterMatcher; } });
|
|
22
20
|
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-server/src/index.ts"],"names":[],"mappings":";;;AACA,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-server/src/index.ts"],"names":[],"mappings":";;;AACA,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AACzB,6DAA4D;AAAnD,0HAAA,mBAAmB,OAAA;AAC5B,yDAAwD;AAA/C,8GAAA,aAAa,OAAA;AACtB,uDAAsD;AAA7C,4GAAA,YAAY,OAAA;AAErB,yDAAyD;AACzD,wDASiC;AAR7B,4GAAA,YAAY,OAAA;AAEZ,0GAAA,UAAU,OAAA;AACV,gHAAA,gBAAgB,OAAA;AAChB,oHAAA,oBAAoB,OAAA;AACpB,8GAAA,cAAc,OAAA;AAEd,6GAAA,aAAa,OAAA","sourcesContent":["export { WebpiecesServer } from './WebpiecesServer';\nexport { WebpiecesFactory } from './WebpiecesFactory';\nexport { WebpiecesMiddleware } from './WebpiecesMiddleware';\nexport { ContextFilter } from './filters/ContextFilter';\nexport { LogApiFilter } from './filters/LogApiFilter';\n\n// Re-export from http-routing for backward compatibility\nexport {\n RouteHandler,\n ExpressRouteHandler,\n MethodMeta,\n RouteBuilderImpl,\n RouteHandlerWithMeta,\n FilterWithMeta,\n HttpFilter,\n FilterMatcher,\n} from '@webpieces/http-routing';\n"]}
|
package/src/FilterMatcher.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Filter, WpResponse } from '@webpieces/http-filters';
|
|
2
|
-
import { MethodMeta } from './MethodMeta';
|
|
3
|
-
import { FilterDefinition } from '@webpieces/core-meta';
|
|
4
|
-
/**
|
|
5
|
-
* Type alias for HTTP filters that work with MethodMeta and ResponseWrapper.
|
|
6
|
-
*/
|
|
7
|
-
export type HttpFilter = Filter<MethodMeta, WpResponse<unknown>>;
|
|
8
|
-
/**
|
|
9
|
-
* FilterMatcher - Matches filters to routes based on filepath patterns.
|
|
10
|
-
* Similar to Java SharedMatchUtil.findMatchingFilters().
|
|
11
|
-
*
|
|
12
|
-
* Responsibilities:
|
|
13
|
-
* 1. Filter based on filepath glob pattern matching
|
|
14
|
-
* 2. Sort matching filters by priority (higher first)
|
|
15
|
-
*
|
|
16
|
-
* Differences from Java:
|
|
17
|
-
* - Uses glob patterns instead of regex
|
|
18
|
-
* - Only matches filepaths (no URL path or HTTPS filtering yet)
|
|
19
|
-
* - Simpler API focused on one responsibility
|
|
20
|
-
*/
|
|
21
|
-
export declare class FilterMatcher {
|
|
22
|
-
/**
|
|
23
|
-
* Find filters that match the given controller filepath.
|
|
24
|
-
*
|
|
25
|
-
* @param controllerFilepath - The filepath of the controller source file
|
|
26
|
-
* @param allFilters - All registered filters with their definitions
|
|
27
|
-
* @returns Array of matching filters, sorted by priority (highest first)
|
|
28
|
-
*/
|
|
29
|
-
static findMatchingFilters(controllerFilepath: string | undefined, allFilters: Array<FilterDefinition>): HttpFilter[];
|
|
30
|
-
/**
|
|
31
|
-
* Normalize a controller filepath for consistent matching.
|
|
32
|
-
* - Converts backslashes to forward slashes (Windows compatibility)
|
|
33
|
-
* - Removes leading './'
|
|
34
|
-
*
|
|
35
|
-
* @param filepath - Raw filepath
|
|
36
|
-
* @returns Normalized filepath
|
|
37
|
-
*/
|
|
38
|
-
static normalizeFilepath(filepath: string): string;
|
|
39
|
-
}
|
package/src/FilterMatcher.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FilterMatcher = void 0;
|
|
4
|
-
const minimatch_1 = require("minimatch");
|
|
5
|
-
/**
|
|
6
|
-
* FilterMatcher - Matches filters to routes based on filepath patterns.
|
|
7
|
-
* Similar to Java SharedMatchUtil.findMatchingFilters().
|
|
8
|
-
*
|
|
9
|
-
* Responsibilities:
|
|
10
|
-
* 1. Filter based on filepath glob pattern matching
|
|
11
|
-
* 2. Sort matching filters by priority (higher first)
|
|
12
|
-
*
|
|
13
|
-
* Differences from Java:
|
|
14
|
-
* - Uses glob patterns instead of regex
|
|
15
|
-
* - Only matches filepaths (no URL path or HTTPS filtering yet)
|
|
16
|
-
* - Simpler API focused on one responsibility
|
|
17
|
-
*/
|
|
18
|
-
class FilterMatcher {
|
|
19
|
-
/**
|
|
20
|
-
* Find filters that match the given controller filepath.
|
|
21
|
-
*
|
|
22
|
-
* @param controllerFilepath - The filepath of the controller source file
|
|
23
|
-
* @param allFilters - All registered filters with their definitions
|
|
24
|
-
* @returns Array of matching filters, sorted by priority (highest first)
|
|
25
|
-
*/
|
|
26
|
-
static findMatchingFilters(controllerFilepath, allFilters) {
|
|
27
|
-
const matchingFilters = [];
|
|
28
|
-
for (const definition of allFilters) {
|
|
29
|
-
const pattern = definition.filepathPattern;
|
|
30
|
-
const filter = definition.filter;
|
|
31
|
-
// Special case: '*' matches all controllers (global filter)
|
|
32
|
-
if (pattern === '*') {
|
|
33
|
-
matchingFilters.push({ filter, priority: definition.priority });
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
// If no filepath available, only match wildcard patterns
|
|
37
|
-
if (!controllerFilepath) {
|
|
38
|
-
if (pattern === '**/*') {
|
|
39
|
-
matchingFilters.push({ filter, priority: definition.priority });
|
|
40
|
-
}
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
// Normalize filepath for consistent matching
|
|
44
|
-
const normalizedPath = FilterMatcher.normalizeFilepath(controllerFilepath);
|
|
45
|
-
// Match using minimatch
|
|
46
|
-
if ((0, minimatch_1.minimatch)(normalizedPath, pattern)) {
|
|
47
|
-
matchingFilters.push({ filter, priority: definition.priority });
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
// Sort by priority (highest first)
|
|
51
|
-
matchingFilters.sort((a, b) => b.priority - a.priority);
|
|
52
|
-
return matchingFilters.map((item) => item.filter);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Normalize a controller filepath for consistent matching.
|
|
56
|
-
* - Converts backslashes to forward slashes (Windows compatibility)
|
|
57
|
-
* - Removes leading './'
|
|
58
|
-
*
|
|
59
|
-
* @param filepath - Raw filepath
|
|
60
|
-
* @returns Normalized filepath
|
|
61
|
-
*/
|
|
62
|
-
static normalizeFilepath(filepath) {
|
|
63
|
-
return filepath
|
|
64
|
-
.replace(/\\/g, '/') // Windows backslashes to forward slashes
|
|
65
|
-
.replace(/^\.\//, ''); // Remove leading './'
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
exports.FilterMatcher = FilterMatcher;
|
|
69
|
-
//# sourceMappingURL=FilterMatcher.js.map
|
package/src/FilterMatcher.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FilterMatcher.js","sourceRoot":"","sources":["../../../../../packages/http/http-server/src/FilterMatcher.ts"],"names":[],"mappings":";;;AAGA,yCAAsC;AAOtC;;;;;;;;;;;;GAYG;AACH,MAAa,aAAa;IACtB;;;;;;OAMG;IACH,MAAM,CAAC,mBAAmB,CACtB,kBAAsC,EACtC,UAAmC;QAEnC,MAAM,eAAe,GAAoD,EAAE,CAAC;QAE5E,KAAK,MAAM,UAAU,IAAI,UAAU,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC;YAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAoB,CAAC;YAE/C,4DAA4D;YAC5D,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;gBAClB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAChE,SAAS;YACb,CAAC;YAED,yDAAyD;YACzD,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACtB,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;oBACrB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACpE,CAAC;gBACD,SAAS;YACb,CAAC;YAED,6CAA6C;YAC7C,MAAM,cAAc,GAAG,aAAa,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;YAE3E,wBAAwB;YACxB,IAAI,IAAA,qBAAS,EAAC,cAAc,EAAE,OAAO,CAAC,EAAE,CAAC;gBACrC,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;YACpE,CAAC;QACL,CAAC;QAED,mCAAmC;QACnC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAExD,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,iBAAiB,CAAC,QAAgB;QACrC,OAAO,QAAQ;aACV,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,yCAAyC;aAC7D,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB;IACrD,CAAC;CACJ;AA5DD,sCA4DC","sourcesContent":["import { Filter, WpResponse } from '@webpieces/http-filters';\nimport { MethodMeta } from './MethodMeta';\nimport { FilterDefinition } from '@webpieces/core-meta';\nimport { minimatch } from 'minimatch';\n\n/**\n * Type alias for HTTP filters that work with MethodMeta and ResponseWrapper.\n */\nexport type HttpFilter = Filter<MethodMeta, WpResponse<unknown>>;\n\n/**\n * FilterMatcher - Matches filters to routes based on filepath patterns.\n * Similar to Java SharedMatchUtil.findMatchingFilters().\n *\n * Responsibilities:\n * 1. Filter based on filepath glob pattern matching\n * 2. Sort matching filters by priority (higher first)\n *\n * Differences from Java:\n * - Uses glob patterns instead of regex\n * - Only matches filepaths (no URL path or HTTPS filtering yet)\n * - Simpler API focused on one responsibility\n */\nexport class FilterMatcher {\n /**\n * Find filters that match the given controller filepath.\n *\n * @param controllerFilepath - The filepath of the controller source file\n * @param allFilters - All registered filters with their definitions\n * @returns Array of matching filters, sorted by priority (highest first)\n */\n static findMatchingFilters(\n controllerFilepath: string | undefined,\n allFilters: Array<FilterDefinition>,\n ): HttpFilter[] {\n const matchingFilters: Array<{ filter: HttpFilter; priority: number }> = [];\n\n for (const definition of allFilters) {\n const pattern = definition.filepathPattern;\n const filter = definition.filter as HttpFilter;\n\n // Special case: '*' matches all controllers (global filter)\n if (pattern === '*') {\n matchingFilters.push({ filter, priority: definition.priority });\n continue;\n }\n\n // If no filepath available, only match wildcard patterns\n if (!controllerFilepath) {\n if (pattern === '**/*') {\n matchingFilters.push({ filter, priority: definition.priority });\n }\n continue;\n }\n\n // Normalize filepath for consistent matching\n const normalizedPath = FilterMatcher.normalizeFilepath(controllerFilepath);\n\n // Match using minimatch\n if (minimatch(normalizedPath, pattern)) {\n matchingFilters.push({ filter, priority: definition.priority });\n }\n }\n\n // Sort by priority (highest first)\n matchingFilters.sort((a, b) => b.priority - a.priority);\n\n return matchingFilters.map((item) => item.filter);\n }\n\n /**\n * Normalize a controller filepath for consistent matching.\n * - Converts backslashes to forward slashes (Windows compatibility)\n * - Removes leading './'\n *\n * @param filepath - Raw filepath\n * @returns Normalized filepath\n */\n static normalizeFilepath(filepath: string): string {\n return filepath\n .replace(/\\\\/g, '/') // Windows backslashes to forward slashes\n .replace(/^\\.\\//, ''); // Remove leading './'\n }\n}\n"]}
|
package/src/MethodMeta.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { RouteMetadata2, RouteRequest } from '@webpieces/core-meta';
|
|
2
|
-
/**
|
|
3
|
-
* Metadata about the method being invoked.
|
|
4
|
-
* Passed to filters and contains request information.
|
|
5
|
-
*
|
|
6
|
-
* MethodMeta is created by WebpiecesServerImpl when handling a request:
|
|
7
|
-
* - routeMeta: Static route information (httpMethod, path, methodName)
|
|
8
|
-
* - routeRequest: Express Request/Response objects
|
|
9
|
-
* - requestDto: Set by JsonFilter after deserializing the request body
|
|
10
|
-
*/
|
|
11
|
-
export declare class MethodMeta {
|
|
12
|
-
/**
|
|
13
|
-
* Route metadata (httpMethod, path, methodName, parameterTypes)
|
|
14
|
-
*/
|
|
15
|
-
routeMeta: RouteMetadata2;
|
|
16
|
-
/**
|
|
17
|
-
* Express Request and Response objects
|
|
18
|
-
*/
|
|
19
|
-
routeRequest: RouteRequest;
|
|
20
|
-
/**
|
|
21
|
-
* The deserialized request DTO.
|
|
22
|
-
* Set by JsonFilter after deserializing the request body.
|
|
23
|
-
*/
|
|
24
|
-
requestDto?: unknown;
|
|
25
|
-
/**
|
|
26
|
-
* Additional metadata for storing request-scoped data.
|
|
27
|
-
*/
|
|
28
|
-
metadata: Map<string, unknown>;
|
|
29
|
-
constructor(routeMeta: RouteMetadata2, routeRequest: RouteRequest, requestDto?: unknown, metadata?: Map<string, unknown>);
|
|
30
|
-
/**
|
|
31
|
-
* Get the HTTP method (convenience accessor).
|
|
32
|
-
*/
|
|
33
|
-
get httpMethod(): string;
|
|
34
|
-
/**
|
|
35
|
-
* Get the request path (convenience accessor).
|
|
36
|
-
*/
|
|
37
|
-
get path(): string;
|
|
38
|
-
/**
|
|
39
|
-
* Get the method name (convenience accessor).
|
|
40
|
-
*/
|
|
41
|
-
get methodName(): string;
|
|
42
|
-
}
|
package/src/MethodMeta.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MethodMeta = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Metadata about the method being invoked.
|
|
6
|
-
* Passed to filters and contains request information.
|
|
7
|
-
*
|
|
8
|
-
* MethodMeta is created by WebpiecesServerImpl when handling a request:
|
|
9
|
-
* - routeMeta: Static route information (httpMethod, path, methodName)
|
|
10
|
-
* - routeRequest: Express Request/Response objects
|
|
11
|
-
* - requestDto: Set by JsonFilter after deserializing the request body
|
|
12
|
-
*/
|
|
13
|
-
class MethodMeta {
|
|
14
|
-
constructor(routeMeta, routeRequest, requestDto, metadata) {
|
|
15
|
-
this.routeMeta = routeMeta;
|
|
16
|
-
this.routeRequest = routeRequest;
|
|
17
|
-
this.requestDto = requestDto;
|
|
18
|
-
this.metadata = metadata ?? new Map();
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Get the HTTP method (convenience accessor).
|
|
22
|
-
*/
|
|
23
|
-
get httpMethod() {
|
|
24
|
-
return this.routeMeta.httpMethod;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Get the request path (convenience accessor).
|
|
28
|
-
*/
|
|
29
|
-
get path() {
|
|
30
|
-
return this.routeMeta.path;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Get the method name (convenience accessor).
|
|
34
|
-
*/
|
|
35
|
-
get methodName() {
|
|
36
|
-
return this.routeMeta.methodName;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
exports.MethodMeta = MethodMeta;
|
|
40
|
-
//# sourceMappingURL=MethodMeta.js.map
|
package/src/MethodMeta.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MethodMeta.js","sourceRoot":"","sources":["../../../../../packages/http/http-server/src/MethodMeta.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;GAQG;AACH,MAAa,UAAU;IAsBnB,YACI,SAAyB,EACzB,YAA0B,EAC1B,UAAoB,EACpB,QAA+B;QAE/B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,IAAI,GAAG,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;IACrC,CAAC;CACJ;AAtDD,gCAsDC","sourcesContent":["import { RouteMetadata2, RouteRequest } from '@webpieces/core-meta';\n\n/**\n * Metadata about the method being invoked.\n * Passed to filters and contains request information.\n *\n * MethodMeta is created by WebpiecesServerImpl when handling a request:\n * - routeMeta: Static route information (httpMethod, path, methodName)\n * - routeRequest: Express Request/Response objects\n * - requestDto: Set by JsonFilter after deserializing the request body\n */\nexport class MethodMeta {\n /**\n * Route metadata (httpMethod, path, methodName, parameterTypes)\n */\n routeMeta: RouteMetadata2;\n\n /**\n * Express Request and Response objects\n */\n routeRequest: RouteRequest;\n\n /**\n * The deserialized request DTO.\n * Set by JsonFilter after deserializing the request body.\n */\n requestDto?: unknown;\n\n /**\n * Additional metadata for storing request-scoped data.\n */\n metadata: Map<string, unknown>;\n\n constructor(\n routeMeta: RouteMetadata2,\n routeRequest: RouteRequest,\n requestDto?: unknown,\n metadata?: Map<string, unknown>,\n ) {\n this.routeMeta = routeMeta;\n this.routeRequest = routeRequest;\n this.requestDto = requestDto;\n this.metadata = metadata ?? new Map();\n }\n\n /**\n * Get the HTTP method (convenience accessor).\n */\n get httpMethod(): string {\n return this.routeMeta.httpMethod;\n }\n\n /**\n * Get the request path (convenience accessor).\n */\n get path(): string {\n return this.routeMeta.path;\n }\n\n /**\n * Get the method name (convenience accessor).\n */\n get methodName(): string {\n return this.routeMeta.methodName;\n }\n}\n"]}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { Container } from 'inversify';
|
|
2
|
-
import { RouteBuilder, RouteDefinition, FilterDefinition } from '@webpieces/core-meta';
|
|
3
|
-
import { Filter, WpResponse } from '@webpieces/http-filters';
|
|
4
|
-
import { RouteHandler } from './RouteHandler';
|
|
5
|
-
import { MethodMeta } from './MethodMeta';
|
|
6
|
-
/**
|
|
7
|
-
* Type alias for HTTP filters that work with MethodMeta and ResponseWrapper.
|
|
8
|
-
*/
|
|
9
|
-
export type HttpFilter = Filter<MethodMeta, WpResponse<unknown>>;
|
|
10
|
-
/**
|
|
11
|
-
* FilterWithMeta - Pairs a resolved filter instance with its definition.
|
|
12
|
-
* Stores both the DI-resolved filter and the metadata needed for matching.
|
|
13
|
-
*/
|
|
14
|
-
export declare class FilterWithMeta {
|
|
15
|
-
filter: HttpFilter;
|
|
16
|
-
definition: FilterDefinition;
|
|
17
|
-
constructor(filter: HttpFilter, definition: FilterDefinition);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* RouteHandlerWithMeta - Pairs a route handler with its definition.
|
|
21
|
-
* Stores both the handler (which wraps the DI-resolved controller) and the route metadata.
|
|
22
|
-
*
|
|
23
|
-
* We use unknown for the generic type since we store different TResult types in the same Map.
|
|
24
|
-
* Type safety is maintained through the generic on RouteDefinition at registration time.
|
|
25
|
-
*/
|
|
26
|
-
export declare class RouteHandlerWithMeta {
|
|
27
|
-
handler: RouteHandler<unknown>;
|
|
28
|
-
definition: RouteDefinition<unknown>;
|
|
29
|
-
constructor(handler: RouteHandler<unknown>, definition: RouteDefinition<unknown>);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* RouteBuilderImpl - Concrete implementation of RouteBuilder interface.
|
|
33
|
-
*
|
|
34
|
-
* Similar to Java WebPieces RouteBuilder, this class is responsible for:
|
|
35
|
-
* 1. Registering routes with their handlers
|
|
36
|
-
* 2. Registering filters with priority
|
|
37
|
-
*
|
|
38
|
-
* This class is explicit (not anonymous) to:
|
|
39
|
-
* - Improve traceability and debugging
|
|
40
|
-
* - Make the code easier to understand
|
|
41
|
-
* - Enable better IDE navigation (Cmd+Click on addRoute works!)
|
|
42
|
-
*
|
|
43
|
-
* DI Pattern: This class is registered in webpiecesContainer via @provideSingleton()
|
|
44
|
-
* but needs appContainer to resolve filters/controllers. The container is set via
|
|
45
|
-
* setContainer() after appContainer is created (late binding pattern).
|
|
46
|
-
*/
|
|
47
|
-
export declare class RouteBuilderImpl implements RouteBuilder {
|
|
48
|
-
private routes;
|
|
49
|
-
private filterRegistry;
|
|
50
|
-
private container?;
|
|
51
|
-
/**
|
|
52
|
-
* Set the DI container used for resolving filters and controllers.
|
|
53
|
-
* Called by WebpiecesCoreServer after appContainer is created.
|
|
54
|
-
*
|
|
55
|
-
* @param container - The application DI container (appContainer)
|
|
56
|
-
*/
|
|
57
|
-
setContainer(container: Container): void;
|
|
58
|
-
/**
|
|
59
|
-
* Register a route with the router.
|
|
60
|
-
*
|
|
61
|
-
* Resolves the controller from DI container ONCE and creates a handler that uses
|
|
62
|
-
* the resolved controller instance. This is more efficient than resolving on every request.
|
|
63
|
-
*
|
|
64
|
-
* The route is stored with a key of "METHOD:path" (e.g., "POST:/search/item").
|
|
65
|
-
*
|
|
66
|
-
* @param route - Route definition with controller class and method name
|
|
67
|
-
*/
|
|
68
|
-
addRoute<TResult = unknown>(route: RouteDefinition<TResult>): void;
|
|
69
|
-
/**
|
|
70
|
-
* Register a filter with the filter chain.
|
|
71
|
-
*
|
|
72
|
-
* Resolves the filter from DI container and pairs it with the filter definition.
|
|
73
|
-
* The definition includes pattern information used for route-specific filtering.
|
|
74
|
-
*
|
|
75
|
-
* @param filterDef - Filter definition with priority, filter class, and optional filepath pattern
|
|
76
|
-
*/
|
|
77
|
-
addFilter(filterDef: FilterDefinition): void;
|
|
78
|
-
/**
|
|
79
|
-
* Get all registered routes.
|
|
80
|
-
*
|
|
81
|
-
* @returns Map of routes with handlers and definitions, keyed by "METHOD:path"
|
|
82
|
-
*/
|
|
83
|
-
getRoutes(): Map<string, RouteHandlerWithMeta>;
|
|
84
|
-
/**
|
|
85
|
-
* Get all filters sorted by priority (highest priority first).
|
|
86
|
-
*
|
|
87
|
-
* @returns Array of FilterWithMeta sorted by priority
|
|
88
|
-
*/
|
|
89
|
-
getSortedFilters(): Array<FilterWithMeta>;
|
|
90
|
-
}
|
package/src/RouteBuilderImpl.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RouteBuilderImpl = exports.RouteHandlerWithMeta = exports.FilterWithMeta = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const inversify_1 = require("inversify");
|
|
6
|
-
const http_routing_1 = require("@webpieces/http-routing");
|
|
7
|
-
const RouteHandler_1 = require("./RouteHandler");
|
|
8
|
-
/**
|
|
9
|
-
* FilterWithMeta - Pairs a resolved filter instance with its definition.
|
|
10
|
-
* Stores both the DI-resolved filter and the metadata needed for matching.
|
|
11
|
-
*/
|
|
12
|
-
class FilterWithMeta {
|
|
13
|
-
constructor(filter, definition) {
|
|
14
|
-
this.filter = filter;
|
|
15
|
-
this.definition = definition;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
exports.FilterWithMeta = FilterWithMeta;
|
|
19
|
-
/**
|
|
20
|
-
* RouteHandlerWithMeta - Pairs a route handler with its definition.
|
|
21
|
-
* Stores both the handler (which wraps the DI-resolved controller) and the route metadata.
|
|
22
|
-
*
|
|
23
|
-
* We use unknown for the generic type since we store different TResult types in the same Map.
|
|
24
|
-
* Type safety is maintained through the generic on RouteDefinition at registration time.
|
|
25
|
-
*/
|
|
26
|
-
class RouteHandlerWithMeta {
|
|
27
|
-
constructor(handler, definition) {
|
|
28
|
-
this.handler = handler;
|
|
29
|
-
this.definition = definition;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
exports.RouteHandlerWithMeta = RouteHandlerWithMeta;
|
|
33
|
-
/**
|
|
34
|
-
* RouteBuilderImpl - Concrete implementation of RouteBuilder interface.
|
|
35
|
-
*
|
|
36
|
-
* Similar to Java WebPieces RouteBuilder, this class is responsible for:
|
|
37
|
-
* 1. Registering routes with their handlers
|
|
38
|
-
* 2. Registering filters with priority
|
|
39
|
-
*
|
|
40
|
-
* This class is explicit (not anonymous) to:
|
|
41
|
-
* - Improve traceability and debugging
|
|
42
|
-
* - Make the code easier to understand
|
|
43
|
-
* - Enable better IDE navigation (Cmd+Click on addRoute works!)
|
|
44
|
-
*
|
|
45
|
-
* DI Pattern: This class is registered in webpiecesContainer via @provideSingleton()
|
|
46
|
-
* but needs appContainer to resolve filters/controllers. The container is set via
|
|
47
|
-
* setContainer() after appContainer is created (late binding pattern).
|
|
48
|
-
*/
|
|
49
|
-
let RouteBuilderImpl = class RouteBuilderImpl {
|
|
50
|
-
constructor() {
|
|
51
|
-
this.routes = new Map();
|
|
52
|
-
this.filterRegistry = [];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Set the DI container used for resolving filters and controllers.
|
|
56
|
-
* Called by WebpiecesCoreServer after appContainer is created.
|
|
57
|
-
*
|
|
58
|
-
* @param container - The application DI container (appContainer)
|
|
59
|
-
*/
|
|
60
|
-
setContainer(container) {
|
|
61
|
-
this.container = container;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Register a route with the router.
|
|
65
|
-
*
|
|
66
|
-
* Resolves the controller from DI container ONCE and creates a handler that uses
|
|
67
|
-
* the resolved controller instance. This is more efficient than resolving on every request.
|
|
68
|
-
*
|
|
69
|
-
* The route is stored with a key of "METHOD:path" (e.g., "POST:/search/item").
|
|
70
|
-
*
|
|
71
|
-
* @param route - Route definition with controller class and method name
|
|
72
|
-
*/
|
|
73
|
-
addRoute(route) {
|
|
74
|
-
if (!this.container) {
|
|
75
|
-
throw new Error('Container not set. Call setContainer() before registering routes.');
|
|
76
|
-
}
|
|
77
|
-
const routeMeta = route.routeMeta;
|
|
78
|
-
const key = `${routeMeta.httpMethod}:${routeMeta.path}`;
|
|
79
|
-
// Resolve controller instance from DI container ONCE (not on every request!)
|
|
80
|
-
const controller = this.container.get(route.controllerClass);
|
|
81
|
-
// Get the controller method
|
|
82
|
-
const method = controller[routeMeta.methodName];
|
|
83
|
-
if (typeof method !== 'function') {
|
|
84
|
-
const controllerName = route.controllerClass.name || 'Unknown';
|
|
85
|
-
throw new Error(`Method ${routeMeta.methodName} not found on controller ${controllerName}`);
|
|
86
|
-
}
|
|
87
|
-
// Create handler that uses the resolved controller instance
|
|
88
|
-
const handler = new (class extends RouteHandler_1.RouteHandler {
|
|
89
|
-
async execute(meta) {
|
|
90
|
-
// Invoke the method with requestDto from meta
|
|
91
|
-
// The controller is already resolved - no DI lookup on every request!
|
|
92
|
-
// Pass requestDto as the single argument to the controller method
|
|
93
|
-
const result = await method.call(controller, meta.requestDto);
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
|
-
})();
|
|
97
|
-
// Store handler with route definition
|
|
98
|
-
const routeWithMeta = new RouteHandlerWithMeta(handler, route);
|
|
99
|
-
this.routes.set(key, routeWithMeta);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Register a filter with the filter chain.
|
|
103
|
-
*
|
|
104
|
-
* Resolves the filter from DI container and pairs it with the filter definition.
|
|
105
|
-
* The definition includes pattern information used for route-specific filtering.
|
|
106
|
-
*
|
|
107
|
-
* @param filterDef - Filter definition with priority, filter class, and optional filepath pattern
|
|
108
|
-
*/
|
|
109
|
-
addFilter(filterDef) {
|
|
110
|
-
if (!this.container) {
|
|
111
|
-
throw new Error('Container not set. Call setContainer() before registering filters.');
|
|
112
|
-
}
|
|
113
|
-
// Resolve filter instance from DI container
|
|
114
|
-
const filter = this.container.get(filterDef.filterClass);
|
|
115
|
-
// Store filter with its definition
|
|
116
|
-
const filterWithMeta = new FilterWithMeta(filter, filterDef);
|
|
117
|
-
this.filterRegistry.push(filterWithMeta);
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Get all registered routes.
|
|
121
|
-
*
|
|
122
|
-
* @returns Map of routes with handlers and definitions, keyed by "METHOD:path"
|
|
123
|
-
*/
|
|
124
|
-
getRoutes() {
|
|
125
|
-
return this.routes;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Get all filters sorted by priority (highest priority first).
|
|
129
|
-
*
|
|
130
|
-
* @returns Array of FilterWithMeta sorted by priority
|
|
131
|
-
*/
|
|
132
|
-
getSortedFilters() {
|
|
133
|
-
return [...this.filterRegistry].sort((a, b) => b.definition.priority - a.definition.priority);
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
exports.RouteBuilderImpl = RouteBuilderImpl;
|
|
137
|
-
exports.RouteBuilderImpl = RouteBuilderImpl = tslib_1.__decorate([
|
|
138
|
-
(0, http_routing_1.provideSingleton)(),
|
|
139
|
-
(0, inversify_1.injectable)()
|
|
140
|
-
], RouteBuilderImpl);
|
|
141
|
-
//# sourceMappingURL=RouteBuilderImpl.js.map
|