@fluojs/event-bus 1.0.0-beta.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/LICENSE +21 -0
- package/README.ko.md +123 -0
- package/README.md +122 -0
- package/dist/decorators.d.ts +28 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +53 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/metadata.d.ts +10 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +45 -0
- package/dist/module.d.ts +15 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +35 -0
- package/dist/service.d.ts +72 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +500 -0
- package/dist/status.d.ts +20 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +96 -0
- package/dist/tokens.d.ts +7 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +4 -0
- package/dist/transports/redis-transport.d.ts +57 -0
- package/dist/transports/redis-transport.d.ts.map +1 -0
- package/dist/transports/redis-transport.js +98 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fluo contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# @fluojs/event-bus
|
|
2
|
+
|
|
3
|
+
<p><a href="./README.md"><kbd>English</kbd></a> <strong><kbd>한국어</kbd></strong></p>
|
|
4
|
+
|
|
5
|
+
fluo를 위한 인프로세스(In-process) 이벤트 발행 및 구독 패키지입니다. 데코레이터 기반의 핸들러 탐색 기능을 제공하며, Redis Pub/Sub과 같은 외부 트랜스포트 어댑터를 통해 프로세스 간 통신을 지원합니다.
|
|
6
|
+
|
|
7
|
+
## 목차
|
|
8
|
+
|
|
9
|
+
- [설치](#설치)
|
|
10
|
+
- [사용 시점](#사용-시점)
|
|
11
|
+
- [빠른 시작](#빠른-시작)
|
|
12
|
+
- [일반적인 패턴](#일반적인-패턴)
|
|
13
|
+
- [공개 API 개요](#공개-api-개요)
|
|
14
|
+
- [관련 패키지](#관련-패키지)
|
|
15
|
+
- [예제 소스](#예제-소스)
|
|
16
|
+
|
|
17
|
+
## 설치
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @fluojs/event-bus
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 사용 시점
|
|
24
|
+
|
|
25
|
+
- 직접적인 서비스 호출 대신 이벤트를 통해 컴포넌트 간의 결합도를 낮추고 싶을 때.
|
|
26
|
+
- 하나의 동작에 대해 시스템의 여러 부분에서 반응해야 할 때 (예: 사용자 가입 시 환영 이메일 발송과 대시보드 업데이트를 동시에 수행).
|
|
27
|
+
- 분산 환경 지원이 선택적으로 필요한 간단한 인메모리 이벤트 버스가 필요할 때.
|
|
28
|
+
|
|
29
|
+
## 빠른 시작
|
|
30
|
+
|
|
31
|
+
### 1. 이벤트 및 핸들러 정의
|
|
32
|
+
|
|
33
|
+
이벤트 클래스를 정의하고, 핸들러 메서드에 `@OnEvent` 데코레이터를 사용합니다.
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { OnEvent } from '@fluojs/event-bus';
|
|
37
|
+
|
|
38
|
+
export class UserSignedUpEvent {
|
|
39
|
+
constructor(public readonly email: string) {}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class NotificationService {
|
|
43
|
+
@OnEvent(UserSignedUpEvent)
|
|
44
|
+
async notify(event: UserSignedUpEvent) {
|
|
45
|
+
console.log(`환영 이메일 전송 대상: ${event.email}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. 모듈 등록 및 이벤트 발행
|
|
51
|
+
|
|
52
|
+
`EventBusModule`을 등록하고 `EventBusLifecycleService`를 주입받아 이벤트를 발행합니다.
|
|
53
|
+
|
|
54
|
+
인프로세스 이벤트 버스 등록은 `EventBusModule.forRoot(...)`로 구성합니다.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { Module, Inject } from '@fluojs/core';
|
|
58
|
+
import { EventBusModule, EventBusLifecycleService } from '@fluojs/event-bus';
|
|
59
|
+
|
|
60
|
+
@Module({
|
|
61
|
+
imports: [EventBusModule.forRoot()],
|
|
62
|
+
providers: [NotificationService],
|
|
63
|
+
})
|
|
64
|
+
export class AppModule {}
|
|
65
|
+
|
|
66
|
+
export class UserService {
|
|
67
|
+
@Inject(EventBusLifecycleService)
|
|
68
|
+
private readonly eventBus: EventBusLifecycleService;
|
|
69
|
+
|
|
70
|
+
async signUp(email: string) {
|
|
71
|
+
// 사용자 저장 로직...
|
|
72
|
+
await this.eventBus.publish(new UserSignedUpEvent(email));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 일반적인 패턴
|
|
78
|
+
|
|
79
|
+
### 분산 팬아웃 (Redis)
|
|
80
|
+
|
|
81
|
+
트랜스포트 어댑터를 연결하여 이벤트 버스를 다른 프로세스로 확장할 수 있습니다.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { RedisEventBusTransport } from '@fluojs/event-bus/redis';
|
|
85
|
+
|
|
86
|
+
EventBusModule.forRoot({
|
|
87
|
+
transport: new RedisEventBusTransport({
|
|
88
|
+
publishClient: redis,
|
|
89
|
+
subscribeClient: redisSubscriber
|
|
90
|
+
}),
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 버전이 명시된 이벤트 키
|
|
95
|
+
|
|
96
|
+
`static eventKey`를 사용하여 클래스 이름 변경이나 코드 압축(minification)과 관계없이 안정적인 채널 이름을 유지할 수 있습니다.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
class UserRegisteredEvent {
|
|
100
|
+
static readonly eventKey = 'user.registered.v1';
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 공개 API 개요
|
|
105
|
+
|
|
106
|
+
### 핵심 구성 요소
|
|
107
|
+
- `EventBusModule`: 이벤트 버스 기능을 위한 기본 모듈입니다.
|
|
108
|
+
- `EventBusLifecycleService`: 이벤트를 발행(`publish(event)`)하기 위한 기본 서비스입니다.
|
|
109
|
+
- `@OnEvent(EventClass)`: 특정 메서드를 이벤트 핸들러로 지정하는 데코레이터입니다.
|
|
110
|
+
- `EventBusModule.forRoot(...)`: in-process 이벤트 버스 구성을 설정합니다.
|
|
111
|
+
|
|
112
|
+
### 인터페이스
|
|
113
|
+
- `EventBusTransport`: 외부 트랜스포트 어댑터 구현을 위한 계약입니다.
|
|
114
|
+
|
|
115
|
+
## 관련 패키지
|
|
116
|
+
|
|
117
|
+
- `@fluojs/cqrs`: 더 정형화된 아키텍처 패턴을 위해 이벤트 버스 위에 구축된 패키지입니다.
|
|
118
|
+
- `@fluojs/redis`: `RedisEventBusTransport` 사용 시 필요한 클라이언트를 제공합니다.
|
|
119
|
+
|
|
120
|
+
## 예제 소스
|
|
121
|
+
|
|
122
|
+
- `packages/event-bus/src/module.test.ts`: 핸들러 탐색 및 발행/구독 테스트 예제.
|
|
123
|
+
- `packages/event-bus/src/public-surface.test.ts`: 공개 API 계약 검증 예제.
|
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# @fluojs/event-bus
|
|
2
|
+
|
|
3
|
+
<p><strong><kbd>English</kbd></strong> <a href="./README.ko.md"><kbd>한국어</kbd></a></p>
|
|
4
|
+
|
|
5
|
+
In-process event publishing and subscription for fluo. It features decorator-based handler discovery and support for external transport adapters like Redis Pub/Sub for cross-process communication.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [When to use](#when-to-use)
|
|
11
|
+
- [Quick Start](#quick-start)
|
|
12
|
+
- [Common Patterns](#common-patterns)
|
|
13
|
+
- [Public API](#public-api)
|
|
14
|
+
- [Related Packages](#related-packages)
|
|
15
|
+
- [Example Sources](#example-sources)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @fluojs/event-bus
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## When to Use
|
|
24
|
+
|
|
25
|
+
- When you need to decouple components by communicating via events instead of direct service calls.
|
|
26
|
+
- When multiple parts of the system need to react to a single action (e.g., sending an email and updating a dashboard when a user registers).
|
|
27
|
+
- When you need a simple in-memory event bus with optional support for distributed systems.
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### 1. Define an Event and Handler
|
|
32
|
+
|
|
33
|
+
Create an event class and a handler method decorated with `@OnEvent`.
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { OnEvent } from '@fluojs/event-bus';
|
|
37
|
+
|
|
38
|
+
export class UserSignedUpEvent {
|
|
39
|
+
constructor(public readonly email: string) {}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class NotificationService {
|
|
43
|
+
@OnEvent(UserSignedUpEvent)
|
|
44
|
+
async notify(event: UserSignedUpEvent) {
|
|
45
|
+
console.log(`Sending welcome email to: ${event.email}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Register and Publish
|
|
51
|
+
|
|
52
|
+
Import `EventBusModule` and inject `EventBusLifecycleService` to publish events.
|
|
53
|
+
|
|
54
|
+
Use `EventBusModule.forRoot(...)` to wire the in-process event bus.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { Module, Inject } from '@fluojs/core';
|
|
58
|
+
import { EventBusModule, EventBusLifecycleService } from '@fluojs/event-bus';
|
|
59
|
+
|
|
60
|
+
@Module({
|
|
61
|
+
imports: [EventBusModule.forRoot()],
|
|
62
|
+
providers: [NotificationService],
|
|
63
|
+
})
|
|
64
|
+
export class AppModule {}
|
|
65
|
+
|
|
66
|
+
export class UserService {
|
|
67
|
+
@Inject(EventBusLifecycleService)
|
|
68
|
+
private readonly eventBus: EventBusLifecycleService;
|
|
69
|
+
|
|
70
|
+
async signUp(email: string) {
|
|
71
|
+
// Logic to save user...
|
|
72
|
+
await this.eventBus.publish(new UserSignedUpEvent(email));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Common Patterns
|
|
78
|
+
|
|
79
|
+
### Distributed Fan-out (Redis)
|
|
80
|
+
|
|
81
|
+
Extend the event bus to other processes by plugging in a transport adapter.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { RedisEventBusTransport } from '@fluojs/event-bus/redis';
|
|
85
|
+
|
|
86
|
+
EventBusModule.forRoot({
|
|
87
|
+
transport: new RedisEventBusTransport({
|
|
88
|
+
publishClient: redis,
|
|
89
|
+
subscribeClient: redisSubscriber
|
|
90
|
+
}),
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Versioned Event Keys
|
|
95
|
+
|
|
96
|
+
Use static `eventKey` to ensure stable channel names regardless of class minification or renames.
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
class UserRegisteredEvent {
|
|
100
|
+
static readonly eventKey = 'user.registered.v1';
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Public API Overview
|
|
105
|
+
|
|
106
|
+
### Core
|
|
107
|
+
- `EventBusModule`: Main entry point for event bus registration.
|
|
108
|
+
- `EventBusLifecycleService`: Primary service for publishing events (`publish(event)`).
|
|
109
|
+
- `@OnEvent(EventClass)`: Decorator to mark a method as an event handler.
|
|
110
|
+
|
|
111
|
+
### Interfaces
|
|
112
|
+
- `EventBusTransport`: Contract for implementing external transport adapters.
|
|
113
|
+
|
|
114
|
+
## Related Packages
|
|
115
|
+
|
|
116
|
+
- `@fluojs/cqrs`: Built on top of the event bus for more formal architectural patterns.
|
|
117
|
+
- `@fluojs/redis`: Provides the clients required for `RedisEventBusTransport`.
|
|
118
|
+
|
|
119
|
+
## Example Sources
|
|
120
|
+
|
|
121
|
+
- `packages/event-bus/src/module.test.ts`: Handler discovery and publish/subscribe tests.
|
|
122
|
+
- `packages/event-bus/src/public-surface.test.ts`: Public API contract verification.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { EventType } from './types.js';
|
|
2
|
+
type StandardMethodDecoratorFn = (value: Function, context: ClassMethodDecoratorContext) => void;
|
|
3
|
+
type MethodDecoratorLike = StandardMethodDecoratorFn;
|
|
4
|
+
/**
|
|
5
|
+
* Marks a public instance method as the handler for one event type.
|
|
6
|
+
*
|
|
7
|
+
* @param eventType Event constructor that should trigger the decorated method.
|
|
8
|
+
* @returns A method decorator that stores handler metadata for bootstrap discovery.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { OnEvent } from '@fluojs/event-bus';
|
|
13
|
+
*
|
|
14
|
+
* class UserRegisteredEvent {
|
|
15
|
+
* constructor(public readonly email: string) {}
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* export class NotificationService {
|
|
19
|
+
* @OnEvent(UserRegisteredEvent)
|
|
20
|
+
* async notify(event: UserRegisteredEvent) {
|
|
21
|
+
* await mailer.send(event.email);
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function OnEvent(eventType: EventType): MethodDecoratorLike;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAwB,SAAS,EAAE,MAAM,YAAY,CAAC;AAIlE,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACjG,KAAK,mBAAmB,GAAG,yBAAyB,CAAC;AAqBrD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,mBAAmB,CAkBjE"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { metadataSymbol } from '@fluojs/core/internal';
|
|
2
|
+
import { eventBusMetadataSymbol } from './metadata.js';
|
|
3
|
+
function getStandardMetadataBag(metadata) {
|
|
4
|
+
void metadataSymbol;
|
|
5
|
+
return metadata;
|
|
6
|
+
}
|
|
7
|
+
function defineStandardEventHandlerMetadata(metadata, propertyKey, eventHandlerMetadata) {
|
|
8
|
+
const bag = getStandardMetadataBag(metadata);
|
|
9
|
+
const current = bag[eventBusMetadataSymbol];
|
|
10
|
+
const map = current ?? new Map();
|
|
11
|
+
map.set(propertyKey, {
|
|
12
|
+
eventType: eventHandlerMetadata.eventType
|
|
13
|
+
});
|
|
14
|
+
bag[eventBusMetadataSymbol] = map;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Marks a public instance method as the handler for one event type.
|
|
19
|
+
*
|
|
20
|
+
* @param eventType Event constructor that should trigger the decorated method.
|
|
21
|
+
* @returns A method decorator that stores handler metadata for bootstrap discovery.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { OnEvent } from '@fluojs/event-bus';
|
|
26
|
+
*
|
|
27
|
+
* class UserRegisteredEvent {
|
|
28
|
+
* constructor(public readonly email: string) {}
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* export class NotificationService {
|
|
32
|
+
* @OnEvent(UserRegisteredEvent)
|
|
33
|
+
* async notify(event: UserRegisteredEvent) {
|
|
34
|
+
* await mailer.send(event.email);
|
|
35
|
+
* }
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function OnEvent(eventType) {
|
|
40
|
+
const decorator = (_value, context) => {
|
|
41
|
+
if (context.private) {
|
|
42
|
+
throw new Error('@OnEvent() cannot be used on private methods.');
|
|
43
|
+
}
|
|
44
|
+
if (context.static) {
|
|
45
|
+
throw new Error('@OnEvent() cannot be used on static methods.');
|
|
46
|
+
}
|
|
47
|
+
const metadata = {
|
|
48
|
+
eventType
|
|
49
|
+
};
|
|
50
|
+
defineStandardEventHandlerMetadata(context.metadata, context.name, metadata);
|
|
51
|
+
};
|
|
52
|
+
return decorator;
|
|
53
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { OnEvent } from './decorators.js';
|
|
2
|
+
export { EventBusModule } from './module.js';
|
|
3
|
+
export { EventBusLifecycleService } from './service.js';
|
|
4
|
+
export * from './status.js';
|
|
5
|
+
export { EVENT_BUS } from './tokens.js';
|
|
6
|
+
export type { EventBus, EventBusModuleOptions, EventBusTransport, EventPublishOptions, EventType } from './types.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,QAAQ,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type MetadataPropertyKey } from '@fluojs/core';
|
|
2
|
+
import type { EventHandlerMetadata } from './types.js';
|
|
3
|
+
export declare function defineEventHandlerMetadata(target: object, propertyKey: MetadataPropertyKey, metadata: EventHandlerMetadata): void;
|
|
4
|
+
export declare function getEventHandlerMetadata(target: object, propertyKey: MetadataPropertyKey): EventHandlerMetadata | undefined;
|
|
5
|
+
export declare function getEventHandlerMetadataEntries(target: object): Array<{
|
|
6
|
+
metadata: EventHandlerMetadata;
|
|
7
|
+
propertyKey: MetadataPropertyKey;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const eventBusMetadataSymbol: symbol;
|
|
10
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsCvD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,mBAAmB,EAChC,QAAQ,EAAE,oBAAoB,GAC7B,IAAI,CAEN;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,GAAG,oBAAoB,GAAG,SAAS,CAS1H;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,QAAQ,EAAE,oBAAoB,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAW7E;AAED,eAAO,MAAM,sBAAsB,QAAkC,CAAC"}
|
package/dist/metadata.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ensureSymbolMetadataPolyfill, metadataSymbol } from '@fluojs/core/internal';
|
|
2
|
+
void ensureSymbolMetadataPolyfill();
|
|
3
|
+
const standardEventHandlerMetadataKey = Symbol.for('fluo.event-bus.standard.handler');
|
|
4
|
+
const eventHandlerMetadataStore = new WeakMap();
|
|
5
|
+
function cloneEventHandlerMetadata(metadata) {
|
|
6
|
+
return {
|
|
7
|
+
eventType: metadata.eventType
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function getStandardMetadataBag(target) {
|
|
11
|
+
return target[metadataSymbol];
|
|
12
|
+
}
|
|
13
|
+
function getStandardEventHandlerMap(target) {
|
|
14
|
+
const constructor = target.constructor;
|
|
15
|
+
return constructor ? getStandardMetadataBag(constructor)?.[standardEventHandlerMetadataKey] : undefined;
|
|
16
|
+
}
|
|
17
|
+
function getOrCreateEventHandlerMap(target) {
|
|
18
|
+
let map = eventHandlerMetadataStore.get(target);
|
|
19
|
+
if (!map) {
|
|
20
|
+
map = new Map();
|
|
21
|
+
eventHandlerMetadataStore.set(target, map);
|
|
22
|
+
}
|
|
23
|
+
return map;
|
|
24
|
+
}
|
|
25
|
+
export function defineEventHandlerMetadata(target, propertyKey, metadata) {
|
|
26
|
+
getOrCreateEventHandlerMap(target).set(propertyKey, cloneEventHandlerMetadata(metadata));
|
|
27
|
+
}
|
|
28
|
+
export function getEventHandlerMetadata(target, propertyKey) {
|
|
29
|
+
const stored = eventHandlerMetadataStore.get(target)?.get(propertyKey);
|
|
30
|
+
const standard = getStandardEventHandlerMap(target)?.get(propertyKey);
|
|
31
|
+
if (!stored && !standard) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return cloneEventHandlerMetadata(stored ?? standard);
|
|
35
|
+
}
|
|
36
|
+
export function getEventHandlerMetadataEntries(target) {
|
|
37
|
+
const stored = eventHandlerMetadataStore.get(target) ?? new Map();
|
|
38
|
+
const standard = getStandardEventHandlerMap(target) ?? new Map();
|
|
39
|
+
const keys = new Set([...stored.keys(), ...standard.keys()]);
|
|
40
|
+
return Array.from(keys).map(propertyKey => ({
|
|
41
|
+
metadata: getEventHandlerMetadata(target, propertyKey),
|
|
42
|
+
propertyKey
|
|
43
|
+
})).filter(entry => entry.metadata !== undefined);
|
|
44
|
+
}
|
|
45
|
+
export const eventBusMetadataSymbol = standardEventHandlerMetadataKey;
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ModuleType } from '@fluojs/runtime';
|
|
2
|
+
import type { EventBusModuleOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Runtime module entrypoint for the in-process event bus.
|
|
5
|
+
*/
|
|
6
|
+
export declare class EventBusModule {
|
|
7
|
+
/**
|
|
8
|
+
* Registers the event-bus providers as a global module.
|
|
9
|
+
*
|
|
10
|
+
* @param options Event bus module options for publish defaults and optional transport integration.
|
|
11
|
+
* @returns A module definition that exports `EventBusLifecycleService` and the compatibility token `EVENT_BUS`.
|
|
12
|
+
*/
|
|
13
|
+
static forRoot(options?: EventBusModuleOptions): ModuleType;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAIhE,OAAO,KAAK,EAAE,qBAAqB,EAAuB,MAAM,YAAY,CAAC;AAoB7E;;GAEG;AACH,qBAAa,cAAc;IACzB;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,qBAA0B,GAAG,UAAU;CAShE"}
|
package/dist/module.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineModule } from '@fluojs/runtime';
|
|
2
|
+
import { EventBusLifecycleService } from './service.js';
|
|
3
|
+
import { EVENT_BUS, EVENT_BUS_OPTIONS } from './tokens.js';
|
|
4
|
+
function createEventBusProviders(options = {}) {
|
|
5
|
+
return [{
|
|
6
|
+
provide: EVENT_BUS_OPTIONS,
|
|
7
|
+
useValue: options
|
|
8
|
+
}, EventBusLifecycleService, {
|
|
9
|
+
inject: [EventBusLifecycleService],
|
|
10
|
+
provide: EVENT_BUS,
|
|
11
|
+
useFactory: service => ({
|
|
12
|
+
publish: (event, publishOptions) => service.publish(event, publishOptions)
|
|
13
|
+
})
|
|
14
|
+
}];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Runtime module entrypoint for the in-process event bus.
|
|
19
|
+
*/
|
|
20
|
+
export class EventBusModule {
|
|
21
|
+
/**
|
|
22
|
+
* Registers the event-bus providers as a global module.
|
|
23
|
+
*
|
|
24
|
+
* @param options Event bus module options for publish defaults and optional transport integration.
|
|
25
|
+
* @returns A module definition that exports `EventBusLifecycleService` and the compatibility token `EVENT_BUS`.
|
|
26
|
+
*/
|
|
27
|
+
static forRoot(options = {}) {
|
|
28
|
+
class EventBusModuleDefinition {}
|
|
29
|
+
return defineModule(EventBusModuleDefinition, {
|
|
30
|
+
exports: [EventBusLifecycleService, EVENT_BUS],
|
|
31
|
+
global: true,
|
|
32
|
+
providers: createEventBusProviders(options)
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Container } from '@fluojs/di';
|
|
2
|
+
import { type ApplicationLogger, type CompiledModule, type OnApplicationBootstrap, type OnApplicationShutdown } from '@fluojs/runtime';
|
|
3
|
+
import type { EventBus, EventBusModuleOptions, EventPublishOptions } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Lifecycle-managed in-process event bus with optional external transport fan-out.
|
|
6
|
+
*
|
|
7
|
+
* The service discovers `@OnEvent()` handlers, clones payloads before dispatch,
|
|
8
|
+
* and can publish the same events to an external transport such as Redis Pub/Sub.
|
|
9
|
+
*/
|
|
10
|
+
export declare class EventBusLifecycleService implements EventBus, OnApplicationBootstrap, OnApplicationShutdown {
|
|
11
|
+
private readonly runtimeContainer;
|
|
12
|
+
private readonly compiledModules;
|
|
13
|
+
private readonly logger;
|
|
14
|
+
private readonly moduleOptions;
|
|
15
|
+
private descriptors;
|
|
16
|
+
private discoveryPromise;
|
|
17
|
+
private discovered;
|
|
18
|
+
private lifecycleState;
|
|
19
|
+
private readonly handlerInstances;
|
|
20
|
+
private readonly subscribedChannels;
|
|
21
|
+
private transportCloseFailures;
|
|
22
|
+
private transportPublishFailures;
|
|
23
|
+
private transportSubscribeFailures;
|
|
24
|
+
private readonly transport;
|
|
25
|
+
constructor(runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger, moduleOptions: EventBusModuleOptions);
|
|
26
|
+
onApplicationBootstrap(): Promise<void>;
|
|
27
|
+
onApplicationShutdown(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a platform status snapshot for health checks and diagnostics.
|
|
30
|
+
*
|
|
31
|
+
* @returns A structured snapshot describing discovery state, transport wiring, and failure counters.
|
|
32
|
+
*/
|
|
33
|
+
createPlatformStatusSnapshot(): import("./status.js").EventBusPlatformStatusSnapshot;
|
|
34
|
+
/**
|
|
35
|
+
* Publishes one event to matching local handlers and, when configured, to the external transport.
|
|
36
|
+
*
|
|
37
|
+
* @param event Event instance to publish.
|
|
38
|
+
* @param options Optional timeout, abort signal, and wait-for-handler controls.
|
|
39
|
+
* @returns A promise that resolves once the configured local/transport publication completes.
|
|
40
|
+
*/
|
|
41
|
+
publish(event: object, options?: EventPublishOptions): Promise<void>;
|
|
42
|
+
private matchEventDescriptors;
|
|
43
|
+
private createInvocationTasks;
|
|
44
|
+
private createBackgroundInvocationTasks;
|
|
45
|
+
private runInvocationTasksInBackground;
|
|
46
|
+
private invokeHandlerInBackground;
|
|
47
|
+
private ensureDiscovered;
|
|
48
|
+
private resolvePublishOptions;
|
|
49
|
+
private normalizeTimeoutMs;
|
|
50
|
+
private discoverHandlers;
|
|
51
|
+
private channelFromEventType;
|
|
52
|
+
private channelsForTransportPublish;
|
|
53
|
+
private publishToTransport;
|
|
54
|
+
private subscribeTransportChannels;
|
|
55
|
+
private subscribeTransportChannel;
|
|
56
|
+
private preloadHandlerInstances;
|
|
57
|
+
private invokeHandlerWithBounds;
|
|
58
|
+
private logPublishCancelledBeforeDispatch;
|
|
59
|
+
private logBoundedInvocationError;
|
|
60
|
+
private awaitInvocationBounds;
|
|
61
|
+
private createInvocationBounds;
|
|
62
|
+
private createTimeoutBound;
|
|
63
|
+
private createAbortBound;
|
|
64
|
+
private discoverHandlerDescriptors;
|
|
65
|
+
private shouldSkipNonSingletonCandidate;
|
|
66
|
+
private isDuplicateHandlerRegistration;
|
|
67
|
+
private createHandlerDescriptor;
|
|
68
|
+
private discoveryCandidates;
|
|
69
|
+
private invokeHandler;
|
|
70
|
+
private resolveHandlerInstance;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,YAAY,CAAC;AACtD,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC3B,MAAM,iBAAiB,CAAC;AAMzB,OAAO,KAAK,EACV,QAAQ,EACR,qBAAqB,EAGrB,mBAAmB,EAEpB,MAAM,YAAY,CAAC;AA8DpB;;;;;GAKG;AACH,qBACa,wBAAyB,YAAW,QAAQ,EAAE,sBAAsB,EAAE,qBAAqB;IAapG,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAfhC,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,cAAc,CAAsF;IAC5G,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsC;IACvE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,wBAAwB,CAAK;IACrC,OAAO,CAAC,0BAA0B,CAAK;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;gBAGvC,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,qBAAqB;IAKjD,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAavC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB5C;;;;OAIG;IACH,4BAA4B;IAa5B;;;;;;OAMG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B1E,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,+BAA+B;IAWvC,OAAO,CAAC,8BAA8B;YAMxB,yBAAyB;YAazB,gBAAgB;IAqB9B,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,kBAAkB;YAQZ,gBAAgB;IAW9B,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,2BAA2B;YAcrB,kBAAkB;YAyBlB,0BAA0B;YAmB1B,yBAAyB;YAqCzB,uBAAuB;YAUvB,uBAAuB;IAmBrC,OAAO,CAAC,iCAAiC;IAOzC,OAAO,CAAC,yBAAyB;YAwBnB,qBAAqB;IAuBnC,OAAO,CAAC,sBAAsB;IAqB9B,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,0BAA0B;IAyBlC,OAAO,CAAC,+BAA+B;IAevC,OAAO,CAAC,8BAA8B;IA4BtC,OAAO,CAAC,uBAAuB;IAe/B,OAAO,CAAC,mBAAmB;YAsCb,aAAa;YA4Bb,sBAAsB;CAsBrC"}
|