@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
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Redis } from 'ioredis';
|
|
2
|
+
import type { EventBusTransport } from '../types.js';
|
|
3
|
+
/** Clients used by {@link RedisEventBusTransport} for publish and subscribe responsibilities. */
|
|
4
|
+
export interface RedisEventBusTransportOptions {
|
|
5
|
+
publishClient: Redis;
|
|
6
|
+
subscribeClient: Redis;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Redis Pub/Sub transport adapter for cross-process event fan-out.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import Redis from 'ioredis';
|
|
14
|
+
* import { RedisEventBusTransport } from '@fluojs/event-bus/redis';
|
|
15
|
+
*
|
|
16
|
+
* const publishClient = new Redis();
|
|
17
|
+
* const subscribeClient = new Redis();
|
|
18
|
+
*
|
|
19
|
+
* const transport = new RedisEventBusTransport({ publishClient, subscribeClient });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class RedisEventBusTransport implements EventBusTransport {
|
|
23
|
+
private readonly publishClient;
|
|
24
|
+
private readonly subscribeClient;
|
|
25
|
+
private readonly handlersByChannel;
|
|
26
|
+
private messageListenerAttached;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a Redis-backed event-bus transport.
|
|
29
|
+
*
|
|
30
|
+
* @param options Redis clients dedicated to publish and subscribe operations.
|
|
31
|
+
*/
|
|
32
|
+
constructor(options: RedisEventBusTransportOptions);
|
|
33
|
+
private readonly onMessage;
|
|
34
|
+
/**
|
|
35
|
+
* Publishes one event payload to a Redis Pub/Sub channel.
|
|
36
|
+
*
|
|
37
|
+
* @param channel Channel name derived from the event type.
|
|
38
|
+
* @param payload Serializable event payload.
|
|
39
|
+
* @returns A promise that resolves once Redis accepts the publication.
|
|
40
|
+
*/
|
|
41
|
+
publish(channel: string, payload: unknown): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Subscribes one local handler to a Redis Pub/Sub channel.
|
|
44
|
+
*
|
|
45
|
+
* @param channel Channel name to subscribe to.
|
|
46
|
+
* @param handler Async handler invoked with JSON-decoded payloads.
|
|
47
|
+
* @returns A promise that resolves once Redis confirms the subscription.
|
|
48
|
+
*/
|
|
49
|
+
subscribe(channel: string, handler: (payload: unknown) => Promise<void>): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Unsubscribes all tracked channels and detaches the Redis message listener.
|
|
52
|
+
*
|
|
53
|
+
* @returns A promise that resolves once the transport cleanup finishes.
|
|
54
|
+
*/
|
|
55
|
+
close(): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=redis-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-transport.d.ts","sourceRoot":"","sources":["../../src/transports/redis-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,iGAAiG;AACjG,MAAM,WAAW,6BAA6B;IAC5C,aAAa,EAAE,KAAK,CAAC;IACrB,eAAe,EAAE,KAAK,CAAC;CACxB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,sBAAuB,YAAW,iBAAiB;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0D;IAC5F,OAAO,CAAC,uBAAuB,CAAS;IAExC;;;;OAIG;gBACS,OAAO,EAAE,6BAA6B;IAKlD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAgBxB;IAEF;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/D;;;;;;OAMG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7F;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAsB7B"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Clients used by {@link RedisEventBusTransport} for publish and subscribe responsibilities. */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Redis Pub/Sub transport adapter for cross-process event fan-out.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import Redis from 'ioredis';
|
|
9
|
+
* import { RedisEventBusTransport } from '@fluojs/event-bus/redis';
|
|
10
|
+
*
|
|
11
|
+
* const publishClient = new Redis();
|
|
12
|
+
* const subscribeClient = new Redis();
|
|
13
|
+
*
|
|
14
|
+
* const transport = new RedisEventBusTransport({ publishClient, subscribeClient });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export class RedisEventBusTransport {
|
|
18
|
+
publishClient;
|
|
19
|
+
subscribeClient;
|
|
20
|
+
handlersByChannel = new Map();
|
|
21
|
+
messageListenerAttached = false;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a Redis-backed event-bus transport.
|
|
25
|
+
*
|
|
26
|
+
* @param options Redis clients dedicated to publish and subscribe operations.
|
|
27
|
+
*/
|
|
28
|
+
constructor(options) {
|
|
29
|
+
this.publishClient = options.publishClient;
|
|
30
|
+
this.subscribeClient = options.subscribeClient;
|
|
31
|
+
}
|
|
32
|
+
onMessage = (receivedChannel, message) => {
|
|
33
|
+
const handler = this.handlersByChannel.get(receivedChannel);
|
|
34
|
+
if (!handler) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
let payload;
|
|
38
|
+
try {
|
|
39
|
+
payload = JSON.parse(message);
|
|
40
|
+
} catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
void handler(payload);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Publishes one event payload to a Redis Pub/Sub channel.
|
|
48
|
+
*
|
|
49
|
+
* @param channel Channel name derived from the event type.
|
|
50
|
+
* @param payload Serializable event payload.
|
|
51
|
+
* @returns A promise that resolves once Redis accepts the publication.
|
|
52
|
+
*/
|
|
53
|
+
async publish(channel, payload) {
|
|
54
|
+
await this.publishClient.publish(channel, JSON.stringify(payload));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Subscribes one local handler to a Redis Pub/Sub channel.
|
|
59
|
+
*
|
|
60
|
+
* @param channel Channel name to subscribe to.
|
|
61
|
+
* @param handler Async handler invoked with JSON-decoded payloads.
|
|
62
|
+
* @returns A promise that resolves once Redis confirms the subscription.
|
|
63
|
+
*/
|
|
64
|
+
async subscribe(channel, handler) {
|
|
65
|
+
this.handlersByChannel.set(channel, handler);
|
|
66
|
+
await this.subscribeClient.subscribe(channel);
|
|
67
|
+
if (!this.messageListenerAttached) {
|
|
68
|
+
this.subscribeClient.on('message', this.onMessage);
|
|
69
|
+
this.messageListenerAttached = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Unsubscribes all tracked channels and detaches the Redis message listener.
|
|
75
|
+
*
|
|
76
|
+
* @returns A promise that resolves once the transport cleanup finishes.
|
|
77
|
+
*/
|
|
78
|
+
async close() {
|
|
79
|
+
let closeError;
|
|
80
|
+
const channels = [...this.handlersByChannel.keys()];
|
|
81
|
+
try {
|
|
82
|
+
if (channels.length > 0) {
|
|
83
|
+
await this.subscribeClient.unsubscribe(...channels);
|
|
84
|
+
}
|
|
85
|
+
} catch (error) {
|
|
86
|
+
closeError = error;
|
|
87
|
+
} finally {
|
|
88
|
+
this.handlersByChannel.clear();
|
|
89
|
+
if (this.messageListenerAttached) {
|
|
90
|
+
this.subscribeClient.off('message', this.onMessage);
|
|
91
|
+
this.messageListenerAttached = false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (closeError) {
|
|
95
|
+
throw closeError;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { MetadataPropertyKey, Token } from '@fluojs/core';
|
|
2
|
+
/** Constructor type used to identify one published event shape and optional stable transport key. */
|
|
3
|
+
export interface EventType<TEvent extends object = object> {
|
|
4
|
+
new (...args: never[]): TEvent;
|
|
5
|
+
readonly eventKey?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Metadata stored by {@link OnEvent}. */
|
|
8
|
+
export interface EventHandlerMetadata {
|
|
9
|
+
eventType: EventType;
|
|
10
|
+
}
|
|
11
|
+
/** Runtime descriptor for one discovered event handler method. */
|
|
12
|
+
export interface EventHandlerDescriptor {
|
|
13
|
+
eventType: EventType;
|
|
14
|
+
methodKey: MetadataPropertyKey;
|
|
15
|
+
methodName: string;
|
|
16
|
+
moduleName: string;
|
|
17
|
+
targetName: string;
|
|
18
|
+
token: Token;
|
|
19
|
+
}
|
|
20
|
+
/** Options that control how one `publish()` call waits for local handlers. */
|
|
21
|
+
export interface EventPublishOptions {
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
waitForHandlers?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Transport adapter contract for cross-process event fan-out and inbound subscription wiring. */
|
|
27
|
+
export interface EventBusTransport {
|
|
28
|
+
/**
|
|
29
|
+
* Publish an event payload to the external transport under the given channel name.
|
|
30
|
+
* Called by the event bus on every local `publish()` invocation when a transport is configured.
|
|
31
|
+
*/
|
|
32
|
+
publish(channel: string, payload: unknown): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Subscribe to incoming messages on the given channel from the external transport.
|
|
35
|
+
* The event bus calls this once per discovered local handler during bootstrap.
|
|
36
|
+
* Received messages are deserialized and dispatched to matching local handlers.
|
|
37
|
+
*/
|
|
38
|
+
subscribe(channel: string, handler: (payload: unknown) => Promise<void>): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Tear down any open connections. Called during application shutdown.
|
|
41
|
+
*/
|
|
42
|
+
close(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/** Module options for local event dispatch defaults and optional external fan-out. */
|
|
45
|
+
export interface EventBusModuleOptions {
|
|
46
|
+
publish?: {
|
|
47
|
+
timeoutMs?: number;
|
|
48
|
+
waitForHandlers?: boolean;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Optional external transport adapter (e.g. Redis Pub/Sub).
|
|
52
|
+
* When provided, `publish()` fans out to the transport in addition to local handlers,
|
|
53
|
+
* and incoming transport messages are dispatched to local handlers on bootstrap.
|
|
54
|
+
*/
|
|
55
|
+
transport?: EventBusTransport;
|
|
56
|
+
}
|
|
57
|
+
/** Event publishing facade exposed by the event-bus module. */
|
|
58
|
+
export interface EventBus {
|
|
59
|
+
/**
|
|
60
|
+
* Publishes one event to matching local handlers and the optional external transport.
|
|
61
|
+
*
|
|
62
|
+
* @param event Event instance to publish.
|
|
63
|
+
* @param options Optional timeout, abort signal, and wait-for-handler controls.
|
|
64
|
+
* @returns A promise that resolves once the configured publish workflow completes.
|
|
65
|
+
*/
|
|
66
|
+
publish(event: object, options?: EventPublishOptions): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE/D,qGAAqG;AACrG,MAAM,WAAW,SAAS,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM;IACvD,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,8EAA8E;AAC9E,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,kGAAkG;AAClG,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExF;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,sFAAsF;AACtF,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,CAAC;IACF;;;;OAIG;IACH,SAAS,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED,+DAA+D;AAC/D,MAAM,WAAW,QAAQ;IACvB;;;;;;OAMG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluojs/event-bus",
|
|
3
|
+
"description": "In-process event publishing and handler discovery for Fluo applications.",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"fluo",
|
|
6
|
+
"event-bus",
|
|
7
|
+
"events",
|
|
8
|
+
"pubsub",
|
|
9
|
+
"in-process"
|
|
10
|
+
],
|
|
11
|
+
"version": "1.0.0-beta.1",
|
|
12
|
+
"private": false,
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/fluojs/fluo.git",
|
|
17
|
+
"directory": "packages/event-bus"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=20.0.0"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./redis": {
|
|
32
|
+
"types": "./dist/transports/redis-transport.d.ts",
|
|
33
|
+
"import": "./dist/transports/redis-transport.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"main": "./dist/index.js",
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"files": [
|
|
39
|
+
"dist"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@fluojs/di": "^1.0.0-beta.1",
|
|
43
|
+
"@fluojs/core": "^1.0.0-beta.1",
|
|
44
|
+
"@fluojs/runtime": "^1.0.0-beta.1"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"ioredis": "^5.0.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"ioredis": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"vitest": "^3.2.4"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|
|
59
|
+
"build": "pnpm exec babel src --extensions .ts --ignore 'src/**/*.test.ts' --out-dir dist --config-file ../../tooling/babel/babel.config.cjs && pnpm exec tsc -p tsconfig.build.json",
|
|
60
|
+
"typecheck": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
61
|
+
"test": "pnpm exec vitest run -c vitest.config.ts",
|
|
62
|
+
"test:watch": "pnpm exec vitest -c vitest.config.ts"
|
|
63
|
+
}
|
|
64
|
+
}
|