@webpieces/http-server 0.2.15 → 0.2.16
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 +59 -0
- package/src/WebpiecesMiddleware.js +159 -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
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RouteBuilderImpl.js","sourceRoot":"","sources":["../../../../../packages/http/http-server/src/RouteBuilderImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container, injectable } from 'inversify';\nimport { RouteBuilder, RouteDefinition, FilterDefinition } from '@webpieces/core-meta';\nimport { Filter, WpResponse } from '@webpieces/http-filters';\nimport { provideSingleton } from '@webpieces/http-routing';\nimport { RouteHandler } from './RouteHandler';\nimport { MethodMeta } from './MethodMeta';\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 * FilterWithMeta - Pairs a resolved filter instance with its definition.\n * Stores both the DI-resolved filter and the metadata needed for matching.\n */\nexport class FilterWithMeta {\n constructor(\n public filter: HttpFilter,\n public definition: FilterDefinition,\n ) {}\n}\n\n/**\n * RouteHandlerWithMeta - Pairs a route handler with its definition.\n * Stores both the handler (which wraps the DI-resolved controller) and the route metadata.\n *\n * We use unknown for the generic type since we store different TResult types in the same Map.\n * Type safety is maintained through the generic on RouteDefinition at registration time.\n */\nexport class RouteHandlerWithMeta {\n constructor(\n public handler: RouteHandler<unknown>,\n public definition: RouteDefinition<unknown>,\n ) {}\n}\n\n/**\n * RouteBuilderImpl - Concrete implementation of RouteBuilder interface.\n *\n * Similar to Java WebPieces RouteBuilder, this class is responsible for:\n * 1. Registering routes with their handlers\n * 2. Registering filters with priority\n *\n * This class is explicit (not anonymous) to:\n * - Improve traceability and debugging\n * - Make the code easier to understand\n * - Enable better IDE navigation (Cmd+Click on addRoute works!)\n *\n * DI Pattern: This class is registered in webpiecesContainer via @provideSingleton()\n * but needs appContainer to resolve filters/controllers. The container is set via\n * setContainer() after appContainer is created (late binding pattern).\n */\n@provideSingleton()\n@injectable()\nexport class RouteBuilderImpl implements RouteBuilder {\n private routes: Map<string, RouteHandlerWithMeta> = new Map();\n private filterRegistry: Array<FilterWithMeta> = [];\n private container?: Container;\n\n /**\n * Set the DI container used for resolving filters and controllers.\n * Called by WebpiecesCoreServer after appContainer is created.\n *\n * @param container - The application DI container (appContainer)\n */\n setContainer(container: Container): void {\n this.container = container;\n }\n\n /**\n * Register a route with the router.\n *\n * Resolves the controller from DI container ONCE and creates a handler that uses\n * the resolved controller instance. This is more efficient than resolving on every request.\n *\n * The route is stored with a key of \"METHOD:path\" (e.g., \"POST:/search/item\").\n *\n * @param route - Route definition with controller class and method name\n */\n addRoute<TResult = unknown>(route: RouteDefinition<TResult>): void {\n if (!this.container) {\n throw new Error('Container not set. Call setContainer() before registering routes.');\n }\n\n const routeMeta = route.routeMeta;\n\n const key = `${routeMeta.httpMethod}:${routeMeta.path}`;\n\n // Resolve controller instance from DI container ONCE (not on every request!)\n const controller = this.container.get(route.controllerClass);\n\n // Get the controller method\n const method = (controller as Record<string, unknown>)[routeMeta.methodName];\n if (typeof method !== 'function') {\n const controllerName = (route.controllerClass as { name?: string }).name || 'Unknown';\n throw new Error(\n `Method ${routeMeta.methodName} not found on controller ${controllerName}`,\n );\n }\n\n // Create handler that uses the resolved controller instance\n const handler = new (class extends RouteHandler<TResult> {\n async execute(meta: MethodMeta): Promise<TResult> {\n // Invoke the method with requestDto from meta\n // The controller is already resolved - no DI lookup on every request!\n // Pass requestDto as the single argument to the controller method\n const result: TResult = await method.call(controller, meta.requestDto);\n return result;\n }\n })();\n\n // Store handler with route definition\n const routeWithMeta = new RouteHandlerWithMeta(\n handler as RouteHandler<unknown>,\n route as RouteDefinition<unknown>,\n );\n\n this.routes.set(key, routeWithMeta);\n }\n\n /**\n * Register a filter with the filter chain.\n *\n * Resolves the filter from DI container and pairs it with the filter definition.\n * The definition includes pattern information used for route-specific filtering.\n *\n * @param filterDef - Filter definition with priority, filter class, and optional filepath pattern\n */\n addFilter(filterDef: FilterDefinition): void {\n if (!this.container) {\n throw new Error('Container not set. Call setContainer() before registering filters.');\n }\n\n // Resolve filter instance from DI container\n const filter = this.container.get<HttpFilter>(filterDef.filterClass);\n\n // Store filter with its definition\n const filterWithMeta = new FilterWithMeta(filter, filterDef);\n this.filterRegistry.push(filterWithMeta);\n }\n\n /**\n * Get all registered routes.\n *\n * @returns Map of routes with handlers and definitions, keyed by \"METHOD:path\"\n */\n getRoutes(): Map<string, RouteHandlerWithMeta> {\n return this.routes;\n }\n\n /**\n * Get all filters sorted by priority (highest priority first).\n *\n * @returns Array of FilterWithMeta sorted by priority\n */\n getSortedFilters(): Array<FilterWithMeta> {\n return [...this.filterRegistry].sort(\n (a, b) => b.definition.priority - a.definition.priority,\n );\n }\n}\n"]}
|
package/src/RouteHandler.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { MethodMeta } from './MethodMeta';
|
|
2
|
-
/**
|
|
3
|
-
* Handler class for routes.
|
|
4
|
-
* Takes a MethodMeta and returns the controller method result.
|
|
5
|
-
*
|
|
6
|
-
* Generic type parameter TResult represents the return type of the controller method.
|
|
7
|
-
* Example: RouteHandler<SaveResponse> for a method that returns Promise<SaveResponse>
|
|
8
|
-
*
|
|
9
|
-
* Using unknown as default instead of any forces type safety - consumers must
|
|
10
|
-
* handle the result appropriately rather than assuming any type.
|
|
11
|
-
*
|
|
12
|
-
* This is a class instead of a function type to make it easier to trace
|
|
13
|
-
* who is calling what in the debugger/IDE.
|
|
14
|
-
*/
|
|
15
|
-
export declare abstract class RouteHandler<TResult = unknown> {
|
|
16
|
-
/**
|
|
17
|
-
* Execute the route handler.
|
|
18
|
-
* @param meta - The method metadata containing request info and params
|
|
19
|
-
* @returns Promise of the controller method result
|
|
20
|
-
*/
|
|
21
|
-
abstract execute(meta: MethodMeta): Promise<TResult>;
|
|
22
|
-
}
|
package/src/RouteHandler.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RouteHandler = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Handler class for routes.
|
|
6
|
-
* Takes a MethodMeta and returns the controller method result.
|
|
7
|
-
*
|
|
8
|
-
* Generic type parameter TResult represents the return type of the controller method.
|
|
9
|
-
* Example: RouteHandler<SaveResponse> for a method that returns Promise<SaveResponse>
|
|
10
|
-
*
|
|
11
|
-
* Using unknown as default instead of any forces type safety - consumers must
|
|
12
|
-
* handle the result appropriately rather than assuming any type.
|
|
13
|
-
*
|
|
14
|
-
* This is a class instead of a function type to make it easier to trace
|
|
15
|
-
* who is calling what in the debugger/IDE.
|
|
16
|
-
*/
|
|
17
|
-
class RouteHandler {
|
|
18
|
-
}
|
|
19
|
-
exports.RouteHandler = RouteHandler;
|
|
20
|
-
//# sourceMappingURL=RouteHandler.js.map
|
package/src/RouteHandler.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RouteHandler.js","sourceRoot":"","sources":["../../../../../packages/http/http-server/src/RouteHandler.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;GAYG;AACH,MAAsB,YAAY;CAOjC;AAPD,oCAOC","sourcesContent":["import { MethodMeta } from './MethodMeta';\n\n/**\n * Handler class for routes.\n * Takes a MethodMeta and returns the controller method result.\n *\n * Generic type parameter TResult represents the return type of the controller method.\n * Example: RouteHandler<SaveResponse> for a method that returns Promise<SaveResponse>\n *\n * Using unknown as default instead of any forces type safety - consumers must\n * handle the result appropriately rather than assuming any type.\n *\n * This is a class instead of a function type to make it easier to trace\n * who is calling what in the debugger/IDE.\n */\nexport abstract class RouteHandler<TResult = unknown> {\n /**\n * Execute the route handler.\n * @param meta - The method metadata containing request info and params\n * @returns Promise of the controller method result\n */\n abstract execute(meta: MethodMeta): Promise<TResult>;\n}\n"]}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Filter, WpResponse, Service } from '@webpieces/http-filters';
|
|
2
|
-
import { MethodMeta } from '../MethodMeta';
|
|
3
|
-
/**
|
|
4
|
-
* DI tokens for JsonFilter.
|
|
5
|
-
*/
|
|
6
|
-
export declare const FILTER_TYPES: {
|
|
7
|
-
JsonFilterConfig: symbol;
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Configuration for JsonFilter.
|
|
11
|
-
* Register this in your DI container to customize JsonFilter behavior.
|
|
12
|
-
*/
|
|
13
|
-
export declare class JsonFilterConfig {
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* JsonFilter - Handles JSON serialization/deserialization and writes response to HTTP body.
|
|
17
|
-
*
|
|
18
|
-
* Similar to Java WebPieces JacksonCatchAllFilter.
|
|
19
|
-
*
|
|
20
|
-
* Flow:
|
|
21
|
-
* 1. Log request
|
|
22
|
-
* 2. Deserialize request body to DTO and set on meta.requestDto
|
|
23
|
-
* 3. Call next filter/controller
|
|
24
|
-
* 4. Get response (WpResponse)
|
|
25
|
-
* 5. Write response to Express response
|
|
26
|
-
* 6. On ANY exception, send 500
|
|
27
|
-
*/
|
|
28
|
-
export declare class JsonFilter extends Filter<MethodMeta, WpResponse<unknown>> {
|
|
29
|
-
private config;
|
|
30
|
-
constructor(config: JsonFilterConfig);
|
|
31
|
-
filter(meta: MethodMeta, nextFilter: Service<MethodMeta, WpResponse<unknown>>): Promise<WpResponse<unknown>>;
|
|
32
|
-
/**
|
|
33
|
-
* Deserialize request body to DTO and set on meta.requestDto.
|
|
34
|
-
*/
|
|
35
|
-
private deserializeRequest;
|
|
36
|
-
/**
|
|
37
|
-
* Write WpResponse to HTTP response body as JSON.
|
|
38
|
-
*/
|
|
39
|
-
private writeResponse;
|
|
40
|
-
/**
|
|
41
|
-
* Log the incoming request.
|
|
42
|
-
*/
|
|
43
|
-
private logRequest;
|
|
44
|
-
/**
|
|
45
|
-
* Log the outgoing response.
|
|
46
|
-
*/
|
|
47
|
-
private logResponse;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Exception thrown when validation fails.
|
|
51
|
-
*/
|
|
52
|
-
export declare class ValidationException extends Error {
|
|
53
|
-
violations: string[];
|
|
54
|
-
constructor(violations: string[]);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* HTTP exception with status code.
|
|
58
|
-
*/
|
|
59
|
-
export declare class HttpException extends Error {
|
|
60
|
-
statusCode: number;
|
|
61
|
-
constructor(message: string, statusCode: number);
|
|
62
|
-
}
|