@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,110 @@
|
|
|
1
|
+
import { EventRegistry, EventEmitter, EventRecorder, EventFlowTracker, } from "@expressots/core";
|
|
2
|
+
/**
|
|
3
|
+
* Set up the ExpressoTS Event System with zero boilerplate.
|
|
4
|
+
*
|
|
5
|
+
* This function:
|
|
6
|
+
* 1. Registers all event system services (EventRegistry, EventEmitter, EventRecorder, EventFlowTracker)
|
|
7
|
+
* 2. Auto-discovers and registers all @OnEvent decorated handlers
|
|
8
|
+
* 3. Configures recording and flow tracking based on environment
|
|
9
|
+
* 4. Sets up replay emitter for development debugging
|
|
10
|
+
*
|
|
11
|
+
* @param container - The DI container
|
|
12
|
+
* @param options - Configuration options for the event system
|
|
13
|
+
* @returns Setup result with references to all event system services
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* export class App extends AppExpress {
|
|
18
|
+
* async configureServices(): Promise<void> {
|
|
19
|
+
* // Simple setup with defaults (recommended)
|
|
20
|
+
* const { handlersDiscovered } = setupEventSystemForExpress(
|
|
21
|
+
* this.config.Container
|
|
22
|
+
* );
|
|
23
|
+
* console.log(`Discovered ${handlersDiscovered} event handlers`);
|
|
24
|
+
*
|
|
25
|
+
* // Or with custom options
|
|
26
|
+
* setupEventSystemForExpress(this.config.Container, {
|
|
27
|
+
* enableRecording: true,
|
|
28
|
+
* maxRecordedEvents: 500,
|
|
29
|
+
* defaultTimeout: 10000,
|
|
30
|
+
* onError: (error, event, handler) => {
|
|
31
|
+
* console.error(`Handler ${handler} failed:`, error);
|
|
32
|
+
* }
|
|
33
|
+
* });
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @public API
|
|
39
|
+
*/
|
|
40
|
+
export function setupEventSystemForExpress(container, options = {}) {
|
|
41
|
+
const isDev = process.env.NODE_ENV === "development" || process.env.NODE_ENV === undefined;
|
|
42
|
+
// Default options
|
|
43
|
+
const config = {
|
|
44
|
+
enableRecording: isDev,
|
|
45
|
+
enableFlowTracking: isDev,
|
|
46
|
+
maxRecordedEvents: 1000,
|
|
47
|
+
defaultTimeout: 30000,
|
|
48
|
+
autoDiscover: true,
|
|
49
|
+
...options,
|
|
50
|
+
};
|
|
51
|
+
// Register EventRegistry (singleton)
|
|
52
|
+
if (!container.isBound(EventRegistry)) {
|
|
53
|
+
container.bind(EventRegistry).toSelf().inSingletonScope();
|
|
54
|
+
}
|
|
55
|
+
// Register EventEmitter (singleton)
|
|
56
|
+
if (!container.isBound(EventEmitter)) {
|
|
57
|
+
container.bind(EventEmitter).toSelf().inSingletonScope();
|
|
58
|
+
}
|
|
59
|
+
// Register EventRecorder (singleton)
|
|
60
|
+
if (!container.isBound(EventRecorder)) {
|
|
61
|
+
container.bind(EventRecorder).toSelf().inSingletonScope();
|
|
62
|
+
}
|
|
63
|
+
// Register EventFlowTracker (singleton)
|
|
64
|
+
if (!container.isBound(EventFlowTracker)) {
|
|
65
|
+
container.bind(EventFlowTracker).toSelf().inSingletonScope();
|
|
66
|
+
}
|
|
67
|
+
// Get instances
|
|
68
|
+
const registry = container.get(EventRegistry);
|
|
69
|
+
const emitter = container.get(EventEmitter);
|
|
70
|
+
const recorder = container.get(EventRecorder);
|
|
71
|
+
const flowTracker = container.get(EventFlowTracker);
|
|
72
|
+
// Auto-discover event handlers
|
|
73
|
+
let handlersDiscovered = 0;
|
|
74
|
+
if (config.autoDiscover) {
|
|
75
|
+
handlersDiscovered = registry.discoverHandlers(container);
|
|
76
|
+
}
|
|
77
|
+
// Configure emitter
|
|
78
|
+
const emitterConfig = {
|
|
79
|
+
enableRecording: config.enableRecording,
|
|
80
|
+
enableFlowTracking: config.enableFlowTracking,
|
|
81
|
+
maxRecordedEvents: config.maxRecordedEvents,
|
|
82
|
+
defaultTimeout: config.defaultTimeout,
|
|
83
|
+
};
|
|
84
|
+
if (config.onEmit) {
|
|
85
|
+
emitterConfig.onEmit = config.onEmit;
|
|
86
|
+
}
|
|
87
|
+
if (config.onHandlerComplete) {
|
|
88
|
+
emitterConfig.onHandlerComplete = config.onHandlerComplete;
|
|
89
|
+
}
|
|
90
|
+
if (config.onError) {
|
|
91
|
+
emitterConfig.onError = config.onError;
|
|
92
|
+
}
|
|
93
|
+
emitter.configure(emitterConfig);
|
|
94
|
+
// Configure recorder
|
|
95
|
+
recorder.configure({
|
|
96
|
+
maxEvents: config.maxRecordedEvents || 1000,
|
|
97
|
+
autoStart: config.enableRecording,
|
|
98
|
+
});
|
|
99
|
+
// Set up replay emitter (so recorded events can be replayed)
|
|
100
|
+
recorder.setReplayEmitter(async (event) => {
|
|
101
|
+
await emitter.emit(event);
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
registry,
|
|
105
|
+
emitter,
|
|
106
|
+
recorder,
|
|
107
|
+
flowTracker,
|
|
108
|
+
handlersDiscovered,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { InterceptorRegistry, InterceptorExecutor, PerformanceInterceptorService, PerformanceInterceptor, LoggingInterceptor, TimeoutInterceptor, } from "@expressots/core";
|
|
2
|
+
/**
|
|
3
|
+
* Set up the ExpressoTS Interceptor System with zero boilerplate.
|
|
4
|
+
*
|
|
5
|
+
* This function:
|
|
6
|
+
* 1. Registers all interceptor infrastructure (InterceptorRegistry, InterceptorExecutor)
|
|
7
|
+
* 2. Optionally enables built-in interceptors (Performance, Logging, Timeout)
|
|
8
|
+
* 3. Registers custom interceptor classes
|
|
9
|
+
* 4. Initializes the interceptor registry
|
|
10
|
+
*
|
|
11
|
+
* @param container - The DI container
|
|
12
|
+
* @param options - Configuration options for the interceptor system
|
|
13
|
+
* @returns Setup result with references to interceptor services
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* export class App extends AppExpress {
|
|
18
|
+
* async configureServices(): Promise<void> {
|
|
19
|
+
* // Simple setup with performance interceptor
|
|
20
|
+
* setupInterceptorsForExpress(this.config.Container, {
|
|
21
|
+
* builtIn: { performance: true }
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // Full setup with custom interceptors
|
|
25
|
+
* setupInterceptorsForExpress(this.config.Container, {
|
|
26
|
+
* builtIn: {
|
|
27
|
+
* performance: true,
|
|
28
|
+
* logging: true,
|
|
29
|
+
* timeout: { defaultTimeout: 5000 }
|
|
30
|
+
* },
|
|
31
|
+
* customInterceptors: [CacheInterceptor, AuditInterceptor]
|
|
32
|
+
* });
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @public API
|
|
38
|
+
*/
|
|
39
|
+
export function setupInterceptorsForExpress(container, options = {}) {
|
|
40
|
+
// Default options
|
|
41
|
+
const config = {
|
|
42
|
+
autoDiscover: true,
|
|
43
|
+
...options,
|
|
44
|
+
};
|
|
45
|
+
let interceptorsRegistered = 0;
|
|
46
|
+
// Register InterceptorRegistry (singleton)
|
|
47
|
+
if (!container.isBound(InterceptorRegistry)) {
|
|
48
|
+
container.bind(InterceptorRegistry).toSelf().inSingletonScope();
|
|
49
|
+
}
|
|
50
|
+
// Register InterceptorExecutor (singleton)
|
|
51
|
+
if (!container.isBound(InterceptorExecutor)) {
|
|
52
|
+
container.bind(InterceptorExecutor).toSelf().inSingletonScope();
|
|
53
|
+
}
|
|
54
|
+
// Register PerformanceInterceptorService (needed by PerformanceInterceptor)
|
|
55
|
+
if (!container.isBound(PerformanceInterceptorService)) {
|
|
56
|
+
container.bind(PerformanceInterceptorService).toSelf().inSingletonScope();
|
|
57
|
+
}
|
|
58
|
+
// Register built-in interceptors if enabled
|
|
59
|
+
if (config.builtIn?.performance) {
|
|
60
|
+
if (!container.isBound(PerformanceInterceptor)) {
|
|
61
|
+
container.bind(PerformanceInterceptor).toSelf().inSingletonScope();
|
|
62
|
+
interceptorsRegistered++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (config.builtIn?.logging) {
|
|
66
|
+
if (!container.isBound(LoggingInterceptor)) {
|
|
67
|
+
container.bind(LoggingInterceptor).toSelf().inSingletonScope();
|
|
68
|
+
interceptorsRegistered++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (config.builtIn?.timeout) {
|
|
72
|
+
if (!container.isBound(TimeoutInterceptor)) {
|
|
73
|
+
container.bind(TimeoutInterceptor).toSelf().inSingletonScope();
|
|
74
|
+
interceptorsRegistered++;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Register custom interceptors
|
|
78
|
+
if (config.customInterceptors && config.customInterceptors.length > 0) {
|
|
79
|
+
for (const interceptorClass of config.customInterceptors) {
|
|
80
|
+
if (!container.isBound(interceptorClass)) {
|
|
81
|
+
container.bind(interceptorClass).toSelf().inSingletonScope();
|
|
82
|
+
interceptorsRegistered++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Get instances
|
|
87
|
+
const registry = container.get(InterceptorRegistry);
|
|
88
|
+
const executor = container.get(InterceptorExecutor);
|
|
89
|
+
// Initialize registry (auto-discovers interceptors from container bindings)
|
|
90
|
+
if (config.autoDiscover) {
|
|
91
|
+
registry.initialize();
|
|
92
|
+
// Update count from registry
|
|
93
|
+
interceptorsRegistered = registry.getAll().length;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
registry,
|
|
97
|
+
executor,
|
|
98
|
+
interceptorsRegistered,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup Lazy Loading for Express
|
|
3
|
+
*
|
|
4
|
+
* One-liner helper function to configure the lazy loading system.
|
|
5
|
+
*
|
|
6
|
+
* @module adapter-express
|
|
7
|
+
*/
|
|
8
|
+
import { LazyModuleLoader, LazyModuleManager, LazyLoadMetrics, LazyModuleWarmup, Scope, ProviderManager, Logger, } from "@expressots/core";
|
|
9
|
+
import { createLazyModuleMiddleware, createRouteMappings, } from "./lazy-module-middleware.js";
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Setup Function
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Set up the lazy loading system with one function call.
|
|
15
|
+
*
|
|
16
|
+
* @layer public
|
|
17
|
+
* @audience application-developers
|
|
18
|
+
* @concept lazy-loading
|
|
19
|
+
*
|
|
20
|
+
* UNIQUE: Zero-configuration lazy loading!
|
|
21
|
+
* - Auto-detects routes from @controller() decorators
|
|
22
|
+
* - Creates middleware for automatic module loading
|
|
23
|
+
* - Optional metrics and background warmup
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // 1. Define lazy modules (routes auto-detected from @controller)
|
|
28
|
+
* // lazy-modules.ts
|
|
29
|
+
* export const AdminModule = CreateLazyModule([AdminController]);
|
|
30
|
+
* // Routes auto-detected: ["/admin"] from @controller("/admin")
|
|
31
|
+
*
|
|
32
|
+
* export const ReportsModule = CreateLazyModule([ReportsController]);
|
|
33
|
+
* // Routes auto-detected: ["/reports"] from @controller("/reports")
|
|
34
|
+
*
|
|
35
|
+
* // 2. Setup in app.ts (just pass the modules!)
|
|
36
|
+
* export class App extends AppExpress {
|
|
37
|
+
* async configureServices(): Promise<void> {
|
|
38
|
+
* const { middleware } = setupLazyLoadingForExpress(
|
|
39
|
+
* this.config.Container,
|
|
40
|
+
* {
|
|
41
|
+
* lazyModules: [AdminModule, ReportsModule],
|
|
42
|
+
* globalPrefix: "/api" // Optional
|
|
43
|
+
* }
|
|
44
|
+
* );
|
|
45
|
+
*
|
|
46
|
+
* // Add middleware - that's it!
|
|
47
|
+
* if (middleware) {
|
|
48
|
+
* this.Middleware.addMiddleware(middleware);
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* // Now:
|
|
54
|
+
* // - GET /api/admin/* → AdminModule auto-loads
|
|
55
|
+
* // - GET /api/reports/* → ReportsModule auto-loads
|
|
56
|
+
* // - No manual route mapping needed!
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @param container - The DI container
|
|
60
|
+
* @param options - Configuration options
|
|
61
|
+
* @returns Setup result with loader, manager, and middleware
|
|
62
|
+
*
|
|
63
|
+
* @public API
|
|
64
|
+
*/
|
|
65
|
+
export function setupLazyLoadingForExpress(container, options = {}) {
|
|
66
|
+
const isDev = process.env.NODE_ENV === "development";
|
|
67
|
+
// Get or create provider manager
|
|
68
|
+
let provider;
|
|
69
|
+
try {
|
|
70
|
+
provider = container.get(ProviderManager);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// ProviderManager not available, create bindings manually
|
|
74
|
+
provider = null;
|
|
75
|
+
}
|
|
76
|
+
// ============================================
|
|
77
|
+
// Register Services
|
|
78
|
+
// ============================================
|
|
79
|
+
// Register LazyModuleLoader if not already bound
|
|
80
|
+
if (!container.isBound(LazyModuleLoader)) {
|
|
81
|
+
if (provider) {
|
|
82
|
+
provider.register(LazyModuleLoader, Scope.Singleton);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
container.bind(LazyModuleLoader).toSelf().inSingletonScope();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Register LazyModuleManager if not already bound
|
|
89
|
+
if (!container.isBound(LazyModuleManager)) {
|
|
90
|
+
if (provider) {
|
|
91
|
+
provider.register(LazyModuleManager, Scope.Singleton);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
container.bind(LazyModuleManager).toSelf().inSingletonScope();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Register LazyLoadMetrics if enabled
|
|
98
|
+
const enableMetrics = options.enableMetrics ?? isDev;
|
|
99
|
+
if (enableMetrics && !container.isBound(LazyLoadMetrics)) {
|
|
100
|
+
if (provider) {
|
|
101
|
+
provider.register(LazyLoadMetrics, Scope.Singleton);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
container.bind(LazyLoadMetrics).toSelf().inSingletonScope();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Register LazyModuleWarmup if enabled
|
|
108
|
+
const enableWarmup = options.enableWarmup ?? true;
|
|
109
|
+
if (enableWarmup && !container.isBound(LazyModuleWarmup)) {
|
|
110
|
+
if (provider) {
|
|
111
|
+
provider.register(LazyModuleWarmup, Scope.Singleton);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
container.bind(LazyModuleWarmup).toSelf().inSingletonScope();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// ============================================
|
|
118
|
+
// Get Service Instances
|
|
119
|
+
// ============================================
|
|
120
|
+
const loader = container.get(LazyModuleLoader);
|
|
121
|
+
loader.setContainer(container);
|
|
122
|
+
const manager = container.get(LazyModuleManager);
|
|
123
|
+
const metrics = enableMetrics ? container.get(LazyLoadMetrics) : undefined;
|
|
124
|
+
const warmup = enableWarmup ? container.get(LazyModuleWarmup) : undefined;
|
|
125
|
+
// ============================================
|
|
126
|
+
// Register Lazy Modules
|
|
127
|
+
// ============================================
|
|
128
|
+
const lazyModules = options.lazyModules || [];
|
|
129
|
+
let lazyCount = 0;
|
|
130
|
+
let eagerCount = 0;
|
|
131
|
+
for (const lazyModule of lazyModules) {
|
|
132
|
+
// Check if module should always be loaded eagerly
|
|
133
|
+
const alwaysLoad = options.alwaysLoad || [];
|
|
134
|
+
const neverLoad = options.neverLoad || [];
|
|
135
|
+
if (alwaysLoad.includes(lazyModule.name)) {
|
|
136
|
+
// Load immediately
|
|
137
|
+
lazyModule.load().catch((err) => {
|
|
138
|
+
console.warn(`[Lazy Loading] Failed to eager-load ${lazyModule.name}:`, err);
|
|
139
|
+
});
|
|
140
|
+
eagerCount++;
|
|
141
|
+
}
|
|
142
|
+
else if (!neverLoad.includes(lazyModule.name)) {
|
|
143
|
+
// Register for lazy loading
|
|
144
|
+
loader.register(lazyModule);
|
|
145
|
+
lazyCount++;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// ============================================
|
|
149
|
+
// Log Summary
|
|
150
|
+
// ============================================
|
|
151
|
+
const logLevel = options.logLevel ?? "info";
|
|
152
|
+
if (logLevel !== "none") {
|
|
153
|
+
let logger;
|
|
154
|
+
try {
|
|
155
|
+
logger = container.get(Logger);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// Logger not available
|
|
159
|
+
}
|
|
160
|
+
const message = `[Lazy Loading] Registered ${lazyCount} lazy modules, ${eagerCount} eager modules`;
|
|
161
|
+
if (logger) {
|
|
162
|
+
logger.info(message);
|
|
163
|
+
}
|
|
164
|
+
else if (logLevel === "debug" || logLevel === "info") {
|
|
165
|
+
console.log(message);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// ============================================
|
|
169
|
+
// Start Warmup if Enabled
|
|
170
|
+
// ============================================
|
|
171
|
+
if (warmup && options.warmupConfig) {
|
|
172
|
+
// Schedule warmup to start after a delay
|
|
173
|
+
const warmupDelay = options.warmupConfig.delay ?? 5000;
|
|
174
|
+
setTimeout(() => {
|
|
175
|
+
warmup.start(options.warmupConfig).catch((err) => {
|
|
176
|
+
console.warn("[Lazy Loading] Warmup failed:", err);
|
|
177
|
+
});
|
|
178
|
+
}, warmupDelay);
|
|
179
|
+
}
|
|
180
|
+
// ============================================
|
|
181
|
+
// Create Auto-Load Middleware
|
|
182
|
+
// ============================================
|
|
183
|
+
let middleware;
|
|
184
|
+
let routeMappings = [];
|
|
185
|
+
if (lazyCount > 0 && options.enableAutoLoad !== false) {
|
|
186
|
+
// Create route mappings from lazy modules
|
|
187
|
+
routeMappings = createRouteMappings(lazyModules.filter((m) => !options.alwaysLoad?.includes(m.name)), options.routePrefixes);
|
|
188
|
+
// Create the middleware
|
|
189
|
+
middleware = createLazyModuleMiddleware({
|
|
190
|
+
routes: routeMappings,
|
|
191
|
+
loader,
|
|
192
|
+
globalPrefix: options.globalPrefix || "",
|
|
193
|
+
onLoadStart: (moduleName, path) => {
|
|
194
|
+
if (options.logLevel !== "none") {
|
|
195
|
+
console.log(`[Lazy Loading] Loading '${moduleName}' (triggered by ${path})...`);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
onLoadComplete: (moduleName, loadTimeMs) => {
|
|
199
|
+
metrics?.recordLoadTime(moduleName, loadTimeMs);
|
|
200
|
+
},
|
|
201
|
+
onLoadError: (moduleName, error) => {
|
|
202
|
+
console.error(`[Lazy Loading] Failed to load '${moduleName}':`, error.message);
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
if (options.logLevel !== "none") {
|
|
206
|
+
const routes = routeMappings
|
|
207
|
+
.map((r) => `${options.globalPrefix || ""}${r.prefix}`)
|
|
208
|
+
.join(", ");
|
|
209
|
+
console.log(`[Lazy Loading] Auto-load middleware active for routes: ${routes}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// ============================================
|
|
213
|
+
// Return Result
|
|
214
|
+
// ============================================
|
|
215
|
+
return {
|
|
216
|
+
loader,
|
|
217
|
+
manager,
|
|
218
|
+
metrics,
|
|
219
|
+
warmup,
|
|
220
|
+
middleware,
|
|
221
|
+
routeMappings,
|
|
222
|
+
lazyModulesCount: lazyCount,
|
|
223
|
+
eagerModulesCount: eagerCount,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Logger } from "@expressots/core";
|
|
2
|
+
import { METADATA_KEY, NO_CONTROLLERS_FOUND, TYPE } from "./constants.js";
|
|
3
|
+
export function getControllersFromContainer(container, forceControllers) {
|
|
4
|
+
if (container.isBound(TYPE.Controller)) {
|
|
5
|
+
return container.getAll(TYPE.Controller);
|
|
6
|
+
}
|
|
7
|
+
if (forceControllers) {
|
|
8
|
+
const logger = new Logger();
|
|
9
|
+
logger.error(NO_CONTROLLERS_FOUND, "adapter-express");
|
|
10
|
+
throw new Error(NO_CONTROLLERS_FOUND);
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function getControllersFromMetadata() {
|
|
17
|
+
const arrayOfControllerMetadata = Reflect.getMetadata(METADATA_KEY.controller, Reflect) || [];
|
|
18
|
+
return arrayOfControllerMetadata.map((metadata) => metadata.target);
|
|
19
|
+
}
|
|
20
|
+
export function getControllerMetadata(constructor) {
|
|
21
|
+
const controllerMetadata = Reflect.getOwnMetadata(METADATA_KEY.controller, constructor);
|
|
22
|
+
return controllerMetadata;
|
|
23
|
+
}
|
|
24
|
+
export function getControllerMethodMetadata(constructor) {
|
|
25
|
+
const methodMetadata = Reflect.getOwnMetadata(METADATA_KEY.controllerMethod, constructor);
|
|
26
|
+
const genericMetadata = Reflect.getMetadata(METADATA_KEY.controllerMethod, Reflect.getPrototypeOf(constructor));
|
|
27
|
+
if (genericMetadata !== undefined && methodMetadata !== undefined) {
|
|
28
|
+
return methodMetadata.concat(genericMetadata);
|
|
29
|
+
}
|
|
30
|
+
if (genericMetadata !== undefined) {
|
|
31
|
+
return genericMetadata;
|
|
32
|
+
}
|
|
33
|
+
return methodMetadata;
|
|
34
|
+
}
|
|
35
|
+
export function getControllerParameterMetadata(constructor) {
|
|
36
|
+
const parameterMetadata = Reflect.getOwnMetadata(METADATA_KEY.controllerParameter, constructor);
|
|
37
|
+
const genericMetadata = Reflect.getMetadata(METADATA_KEY.controllerParameter, Reflect.getPrototypeOf(constructor));
|
|
38
|
+
if (genericMetadata !== undefined && parameterMetadata !== undefined) {
|
|
39
|
+
return { ...parameterMetadata, ...genericMetadata };
|
|
40
|
+
}
|
|
41
|
+
if (genericMetadata !== undefined) {
|
|
42
|
+
return genericMetadata;
|
|
43
|
+
}
|
|
44
|
+
return parameterMetadata;
|
|
45
|
+
}
|
|
46
|
+
export function cleanUpMetadata() {
|
|
47
|
+
Reflect.defineMetadata(METADATA_KEY.controller, [], Reflect);
|
|
48
|
+
}
|
|
49
|
+
export function instanceOfIHttpActionResult(value) {
|
|
50
|
+
return value != null && typeof value.executeAsync === "function";
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Gets content negotiation metadata from a controller method.
|
|
54
|
+
* @param target - Controller instance
|
|
55
|
+
* @param propertyKey - Method name
|
|
56
|
+
* @returns Content negotiation metadata
|
|
57
|
+
*/
|
|
58
|
+
export function getContentNegotiationMetadata(target, propertyKey) {
|
|
59
|
+
return {
|
|
60
|
+
accept: Reflect.getMetadata(METADATA_KEY.accept, target, propertyKey),
|
|
61
|
+
consumes: Reflect.getMetadata(METADATA_KEY.consumes, target, propertyKey),
|
|
62
|
+
produces: Reflect.getMetadata(METADATA_KEY.produces, target, propertyKey),
|
|
63
|
+
csvOptions: Reflect.getMetadata(METADATA_KEY.csvOptions, target, propertyKey),
|
|
64
|
+
xmlOptions: Reflect.getMetadata(METADATA_KEY.xmlOptions, target, propertyKey),
|
|
65
|
+
yamlOptions: Reflect.getMetadata(METADATA_KEY.yamlOptions, target, propertyKey),
|
|
66
|
+
streamResponse: Reflect.getMetadata(METADATA_KEY.streamResponse, target, propertyKey),
|
|
67
|
+
};
|
|
68
|
+
}
|