@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,157 @@
|
|
|
1
|
+
import { Logger, Middleware } from "@expressots/core";
|
|
2
|
+
import express from "express";
|
|
3
|
+
import { IOC } from "./application-express-micro-container.js";
|
|
4
|
+
import { Route } from "./application-express-micro-route.js";
|
|
5
|
+
class AppExpressMicro {
|
|
6
|
+
logger = new Logger();
|
|
7
|
+
app;
|
|
8
|
+
httpServer;
|
|
9
|
+
port;
|
|
10
|
+
environment;
|
|
11
|
+
container;
|
|
12
|
+
globalPrefix = "/";
|
|
13
|
+
middlewareManager;
|
|
14
|
+
routeManager;
|
|
15
|
+
/**
|
|
16
|
+
* Handle the exit of the server
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
handleExit() {
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Configure the middleware for the application
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
configureMiddleware() {
|
|
27
|
+
const sortedMiddlewarePipeline = this.middlewareManager.getMiddlewarePipeline();
|
|
28
|
+
const pipeline = sortedMiddlewarePipeline.map((entry) => entry.middleware);
|
|
29
|
+
for (const entry of pipeline) {
|
|
30
|
+
if (typeof entry === "function") {
|
|
31
|
+
this.app.use(entry);
|
|
32
|
+
}
|
|
33
|
+
else if (entry.middlewares) {
|
|
34
|
+
const { path, middlewares } = entry;
|
|
35
|
+
for (const mid of middlewares) {
|
|
36
|
+
if (path) {
|
|
37
|
+
this.app.use(path, mid);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.app.use(mid);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Set the global route prefix
|
|
48
|
+
* @param prefix - The global route prefix
|
|
49
|
+
* @public API
|
|
50
|
+
*/
|
|
51
|
+
setGlobalRoutePrefix(prefix) {
|
|
52
|
+
this.globalPrefix = prefix;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the Middleware instance
|
|
56
|
+
* @returns IMiddleware
|
|
57
|
+
* @public API
|
|
58
|
+
*/
|
|
59
|
+
get Middleware() {
|
|
60
|
+
return this.middlewareManager;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get the Route instance
|
|
64
|
+
* @returns IRoute
|
|
65
|
+
* @public API
|
|
66
|
+
*/
|
|
67
|
+
get Route() {
|
|
68
|
+
return this.routeManager;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the Container instance
|
|
72
|
+
* @returns IIOC
|
|
73
|
+
* @public API
|
|
74
|
+
*/
|
|
75
|
+
get Container() {
|
|
76
|
+
return this.container;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get the Express HTTP Server instance
|
|
80
|
+
* @returns express.Application
|
|
81
|
+
* @public API
|
|
82
|
+
*/
|
|
83
|
+
getHttpServer() {
|
|
84
|
+
return this.httpServer;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create a new instance of the Express Micro API adapter
|
|
88
|
+
* @param config - Configuration options
|
|
89
|
+
* @returns ICreateMicroAPI
|
|
90
|
+
* @public API
|
|
91
|
+
*/
|
|
92
|
+
create(config) {
|
|
93
|
+
this.app = express();
|
|
94
|
+
this.routeManager = new Route(this.app);
|
|
95
|
+
this.container = new IOC(config?.containerOptions);
|
|
96
|
+
this.middlewareManager = new Middleware();
|
|
97
|
+
this.environment = "development";
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Build the Web Server Micro API
|
|
102
|
+
* @returns IWebServerMicroAPI
|
|
103
|
+
* @public API
|
|
104
|
+
*/
|
|
105
|
+
build() {
|
|
106
|
+
this.routeManager.setGlobalRoutePrefix(this.globalPrefix);
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Listen for incoming requests
|
|
111
|
+
* @param port - The port to listen on
|
|
112
|
+
* @param appInfo - Information about the application
|
|
113
|
+
* @public API
|
|
114
|
+
*/
|
|
115
|
+
async listen(port, appInfo) {
|
|
116
|
+
const logger = new Logger();
|
|
117
|
+
const normalizedPort = typeof port === "string" ? parseInt(port, 10) : port;
|
|
118
|
+
this.configureMiddleware();
|
|
119
|
+
this.routeManager.applyRoutes();
|
|
120
|
+
if (this.Middleware.getErrorHandler()) {
|
|
121
|
+
this.app.use(this.Middleware.getErrorHandler());
|
|
122
|
+
}
|
|
123
|
+
return new Promise((resolve, reject) => {
|
|
124
|
+
this.httpServer = this.app.listen(normalizedPort, () => {
|
|
125
|
+
const address = this.httpServer.address();
|
|
126
|
+
if (typeof address === "object" && address?.port) {
|
|
127
|
+
this.port = address.port;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
this.port = normalizedPort;
|
|
131
|
+
}
|
|
132
|
+
const name = appInfo?.appName || "ExpressoTS Micro";
|
|
133
|
+
const version = appInfo?.appVersion || "1.0.0";
|
|
134
|
+
logger.info(`${name} version ${version} is running on port ${this.port} - Environment: ${this.environment}`, "micro");
|
|
135
|
+
["SIGTERM", "SIGHUP", "SIGBREAK", "SIGQUIT", "SIGINT"].forEach((signal) => {
|
|
136
|
+
process.on(signal, this.handleExit.bind(this));
|
|
137
|
+
});
|
|
138
|
+
resolve();
|
|
139
|
+
});
|
|
140
|
+
this.httpServer.on("error", (error) => {
|
|
141
|
+
logger.error(`Error starting server: ${error.message}`, "micro");
|
|
142
|
+
reject(error);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Create a new instance of the Express Micro API adapter
|
|
149
|
+
* @param config - Configuration options
|
|
150
|
+
* @returns ICreateMicroAPI
|
|
151
|
+
* @public API
|
|
152
|
+
*/
|
|
153
|
+
export function createMicroAPI(config) {
|
|
154
|
+
const microAPI = new AppExpressMicro();
|
|
155
|
+
const create = microAPI.create.bind(microAPI);
|
|
156
|
+
return create(config);
|
|
157
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CircuitBreaker - Protect against cascading failures in distributed systems.
|
|
3
|
+
*
|
|
4
|
+
* States:
|
|
5
|
+
* - CLOSED: Normal operation, requests pass through
|
|
6
|
+
* - OPEN: Requests fail immediately without calling the service
|
|
7
|
+
* - HALF_OPEN: Limited requests pass through to test if service recovered
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const circuitBreaker = new CircuitBreaker({
|
|
12
|
+
* failureThreshold: 5,
|
|
13
|
+
* timeout: 60000,
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* app.Route.get("/external-api", async (req, res) => {
|
|
17
|
+
* try {
|
|
18
|
+
* const result = await circuitBreaker.execute(async () => {
|
|
19
|
+
* return await fetch("https://external-api.com/data");
|
|
20
|
+
* });
|
|
21
|
+
* res.json(await result.json());
|
|
22
|
+
* } catch (error) {
|
|
23
|
+
* if (error.message === "Circuit breaker is OPEN") {
|
|
24
|
+
* res.status(503).json({ error: "Service temporarily unavailable" });
|
|
25
|
+
* } else {
|
|
26
|
+
* res.status(500).json({ error: error.message });
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export class CircuitBreaker {
|
|
33
|
+
state = "CLOSED";
|
|
34
|
+
failures = 0;
|
|
35
|
+
successes = 0;
|
|
36
|
+
totalSuccesses = 0;
|
|
37
|
+
totalCalls = 0;
|
|
38
|
+
lastFailure;
|
|
39
|
+
lastSuccess;
|
|
40
|
+
openedAt;
|
|
41
|
+
recentFailures = [];
|
|
42
|
+
config;
|
|
43
|
+
constructor(config) {
|
|
44
|
+
this.config = {
|
|
45
|
+
failureThreshold: config?.failureThreshold ?? 5,
|
|
46
|
+
successThreshold: config?.successThreshold ?? 2,
|
|
47
|
+
timeout: config?.timeout ?? 60000,
|
|
48
|
+
monitoringPeriod: config?.monitoringPeriod ?? 10000,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Execute a function with circuit breaker protection
|
|
53
|
+
* @param fn - Function to execute
|
|
54
|
+
* @throws Error if circuit is open
|
|
55
|
+
*/
|
|
56
|
+
async execute(fn) {
|
|
57
|
+
this.totalCalls++;
|
|
58
|
+
// Check if circuit is open
|
|
59
|
+
if (this.state === "OPEN") {
|
|
60
|
+
// Check if timeout has passed
|
|
61
|
+
if (this.shouldAttemptReset()) {
|
|
62
|
+
this.state = "HALF_OPEN";
|
|
63
|
+
this.successes = 0;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw new Error("Circuit breaker is OPEN");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const result = await fn();
|
|
71
|
+
this.onSuccess();
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
this.onFailure();
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get current circuit state
|
|
81
|
+
*/
|
|
82
|
+
getState() {
|
|
83
|
+
return this.state;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get circuit breaker statistics
|
|
87
|
+
*/
|
|
88
|
+
getStats() {
|
|
89
|
+
return {
|
|
90
|
+
state: this.state,
|
|
91
|
+
failures: this.failures,
|
|
92
|
+
successes: this.totalSuccesses,
|
|
93
|
+
totalCalls: this.totalCalls,
|
|
94
|
+
lastFailure: this.lastFailure,
|
|
95
|
+
lastSuccess: this.lastSuccess,
|
|
96
|
+
openedAt: this.openedAt,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Manually reset the circuit breaker
|
|
101
|
+
*/
|
|
102
|
+
reset() {
|
|
103
|
+
this.state = "CLOSED";
|
|
104
|
+
this.failures = 0;
|
|
105
|
+
this.successes = 0;
|
|
106
|
+
this.totalSuccesses = 0;
|
|
107
|
+
this.recentFailures = [];
|
|
108
|
+
this.openedAt = undefined;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Manually open the circuit
|
|
112
|
+
*/
|
|
113
|
+
open() {
|
|
114
|
+
this.state = "OPEN";
|
|
115
|
+
this.openedAt = new Date();
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Handle successful call
|
|
119
|
+
*/
|
|
120
|
+
onSuccess() {
|
|
121
|
+
this.totalSuccesses++;
|
|
122
|
+
this.lastSuccess = new Date();
|
|
123
|
+
if (this.state === "HALF_OPEN") {
|
|
124
|
+
this.successes++;
|
|
125
|
+
if (this.successes >= this.config.successThreshold) {
|
|
126
|
+
this.state = "CLOSED";
|
|
127
|
+
this.failures = 0;
|
|
128
|
+
this.recentFailures = [];
|
|
129
|
+
this.openedAt = undefined;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else if (this.state === "CLOSED") {
|
|
133
|
+
// Clear old failures outside monitoring period
|
|
134
|
+
this.cleanupRecentFailures();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Handle failed call
|
|
139
|
+
*/
|
|
140
|
+
onFailure() {
|
|
141
|
+
this.failures++;
|
|
142
|
+
this.lastFailure = new Date();
|
|
143
|
+
this.recentFailures.push(this.lastFailure);
|
|
144
|
+
if (this.state === "HALF_OPEN") {
|
|
145
|
+
// Any failure in half-open state reopens the circuit
|
|
146
|
+
this.state = "OPEN";
|
|
147
|
+
this.openedAt = new Date();
|
|
148
|
+
this.successes = 0;
|
|
149
|
+
}
|
|
150
|
+
else if (this.state === "CLOSED") {
|
|
151
|
+
this.cleanupRecentFailures();
|
|
152
|
+
// Check if we've hit the failure threshold
|
|
153
|
+
if (this.recentFailures.length >= this.config.failureThreshold) {
|
|
154
|
+
this.state = "OPEN";
|
|
155
|
+
this.openedAt = new Date();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Check if timeout has passed and we should try to reset
|
|
161
|
+
*/
|
|
162
|
+
shouldAttemptReset() {
|
|
163
|
+
if (!this.openedAt)
|
|
164
|
+
return true;
|
|
165
|
+
return Date.now() - this.openedAt.getTime() >= this.config.timeout;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Remove failures outside the monitoring period
|
|
169
|
+
*/
|
|
170
|
+
cleanupRecentFailures() {
|
|
171
|
+
const cutoff = Date.now() - this.config.monitoringPeriod;
|
|
172
|
+
this.recentFailures = this.recentFailures.filter((date) => date.getTime() > cutoff);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { CircuitBreaker } from "./circuit-breaker.js";
|
|
2
|
+
/**
|
|
3
|
+
* ServiceProxy - Proxy requests to other microservices.
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Automatic request forwarding
|
|
7
|
+
* - Path rewriting
|
|
8
|
+
* - Custom headers
|
|
9
|
+
* - Request timeout
|
|
10
|
+
* - Retry support
|
|
11
|
+
* - Optional circuit breaker integration
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Proxy to user service
|
|
16
|
+
* const userProxy = createProxy({
|
|
17
|
+
* target: "http://user-service:3001",
|
|
18
|
+
* pathRewrite: (path) => path.replace("/api/users", ""),
|
|
19
|
+
* timeout: 5000,
|
|
20
|
+
* retries: 3,
|
|
21
|
+
* circuitBreaker: true,
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* app.Route.get("/api/users/*", userProxy.handler());
|
|
25
|
+
* app.Route.post("/api/users/*", userProxy.handler());
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class ServiceProxy {
|
|
29
|
+
config;
|
|
30
|
+
constructor(config) {
|
|
31
|
+
this.config = {
|
|
32
|
+
target: config.target,
|
|
33
|
+
timeout: config.timeout ?? 30000,
|
|
34
|
+
retries: config.retries ?? 0,
|
|
35
|
+
headers: config.headers ?? {},
|
|
36
|
+
pathRewrite: config.pathRewrite ?? ((path) => path),
|
|
37
|
+
debug: config.debug ?? false,
|
|
38
|
+
};
|
|
39
|
+
// Initialize circuit breaker if enabled
|
|
40
|
+
if (config.circuitBreaker) {
|
|
41
|
+
const cbConfig = typeof config.circuitBreaker === "object" ? config.circuitBreaker : undefined;
|
|
42
|
+
this.config.circuitBreaker = new CircuitBreaker(cbConfig);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create an Express handler for proxying requests
|
|
47
|
+
*/
|
|
48
|
+
handler() {
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
50
|
+
return async (req, res, _next) => {
|
|
51
|
+
try {
|
|
52
|
+
const result = await this.proxyRequest(req);
|
|
53
|
+
// Copy status and headers
|
|
54
|
+
res.status(result.status);
|
|
55
|
+
result.headers.forEach((value, key) => {
|
|
56
|
+
// Skip certain headers
|
|
57
|
+
if (!["content-encoding", "transfer-encoding"].includes(key.toLowerCase())) {
|
|
58
|
+
res.setHeader(key, value);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// Send body
|
|
62
|
+
const body = await result.text();
|
|
63
|
+
res.send(body);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
67
|
+
if (this.config.debug) {
|
|
68
|
+
console.error(`[Proxy] Error:`, errorMessage);
|
|
69
|
+
}
|
|
70
|
+
if (errorMessage === "Circuit breaker is OPEN") {
|
|
71
|
+
res.status(503).json({
|
|
72
|
+
error: "Service temporarily unavailable",
|
|
73
|
+
service: this.config.target,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
else if (error instanceof Error && error.name === "AbortError") {
|
|
77
|
+
res.status(504).json({
|
|
78
|
+
error: "Gateway timeout",
|
|
79
|
+
service: this.config.target,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
res.status(502).json({
|
|
84
|
+
error: "Bad gateway",
|
|
85
|
+
message: errorMessage,
|
|
86
|
+
service: this.config.target,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Proxy a request to the target service
|
|
94
|
+
*/
|
|
95
|
+
async proxyRequest(req) {
|
|
96
|
+
const execute = async () => {
|
|
97
|
+
return await this.executeWithRetry(req);
|
|
98
|
+
};
|
|
99
|
+
if (this.config.circuitBreaker) {
|
|
100
|
+
return await this.config.circuitBreaker.execute(execute);
|
|
101
|
+
}
|
|
102
|
+
return await execute();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Execute request with retry logic
|
|
106
|
+
*/
|
|
107
|
+
async executeWithRetry(req, attempt = 0) {
|
|
108
|
+
try {
|
|
109
|
+
return await this.executeRequest(req);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (attempt < this.config.retries) {
|
|
113
|
+
// Exponential backoff
|
|
114
|
+
await this.delay(Math.pow(2, attempt) * 100);
|
|
115
|
+
return await this.executeWithRetry(req, attempt + 1);
|
|
116
|
+
}
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Execute a single request
|
|
122
|
+
*/
|
|
123
|
+
async executeRequest(req) {
|
|
124
|
+
// Rewrite path if configured
|
|
125
|
+
const path = this.config.pathRewrite(req.path);
|
|
126
|
+
const url = new URL(path, this.config.target);
|
|
127
|
+
// Copy query parameters
|
|
128
|
+
Object.entries(req.query).forEach(([key, value]) => {
|
|
129
|
+
if (typeof value === "string") {
|
|
130
|
+
url.searchParams.append(key, value);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
// Build headers
|
|
134
|
+
const headers = {
|
|
135
|
+
...this.extractHeaders(req),
|
|
136
|
+
...this.config.headers,
|
|
137
|
+
};
|
|
138
|
+
// Build request options
|
|
139
|
+
const controller = new AbortController();
|
|
140
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
141
|
+
const requestInit = {
|
|
142
|
+
method: req.method,
|
|
143
|
+
headers,
|
|
144
|
+
signal: controller.signal,
|
|
145
|
+
};
|
|
146
|
+
// Add body for non-GET requests
|
|
147
|
+
if (req.method !== "GET" && req.method !== "HEAD" && req.body) {
|
|
148
|
+
requestInit.body = JSON.stringify(req.body);
|
|
149
|
+
headers["content-type"] = "application/json";
|
|
150
|
+
}
|
|
151
|
+
if (this.config.debug) {
|
|
152
|
+
console.log(`[Proxy] ${req.method} ${url.toString()}`);
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const response = await fetch(url.toString(), requestInit);
|
|
156
|
+
clearTimeout(timeoutId);
|
|
157
|
+
// Cast to ProxyResponse to avoid conflict with Express Response type
|
|
158
|
+
return response;
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
clearTimeout(timeoutId);
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Extract relevant headers from incoming request
|
|
167
|
+
*/
|
|
168
|
+
extractHeaders(req) {
|
|
169
|
+
const headers = {};
|
|
170
|
+
const forwardHeaders = [
|
|
171
|
+
"authorization",
|
|
172
|
+
"content-type",
|
|
173
|
+
"accept",
|
|
174
|
+
"user-agent",
|
|
175
|
+
"x-request-id",
|
|
176
|
+
"x-trace-id",
|
|
177
|
+
"x-span-id",
|
|
178
|
+
"x-correlation-id",
|
|
179
|
+
];
|
|
180
|
+
forwardHeaders.forEach((header) => {
|
|
181
|
+
const value = req.headers[header];
|
|
182
|
+
if (typeof value === "string") {
|
|
183
|
+
headers[header] = value;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
// Add X-Forwarded headers
|
|
187
|
+
headers["x-forwarded-for"] = req.ip || req.socket.remoteAddress || "unknown";
|
|
188
|
+
headers["x-forwarded-host"] = req.headers.host || "";
|
|
189
|
+
headers["x-forwarded-proto"] = req.protocol;
|
|
190
|
+
return headers;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Delay helper
|
|
194
|
+
*/
|
|
195
|
+
delay(ms) {
|
|
196
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get circuit breaker stats (if enabled)
|
|
200
|
+
*/
|
|
201
|
+
getCircuitBreakerStats() {
|
|
202
|
+
return this.config.circuitBreaker?.getStats();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Create a new service proxy
|
|
207
|
+
*/
|
|
208
|
+
export function createProxy(config) {
|
|
209
|
+
return new ServiceProxy(config);
|
|
210
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Primary API - pure simplicity
|
|
2
|
+
export { micro } from "./micro.js";
|
|
3
|
+
// Advanced features - import separately when needed
|
|
4
|
+
export * from "./gateway/index.js"; // CircuitBreaker, ServiceProxy
|
|
5
|
+
export * from "./service-mesh/index.js"; // ServiceDiscovery, ServiceClient
|
|
6
|
+
export * from "./serverless/index.js"; // Lambda, Cloudflare, Vercel adapters
|
|
7
|
+
export * from "./queue/index.js"; // RabbitMQ consumer
|
|
8
|
+
// Legacy API - deprecated, will be removed in v6
|
|
9
|
+
/** @deprecated Use micro() instead */
|
|
10
|
+
export { createMicroAPI } from "./application-express-micro.js";
|