@expressots/adapter-express 3.0.0 → 4.0.0-preview.3
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/LICENSE.md +21 -21
- package/README.md +61 -118
- package/lib/CHANGELOG.md +36 -5
- package/lib/README.md +61 -118
- package/lib/cjs/adapter-express/application-express.base.js +3 -1
- package/lib/cjs/adapter-express/application-express.js +1405 -85
- package/lib/cjs/adapter-express/express-utils/conditional-middleware.js +102 -0
- package/lib/cjs/adapter-express/express-utils/constants.js +17 -0
- package/lib/cjs/adapter-express/express-utils/content-negotiation-decorators.js +129 -0
- package/lib/cjs/adapter-express/express-utils/decorators.js +225 -59
- package/lib/cjs/adapter-express/express-utils/exception-filter-decorators.js +11 -0
- package/lib/cjs/adapter-express/express-utils/guard-context-factory.js +84 -0
- package/lib/cjs/adapter-express/express-utils/guard-middleware.js +115 -0
- package/lib/cjs/adapter-express/express-utils/guard-utils.js +18 -0
- package/lib/cjs/adapter-express/express-utils/http-context-store.js +15 -0
- package/lib/cjs/adapter-express/express-utils/http-status-middleware.js +37 -2
- package/lib/cjs/adapter-express/express-utils/index.js +67 -1
- package/lib/cjs/adapter-express/express-utils/interceptor-middleware.js +132 -0
- package/lib/cjs/adapter-express/express-utils/inversify-express-server.js +827 -64
- package/lib/cjs/adapter-express/express-utils/lazy-module-middleware.js +241 -0
- package/lib/cjs/adapter-express/express-utils/middleware-composition.js +95 -0
- package/lib/cjs/adapter-express/express-utils/path-pattern-compat.js +129 -0
- package/lib/cjs/adapter-express/express-utils/permission-preloader.middleware.js +48 -0
- package/lib/cjs/adapter-express/express-utils/route-constraints.js +104 -0
- package/lib/cjs/adapter-express/express-utils/scope-extractor.interface.js +2 -0
- package/lib/cjs/adapter-express/express-utils/scope-extractor.js +66 -0
- package/lib/cjs/adapter-express/express-utils/setup-authorization.js +71 -0
- package/lib/cjs/adapter-express/express-utils/setup-event-system.js +113 -0
- package/lib/cjs/adapter-express/express-utils/setup-interceptors.js +103 -0
- package/lib/cjs/adapter-express/express-utils/setup-lazy-loading.js +228 -0
- package/lib/cjs/adapter-express/express-utils/utils.js +30 -12
- package/lib/cjs/adapter-express/express-utils/validation-decorators.js +205 -0
- package/lib/cjs/adapter-express/express-utils/validation-service.js +252 -0
- package/lib/cjs/adapter-express/index.js +7 -5
- package/lib/cjs/adapter-express/micro-api/application-express-micro-route.js +31 -1
- package/lib/cjs/adapter-express/micro-api/application-express-micro.js +8 -38
- package/lib/cjs/adapter-express/micro-api/gateway/circuit-breaker.js +174 -0
- package/lib/cjs/adapter-express/micro-api/gateway/index.js +11 -0
- package/lib/cjs/adapter-express/micro-api/gateway/service-proxy.js +214 -0
- package/lib/cjs/adapter-express/micro-api/index.js +27 -3
- package/lib/cjs/adapter-express/micro-api/micro.js +272 -0
- package/lib/cjs/adapter-express/micro-api/queue/index.js +8 -0
- package/lib/cjs/adapter-express/micro-api/queue/queue.interface.js +2 -0
- package/lib/cjs/adapter-express/micro-api/queue/rabbitmq-consumer.js +255 -0
- package/lib/cjs/adapter-express/micro-api/serverless/aws-lambda.adapter.js +183 -0
- package/lib/cjs/adapter-express/micro-api/serverless/cloudflare.adapter.js +158 -0
- package/lib/cjs/adapter-express/micro-api/serverless/index.js +12 -0
- package/lib/cjs/adapter-express/micro-api/serverless/vercel.adapter.js +102 -0
- package/lib/cjs/adapter-express/micro-api/service-mesh/index.js +10 -0
- package/lib/cjs/adapter-express/micro-api/service-mesh/service-client.js +194 -0
- package/lib/cjs/adapter-express/micro-api/service-mesh/service-discovery.js +261 -0
- package/lib/cjs/adapter-express/middleware/index.js +21 -0
- package/lib/cjs/adapter-express/middleware/request-logging.middleware.js +244 -0
- package/lib/cjs/adapter-express/render/engine.js +15 -15
- package/lib/cjs/adapter-express/render/index.js +5 -0
- package/lib/cjs/adapter-express/studio/index.js +10 -0
- package/lib/cjs/adapter-express/studio/studio-integration.js +267 -0
- package/lib/cjs/index.js +1 -1
- package/lib/cjs/types/adapter-express/application-express.base.d.ts +20 -7
- package/lib/cjs/types/adapter-express/application-express.d.ts +316 -33
- package/lib/cjs/types/adapter-express/express-utils/base-middleware.d.ts +2 -2
- package/lib/cjs/types/adapter-express/express-utils/conditional-middleware.d.ts +97 -0
- package/lib/cjs/types/adapter-express/express-utils/constants.d.ts +13 -0
- package/lib/cjs/types/adapter-express/express-utils/content-negotiation-decorators.d.ts +94 -0
- package/lib/cjs/types/adapter-express/express-utils/decorators.d.ts +54 -6
- package/lib/cjs/types/adapter-express/express-utils/exception-filter-decorators.d.ts +6 -0
- package/lib/cjs/types/adapter-express/express-utils/guard-context-factory.d.ts +17 -0
- package/lib/cjs/types/adapter-express/express-utils/guard-middleware.d.ts +22 -0
- package/lib/cjs/types/adapter-express/express-utils/guard-utils.d.ts +11 -0
- package/lib/cjs/types/adapter-express/express-utils/http-context-store.d.ts +20 -0
- package/lib/cjs/types/adapter-express/express-utils/httpResponseMessage.d.ts +1 -1
- package/lib/cjs/types/adapter-express/express-utils/index.d.ts +30 -2
- package/lib/cjs/types/adapter-express/express-utils/interceptor-middleware.d.ts +40 -0
- package/lib/cjs/types/adapter-express/express-utils/interfaces.d.ts +42 -5
- package/lib/cjs/types/adapter-express/express-utils/inversify-express-server.d.ts +114 -2
- package/lib/cjs/types/adapter-express/express-utils/lazy-module-middleware.d.ts +122 -0
- package/lib/cjs/types/adapter-express/express-utils/middleware-composition.d.ts +85 -0
- package/lib/cjs/types/adapter-express/express-utils/path-pattern-compat.d.ts +66 -0
- package/lib/cjs/types/adapter-express/express-utils/permission-preloader.middleware.d.ts +10 -0
- package/lib/cjs/types/adapter-express/express-utils/route-constraints.d.ts +98 -0
- package/lib/cjs/types/adapter-express/express-utils/scope-extractor.d.ts +21 -0
- package/lib/cjs/types/adapter-express/express-utils/scope-extractor.interface.d.ts +12 -0
- package/lib/cjs/types/adapter-express/express-utils/setup-authorization.d.ts +34 -0
- package/lib/cjs/types/adapter-express/express-utils/setup-event-system.d.ts +118 -0
- package/lib/cjs/types/adapter-express/express-utils/setup-interceptors.d.ts +115 -0
- package/lib/cjs/types/adapter-express/express-utils/setup-lazy-loading.d.ts +123 -0
- package/lib/cjs/types/adapter-express/express-utils/utils.d.ts +17 -2
- package/lib/cjs/types/adapter-express/express-utils/validation-decorators.d.ts +145 -0
- package/lib/cjs/types/adapter-express/express-utils/validation-service.d.ts +88 -0
- package/lib/cjs/types/adapter-express/index.d.ts +6 -4
- package/lib/cjs/types/adapter-express/micro-api/application-express-micro-route.d.ts +25 -14
- package/lib/cjs/types/adapter-express/micro-api/application-express-micro.d.ts +3 -10
- package/lib/cjs/types/adapter-express/micro-api/gateway/circuit-breaker.d.ts +111 -0
- package/lib/cjs/types/adapter-express/micro-api/gateway/index.d.ts +5 -0
- package/lib/cjs/types/adapter-express/micro-api/gateway/service-proxy.d.ts +83 -0
- package/lib/cjs/types/adapter-express/micro-api/index.d.ts +7 -1
- package/lib/cjs/types/adapter-express/micro-api/micro.d.ts +83 -0
- package/lib/cjs/types/adapter-express/micro-api/queue/index.d.ts +5 -0
- package/lib/cjs/types/adapter-express/micro-api/queue/queue.interface.d.ts +60 -0
- package/lib/cjs/types/adapter-express/micro-api/queue/rabbitmq-consumer.d.ts +86 -0
- package/lib/cjs/types/adapter-express/micro-api/serverless/aws-lambda.adapter.d.ts +77 -0
- package/lib/cjs/types/adapter-express/micro-api/serverless/cloudflare.adapter.d.ts +64 -0
- package/lib/cjs/types/adapter-express/micro-api/serverless/index.d.ts +6 -0
- package/lib/cjs/types/adapter-express/micro-api/serverless/vercel.adapter.d.ts +56 -0
- package/lib/cjs/types/adapter-express/micro-api/service-mesh/index.d.ts +5 -0
- package/lib/cjs/types/adapter-express/micro-api/service-mesh/service-client.d.ts +122 -0
- package/lib/cjs/types/adapter-express/micro-api/service-mesh/service-discovery.d.ts +150 -0
- package/lib/cjs/types/adapter-express/middleware/index.d.ts +5 -0
- package/lib/cjs/types/adapter-express/middleware/request-logging.middleware.d.ts +65 -0
- package/lib/cjs/types/adapter-express/render/index.d.ts +1 -0
- package/lib/cjs/types/adapter-express/studio/index.d.ts +1 -0
- package/lib/cjs/types/adapter-express/studio/studio-integration.d.ts +170 -0
- package/lib/cjs/types/index.d.ts +1 -1
- package/lib/esm/adapter-express/application-express.base.js +24 -0
- package/lib/esm/adapter-express/application-express.js +1656 -0
- package/lib/esm/adapter-express/application-express.types.js +1 -0
- package/lib/esm/adapter-express/express-utils/base-middleware.js +19 -0
- package/lib/esm/adapter-express/express-utils/conditional-middleware.js +96 -0
- package/lib/esm/adapter-express/express-utils/constants.js +63 -0
- package/lib/esm/adapter-express/express-utils/content/httpContent.js +6 -0
- package/lib/esm/adapter-express/express-utils/content-negotiation-decorators.js +120 -0
- package/lib/esm/adapter-express/express-utils/decorators.js +604 -0
- package/lib/esm/adapter-express/express-utils/exception-filter-decorators.js +6 -0
- package/lib/esm/adapter-express/express-utils/guard-context-factory.js +83 -0
- package/lib/esm/adapter-express/express-utils/guard-middleware.js +115 -0
- package/lib/esm/adapter-express/express-utils/guard-utils.js +14 -0
- package/lib/esm/adapter-express/express-utils/http-context-store.js +10 -0
- package/lib/esm/adapter-express/express-utils/http-status-middleware.js +116 -0
- package/lib/esm/adapter-express/express-utils/httpResponseMessage.js +29 -0
- package/lib/esm/adapter-express/express-utils/index.js +24 -0
- package/lib/esm/adapter-express/express-utils/interceptor-middleware.js +130 -0
- package/lib/esm/adapter-express/express-utils/interfaces.js +1 -0
- package/lib/esm/adapter-express/express-utils/inversify-express-server.js +1047 -0
- package/lib/esm/adapter-express/express-utils/lazy-module-middleware.js +236 -0
- package/lib/esm/adapter-express/express-utils/middleware-composition.js +89 -0
- package/lib/esm/adapter-express/express-utils/path-pattern-compat.js +125 -0
- package/lib/esm/adapter-express/express-utils/permission-preloader.middleware.js +45 -0
- package/lib/esm/adapter-express/express-utils/resolver-multer.js +30 -0
- package/lib/esm/adapter-express/express-utils/route-constraints.js +100 -0
- package/lib/esm/adapter-express/express-utils/scope-extractor.interface.js +1 -0
- package/lib/esm/adapter-express/express-utils/scope-extractor.js +63 -0
- package/lib/esm/adapter-express/express-utils/setup-authorization.js +68 -0
- package/lib/esm/adapter-express/express-utils/setup-event-system.js +110 -0
- package/lib/esm/adapter-express/express-utils/setup-interceptors.js +100 -0
- package/lib/esm/adapter-express/express-utils/setup-lazy-loading.js +225 -0
- package/lib/esm/adapter-express/express-utils/utils.js +68 -0
- package/lib/esm/adapter-express/express-utils/validation-decorators.js +199 -0
- package/lib/esm/adapter-express/express-utils/validation-service.js +251 -0
- package/lib/esm/adapter-express/index.js +7 -0
- package/lib/esm/adapter-express/micro-api/application-express-micro-container.js +48 -0
- package/lib/esm/adapter-express/micro-api/application-express-micro-route.js +128 -0
- package/lib/esm/adapter-express/micro-api/application-express-micro.js +157 -0
- package/lib/esm/adapter-express/micro-api/gateway/circuit-breaker.js +174 -0
- package/lib/esm/adapter-express/micro-api/gateway/index.js +5 -0
- package/lib/esm/adapter-express/micro-api/gateway/service-proxy.js +210 -0
- package/lib/esm/adapter-express/micro-api/index.js +10 -0
- package/lib/esm/adapter-express/micro-api/micro.js +266 -0
- package/lib/esm/adapter-express/micro-api/queue/index.js +4 -0
- package/lib/esm/adapter-express/micro-api/queue/queue.interface.js +1 -0
- package/lib/esm/adapter-express/micro-api/queue/rabbitmq-consumer.js +229 -0
- package/lib/esm/adapter-express/micro-api/serverless/aws-lambda.adapter.js +180 -0
- package/lib/esm/adapter-express/micro-api/serverless/cloudflare.adapter.js +155 -0
- package/lib/esm/adapter-express/micro-api/serverless/index.js +6 -0
- package/lib/esm/adapter-express/micro-api/serverless/vercel.adapter.js +99 -0
- package/lib/esm/adapter-express/micro-api/service-mesh/index.js +5 -0
- package/lib/esm/adapter-express/micro-api/service-mesh/service-client.js +191 -0
- package/lib/esm/adapter-express/micro-api/service-mesh/service-discovery.js +259 -0
- package/lib/esm/adapter-express/middleware/index.js +5 -0
- package/lib/esm/adapter-express/middleware/request-logging.middleware.js +239 -0
- package/lib/esm/adapter-express/render/constants.js +37 -0
- package/lib/esm/adapter-express/render/engine.js +51 -0
- package/lib/esm/adapter-express/render/index.js +1 -0
- package/lib/esm/adapter-express/render/resolve-render.js +30 -0
- package/lib/esm/adapter-express/studio/index.js +1 -0
- package/lib/esm/adapter-express/studio/studio-integration.js +236 -0
- package/lib/esm/index.mjs +1 -0
- package/lib/esm/package.json +3 -0
- package/lib/esm/types/adapter-express/application-express.base.d.ts +77 -0
- package/lib/esm/types/adapter-express/application-express.d.ts +453 -0
- package/lib/esm/types/adapter-express/application-express.types.d.ts +23 -0
- package/lib/esm/types/adapter-express/express-utils/base-middleware.d.ts +8 -0
- package/lib/esm/types/adapter-express/express-utils/conditional-middleware.d.ts +97 -0
- package/lib/esm/types/adapter-express/express-utils/constants.d.ts +57 -0
- package/lib/esm/types/adapter-express/express-utils/content/httpContent.d.ts +6 -0
- package/lib/esm/types/adapter-express/express-utils/content-negotiation-decorators.d.ts +94 -0
- package/lib/esm/types/adapter-express/express-utils/decorators.d.ts +257 -0
- package/lib/esm/types/adapter-express/express-utils/exception-filter-decorators.d.ts +6 -0
- package/lib/esm/types/adapter-express/express-utils/guard-context-factory.d.ts +17 -0
- package/lib/esm/types/adapter-express/express-utils/guard-middleware.d.ts +22 -0
- package/lib/esm/types/adapter-express/express-utils/guard-utils.d.ts +11 -0
- package/lib/esm/types/adapter-express/express-utils/http-context-store.d.ts +20 -0
- package/lib/esm/types/adapter-express/express-utils/http-status-middleware.d.ts +26 -0
- package/lib/esm/types/adapter-express/express-utils/httpResponseMessage.d.ts +14 -0
- package/lib/esm/types/adapter-express/express-utils/index.d.ts +30 -0
- package/lib/esm/types/adapter-express/express-utils/interceptor-middleware.d.ts +40 -0
- package/lib/esm/types/adapter-express/express-utils/interfaces.d.ts +115 -0
- package/lib/esm/types/adapter-express/express-utils/inversify-express-server.d.ts +172 -0
- package/lib/esm/types/adapter-express/express-utils/lazy-module-middleware.d.ts +122 -0
- package/lib/esm/types/adapter-express/express-utils/middleware-composition.d.ts +85 -0
- package/lib/esm/types/adapter-express/express-utils/path-pattern-compat.d.ts +66 -0
- package/lib/esm/types/adapter-express/express-utils/permission-preloader.middleware.d.ts +10 -0
- package/lib/esm/types/adapter-express/express-utils/resolver-multer.d.ts +7 -0
- package/lib/esm/types/adapter-express/express-utils/route-constraints.d.ts +98 -0
- package/lib/esm/types/adapter-express/express-utils/scope-extractor.d.ts +21 -0
- package/lib/esm/types/adapter-express/express-utils/scope-extractor.interface.d.ts +12 -0
- package/lib/esm/types/adapter-express/express-utils/setup-authorization.d.ts +34 -0
- package/lib/esm/types/adapter-express/express-utils/setup-event-system.d.ts +118 -0
- package/lib/esm/types/adapter-express/express-utils/setup-interceptors.d.ts +115 -0
- package/lib/esm/types/adapter-express/express-utils/setup-lazy-loading.d.ts +123 -0
- package/lib/esm/types/adapter-express/express-utils/utils.d.ts +24 -0
- package/lib/esm/types/adapter-express/express-utils/validation-decorators.d.ts +145 -0
- package/lib/esm/types/adapter-express/express-utils/validation-service.d.ts +88 -0
- package/lib/esm/types/adapter-express/index.d.ts +7 -0
- package/lib/esm/types/adapter-express/micro-api/application-express-micro-container.d.ts +47 -0
- package/lib/esm/types/adapter-express/micro-api/application-express-micro-route.d.ts +104 -0
- package/lib/esm/types/adapter-express/micro-api/application-express-micro.d.ts +72 -0
- package/lib/esm/types/adapter-express/micro-api/gateway/circuit-breaker.d.ts +111 -0
- package/lib/esm/types/adapter-express/micro-api/gateway/index.d.ts +5 -0
- package/lib/esm/types/adapter-express/micro-api/gateway/service-proxy.d.ts +83 -0
- package/lib/esm/types/adapter-express/micro-api/index.d.ts +7 -0
- package/lib/esm/types/adapter-express/micro-api/micro.d.ts +83 -0
- package/lib/esm/types/adapter-express/micro-api/queue/index.d.ts +5 -0
- package/lib/esm/types/adapter-express/micro-api/queue/queue.interface.d.ts +60 -0
- package/lib/esm/types/adapter-express/micro-api/queue/rabbitmq-consumer.d.ts +86 -0
- package/lib/esm/types/adapter-express/micro-api/serverless/aws-lambda.adapter.d.ts +77 -0
- package/lib/esm/types/adapter-express/micro-api/serverless/cloudflare.adapter.d.ts +64 -0
- package/lib/esm/types/adapter-express/micro-api/serverless/index.d.ts +6 -0
- package/lib/esm/types/adapter-express/micro-api/serverless/vercel.adapter.d.ts +56 -0
- package/lib/esm/types/adapter-express/micro-api/service-mesh/index.d.ts +5 -0
- package/lib/esm/types/adapter-express/micro-api/service-mesh/service-client.d.ts +122 -0
- package/lib/esm/types/adapter-express/micro-api/service-mesh/service-discovery.d.ts +150 -0
- package/lib/esm/types/adapter-express/middleware/index.d.ts +5 -0
- package/lib/esm/types/adapter-express/middleware/request-logging.middleware.d.ts +65 -0
- package/lib/esm/types/adapter-express/render/constants.d.ts +26 -0
- package/lib/esm/types/adapter-express/render/engine.d.ts +20 -0
- package/lib/esm/types/adapter-express/render/index.d.ts +5 -0
- package/lib/esm/types/adapter-express/render/resolve-render.d.ts +7 -0
- package/lib/esm/types/adapter-express/studio/index.d.ts +1 -0
- package/lib/esm/types/adapter-express/studio/studio-integration.d.ts +170 -0
- package/lib/esm/types/index.d.ts +1 -0
- package/lib/package.json +170 -146
- package/package.json +170 -146
- package/lib/cjs/di/di.interfaces.js +0 -10
- package/lib/cjs/types/di/di.interfaces.d.ts +0 -289
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Decorators
|
|
3
|
+
* @module @expressots/adapter-express
|
|
4
|
+
*
|
|
5
|
+
* Enhanced parameter decorators with validation support.
|
|
6
|
+
* These decorators extend the standard @body, @query, @param, @headers
|
|
7
|
+
* to accept optional schema for automatic validation.
|
|
8
|
+
*/
|
|
9
|
+
import "reflect-metadata";
|
|
10
|
+
import { METADATA_KEY, PARAMETER_TYPE } from "./constants.js";
|
|
11
|
+
/**
|
|
12
|
+
* Create a validated parameter decorator
|
|
13
|
+
* @param source - Parameter source type
|
|
14
|
+
* @param parameterType - The PARAMETER_TYPE enum value
|
|
15
|
+
*/
|
|
16
|
+
function createValidatedParamDecorator(source, parameterType) {
|
|
17
|
+
return function (nameOrSchema) {
|
|
18
|
+
return function (target, propertyKey, parameterIndex) {
|
|
19
|
+
let paramName;
|
|
20
|
+
let schema;
|
|
21
|
+
let options;
|
|
22
|
+
// Parse arguments based on type
|
|
23
|
+
if (nameOrSchema === undefined) {
|
|
24
|
+
// No arguments - just inject the whole object
|
|
25
|
+
}
|
|
26
|
+
else if (typeof nameOrSchema === "string") {
|
|
27
|
+
// String argument - it's a parameter name (for query, params, headers)
|
|
28
|
+
paramName = nameOrSchema;
|
|
29
|
+
}
|
|
30
|
+
else if (typeof nameOrSchema === "function") {
|
|
31
|
+
// Function (class constructor) - it's a schema
|
|
32
|
+
schema = nameOrSchema;
|
|
33
|
+
}
|
|
34
|
+
else if (typeof nameOrSchema === "object") {
|
|
35
|
+
// Object - could be schema (Zod, etc.) or options
|
|
36
|
+
if ("group" in nameOrSchema || "partial" in nameOrSchema || "adapter" in nameOrSchema) {
|
|
37
|
+
// It's options
|
|
38
|
+
options = nameOrSchema;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// It's a schema (like Zod schema)
|
|
42
|
+
schema = nameOrSchema;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Store basic parameter metadata using existing pattern
|
|
46
|
+
const controller = target.constructor;
|
|
47
|
+
let metadataList = {};
|
|
48
|
+
if (!Reflect.hasOwnMetadata(METADATA_KEY.controllerParameter, controller)) {
|
|
49
|
+
Reflect.defineMetadata(METADATA_KEY.controllerParameter, metadataList, controller);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
metadataList = Reflect.getOwnMetadata(METADATA_KEY.controllerParameter, controller);
|
|
53
|
+
}
|
|
54
|
+
const methodName = propertyKey;
|
|
55
|
+
if (!metadataList[methodName]) {
|
|
56
|
+
metadataList[methodName] = [];
|
|
57
|
+
}
|
|
58
|
+
metadataList[methodName].unshift({
|
|
59
|
+
index: parameterIndex,
|
|
60
|
+
injectRoot: paramName === undefined,
|
|
61
|
+
parameterName: paramName,
|
|
62
|
+
type: parameterType,
|
|
63
|
+
});
|
|
64
|
+
Reflect.defineMetadata(METADATA_KEY.controllerParameter, metadataList, controller);
|
|
65
|
+
// Store validation schema metadata if provided
|
|
66
|
+
if (schema) {
|
|
67
|
+
const validationMetadata = {
|
|
68
|
+
index: parameterIndex,
|
|
69
|
+
source,
|
|
70
|
+
schema,
|
|
71
|
+
options,
|
|
72
|
+
};
|
|
73
|
+
// Get existing validation metadata for this method
|
|
74
|
+
let validationList = Reflect.getOwnMetadata(METADATA_KEY.validationSchema, controller, propertyKey) || [];
|
|
75
|
+
// Add new validation metadata
|
|
76
|
+
validationList = [...validationList, validationMetadata];
|
|
77
|
+
Reflect.defineMetadata(METADATA_KEY.validationSchema, validationList, controller, propertyKey);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Enhanced body decorator with validation support
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* // Without validation (backward compatible)
|
|
88
|
+
* @Post("/users")
|
|
89
|
+
* createUser(@body() user: CreateUserDTO) {}
|
|
90
|
+
*
|
|
91
|
+
* // With class-validator schema
|
|
92
|
+
* @Post("/users")
|
|
93
|
+
* createUser(@body(CreateUserDTO) user: CreateUserDTO) {}
|
|
94
|
+
*
|
|
95
|
+
* // With Zod schema
|
|
96
|
+
* const UserSchema = z.object({ email: z.string().email() });
|
|
97
|
+
* @Post("/users")
|
|
98
|
+
* createUser(@body(UserSchema) user: z.infer<typeof UserSchema>) {}
|
|
99
|
+
*
|
|
100
|
+
* // With validation options
|
|
101
|
+
* @Post("/users")
|
|
102
|
+
* createUser(@body({ group: "create", partial: false }) user: CreateUserDTO) {}
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export const validatedBody = createValidatedParamDecorator("body", PARAMETER_TYPE.BODY);
|
|
106
|
+
/**
|
|
107
|
+
* Enhanced query decorator with validation support
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* // Extract single query param (backward compatible)
|
|
112
|
+
* @Get("/search")
|
|
113
|
+
* search(@query("page") page: number) {}
|
|
114
|
+
*
|
|
115
|
+
* // Extract all query params with validation
|
|
116
|
+
* @Get("/search")
|
|
117
|
+
* search(@query(SearchQueryDTO) query: SearchQueryDTO) {}
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export const validatedQuery = createValidatedParamDecorator("query", PARAMETER_TYPE.QUERY);
|
|
121
|
+
/**
|
|
122
|
+
* Enhanced param decorator with validation support
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* // Extract single route param (backward compatible)
|
|
127
|
+
* @Get("/:id")
|
|
128
|
+
* getUser(@param("id") id: string) {}
|
|
129
|
+
*
|
|
130
|
+
* // Extract all route params with validation
|
|
131
|
+
* @Get("/:userId/posts/:postId")
|
|
132
|
+
* getPost(@param(RouteParamsDTO) params: RouteParamsDTO) {}
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export const validatedParam = createValidatedParamDecorator("params", PARAMETER_TYPE.PARAMS);
|
|
136
|
+
/**
|
|
137
|
+
* Enhanced headers decorator with validation support
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* // Extract single header (backward compatible)
|
|
142
|
+
* @Get("/")
|
|
143
|
+
* handle(@headers("authorization") auth: string) {}
|
|
144
|
+
*
|
|
145
|
+
* // Extract all headers with validation
|
|
146
|
+
* @Get("/")
|
|
147
|
+
* handle(@headers(RequiredHeadersDTO) headers: RequiredHeadersDTO) {}
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export const validatedHeaders = createValidatedParamDecorator("headers", PARAMETER_TYPE.HEADERS);
|
|
151
|
+
/**
|
|
152
|
+
* Get validation schema metadata for a method
|
|
153
|
+
* @param target - Controller constructor
|
|
154
|
+
* @param methodName - Method name
|
|
155
|
+
* @returns Array of validation metadata
|
|
156
|
+
*/
|
|
157
|
+
export function getValidationMetadata(target, methodName) {
|
|
158
|
+
return Reflect.getOwnMetadata(METADATA_KEY.validationSchema, target, methodName) || [];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check if a method has validation metadata
|
|
162
|
+
* @param target - Controller constructor
|
|
163
|
+
* @param methodName - Method name
|
|
164
|
+
* @returns true if validation is configured
|
|
165
|
+
*/
|
|
166
|
+
export function hasValidationMetadata(target, methodName) {
|
|
167
|
+
const metadata = getValidationMetadata(target, methodName);
|
|
168
|
+
return metadata.length > 0;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* @Validate decorator - marks a parameter for auto-validation
|
|
172
|
+
* Can be used with any parameter decorator
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```typescript
|
|
176
|
+
* @Post("/users")
|
|
177
|
+
* createUser(
|
|
178
|
+
* @Validate(CreateUserDTO)
|
|
179
|
+
* @body() user: CreateUserDTO
|
|
180
|
+
* ) {}
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export function Validate(schema, options) {
|
|
184
|
+
return function (target, propertyKey, parameterIndex) {
|
|
185
|
+
const controller = target.constructor;
|
|
186
|
+
const validationMetadata = {
|
|
187
|
+
index: parameterIndex,
|
|
188
|
+
source: "body", // Default, can be overridden by combining with @body/@query/etc
|
|
189
|
+
schema,
|
|
190
|
+
options,
|
|
191
|
+
};
|
|
192
|
+
// Get existing validation metadata for this method
|
|
193
|
+
let validationList = Reflect.getOwnMetadata(METADATA_KEY.validationSchema, controller, propertyKey) ||
|
|
194
|
+
[];
|
|
195
|
+
// Add new validation metadata
|
|
196
|
+
validationList = [...validationList, validationMetadata];
|
|
197
|
+
Reflect.defineMetadata(METADATA_KEY.validationSchema, validationList, controller, propertyKey);
|
|
198
|
+
};
|
|
199
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Service
|
|
3
|
+
* @module @expressots/adapter-express
|
|
4
|
+
*
|
|
5
|
+
* Service for validating request parameters using the Smart Validation System.
|
|
6
|
+
* Integrates with the route handler to automatically validate parameters.
|
|
7
|
+
*/
|
|
8
|
+
import { ValidationRegistry, SmartFieldDetector, HelpfulErrorFormatter, getParameterType, hasClassValidatorDecorators, detectSchemaType, ClassValidatorAdapter, } from "@expressots/core";
|
|
9
|
+
import { getValidationMetadata } from "./validation-decorators.js";
|
|
10
|
+
/**
|
|
11
|
+
* Validation Service
|
|
12
|
+
*
|
|
13
|
+
* Handles validation of request parameters (body, query, params, headers)
|
|
14
|
+
* using the configured validation adapters and smart field detection.
|
|
15
|
+
*/
|
|
16
|
+
export class ValidationService {
|
|
17
|
+
registry;
|
|
18
|
+
smartDetector;
|
|
19
|
+
errorFormatter;
|
|
20
|
+
enabled = false;
|
|
21
|
+
config = {};
|
|
22
|
+
constructor() {
|
|
23
|
+
this.registry = new ValidationRegistry();
|
|
24
|
+
this.smartDetector = new SmartFieldDetector();
|
|
25
|
+
this.errorFormatter = new HelpfulErrorFormatter();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Enable the validation service with the given configuration
|
|
29
|
+
* @param config - Validation configuration
|
|
30
|
+
*/
|
|
31
|
+
enable(config = {}) {
|
|
32
|
+
this.enabled = true;
|
|
33
|
+
this.config = config;
|
|
34
|
+
this.registry.configure(config);
|
|
35
|
+
// Register built-in adapters automatically
|
|
36
|
+
this.registerBuiltInAdapters();
|
|
37
|
+
// Set smart detection
|
|
38
|
+
if (config.smartDetection !== undefined) {
|
|
39
|
+
this.smartDetector.setEnabled(config.smartDetection);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Register built-in validation adapters
|
|
44
|
+
* Additional adapters (Zod, Yup, Joi) can be registered via config.adapters
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
registerBuiltInAdapters() {
|
|
48
|
+
// Register class-validator adapter (built-in)
|
|
49
|
+
try {
|
|
50
|
+
const classValidatorAdapter = new ClassValidatorAdapter();
|
|
51
|
+
this.registry.register(classValidatorAdapter);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// class-validator may not be installed
|
|
55
|
+
}
|
|
56
|
+
// Register user-provided adapters from config
|
|
57
|
+
if (this.config.adapters) {
|
|
58
|
+
for (const AdapterClass of this.config.adapters) {
|
|
59
|
+
try {
|
|
60
|
+
const adapter = new AdapterClass();
|
|
61
|
+
this.registry.register(adapter);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Adapter instantiation failed
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Disable the validation service
|
|
71
|
+
*/
|
|
72
|
+
disable() {
|
|
73
|
+
this.enabled = false;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if validation is enabled
|
|
77
|
+
*/
|
|
78
|
+
isEnabled() {
|
|
79
|
+
return this.enabled;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get the validation registry for adapter management
|
|
83
|
+
*/
|
|
84
|
+
getRegistry() {
|
|
85
|
+
return this.registry;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get the smart field detector
|
|
89
|
+
*/
|
|
90
|
+
getSmartDetector() {
|
|
91
|
+
return this.smartDetector;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get the error formatter
|
|
95
|
+
*/
|
|
96
|
+
getErrorFormatter() {
|
|
97
|
+
return this.errorFormatter;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Validate request parameters based on controller method metadata
|
|
101
|
+
* @param req - Express request
|
|
102
|
+
* @param res - Express response
|
|
103
|
+
* @param controllerConstructor - Controller class constructor
|
|
104
|
+
* @param methodName - Method name
|
|
105
|
+
* @param args - Current parameter values
|
|
106
|
+
* @returns Validated and transformed arguments, or null if validation failed (response sent)
|
|
107
|
+
*/
|
|
108
|
+
async validateParameters(req, res, controllerConstructor, methodName, args) {
|
|
109
|
+
if (!this.enabled) {
|
|
110
|
+
return args;
|
|
111
|
+
}
|
|
112
|
+
// Get validation metadata for the method
|
|
113
|
+
let validationMetadata = getValidationMetadata(controllerConstructor, methodName);
|
|
114
|
+
// TypeScript-First Auto-Detection: If no explicit validation schema,
|
|
115
|
+
// try to infer from TypeScript type metadata
|
|
116
|
+
if (validationMetadata.length === 0 && this.config.autoDetection !== false) {
|
|
117
|
+
validationMetadata = await this.inferValidationFromTypes(controllerConstructor, methodName, args);
|
|
118
|
+
}
|
|
119
|
+
if (validationMetadata.length === 0) {
|
|
120
|
+
// No explicit validation - try smart detection if enabled
|
|
121
|
+
if (this.smartDetector.isEnabled()) {
|
|
122
|
+
const smartErrors = await this.validateWithSmartDetection(req);
|
|
123
|
+
if (smartErrors.length > 0) {
|
|
124
|
+
this.sendValidationError(res, smartErrors);
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return args;
|
|
129
|
+
}
|
|
130
|
+
// Validate each parameter with schema
|
|
131
|
+
const validatedArgs = [...args];
|
|
132
|
+
const allErrors = [];
|
|
133
|
+
for (const metadata of validationMetadata) {
|
|
134
|
+
const paramValue = this.getParameterValue(req, metadata);
|
|
135
|
+
const result = await this.validateValue(paramValue, metadata);
|
|
136
|
+
if (!result.success) {
|
|
137
|
+
allErrors.push(...(result.errors || []));
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
// Update argument with validated/transformed data
|
|
141
|
+
validatedArgs[metadata.index] = result.data;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (allErrors.length > 0) {
|
|
145
|
+
this.sendValidationError(res, allErrors);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
return validatedArgs;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Infer validation metadata from TypeScript type information
|
|
152
|
+
* Uses reflect-metadata to get parameter types and automatically
|
|
153
|
+
* detect class-validator DTOs or Zod schemas
|
|
154
|
+
*/
|
|
155
|
+
async inferValidationFromTypes(controllerConstructor, methodName, args) {
|
|
156
|
+
const inferredMetadata = [];
|
|
157
|
+
for (let i = 0; i < args.length; i++) {
|
|
158
|
+
const typeInfo = getParameterType(controllerConstructor.prototype, methodName, i);
|
|
159
|
+
if (!typeInfo || !typeInfo.type)
|
|
160
|
+
continue;
|
|
161
|
+
const schemaType = detectSchemaType(typeInfo.type);
|
|
162
|
+
// Only infer validation for class-validator DTOs or Zod schemas
|
|
163
|
+
if (schemaType === "class-validator" || schemaType === "zod") {
|
|
164
|
+
inferredMetadata.push({
|
|
165
|
+
index: i,
|
|
166
|
+
source: "body", // Default to body for inferred types
|
|
167
|
+
schema: typeInfo.type,
|
|
168
|
+
inferred: true, // Mark as auto-inferred
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else if (schemaType === "class" && hasClassValidatorDecorators(typeInfo.type)) {
|
|
172
|
+
// Double-check for class-validator decorators
|
|
173
|
+
inferredMetadata.push({
|
|
174
|
+
index: i,
|
|
175
|
+
source: "body",
|
|
176
|
+
schema: typeInfo.type,
|
|
177
|
+
inferred: true,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return inferredMetadata;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Validate a single value against a schema
|
|
185
|
+
*/
|
|
186
|
+
async validateValue(value, metadata) {
|
|
187
|
+
if (!metadata.schema) {
|
|
188
|
+
return { success: true, data: value };
|
|
189
|
+
}
|
|
190
|
+
const result = await this.registry.validate(value, metadata.schema, {
|
|
191
|
+
...this.config.defaultOptions,
|
|
192
|
+
...metadata.options,
|
|
193
|
+
});
|
|
194
|
+
// If validation passed and smart detection is enabled, also run smart detection
|
|
195
|
+
if (result.success &&
|
|
196
|
+
this.smartDetector.isEnabled() &&
|
|
197
|
+
typeof result.data === "object" &&
|
|
198
|
+
result.data !== null) {
|
|
199
|
+
const smartErrors = this.smartDetector.validateObject(result.data);
|
|
200
|
+
if (smartErrors.length > 0) {
|
|
201
|
+
return {
|
|
202
|
+
success: false,
|
|
203
|
+
errors: smartErrors,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get the parameter value from the request
|
|
211
|
+
*/
|
|
212
|
+
getParameterValue(req, metadata) {
|
|
213
|
+
switch (metadata.source) {
|
|
214
|
+
case "body":
|
|
215
|
+
return req.body;
|
|
216
|
+
case "query":
|
|
217
|
+
return req.query;
|
|
218
|
+
case "params":
|
|
219
|
+
return req.params;
|
|
220
|
+
case "headers":
|
|
221
|
+
return req.headers;
|
|
222
|
+
default:
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Validate request data using smart field detection
|
|
228
|
+
*/
|
|
229
|
+
async validateWithSmartDetection(req) {
|
|
230
|
+
const errors = [];
|
|
231
|
+
// Validate body if present
|
|
232
|
+
if (req.body && typeof req.body === "object") {
|
|
233
|
+
const bodyErrors = this.smartDetector.validateObject(req.body);
|
|
234
|
+
errors.push(...bodyErrors);
|
|
235
|
+
}
|
|
236
|
+
// Validate query if present
|
|
237
|
+
if (req.query && typeof req.query === "object") {
|
|
238
|
+
const queryErrors = this.smartDetector.validateObject(req.query);
|
|
239
|
+
errors.push(...queryErrors);
|
|
240
|
+
}
|
|
241
|
+
return errors;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Send validation error response
|
|
245
|
+
*/
|
|
246
|
+
sendValidationError(res, errors) {
|
|
247
|
+
const format = this.config.errorFormat || "helpful";
|
|
248
|
+
const formattedErrors = this.errorFormatter.format(errors, format);
|
|
249
|
+
res.status(400).json(formattedErrors);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./express-utils/index.js";
|
|
2
|
+
export { AppExpress } from "./application-express.js";
|
|
3
|
+
export * from "./micro-api/index.js";
|
|
4
|
+
export { RenderEngine, } from "@expressots/shared";
|
|
5
|
+
export * from "./render/index.js";
|
|
6
|
+
export * from "./middleware/index.js";
|
|
7
|
+
export * from "./studio/index.js";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Container } from "@expressots/core";
|
|
2
|
+
/**
|
|
3
|
+
* Inversion of Control Container
|
|
4
|
+
* @public API
|
|
5
|
+
*/
|
|
6
|
+
export class IOC {
|
|
7
|
+
container;
|
|
8
|
+
constructor(containerOptions) {
|
|
9
|
+
this.container = new Container(containerOptions);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Add a singleton to the container
|
|
13
|
+
* @param identifierOrConcrete - The identifier or concrete class
|
|
14
|
+
* @param concrete - The concrete class if identifier is provided
|
|
15
|
+
* @public API
|
|
16
|
+
*/
|
|
17
|
+
addSingleton(concrete) {
|
|
18
|
+
this.container.bind(concrete).toSelf().inSingletonScope();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Add a transient to the container
|
|
22
|
+
* @param identifierOrConcrete - The identifier or concrete class
|
|
23
|
+
* @param concrete - The concrete class if identifier is provided
|
|
24
|
+
* @public API
|
|
25
|
+
*/
|
|
26
|
+
addTransient(concrete) {
|
|
27
|
+
this.container.bind(concrete).toSelf().inTransientScope();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Add a scoped to the container
|
|
31
|
+
* @param identifierOrConcrete - The identifier or concrete class
|
|
32
|
+
* @param concrete - The concrete class if identifier is provided
|
|
33
|
+
* @public API
|
|
34
|
+
*/
|
|
35
|
+
addScoped(concrete) {
|
|
36
|
+
this.container.bind(concrete).toSelf().inRequestScope();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get an instance from the container
|
|
40
|
+
* @param identifier - The identifier for the instance
|
|
41
|
+
* @returns The resolved instance
|
|
42
|
+
* @public API
|
|
43
|
+
*/
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
get(identifier) {
|
|
46
|
+
return this.container.get(identifier);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Logger } from "@expressots/core";
|
|
2
|
+
export class Route {
|
|
3
|
+
logger = new Logger();
|
|
4
|
+
routes = [];
|
|
5
|
+
app;
|
|
6
|
+
globalPrefix = "";
|
|
7
|
+
constructor(app) {
|
|
8
|
+
this.app = app;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Set the global route prefix
|
|
12
|
+
* @param prefix
|
|
13
|
+
* @public API
|
|
14
|
+
*/
|
|
15
|
+
setGlobalRoutePrefix(prefix) {
|
|
16
|
+
this.globalPrefix = prefix;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Define a route
|
|
20
|
+
* @param method - HTTP method
|
|
21
|
+
* @param path - Route path
|
|
22
|
+
* @param handler - Route handler
|
|
23
|
+
* @param middleware - Route middleware
|
|
24
|
+
* @public API
|
|
25
|
+
*/
|
|
26
|
+
define(method, path, handler, ...middleware) {
|
|
27
|
+
const normalizedPath = `${this.globalPrefix.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
|
|
28
|
+
this.routes.push({ method, path: normalizedPath, handler, middleware });
|
|
29
|
+
this.logger.info(`Route ${method.toUpperCase()} '${normalizedPath}' added.`, "Route");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Define a GET route
|
|
33
|
+
* @param path - Route path
|
|
34
|
+
* @param handler - Route handler
|
|
35
|
+
* @param middleware - Route middleware
|
|
36
|
+
* @public API
|
|
37
|
+
*/
|
|
38
|
+
get(path, handler, ...middleware) {
|
|
39
|
+
this.define("get", path, handler, ...middleware);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Define a POST route
|
|
43
|
+
* @param path - Route path
|
|
44
|
+
* @param handler - Route handler
|
|
45
|
+
* @param middleware - Route middleware
|
|
46
|
+
* @public API
|
|
47
|
+
*/
|
|
48
|
+
post(path, handler, ...middleware) {
|
|
49
|
+
this.define("post", path, handler, ...middleware);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Define a PUT route
|
|
53
|
+
* @param path - Route path
|
|
54
|
+
* @param handler - Route handler
|
|
55
|
+
* @param middleware - Route middleware
|
|
56
|
+
* @public API
|
|
57
|
+
*/
|
|
58
|
+
put(path, handler, ...middleware) {
|
|
59
|
+
this.define("put", path, handler, ...middleware);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Define a DELETE route
|
|
63
|
+
* @param path - Route path
|
|
64
|
+
* @param handler - Route handler
|
|
65
|
+
* @param middleware - Route middleware
|
|
66
|
+
* @public API
|
|
67
|
+
*/
|
|
68
|
+
delete(path, handler, ...middleware) {
|
|
69
|
+
this.define("delete", path, handler, ...middleware);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Define a PATCH route
|
|
73
|
+
* @param path - Route path
|
|
74
|
+
* @param handler - Route handler
|
|
75
|
+
* @param middleware - Route middleware
|
|
76
|
+
* @public API
|
|
77
|
+
*/
|
|
78
|
+
patch(path, handler, ...middleware) {
|
|
79
|
+
this.define("patch", path, handler, ...middleware);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Wrap a handler to automatically send return values as response
|
|
83
|
+
* @param handler - The original handler
|
|
84
|
+
* @returns Wrapped Express request handler
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
wrapHandler(handler) {
|
|
88
|
+
return async (req, res, next) => {
|
|
89
|
+
try {
|
|
90
|
+
const result = await handler(req, res, next);
|
|
91
|
+
// If the response has already been sent, don't send again
|
|
92
|
+
if (res.headersSent) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// If handler returned a value, send it as response
|
|
96
|
+
if (result !== undefined) {
|
|
97
|
+
if (typeof result === "string") {
|
|
98
|
+
res.send(result);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
res.json(result);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
next(error);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Apply the routes to the Express application
|
|
112
|
+
*/
|
|
113
|
+
applyRoutes() {
|
|
114
|
+
this.routes.forEach(({ method, path, handler, middleware }) => {
|
|
115
|
+
const wrappedHandler = this.wrapHandler(handler);
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
|
+
this.app[method](path, ...middleware, wrappedHandler);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get the routes
|
|
122
|
+
* @returns Array of route definitions
|
|
123
|
+
* @public API
|
|
124
|
+
*/
|
|
125
|
+
get Routes() {
|
|
126
|
+
return this.routes;
|
|
127
|
+
}
|
|
128
|
+
}
|