@wild-framework/events 0.1.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Wild Framework 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.md ADDED
@@ -0,0 +1,29 @@
1
+ # @wild-framework/events
2
+
3
+ Typed event bus for [Wild Framework](https://github.com/your-org/wild-framework).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @wild-framework/events
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { EventBus } from "@wild-framework/events";
15
+
16
+ class UserRegistered {
17
+ constructor(public readonly user: User) {}
18
+ }
19
+
20
+ events.listen(UserRegistered, async (event) => {
21
+ await mail.send(event.user.email);
22
+ });
23
+
24
+ await events.dispatch(new UserRegistered(user));
25
+ ```
26
+
27
+ ## License
28
+
29
+ MIT
package/dist/bus.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Any class constructor. Events are identified by their constructor.
3
+ */
4
+ type EventConstructor<T = unknown> = abstract new (...args: any[]) => T;
5
+ /**
6
+ * A listener function that receives a typed event instance.
7
+ */
8
+ type Listener<T> = (event: T) => void | Promise<void>;
9
+ /**
10
+ * Typed event bus.
11
+ *
12
+ * Events are classes (past tense per NAMING.md). Listeners are registered
13
+ * by event constructor and receive fully typed event instances.
14
+ *
15
+ * On dispatch, all matching listeners are called. If any listener throws,
16
+ * the errors are collected and thrown as an `EventDispatchError`.
17
+ */
18
+ export declare class EventBus {
19
+ private listeners;
20
+ /**
21
+ * Register a listener for an event class.
22
+ *
23
+ * The listener receives a typed event instance.
24
+ *
25
+ * @example
26
+ * events.listen(UserRegistered, async (event) => {
27
+ * // event is UserRegistered
28
+ * });
29
+ */
30
+ listen<T>(eventClass: EventConstructor<T>, listener: Listener<T>): void;
31
+ /**
32
+ * Remove a previously registered listener.
33
+ */
34
+ remove<T>(eventClass: EventConstructor<T>, listener: Listener<T>): void;
35
+ /**
36
+ * Dispatch an event to all registered listeners.
37
+ *
38
+ * Listeners are called in registration order. If any listener throws,
39
+ * errors are collected and thrown as `EventDispatchError` after all
40
+ * listeners have been called.
41
+ */
42
+ dispatch<T extends object>(event: T): Promise<void>;
43
+ /**
44
+ * Check whether any listeners are registered for an event class.
45
+ */
46
+ has<T>(eventClass: EventConstructor<T>): boolean;
47
+ }
48
+ export {};
49
+ //# sourceMappingURL=bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bus.d.ts","sourceRoot":"","sources":["../src/bus.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,KAAK,gBAAgB,CAAC,CAAC,GAAG,OAAO,IAAI,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAExE;;GAEG;AACH,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtD;;;;;;;;GAQG;AACH,qBAAa,QAAQ;IACjB,OAAO,CAAC,SAAS,CAAmD;IAMpE;;;;;;;;;OASG;IACH,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IASvE;;OAEG;IACH,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IAQvE;;;;;;OAMG;IACG,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BzD;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO;CAInD"}
package/dist/bus.js ADDED
@@ -0,0 +1,80 @@
1
+ import { EventDispatchError } from "./errors.js";
2
+ /**
3
+ * Typed event bus.
4
+ *
5
+ * Events are classes (past tense per NAMING.md). Listeners are registered
6
+ * by event constructor and receive fully typed event instances.
7
+ *
8
+ * On dispatch, all matching listeners are called. If any listener throws,
9
+ * the errors are collected and thrown as an `EventDispatchError`.
10
+ */
11
+ export class EventBus {
12
+ listeners = new Map();
13
+ // -------------------------------------------------------------------
14
+ // Registration
15
+ // -------------------------------------------------------------------
16
+ /**
17
+ * Register a listener for an event class.
18
+ *
19
+ * The listener receives a typed event instance.
20
+ *
21
+ * @example
22
+ * events.listen(UserRegistered, async (event) => {
23
+ * // event is UserRegistered
24
+ * });
25
+ */
26
+ listen(eventClass, listener) {
27
+ let set = this.listeners.get(eventClass);
28
+ if (!set) {
29
+ set = new Set();
30
+ this.listeners.set(eventClass, set);
31
+ }
32
+ set.add(listener);
33
+ }
34
+ /**
35
+ * Remove a previously registered listener.
36
+ */
37
+ remove(eventClass, listener) {
38
+ this.listeners.get(eventClass)?.delete(listener);
39
+ }
40
+ // -------------------------------------------------------------------
41
+ // Dispatch
42
+ // -------------------------------------------------------------------
43
+ /**
44
+ * Dispatch an event to all registered listeners.
45
+ *
46
+ * Listeners are called in registration order. If any listener throws,
47
+ * errors are collected and thrown as `EventDispatchError` after all
48
+ * listeners have been called.
49
+ */
50
+ async dispatch(event) {
51
+ const eventClass = event.constructor;
52
+ const listeners = this.listeners.get(eventClass);
53
+ if (!listeners || listeners.size === 0) {
54
+ return;
55
+ }
56
+ const failures = [];
57
+ for (const listener of listeners) {
58
+ try {
59
+ await listener(event);
60
+ }
61
+ catch (error) {
62
+ failures.push({
63
+ listener: listener.name || "anonymous",
64
+ error: error instanceof Error ? error : new Error(String(error)),
65
+ });
66
+ }
67
+ }
68
+ if (failures.length > 0) {
69
+ throw new EventDispatchError(failures);
70
+ }
71
+ }
72
+ /**
73
+ * Check whether any listeners are registered for an event class.
74
+ */
75
+ has(eventClass) {
76
+ const set = this.listeners.get(eventClass);
77
+ return (set?.size ?? 0) > 0;
78
+ }
79
+ }
80
+ //# sourceMappingURL=bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bus.js","sourceRoot":"","sources":["../src/bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAYjD;;;;;;;;GAQG;AACH,MAAM,OAAO,QAAQ;IACT,SAAS,GAAG,IAAI,GAAG,EAAwC,CAAC;IAEpE,sEAAsE;IACtE,eAAe;IACf,sEAAsE;IAEtE;;;;;;;;;OASG;IACH,MAAM,CAAI,UAA+B,EAAE,QAAqB;QAC5D,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,CAAC;YACP,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACxC,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,MAAM,CAAI,UAA+B,EAAE,QAAqB;QAC5D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,sEAAsE;IACtE,WAAW;IACX,sEAAsE;IAEtE;;;;;;OAMG;IACH,KAAK,CAAC,QAAQ,CAAmB,KAAQ;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAkC,CAAC;QAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAEjD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrC,OAAO;QACX,CAAC;QAED,MAAM,QAAQ,GAA8C,EAAE,CAAC;QAE/D,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACD,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,CAAC;oBACV,QAAQ,EAAE,QAAQ,CAAC,IAAI,IAAI,WAAW;oBACtC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;iBACnE,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC3C,CAAC;IACL,CAAC;IAED;;OAEG;IACH,GAAG,CAAI,UAA+B;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;CACJ"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Thrown when one or more listeners fail during event dispatch.
3
+ *
4
+ * Each error includes the listener that failed and the original error.
5
+ */
6
+ export declare class EventDispatchError extends Error {
7
+ readonly failures: Array<{
8
+ listener: string;
9
+ error: Error;
10
+ }>;
11
+ constructor(failures: Array<{
12
+ listener: string;
13
+ error: Error;
14
+ }>);
15
+ }
16
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IACzC,SAAgB,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;gBAExD,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;CAMlE"}
package/dist/errors.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Thrown when one or more listeners fail during event dispatch.
3
+ *
4
+ * Each error includes the listener that failed and the original error.
5
+ */
6
+ export class EventDispatchError extends Error {
7
+ failures;
8
+ constructor(failures) {
9
+ const names = failures.map((f) => f.listener).join(", ");
10
+ super(`Event dispatch failed for listener(s): ${names}`);
11
+ this.name = "EventDispatchError";
12
+ this.failures = failures;
13
+ }
14
+ }
15
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACzB,QAAQ,CAA4C;IAEpE,YAAY,QAAmD;QAC3D,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,KAAK,CAAC,0CAA0C,KAAK,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;CACJ"}
@@ -0,0 +1,4 @@
1
+ export { EventBus } from "./bus.js";
2
+ export { EventProvider } from "./provider.js";
3
+ export { EventDispatchError } from "./errors.js";
4
+ //# 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,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { EventBus } from "./bus.js";
2
+ export { EventProvider } from "./provider.js";
3
+ export { EventDispatchError } from "./errors.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { Provider, Application } from "@wild-framework/core";
2
+ /**
3
+ * Registers the event bus with the application.
4
+ *
5
+ * Must be registered after `ContainerProvider`.
6
+ * Other providers resolve `EventBus` from the container and register listeners.
7
+ */
8
+ export declare class EventProvider implements Provider {
9
+ register(app: Application): void;
10
+ }
11
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIlE;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,QAAQ;IAC1C,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI;CAKnC"}
@@ -0,0 +1,16 @@
1
+ import { Container } from "@wild-framework/container";
2
+ import { EventBus } from "./bus.js";
3
+ /**
4
+ * Registers the event bus with the application.
5
+ *
6
+ * Must be registered after `ContainerProvider`.
7
+ * Other providers resolve `EventBus` from the container and register listeners.
8
+ */
9
+ export class EventProvider {
10
+ register(app) {
11
+ const container = app.resolve(Container);
12
+ const bus = new EventBus();
13
+ container.singleton(EventBus, () => bus);
14
+ }
15
+ }
16
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACtB,QAAQ,CAAC,GAAgB;QACrB,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;CACJ"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@wild-framework/events",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "license": "MIT",
20
+ "author": "Sphah",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/KhandaSoftware/wild-framework.git"
24
+ },
25
+ "description": "Typed event bus for Wild Framework.",
26
+ "keywords": [
27
+ "wild",
28
+ "framework",
29
+ "events",
30
+ "event-bus",
31
+ "listeners"
32
+ ],
33
+ "dependencies": {
34
+ "@wild-framework/core": "0.1.0",
35
+ "@wild-framework/container": "0.1.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsc",
39
+ "clean": "rm -rf dist",
40
+ "test": "vitest run"
41
+ }
42
+ }