@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,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AWS Lambda Adapter for ExpressoTS Micro API
|
|
4
|
+
*
|
|
5
|
+
* Converts Lambda events to Express requests and responses.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.awsLambdaAdapter = awsLambdaAdapter;
|
|
9
|
+
/**
|
|
10
|
+
* Create an AWS Lambda handler from an Express app
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { createMicroAPI, awsLambdaAdapter } from "@expressots/adapter-express";
|
|
15
|
+
*
|
|
16
|
+
* const microAPI = createMicroAPI();
|
|
17
|
+
* const app = microAPI.build();
|
|
18
|
+
*
|
|
19
|
+
* app.Middleware.parse();
|
|
20
|
+
* app.Route.get("/", (req, res) => res.json({ message: "Hello Lambda!" }));
|
|
21
|
+
*
|
|
22
|
+
* export const handler = awsLambdaAdapter(app);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
function awsLambdaAdapter(app, config) {
|
|
26
|
+
const expressApp = "getExpressApp" in app && app.getExpressApp ? app.getExpressApp() : app;
|
|
27
|
+
const binaryTypes = config?.binaryContentTypes ?? [
|
|
28
|
+
"application/octet-stream",
|
|
29
|
+
"image/*",
|
|
30
|
+
"audio/*",
|
|
31
|
+
"video/*",
|
|
32
|
+
"font/*",
|
|
33
|
+
];
|
|
34
|
+
const debug = config?.debug ?? false;
|
|
35
|
+
return async (event, context) => {
|
|
36
|
+
if (debug) {
|
|
37
|
+
console.log("[Lambda] Event:", JSON.stringify(event, null, 2));
|
|
38
|
+
}
|
|
39
|
+
// Parse body
|
|
40
|
+
let body;
|
|
41
|
+
if (event.body) {
|
|
42
|
+
let rawBody;
|
|
43
|
+
if (event.isBase64Encoded) {
|
|
44
|
+
rawBody = Buffer.from(event.body, "base64");
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
rawBody = event.body;
|
|
48
|
+
}
|
|
49
|
+
// Parse JSON body if content-type is application/json
|
|
50
|
+
const contentType = event.headers?.["content-type"] || event.headers?.["Content-Type"] || "";
|
|
51
|
+
if (contentType.includes("application/json")) {
|
|
52
|
+
try {
|
|
53
|
+
const bodyStr = Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : rawBody;
|
|
54
|
+
body = JSON.parse(bodyStr);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Keep as raw if JSON parsing fails
|
|
58
|
+
body = rawBody;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
body = rawBody;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Build request URL
|
|
66
|
+
const queryString = event.queryStringParameters
|
|
67
|
+
? "?" +
|
|
68
|
+
Object.entries(event.queryStringParameters)
|
|
69
|
+
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
|
|
70
|
+
.join("&")
|
|
71
|
+
: "";
|
|
72
|
+
const url = event.path + queryString;
|
|
73
|
+
// Build headers
|
|
74
|
+
const headers = {
|
|
75
|
+
...event.headers,
|
|
76
|
+
};
|
|
77
|
+
// Add Lambda context to headers
|
|
78
|
+
headers["x-lambda-request-id"] = context.awsRequestId;
|
|
79
|
+
headers["x-lambda-function"] = context.functionName;
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
81
|
+
return new Promise((resolve, _reject) => {
|
|
82
|
+
// Create mock Express-compatible request object
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
const req = {
|
|
85
|
+
method: event.httpMethod,
|
|
86
|
+
url,
|
|
87
|
+
path: event.path,
|
|
88
|
+
headers,
|
|
89
|
+
body,
|
|
90
|
+
query: event.queryStringParameters || {},
|
|
91
|
+
params: {},
|
|
92
|
+
lambda: { event, context },
|
|
93
|
+
get: (name) => headers[name.toLowerCase()],
|
|
94
|
+
};
|
|
95
|
+
// Create mock Express-compatible response object
|
|
96
|
+
const chunks = [];
|
|
97
|
+
const responseHeaders = {};
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
const res = {
|
|
100
|
+
statusCode: 200,
|
|
101
|
+
setHeader: (name, value) => {
|
|
102
|
+
responseHeaders[name.toLowerCase()] = value;
|
|
103
|
+
},
|
|
104
|
+
getHeader: (name) => responseHeaders[name.toLowerCase()],
|
|
105
|
+
write: (chunk) => {
|
|
106
|
+
chunks.push(Buffer.from(chunk));
|
|
107
|
+
},
|
|
108
|
+
end: (chunk) => {
|
|
109
|
+
if (chunk) {
|
|
110
|
+
chunks.push(Buffer.from(chunk));
|
|
111
|
+
}
|
|
112
|
+
const bodyBuffer = Buffer.concat(chunks);
|
|
113
|
+
const contentType = responseHeaders["content-type"] || "";
|
|
114
|
+
const isBinary = binaryTypes.some((type) => {
|
|
115
|
+
if (type.endsWith("/*")) {
|
|
116
|
+
return contentType.startsWith(type.replace("/*", "/"));
|
|
117
|
+
}
|
|
118
|
+
return contentType === type;
|
|
119
|
+
});
|
|
120
|
+
const response = {
|
|
121
|
+
statusCode: res.statusCode,
|
|
122
|
+
headers: responseHeaders,
|
|
123
|
+
body: isBinary ? bodyBuffer.toString("base64") : bodyBuffer.toString("utf8"),
|
|
124
|
+
isBase64Encoded: isBinary,
|
|
125
|
+
};
|
|
126
|
+
if (debug) {
|
|
127
|
+
console.log("[Lambda] Response:", {
|
|
128
|
+
statusCode: response.statusCode,
|
|
129
|
+
headers: response.headers,
|
|
130
|
+
bodyLength: response.body.length,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
resolve(response);
|
|
134
|
+
},
|
|
135
|
+
status: (code) => {
|
|
136
|
+
res.statusCode = code;
|
|
137
|
+
return res;
|
|
138
|
+
},
|
|
139
|
+
json: (data) => {
|
|
140
|
+
res.setHeader("content-type", "application/json");
|
|
141
|
+
res.end(JSON.stringify(data));
|
|
142
|
+
},
|
|
143
|
+
send: (data) => {
|
|
144
|
+
if (typeof data === "string") {
|
|
145
|
+
res.setHeader("content-type", "text/html");
|
|
146
|
+
res.end(data);
|
|
147
|
+
}
|
|
148
|
+
else if (Buffer.isBuffer(data)) {
|
|
149
|
+
res.end(data);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
res.json(data);
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
// Handle request through Express
|
|
157
|
+
try {
|
|
158
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
159
|
+
expressApp(req, res, (err) => {
|
|
160
|
+
if (err) {
|
|
161
|
+
console.error("[Lambda] Express error:", err);
|
|
162
|
+
resolve({
|
|
163
|
+
statusCode: 500,
|
|
164
|
+
headers: { "content-type": "application/json" },
|
|
165
|
+
body: JSON.stringify({ error: err.message }),
|
|
166
|
+
isBase64Encoded: false,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
173
|
+
console.error("[Lambda] Handler error:", error);
|
|
174
|
+
resolve({
|
|
175
|
+
statusCode: 500,
|
|
176
|
+
headers: { "content-type": "application/json" },
|
|
177
|
+
body: JSON.stringify({ error: errorMessage }),
|
|
178
|
+
isBase64Encoded: false,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cloudflare Workers Adapter for ExpressoTS Micro API
|
|
4
|
+
*
|
|
5
|
+
* Converts Cloudflare Workers requests to Express format.
|
|
6
|
+
* Note: This adapter requires a Cloudflare Workers-compatible Express implementation
|
|
7
|
+
* or uses a fetch-based approach.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.cloudflareAdapter = cloudflareAdapter;
|
|
11
|
+
/**
|
|
12
|
+
* Create a Cloudflare Workers handler from an Express app
|
|
13
|
+
*
|
|
14
|
+
* Note: Full Express compatibility in Cloudflare Workers requires
|
|
15
|
+
* additional setup. This adapter provides a basic implementation.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // src/worker.ts
|
|
20
|
+
* import { createMicroAPI, cloudflareAdapter } from "@expressots/adapter-express";
|
|
21
|
+
*
|
|
22
|
+
* const microAPI = createMicroAPI();
|
|
23
|
+
* const app = microAPI.build();
|
|
24
|
+
*
|
|
25
|
+
* app.Middleware.parse();
|
|
26
|
+
* app.Route.get("/", (req, res) => res.json({ message: "Hello Workers!" }));
|
|
27
|
+
*
|
|
28
|
+
* export default cloudflareAdapter(app);
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* wrangler.toml:
|
|
32
|
+
* ```toml
|
|
33
|
+
* name = "my-worker"
|
|
34
|
+
* main = "src/worker.ts"
|
|
35
|
+
* compatibility_date = "2024-01-01"
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function cloudflareAdapter(app, config) {
|
|
39
|
+
const expressApp = "getExpressApp" in app && app.getExpressApp ? app.getExpressApp() : app;
|
|
40
|
+
const debug = config?.debug ?? false;
|
|
41
|
+
return {
|
|
42
|
+
async fetch(request, env, ctx) {
|
|
43
|
+
const url = new URL(request.url);
|
|
44
|
+
if (debug) {
|
|
45
|
+
console.log("[Cloudflare] Request:", {
|
|
46
|
+
method: request.method,
|
|
47
|
+
url: request.url,
|
|
48
|
+
path: url.pathname,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Parse body if present
|
|
52
|
+
let body;
|
|
53
|
+
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
54
|
+
body = await request.text();
|
|
55
|
+
}
|
|
56
|
+
// Build query parameters
|
|
57
|
+
const query = {};
|
|
58
|
+
url.searchParams.forEach((value, key) => {
|
|
59
|
+
query[key] = value;
|
|
60
|
+
});
|
|
61
|
+
// Build headers
|
|
62
|
+
const headers = {};
|
|
63
|
+
request.headers.forEach((value, key) => {
|
|
64
|
+
headers[key.toLowerCase()] = value;
|
|
65
|
+
});
|
|
66
|
+
return new Promise((resolve) => {
|
|
67
|
+
// Create mock Express-compatible request object
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
const req = {
|
|
70
|
+
method: request.method,
|
|
71
|
+
url: url.pathname + url.search,
|
|
72
|
+
path: url.pathname,
|
|
73
|
+
headers,
|
|
74
|
+
query,
|
|
75
|
+
params: {},
|
|
76
|
+
body: body ? JSON.parse(body) : undefined,
|
|
77
|
+
get: (name) => headers[name.toLowerCase()],
|
|
78
|
+
cloudflare: { env, ctx },
|
|
79
|
+
};
|
|
80
|
+
// Create mock Express-compatible response object
|
|
81
|
+
const chunks = [];
|
|
82
|
+
const responseHeaders = {};
|
|
83
|
+
let statusCode = 200;
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
+
const res = {
|
|
86
|
+
statusCode: 200,
|
|
87
|
+
setHeader: (name, value) => {
|
|
88
|
+
responseHeaders[name.toLowerCase()] = value;
|
|
89
|
+
},
|
|
90
|
+
getHeader: (name) => responseHeaders[name.toLowerCase()],
|
|
91
|
+
write: (chunk) => {
|
|
92
|
+
chunks.push(Buffer.from(chunk));
|
|
93
|
+
},
|
|
94
|
+
end: (chunk) => {
|
|
95
|
+
if (chunk) {
|
|
96
|
+
chunks.push(Buffer.from(chunk));
|
|
97
|
+
}
|
|
98
|
+
const bodyBuffer = Buffer.concat(chunks);
|
|
99
|
+
if (debug) {
|
|
100
|
+
console.log("[Cloudflare] Response:", {
|
|
101
|
+
statusCode,
|
|
102
|
+
headers: responseHeaders,
|
|
103
|
+
bodyLength: bodyBuffer.length,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
resolve(new globalThis.Response(bodyBuffer, {
|
|
107
|
+
status: statusCode,
|
|
108
|
+
headers: responseHeaders,
|
|
109
|
+
}));
|
|
110
|
+
},
|
|
111
|
+
status: (code) => {
|
|
112
|
+
statusCode = code;
|
|
113
|
+
return res;
|
|
114
|
+
},
|
|
115
|
+
json: (data) => {
|
|
116
|
+
res.setHeader("content-type", "application/json");
|
|
117
|
+
res.end(JSON.stringify(data));
|
|
118
|
+
},
|
|
119
|
+
send: (data) => {
|
|
120
|
+
if (typeof data === "string") {
|
|
121
|
+
res.setHeader("content-type", "text/html");
|
|
122
|
+
res.end(data);
|
|
123
|
+
}
|
|
124
|
+
else if (Buffer.isBuffer(data)) {
|
|
125
|
+
res.end(data);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
res.json(data);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
// Handle request through Express
|
|
133
|
+
try {
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
135
|
+
expressApp(req, res, (err) => {
|
|
136
|
+
if (err) {
|
|
137
|
+
console.error("[Cloudflare] Express error:", err);
|
|
138
|
+
resolve(new globalThis.Response(JSON.stringify({ error: err.message }), {
|
|
139
|
+
status: 500,
|
|
140
|
+
headers: {
|
|
141
|
+
"content-type": "application/json",
|
|
142
|
+
},
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
149
|
+
console.error("[Cloudflare] Handler error:", error);
|
|
150
|
+
resolve(new globalThis.Response(JSON.stringify({ error: errorMessage }), {
|
|
151
|
+
status: 500,
|
|
152
|
+
headers: { "content-type": "application/json" },
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Serverless Adapters for ExpressoTS Micro Template
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.cloudflareAdapter = exports.vercelAdapter = exports.awsLambdaAdapter = void 0;
|
|
7
|
+
var aws_lambda_adapter_js_1 = require("./aws-lambda.adapter.js");
|
|
8
|
+
Object.defineProperty(exports, "awsLambdaAdapter", { enumerable: true, get: function () { return aws_lambda_adapter_js_1.awsLambdaAdapter; } });
|
|
9
|
+
var vercel_adapter_js_1 = require("./vercel.adapter.js");
|
|
10
|
+
Object.defineProperty(exports, "vercelAdapter", { enumerable: true, get: function () { return vercel_adapter_js_1.vercelAdapter; } });
|
|
11
|
+
var cloudflare_adapter_js_1 = require("./cloudflare.adapter.js");
|
|
12
|
+
Object.defineProperty(exports, "cloudflareAdapter", { enumerable: true, get: function () { return cloudflare_adapter_js_1.cloudflareAdapter; } });
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Vercel Adapter for ExpressoTS Micro API
|
|
4
|
+
*
|
|
5
|
+
* Converts Vercel serverless function requests to Express format.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.vercelAdapter = vercelAdapter;
|
|
9
|
+
/**
|
|
10
|
+
* Create a Vercel serverless handler from an Express app
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // api/index.ts
|
|
15
|
+
* import { createMicroAPI, vercelAdapter } from "@expressots/adapter-express";
|
|
16
|
+
*
|
|
17
|
+
* const microAPI = createMicroAPI();
|
|
18
|
+
* const app = microAPI.build();
|
|
19
|
+
*
|
|
20
|
+
* app.Middleware.parse();
|
|
21
|
+
* app.Route.get("/api", (req, res) => res.json({ message: "Hello Vercel!" }));
|
|
22
|
+
*
|
|
23
|
+
* export default vercelAdapter(app);
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* vercel.json:
|
|
27
|
+
* ```json
|
|
28
|
+
* {
|
|
29
|
+
* "rewrites": [{ "source": "/api/(.*)", "destination": "/api" }]
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
function vercelAdapter(app, config) {
|
|
34
|
+
const expressApp = "getExpressApp" in app && app.getExpressApp ? app.getExpressApp() : app;
|
|
35
|
+
const debug = config?.debug ?? false;
|
|
36
|
+
return async (req, res) => {
|
|
37
|
+
if (debug) {
|
|
38
|
+
console.log("[Vercel] Request:", {
|
|
39
|
+
method: req.method,
|
|
40
|
+
url: req.url,
|
|
41
|
+
query: req.query,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// Vercel passes the request directly to Express
|
|
45
|
+
// We just need to handle the response properly
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const originalEnd = res.end.bind(res);
|
|
48
|
+
// Override end to resolve the promise when response is complete
|
|
49
|
+
// Using 'any' to avoid complex Express Response type conflicts
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
+
res.end = function (chunk, encoding, callback) {
|
|
52
|
+
if (debug) {
|
|
53
|
+
console.log("[Vercel] Response:", {
|
|
54
|
+
statusCode: res.statusCode,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// Call original end with proper typing
|
|
58
|
+
if (typeof chunk === "function") {
|
|
59
|
+
originalEnd();
|
|
60
|
+
chunk();
|
|
61
|
+
}
|
|
62
|
+
else if (typeof encoding === "function") {
|
|
63
|
+
originalEnd(chunk);
|
|
64
|
+
encoding();
|
|
65
|
+
}
|
|
66
|
+
else if (callback) {
|
|
67
|
+
originalEnd(chunk, encoding, callback);
|
|
68
|
+
}
|
|
69
|
+
else if (encoding) {
|
|
70
|
+
originalEnd(chunk, encoding);
|
|
71
|
+
}
|
|
72
|
+
else if (chunk) {
|
|
73
|
+
originalEnd(chunk);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
originalEnd();
|
|
77
|
+
}
|
|
78
|
+
resolve();
|
|
79
|
+
return this;
|
|
80
|
+
};
|
|
81
|
+
// Handle request through Express
|
|
82
|
+
try {
|
|
83
|
+
expressApp(req, res, (err) => {
|
|
84
|
+
if (err) {
|
|
85
|
+
console.error("[Vercel] Express error:", err);
|
|
86
|
+
res.status(500).json({
|
|
87
|
+
error: err instanceof Error ? err.message : "Unknown error",
|
|
88
|
+
});
|
|
89
|
+
resolve();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error("[Vercel] Handler error:", error);
|
|
95
|
+
res.status(500).json({
|
|
96
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
97
|
+
});
|
|
98
|
+
resolve();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Service Mesh Utilities for ExpressoTS Micro Template
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ServiceDiscovery = exports.ServiceClient = void 0;
|
|
7
|
+
var service_client_js_1 = require("./service-client.js");
|
|
8
|
+
Object.defineProperty(exports, "ServiceClient", { enumerable: true, get: function () { return service_client_js_1.ServiceClient; } });
|
|
9
|
+
var service_discovery_js_1 = require("./service-discovery.js");
|
|
10
|
+
Object.defineProperty(exports, "ServiceDiscovery", { enumerable: true, get: function () { return service_discovery_js_1.ServiceDiscovery; } });
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ServiceClient = void 0;
|
|
4
|
+
const circuit_breaker_js_1 = require("../gateway/circuit-breaker.js");
|
|
5
|
+
/**
|
|
6
|
+
* ServiceClient - HTTP client for service-to-service communication.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Automatic retries with exponential backoff
|
|
10
|
+
* - Circuit breaker integration
|
|
11
|
+
* - Request timeout
|
|
12
|
+
* - JSON request/response handling
|
|
13
|
+
* - Trace context propagation
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const userService = new ServiceClient({
|
|
18
|
+
* name: "user-service",
|
|
19
|
+
* baseUrl: "http://user-service:3001",
|
|
20
|
+
* timeout: 5000,
|
|
21
|
+
* retries: 3,
|
|
22
|
+
* circuitBreaker: true,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // GET request
|
|
26
|
+
* const user = await userService.call<User>("/users/123");
|
|
27
|
+
*
|
|
28
|
+
* // POST request
|
|
29
|
+
* const newUser = await userService.call<User>("/users", {
|
|
30
|
+
* method: "POST",
|
|
31
|
+
* body: { name: "John", email: "john@example.com" },
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // With query parameters
|
|
35
|
+
* const users = await userService.call<User[]>("/users", {
|
|
36
|
+
* params: { page: "1", limit: "10" },
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
class ServiceClient {
|
|
41
|
+
constructor(config) {
|
|
42
|
+
this.stats = {
|
|
43
|
+
totalRequests: 0,
|
|
44
|
+
successfulRequests: 0,
|
|
45
|
+
failedRequests: 0,
|
|
46
|
+
};
|
|
47
|
+
this.config = {
|
|
48
|
+
name: config.name,
|
|
49
|
+
baseUrl: config.baseUrl.replace(/\/$/, ""), // Remove trailing slash
|
|
50
|
+
timeout: config.timeout ?? 5000,
|
|
51
|
+
retries: config.retries ?? 3,
|
|
52
|
+
headers: config.headers ?? {},
|
|
53
|
+
};
|
|
54
|
+
// Initialize circuit breaker
|
|
55
|
+
if (config.circuitBreaker !== false) {
|
|
56
|
+
const cbConfig = typeof config.circuitBreaker === "object" ? config.circuitBreaker : undefined;
|
|
57
|
+
this.config.circuitBreaker = new circuit_breaker_js_1.CircuitBreaker(cbConfig);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Make a request to the service
|
|
62
|
+
* @param path - Request path
|
|
63
|
+
* @param options - Request options
|
|
64
|
+
*/
|
|
65
|
+
async call(path, options = {}) {
|
|
66
|
+
this.stats.totalRequests++;
|
|
67
|
+
const execute = async () => {
|
|
68
|
+
return await this.executeWithRetry(path, options);
|
|
69
|
+
};
|
|
70
|
+
try {
|
|
71
|
+
let result;
|
|
72
|
+
if (this.config.circuitBreaker) {
|
|
73
|
+
result = await this.config.circuitBreaker.execute(execute);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
result = await execute();
|
|
77
|
+
}
|
|
78
|
+
this.stats.successfulRequests++;
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
this.stats.failedRequests++;
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* GET request helper
|
|
88
|
+
*/
|
|
89
|
+
async get(path, options) {
|
|
90
|
+
return this.call(path, { ...options, method: "GET" });
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* POST request helper
|
|
94
|
+
*/
|
|
95
|
+
async post(path, body, options) {
|
|
96
|
+
return this.call(path, { ...options, method: "POST", body });
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* PUT request helper
|
|
100
|
+
*/
|
|
101
|
+
async put(path, body, options) {
|
|
102
|
+
return this.call(path, { ...options, method: "PUT", body });
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* PATCH request helper
|
|
106
|
+
*/
|
|
107
|
+
async patch(path, body, options) {
|
|
108
|
+
return this.call(path, { ...options, method: "PATCH", body });
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* DELETE request helper
|
|
112
|
+
*/
|
|
113
|
+
async delete(path, options) {
|
|
114
|
+
return this.call(path, { ...options, method: "DELETE" });
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get service stats
|
|
118
|
+
*/
|
|
119
|
+
getStats() {
|
|
120
|
+
return {
|
|
121
|
+
name: this.config.name,
|
|
122
|
+
baseUrl: this.config.baseUrl,
|
|
123
|
+
...this.stats,
|
|
124
|
+
circuitBreaker: this.config.circuitBreaker?.getStats(),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Execute request with retry logic
|
|
129
|
+
*/
|
|
130
|
+
async executeWithRetry(path, options, attempt = 1) {
|
|
131
|
+
try {
|
|
132
|
+
return await this.executeRequest(path, options);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (attempt < this.config.retries) {
|
|
136
|
+
// Exponential backoff
|
|
137
|
+
await this.delay(Math.pow(2, attempt) * 100);
|
|
138
|
+
return await this.executeWithRetry(path, options, attempt + 1);
|
|
139
|
+
}
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Execute a single request
|
|
145
|
+
*/
|
|
146
|
+
async executeRequest(path, options) {
|
|
147
|
+
// Build URL
|
|
148
|
+
const url = new URL(path, this.config.baseUrl);
|
|
149
|
+
// Add query parameters
|
|
150
|
+
if (options.params) {
|
|
151
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
152
|
+
url.searchParams.append(key, value);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Build headers
|
|
156
|
+
const headers = {
|
|
157
|
+
"Content-Type": "application/json",
|
|
158
|
+
Accept: "application/json",
|
|
159
|
+
...this.config.headers,
|
|
160
|
+
...options.headers,
|
|
161
|
+
};
|
|
162
|
+
// Setup timeout
|
|
163
|
+
const controller = new AbortController();
|
|
164
|
+
const timeoutId = setTimeout(() => controller.abort(), options.timeout ?? this.config.timeout);
|
|
165
|
+
try {
|
|
166
|
+
const response = await fetch(url.toString(), {
|
|
167
|
+
method: options.method || "GET",
|
|
168
|
+
headers,
|
|
169
|
+
body: options.body ? JSON.stringify(options.body) : undefined,
|
|
170
|
+
signal: controller.signal,
|
|
171
|
+
});
|
|
172
|
+
clearTimeout(timeoutId);
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
const errorBody = await response.text();
|
|
175
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}. ${errorBody}`);
|
|
176
|
+
}
|
|
177
|
+
return await response.json();
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
clearTimeout(timeoutId);
|
|
181
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
182
|
+
throw new Error(`Request timeout: ${this.config.name} ${path}`);
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Delay helper
|
|
189
|
+
*/
|
|
190
|
+
delay(ms) {
|
|
191
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
exports.ServiceClient = ServiceClient;
|