@expressots/adapter-express 3.0.0-beta.4.2 → 4.0.0-preview.1
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/README.md +39 -96
- package/lib/CHANGELOG.md +43 -0
- package/lib/README.md +39 -96
- package/lib/cjs/adapter-express/application-express.base.js +3 -1
- package/lib/cjs/adapter-express/application-express.js +1049 -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 +186 -49
- 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 +810 -63
- 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/permission-preloader.middleware.js +48 -0
- package/lib/cjs/adapter-express/express-utils/route-constraints.js +95 -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 +11 -37
- 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 +217 -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 +9 -0
- package/lib/cjs/adapter-express/studio/studio-integration.js +214 -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 +273 -32
- 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/permission-preloader.middleware.d.ts +10 -0
- package/lib/cjs/types/adapter-express/express-utils/route-constraints.d.ts +89 -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 +66 -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 +92 -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 +1300 -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 +575 -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 +1031 -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/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 +91 -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 +161 -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 +211 -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 +184 -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 +411 -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/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 +89 -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 +66 -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 +92 -0
- package/lib/esm/types/index.d.ts +1 -0
- package/lib/package.json +156 -146
- package/package.json +156 -146
- package/lib/cjs/di/di.interfaces.js +0 -10
- package/lib/cjs/types/di/di.interfaces.d.ts +0 -289
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ServiceDiscovery - Service discovery for microservices.
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Static service registration
|
|
6
|
+
* - Consul integration
|
|
7
|
+
* - etcd integration
|
|
8
|
+
* - Automatic service refresh
|
|
9
|
+
* - Round-robin load balancing
|
|
10
|
+
* - Health-based filtering
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // Static service discovery
|
|
15
|
+
* const discovery = new ServiceDiscovery({ type: "static" });
|
|
16
|
+
*
|
|
17
|
+
* discovery.registerService({
|
|
18
|
+
* id: "user-service-1",
|
|
19
|
+
* name: "user-service",
|
|
20
|
+
* host: "user-service",
|
|
21
|
+
* port: 3001,
|
|
22
|
+
* health: "healthy",
|
|
23
|
+
* lastCheck: new Date(),
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Get a healthy instance
|
|
27
|
+
* const instance = discovery.getService("user-service");
|
|
28
|
+
* const client = new ServiceClient({
|
|
29
|
+
* name: "user-service",
|
|
30
|
+
* baseUrl: `http://${instance.host}:${instance.port}`,
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Or with Consul
|
|
34
|
+
* const discovery = new ServiceDiscovery({
|
|
35
|
+
* type: "consul",
|
|
36
|
+
* endpoint: "http://consul:8500",
|
|
37
|
+
* });
|
|
38
|
+
* await discovery.initialize();
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class ServiceDiscovery {
|
|
42
|
+
services = new Map();
|
|
43
|
+
roundRobinIndex = new Map();
|
|
44
|
+
refreshTimer;
|
|
45
|
+
config;
|
|
46
|
+
constructor(config) {
|
|
47
|
+
this.config = {
|
|
48
|
+
type: config.type,
|
|
49
|
+
endpoint: config.endpoint ?? "",
|
|
50
|
+
refreshInterval: config.refreshInterval ?? 30000,
|
|
51
|
+
debug: config.debug ?? false,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Initialize the service discovery
|
|
56
|
+
* For consul/etcd, this starts the refresh loop
|
|
57
|
+
*/
|
|
58
|
+
async initialize() {
|
|
59
|
+
if (this.config.type === "static") {
|
|
60
|
+
// Static configuration - no auto-discovery
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// Initial refresh
|
|
64
|
+
await this.refresh();
|
|
65
|
+
// Start refresh loop
|
|
66
|
+
if (this.config.refreshInterval > 0) {
|
|
67
|
+
this.refreshTimer = setInterval(() => this.refresh(), this.config.refreshInterval);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Register a service instance (for static mode)
|
|
72
|
+
* @param service - Service instance to register
|
|
73
|
+
*/
|
|
74
|
+
registerService(service) {
|
|
75
|
+
const instances = this.services.get(service.name) || [];
|
|
76
|
+
// Check if instance already exists
|
|
77
|
+
const existingIndex = instances.findIndex((i) => i.id === service.id);
|
|
78
|
+
if (existingIndex >= 0) {
|
|
79
|
+
instances[existingIndex] = service;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
instances.push(service);
|
|
83
|
+
}
|
|
84
|
+
this.services.set(service.name, instances);
|
|
85
|
+
if (this.config.debug) {
|
|
86
|
+
console.log(`[ServiceDiscovery] Registered ${service.name} (${service.id})`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Deregister a service instance
|
|
91
|
+
* @param serviceName - Service name
|
|
92
|
+
* @param instanceId - Instance ID to remove
|
|
93
|
+
*/
|
|
94
|
+
deregisterService(serviceName, instanceId) {
|
|
95
|
+
const instances = this.services.get(serviceName);
|
|
96
|
+
if (!instances)
|
|
97
|
+
return;
|
|
98
|
+
const filtered = instances.filter((i) => i.id !== instanceId);
|
|
99
|
+
this.services.set(serviceName, filtered);
|
|
100
|
+
if (this.config.debug) {
|
|
101
|
+
console.log(`[ServiceDiscovery] Deregistered ${serviceName} (${instanceId})`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get a healthy instance of a service (round-robin)
|
|
106
|
+
* @param name - Service name
|
|
107
|
+
* @returns A healthy service instance or null
|
|
108
|
+
*/
|
|
109
|
+
getService(name) {
|
|
110
|
+
const instances = this.services.get(name);
|
|
111
|
+
if (!instances || instances.length === 0) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
// Filter to healthy instances only
|
|
115
|
+
const healthy = instances.filter((i) => i.health === "healthy");
|
|
116
|
+
if (healthy.length === 0) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
// Round-robin selection
|
|
120
|
+
const currentIndex = this.roundRobinIndex.get(name) ?? 0;
|
|
121
|
+
const instance = healthy[currentIndex % healthy.length];
|
|
122
|
+
this.roundRobinIndex.set(name, currentIndex + 1);
|
|
123
|
+
return instance;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Get all instances of a service
|
|
127
|
+
* @param name - Service name
|
|
128
|
+
* @param healthyOnly - Only return healthy instances (default: true)
|
|
129
|
+
*/
|
|
130
|
+
getServiceInstances(name, healthyOnly = true) {
|
|
131
|
+
const instances = this.services.get(name) || [];
|
|
132
|
+
if (healthyOnly) {
|
|
133
|
+
return instances.filter((i) => i.health === "healthy");
|
|
134
|
+
}
|
|
135
|
+
return instances;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get all registered services
|
|
139
|
+
*/
|
|
140
|
+
getAllServices() {
|
|
141
|
+
return new Map(this.services);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* List all registered service names
|
|
145
|
+
*/
|
|
146
|
+
listServices() {
|
|
147
|
+
return Array.from(this.services.keys());
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Update health status of a service instance
|
|
151
|
+
* @param serviceName - Service name
|
|
152
|
+
* @param instanceId - Instance ID
|
|
153
|
+
* @param health - New health status
|
|
154
|
+
*/
|
|
155
|
+
updateHealth(serviceName, instanceId, health) {
|
|
156
|
+
const instances = this.services.get(serviceName);
|
|
157
|
+
if (!instances)
|
|
158
|
+
return false;
|
|
159
|
+
const instance = instances.find((i) => i.id === instanceId);
|
|
160
|
+
if (!instance)
|
|
161
|
+
return false;
|
|
162
|
+
instance.health = health;
|
|
163
|
+
instance.lastCheck = new Date();
|
|
164
|
+
if (this.config.debug) {
|
|
165
|
+
console.log(`[ServiceDiscovery] Updated ${serviceName} (${instanceId}) health to ${health}`);
|
|
166
|
+
}
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get service statistics
|
|
171
|
+
*/
|
|
172
|
+
getStats() {
|
|
173
|
+
const stats = {};
|
|
174
|
+
for (const [name, instances] of this.services) {
|
|
175
|
+
stats[name] = {
|
|
176
|
+
total: instances.length,
|
|
177
|
+
healthy: instances.filter((i) => i.health === "healthy").length,
|
|
178
|
+
unhealthy: instances.filter((i) => i.health === "unhealthy").length,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return stats;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Stop the service discovery
|
|
185
|
+
*/
|
|
186
|
+
stop() {
|
|
187
|
+
if (this.refreshTimer) {
|
|
188
|
+
clearInterval(this.refreshTimer);
|
|
189
|
+
this.refreshTimer = undefined;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Refresh service list from discovery backend
|
|
194
|
+
*/
|
|
195
|
+
async refresh() {
|
|
196
|
+
try {
|
|
197
|
+
if (this.config.type === "consul") {
|
|
198
|
+
await this.refreshFromConsul();
|
|
199
|
+
}
|
|
200
|
+
else if (this.config.type === "etcd") {
|
|
201
|
+
await this.refreshFromEtcd();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
console.error("[ServiceDiscovery] Refresh failed:", error);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Refresh from Consul
|
|
210
|
+
*/
|
|
211
|
+
async refreshFromConsul() {
|
|
212
|
+
if (!this.config.endpoint) {
|
|
213
|
+
throw new Error("Consul endpoint not configured");
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
// Get list of services
|
|
217
|
+
const servicesResponse = await fetch(`${this.config.endpoint}/v1/catalog/services`);
|
|
218
|
+
const services = await servicesResponse.json();
|
|
219
|
+
// Get instances for each service
|
|
220
|
+
for (const serviceName of Object.keys(services)) {
|
|
221
|
+
const instances = await this.getConsulInstances(serviceName);
|
|
222
|
+
this.services.set(serviceName, instances);
|
|
223
|
+
}
|
|
224
|
+
if (this.config.debug) {
|
|
225
|
+
console.log(`[ServiceDiscovery] Refreshed ${this.services.size} services from Consul`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
console.error("[ServiceDiscovery] Consul refresh failed:", error);
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get instances from Consul for a specific service
|
|
235
|
+
*/
|
|
236
|
+
async getConsulInstances(serviceName) {
|
|
237
|
+
const response = await fetch(`${this.config.endpoint}/v1/health/service/${serviceName}?passing=true`);
|
|
238
|
+
const data = (await response.json());
|
|
239
|
+
return data.map((entry) => ({
|
|
240
|
+
id: entry.Service.ID,
|
|
241
|
+
name: entry.Service.Service,
|
|
242
|
+
host: entry.Service.Address || entry.Node.Address,
|
|
243
|
+
port: entry.Service.Port,
|
|
244
|
+
metadata: entry.Service.Meta,
|
|
245
|
+
health: "healthy",
|
|
246
|
+
lastCheck: new Date(),
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Refresh from etcd
|
|
251
|
+
*/
|
|
252
|
+
async refreshFromEtcd() {
|
|
253
|
+
if (!this.config.endpoint) {
|
|
254
|
+
throw new Error("etcd endpoint not configured");
|
|
255
|
+
}
|
|
256
|
+
// etcd v3 API implementation
|
|
257
|
+
console.log("[ServiceDiscovery] etcd integration requires etcd3 client library");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file request-logging.middleware.ts
|
|
3
|
+
* @description HTTP request/response logging middleware with context enrichment
|
|
4
|
+
* @module @expressots/adapter-express
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Request ID generation/extraction
|
|
8
|
+
* - Request/response timing
|
|
9
|
+
* - Slow request detection
|
|
10
|
+
* - Configurable verbosity levels
|
|
11
|
+
* - Body logging with redaction support
|
|
12
|
+
*/
|
|
13
|
+
import { ContextManager, getFlowTracker, removeFlowTracker, } from "@expressots/core";
|
|
14
|
+
/**
|
|
15
|
+
* Default request logging configuration.
|
|
16
|
+
*/
|
|
17
|
+
export function getDefaultRequestLoggingConfig() {
|
|
18
|
+
return {
|
|
19
|
+
verbosity: "normal",
|
|
20
|
+
logBody: false,
|
|
21
|
+
logHeaders: false,
|
|
22
|
+
logResponseBody: false,
|
|
23
|
+
slowRequestThreshold: 1000, // 1 second
|
|
24
|
+
skipPatterns: [/^\/health$/, /^\/ready$/, /^\/live$/, /^\/_health$/],
|
|
25
|
+
requestIdHeader: "x-request-id",
|
|
26
|
+
correlationIdHeader: "x-correlation-id",
|
|
27
|
+
logUserAgent: true,
|
|
28
|
+
logIp: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create request logging middleware.
|
|
33
|
+
* @param logger - Logger instance to use
|
|
34
|
+
* @param config - Optional configuration
|
|
35
|
+
* @returns Express middleware function
|
|
36
|
+
* @public API
|
|
37
|
+
*/
|
|
38
|
+
export function createRequestLoggingMiddleware(logger, config) {
|
|
39
|
+
const finalConfig = {
|
|
40
|
+
...getDefaultRequestLoggingConfig(),
|
|
41
|
+
...config,
|
|
42
|
+
};
|
|
43
|
+
return (req, res, next) => {
|
|
44
|
+
// Skip logging for configured patterns
|
|
45
|
+
if (finalConfig.skipPatterns.some((pattern) => pattern.test(req.path))) {
|
|
46
|
+
next();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// Create HTTP context with custom header names
|
|
50
|
+
const httpContext = ContextManager.createHttpContext(req, {
|
|
51
|
+
requestIdHeader: finalConfig.requestIdHeader,
|
|
52
|
+
correlationIdHeader: finalConfig.correlationIdHeader,
|
|
53
|
+
});
|
|
54
|
+
// Set request/correlation ID headers for downstream services
|
|
55
|
+
res.setHeader(finalConfig.requestIdHeader, httpContext.requestId);
|
|
56
|
+
if (httpContext.correlationId) {
|
|
57
|
+
res.setHeader(finalConfig.correlationIdHeader, httpContext.correlationId);
|
|
58
|
+
}
|
|
59
|
+
// Create log context
|
|
60
|
+
const logContext = {
|
|
61
|
+
requestId: httpContext.requestId,
|
|
62
|
+
userId: httpContext.userId,
|
|
63
|
+
tenantId: httpContext.tenantId,
|
|
64
|
+
metadata: {
|
|
65
|
+
method: httpContext.method,
|
|
66
|
+
path: httpContext.path,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
// Initialize flow tracker (if flow tracking is enabled)
|
|
70
|
+
const flowConfig = logger.getConfig()?.flow;
|
|
71
|
+
const flowTracker = getFlowTracker(httpContext.requestId, httpContext.method, httpContext.path, flowConfig);
|
|
72
|
+
// Log request start based on verbosity
|
|
73
|
+
logRequestStart(logger, httpContext, finalConfig);
|
|
74
|
+
// Capture response timing
|
|
75
|
+
const startTime = Date.now();
|
|
76
|
+
const startMemory = process.memoryUsage().heapUsed;
|
|
77
|
+
// Store error on request for later retrieval
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
|
+
req.__expressotsFlowError = undefined;
|
|
80
|
+
// Override res.end to capture response
|
|
81
|
+
const originalEnd = res.end;
|
|
82
|
+
let endCalled = false;
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
res.end = function (...args) {
|
|
85
|
+
// Prevent multiple calls
|
|
86
|
+
if (endCalled) {
|
|
87
|
+
return originalEnd.apply(this, args);
|
|
88
|
+
}
|
|
89
|
+
endCalled = true;
|
|
90
|
+
const duration = Date.now() - startTime;
|
|
91
|
+
const memoryDelta = process.memoryUsage().heapUsed - startMemory;
|
|
92
|
+
// Get error from request if available (set by controllers, guards, or error handlers)
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
|
+
const error = req.__expressotsFlowError;
|
|
95
|
+
// Finalize flow and get flow data (pass error if available)
|
|
96
|
+
const flow = flowTracker.finalize(res.statusCode, error);
|
|
97
|
+
// Log response with flow data
|
|
98
|
+
logRequestEnd(logger, httpContext, res, duration, memoryDelta, finalConfig, flow);
|
|
99
|
+
// Cleanup flow tracker
|
|
100
|
+
removeFlowTracker(httpContext.requestId);
|
|
101
|
+
// Call original end
|
|
102
|
+
return originalEnd.apply(this, args);
|
|
103
|
+
};
|
|
104
|
+
// Wrap next to capture errors passed to next()
|
|
105
|
+
const wrappedNext = (err) => {
|
|
106
|
+
if (err) {
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
108
|
+
req.__expressotsFlowError = err instanceof Error ? err : new Error(String(err));
|
|
109
|
+
}
|
|
110
|
+
next(err);
|
|
111
|
+
};
|
|
112
|
+
// Also hook into res.status() to capture error status codes
|
|
113
|
+
// This helps capture errors that Express error handlers set
|
|
114
|
+
const originalStatus = res.status.bind(res);
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
116
|
+
res.status = function (code) {
|
|
117
|
+
// If status is >= 400 and no error is stored yet, try to get it from Express error handling
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
119
|
+
if (code >= 400 && !req.__expressotsFlowError) {
|
|
120
|
+
// Check if there's an error in the response locals (Express error handlers sometimes put it there)
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
const errorFromLocals = res.locals?.error;
|
|
123
|
+
if (errorFromLocals) {
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
125
|
+
req.__expressotsFlowError =
|
|
126
|
+
errorFromLocals instanceof Error ? errorFromLocals : new Error(String(errorFromLocals));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return originalStatus(code);
|
|
130
|
+
};
|
|
131
|
+
// Run the rest of the middleware chain with context
|
|
132
|
+
ContextManager.runWithContext(logContext, () => {
|
|
133
|
+
wrappedNext();
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Log request start.
|
|
139
|
+
*/
|
|
140
|
+
function logRequestStart(logger, context, config) {
|
|
141
|
+
const { verbosity, logHeaders, logUserAgent, logIp } = config;
|
|
142
|
+
if (verbosity === "minimal") {
|
|
143
|
+
// Minimal: Just log that request started
|
|
144
|
+
logger.debug(`→ ${context.method} ${context.path}`, { requestId: context.requestId });
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// Build log data based on verbosity
|
|
148
|
+
const logData = {
|
|
149
|
+
requestId: context.requestId,
|
|
150
|
+
};
|
|
151
|
+
if (logIp && context.ip) {
|
|
152
|
+
logData.ip = context.ip;
|
|
153
|
+
}
|
|
154
|
+
if (logUserAgent && context.userAgent) {
|
|
155
|
+
logData.userAgent =
|
|
156
|
+
context.userAgent.length > 50
|
|
157
|
+
? context.userAgent.substring(0, 50) + "..."
|
|
158
|
+
: context.userAgent;
|
|
159
|
+
}
|
|
160
|
+
if (context.userId) {
|
|
161
|
+
logData.userId = context.userId;
|
|
162
|
+
}
|
|
163
|
+
if (context.tenantId) {
|
|
164
|
+
logData.tenantId = context.tenantId;
|
|
165
|
+
}
|
|
166
|
+
if (verbosity === "detailed" || verbosity === "debug") {
|
|
167
|
+
if (logHeaders && context.headers) {
|
|
168
|
+
logData.headers = context.headers;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
logger.info(`→ ${context.method} ${context.path}`, "request", logData);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Log request end.
|
|
175
|
+
*/
|
|
176
|
+
function logRequestEnd(logger, context, res, duration, memoryDelta, config, flow) {
|
|
177
|
+
const { verbosity, slowRequestThreshold } = config;
|
|
178
|
+
const statusCode = res.statusCode;
|
|
179
|
+
// Determine log level based on status and duration
|
|
180
|
+
const isSlowRequest = duration >= slowRequestThreshold;
|
|
181
|
+
const isError = statusCode >= 400;
|
|
182
|
+
// Build log data
|
|
183
|
+
const logData = {
|
|
184
|
+
requestId: context.requestId,
|
|
185
|
+
status: statusCode,
|
|
186
|
+
duration: `${duration}ms`,
|
|
187
|
+
};
|
|
188
|
+
if (verbosity === "detailed" || verbosity === "debug") {
|
|
189
|
+
logData.memoryDelta = `${(memoryDelta / 1024).toFixed(1)}KB`;
|
|
190
|
+
}
|
|
191
|
+
if (context.userId) {
|
|
192
|
+
logData.userId = context.userId;
|
|
193
|
+
}
|
|
194
|
+
// Format message
|
|
195
|
+
const statusEmoji = isError ? "✗" : "✓";
|
|
196
|
+
const message = `← ${context.method} ${context.path} ${statusCode} ${statusEmoji} ${duration}ms`;
|
|
197
|
+
// Log with appropriate level and include flow data if available
|
|
198
|
+
if (isError && statusCode >= 500) {
|
|
199
|
+
logger.error(message, "request", { ...logData, flow });
|
|
200
|
+
}
|
|
201
|
+
else if (isError) {
|
|
202
|
+
logger.warn(message, "request", { ...logData, flow });
|
|
203
|
+
}
|
|
204
|
+
else if (isSlowRequest) {
|
|
205
|
+
logger.warn(`[SLOW] ${message}`, "request", {
|
|
206
|
+
...logData,
|
|
207
|
+
slowRequestThreshold: `${slowRequestThreshold}ms`,
|
|
208
|
+
flow,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
else if (verbosity !== "minimal") {
|
|
212
|
+
logger.info(message, "request", { ...logData, flow });
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
// debug only takes 2 args: message and data
|
|
216
|
+
logger.debug(`[request] ${message}`, { ...logData, flow });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Express middleware that assigns a request ID to each request.
|
|
221
|
+
* Simpler alternative to full request logging.
|
|
222
|
+
* @param headerName - Header name for request ID (default: x-request-id)
|
|
223
|
+
* @returns Express middleware
|
|
224
|
+
* @public API
|
|
225
|
+
*/
|
|
226
|
+
export function requestIdMiddleware(headerName = "x-request-id") {
|
|
227
|
+
return (req, res, next) => {
|
|
228
|
+
const existingId = req.headers[headerName.toLowerCase()];
|
|
229
|
+
const requestId = existingId || ContextManager.generateRequestId();
|
|
230
|
+
// Set on request for access by other middleware
|
|
231
|
+
req.requestId = requestId;
|
|
232
|
+
// Set on response header
|
|
233
|
+
res.setHeader(headerName, requestId);
|
|
234
|
+
// Run with context
|
|
235
|
+
ContextManager.runWithContext({ requestId }, () => {
|
|
236
|
+
next();
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { join } from "path";
|
|
2
|
+
/**
|
|
3
|
+
* Ejs defaults
|
|
4
|
+
* @type {EjsOptions}
|
|
5
|
+
* @constant
|
|
6
|
+
* @default
|
|
7
|
+
*/
|
|
8
|
+
export const EJS_DEFAULTS = {
|
|
9
|
+
viewsDir: join(process.cwd(), "views"),
|
|
10
|
+
viewEngine: "ejs",
|
|
11
|
+
serverOptions: {},
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Handlebars defaults
|
|
15
|
+
* @type {HandlebarsOptions}
|
|
16
|
+
* @constant
|
|
17
|
+
* @default
|
|
18
|
+
*/
|
|
19
|
+
export const HANDLEBARS_DEFAULTS = {
|
|
20
|
+
viewEngine: "hbs",
|
|
21
|
+
viewsDir: join(process.cwd(), "views"),
|
|
22
|
+
partialsDir: join(process.cwd(), "views/partials"),
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Default partials directory
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_PARTIALS_DIR = join(process.cwd(), "views/partials");
|
|
28
|
+
/**
|
|
29
|
+
* Pug defaults
|
|
30
|
+
* @type {PugOptions}
|
|
31
|
+
* @constant
|
|
32
|
+
* @default
|
|
33
|
+
*/
|
|
34
|
+
export const PUG_DEFAULTS = {
|
|
35
|
+
viewEngine: "pug",
|
|
36
|
+
viewsDir: join(process.cwd(), "views"),
|
|
37
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Logger } from "@expressots/core";
|
|
2
|
+
import { packageResolver } from "./resolve-render.js";
|
|
3
|
+
import { DEFAULT_PARTIALS_DIR, EJS_DEFAULTS, HANDLEBARS_DEFAULTS, PUG_DEFAULTS, } from "./constants.js";
|
|
4
|
+
/**
|
|
5
|
+
* Set Ejs as the view engine
|
|
6
|
+
* @param {Application} app - The express application
|
|
7
|
+
* @param {EjsOptions} [options=EJS_DEFAULTS] - The ejs options
|
|
8
|
+
*/
|
|
9
|
+
export async function setEngineEjs(app, options = EJS_DEFAULTS) {
|
|
10
|
+
packageResolver("ejs");
|
|
11
|
+
app.set("view engine", options.viewEngine || EJS_DEFAULTS.viewEngine);
|
|
12
|
+
app.set("views", options.viewsDir || EJS_DEFAULTS.viewsDir);
|
|
13
|
+
if (Array.isArray(options.viewsDir)) {
|
|
14
|
+
options.viewsDir.forEach((dir) => {
|
|
15
|
+
app.set("views", dir);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (options.serverOptions) {
|
|
19
|
+
app.locals = {
|
|
20
|
+
...app.locals,
|
|
21
|
+
...options.serverOptions,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Set Handlebars as the view engine
|
|
27
|
+
* @param {express.Application} app - The express application
|
|
28
|
+
* @param {HandlebarsOptions} [options=HANDLEBARS_DEFAULTS] - The handlebars options
|
|
29
|
+
*/
|
|
30
|
+
export async function setEngineHandlebars(app, options = HANDLEBARS_DEFAULTS) {
|
|
31
|
+
const logger = new Logger();
|
|
32
|
+
try {
|
|
33
|
+
const hbs = packageResolver("hbs");
|
|
34
|
+
hbs.registerPartials(options.partialsDir || DEFAULT_PARTIALS_DIR);
|
|
35
|
+
app.set("view engine", options.viewEngine || HANDLEBARS_DEFAULTS.viewEngine);
|
|
36
|
+
app.set("views", options.viewsDir || HANDLEBARS_DEFAULTS.viewsDir);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
logger.error(error.message, "handlebars-config");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Set Pug as the view engine
|
|
44
|
+
* @param {express.Application} app - The express application
|
|
45
|
+
* @param {PugOptions} [options=PUG_DEFAULTS] - The pug options
|
|
46
|
+
*/
|
|
47
|
+
export async function setEnginePug(app, options = PUG_DEFAULTS) {
|
|
48
|
+
packageResolver("pug");
|
|
49
|
+
app.set("view engine", options.viewEngine || PUG_DEFAULTS.viewEngine);
|
|
50
|
+
app.set("views", options.viewsDir || PUG_DEFAULTS.viewsDir);
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { setEngineEjs, setEngineHandlebars, setEnginePug } from "./engine.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { Logger } from "@expressots/core";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve package from the current working directory.
|
|
5
|
+
* @param packageName
|
|
6
|
+
* @param options
|
|
7
|
+
* @returns
|
|
8
|
+
*/
|
|
9
|
+
export function packageResolver(packageName, ...options) {
|
|
10
|
+
const logger = new Logger();
|
|
11
|
+
try {
|
|
12
|
+
const hasPackage = require.resolve(packageName, {
|
|
13
|
+
paths: [process.cwd()],
|
|
14
|
+
});
|
|
15
|
+
if (hasPackage) {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
17
|
+
const packageResolved = require(hasPackage);
|
|
18
|
+
if (typeof packageResolved === "function") {
|
|
19
|
+
return packageResolved(...options);
|
|
20
|
+
}
|
|
21
|
+
if (packageResolved.default && typeof packageResolved.default === "function") {
|
|
22
|
+
return packageResolved.default(...options);
|
|
23
|
+
}
|
|
24
|
+
return packageResolved;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
logger.warn(`Package [${packageName}] not installed. Please install it using your package manager.`, "package-resolver");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { initializeStudio, stopStudio, isStudioEnabled, getStudioAgent, reportStudioRuntimeInfo, } from "./studio-integration.js";
|