@zudojs/events 0.1.0 → 1.0.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.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -11
  3. package/dist/eventBus/eventBus.core.d.ts +28 -2
  4. package/dist/eventBus/eventBus.core.js +104 -31
  5. package/dist/eventBus/eventBus.publish.d.ts +23 -5
  6. package/dist/eventBus/eventBus.publish.js +72 -32
  7. package/dist/eventBus/eventBus.registration.d.ts +24 -13
  8. package/dist/eventBus/eventBus.registration.js +31 -28
  9. package/dist/eventBus/eventBus.type.d.ts +75 -3
  10. package/dist/eventBus/eventBus.type.js +9 -0
  11. package/dist/eventBus/index.d.ts +2 -0
  12. package/dist/eventBus/index.js +2 -0
  13. package/dist/eventEmitter/eventEmitter.abort.d.ts +11 -2
  14. package/dist/eventEmitter/eventEmitter.abort.js +20 -5
  15. package/dist/eventEmitter/eventEmitter.core.d.ts +14 -3
  16. package/dist/eventEmitter/eventEmitter.core.js +63 -55
  17. package/dist/eventEmitter/eventEmitter.parallel.d.ts +7 -1
  18. package/dist/eventEmitter/eventEmitter.parallel.js +31 -13
  19. package/dist/eventEmitter/eventEmitter.sequential.d.ts +17 -1
  20. package/dist/eventEmitter/eventEmitter.sequential.js +19 -12
  21. package/dist/eventEmitter/eventEmitter.type.d.ts +60 -0
  22. package/dist/eventErrors/eventError.base.d.ts +50 -3
  23. package/dist/eventErrors/eventError.base.js +64 -3
  24. package/dist/eventHandler/eventHandler.core.d.ts +19 -0
  25. package/dist/eventHandler/eventHandler.core.js +67 -4
  26. package/dist/eventMiddleware/eventMiddleware.builder.js +5 -11
  27. package/dist/eventMiddleware/eventMiddleware.helper.js +0 -1
  28. package/dist/eventMiddleware/eventMiddleware.pipeline.d.ts +5 -0
  29. package/dist/eventMiddleware/eventMiddleware.pipeline.js +33 -9
  30. package/dist/eventRegistry/eventRegistry.lifecycle.d.ts +10 -5
  31. package/dist/eventRegistry/eventRegistry.lifecycle.js +23 -10
  32. package/dist/eventRegistry/eventRegistry.queries.d.ts +16 -7
  33. package/dist/eventRegistry/eventRegistry.queries.js +22 -13
  34. package/dist/eventRegistry/eventRegistry.registration.d.ts +14 -7
  35. package/dist/eventRegistry/eventRegistry.registration.js +120 -41
  36. package/dist/eventRegistry/eventRegistry.store.d.ts +12 -5
  37. package/dist/eventRegistry/eventRegistry.store.js +37 -12
  38. package/dist/eventRegistry/eventRegistry.type.d.ts +87 -2
  39. package/dist/eventRegistry/eventRegistry.type.js +5 -0
  40. package/dist/eventSubscription/eventSubscription.core.d.ts +5 -0
  41. package/dist/eventSubscription/eventSubscription.core.js +17 -3
  42. package/dist/eventTypes/eventDefinition.type.d.ts +11 -4
  43. package/dist/eventTypes/eventDefinition.type.js +49 -17
  44. package/dist/eventTypes/eventPayload.type.d.ts +5 -0
  45. package/dist/eventTypes/eventPayload.type.js +56 -15
  46. package/dist/eventTypes/eventType.type.d.ts +22 -5
  47. package/dist/eventTypes/eventType.type.js +33 -11
  48. package/dist/eventTypes/index.d.ts +2 -2
  49. package/dist/eventTypes/index.js +2 -2
  50. package/package.json +22 -14
  51. package/dist/.tsbuildinfo +0 -1
  52. package/dist/eventBus/eventBus.core.d.ts.map +0 -1
  53. package/dist/eventBus/eventBus.core.js.map +0 -1
  54. package/dist/eventBus/eventBus.factory.d.ts.map +0 -1
  55. package/dist/eventBus/eventBus.factory.js.map +0 -1
  56. package/dist/eventBus/eventBus.publish.d.ts.map +0 -1
  57. package/dist/eventBus/eventBus.publish.js.map +0 -1
  58. package/dist/eventBus/eventBus.registration.d.ts.map +0 -1
  59. package/dist/eventBus/eventBus.registration.js.map +0 -1
  60. package/dist/eventBus/eventBus.type.d.ts.map +0 -1
  61. package/dist/eventBus/eventBus.type.js.map +0 -1
  62. package/dist/eventBus/index.d.ts.map +0 -1
  63. package/dist/eventBus/index.js.map +0 -1
  64. package/dist/eventEmitter/eventEmitter.abort.d.ts.map +0 -1
  65. package/dist/eventEmitter/eventEmitter.abort.js.map +0 -1
  66. package/dist/eventEmitter/eventEmitter.core.d.ts.map +0 -1
  67. package/dist/eventEmitter/eventEmitter.core.js.map +0 -1
  68. package/dist/eventEmitter/eventEmitter.parallel.d.ts.map +0 -1
  69. package/dist/eventEmitter/eventEmitter.parallel.js.map +0 -1
  70. package/dist/eventEmitter/eventEmitter.sequential.d.ts.map +0 -1
  71. package/dist/eventEmitter/eventEmitter.sequential.js.map +0 -1
  72. package/dist/eventEmitter/eventEmitter.type.d.ts.map +0 -1
  73. package/dist/eventEmitter/eventEmitter.type.js.map +0 -1
  74. package/dist/eventEmitter/index.d.ts.map +0 -1
  75. package/dist/eventEmitter/index.js.map +0 -1
  76. package/dist/eventErrors/eventError.base.d.ts.map +0 -1
  77. package/dist/eventErrors/eventError.base.js.map +0 -1
  78. package/dist/eventErrors/index.d.ts.map +0 -1
  79. package/dist/eventErrors/index.js.map +0 -1
  80. package/dist/eventHandler/eventHandler.core.d.ts.map +0 -1
  81. package/dist/eventHandler/eventHandler.core.js.map +0 -1
  82. package/dist/eventHandler/index.d.ts.map +0 -1
  83. package/dist/eventHandler/index.js.map +0 -1
  84. package/dist/eventMiddleware/eventMiddleware.builder.d.ts.map +0 -1
  85. package/dist/eventMiddleware/eventMiddleware.builder.js.map +0 -1
  86. package/dist/eventMiddleware/eventMiddleware.helper.d.ts.map +0 -1
  87. package/dist/eventMiddleware/eventMiddleware.helper.js.map +0 -1
  88. package/dist/eventMiddleware/eventMiddleware.pipeline.d.ts.map +0 -1
  89. package/dist/eventMiddleware/eventMiddleware.pipeline.js.map +0 -1
  90. package/dist/eventMiddleware/eventMiddleware.type.d.ts.map +0 -1
  91. package/dist/eventMiddleware/eventMiddleware.type.js.map +0 -1
  92. package/dist/eventMiddleware/index.d.ts.map +0 -1
  93. package/dist/eventMiddleware/index.js.map +0 -1
  94. package/dist/eventRegistry/eventRegistry.lifecycle.d.ts.map +0 -1
  95. package/dist/eventRegistry/eventRegistry.lifecycle.js.map +0 -1
  96. package/dist/eventRegistry/eventRegistry.queries.d.ts.map +0 -1
  97. package/dist/eventRegistry/eventRegistry.queries.js.map +0 -1
  98. package/dist/eventRegistry/eventRegistry.registration.d.ts.map +0 -1
  99. package/dist/eventRegistry/eventRegistry.registration.js.map +0 -1
  100. package/dist/eventRegistry/eventRegistry.store.d.ts.map +0 -1
  101. package/dist/eventRegistry/eventRegistry.store.js.map +0 -1
  102. package/dist/eventRegistry/eventRegistry.type.d.ts.map +0 -1
  103. package/dist/eventRegistry/eventRegistry.type.js.map +0 -1
  104. package/dist/eventRegistry/index.d.ts.map +0 -1
  105. package/dist/eventRegistry/index.js.map +0 -1
  106. package/dist/eventSubscription/eventSubscription.core.d.ts.map +0 -1
  107. package/dist/eventSubscription/eventSubscription.core.js.map +0 -1
  108. package/dist/eventSubscription/index.d.ts.map +0 -1
  109. package/dist/eventSubscription/index.js.map +0 -1
  110. package/dist/eventTypes/eventDefinition.type.d.ts.map +0 -1
  111. package/dist/eventTypes/eventDefinition.type.js.map +0 -1
  112. package/dist/eventTypes/eventPayload.type.d.ts.map +0 -1
  113. package/dist/eventTypes/eventPayload.type.js.map +0 -1
  114. package/dist/eventTypes/eventType.type.d.ts.map +0 -1
  115. package/dist/eventTypes/eventType.type.js.map +0 -1
  116. package/dist/eventTypes/index.d.ts.map +0 -1
  117. package/dist/eventTypes/index.js.map +0 -1
  118. package/dist/index.d.ts.map +0 -1
  119. package/dist/index.js.map +0 -1
@@ -6,30 +6,29 @@ import type { EventTypePattern } from "../eventTypes/eventType.type.js";
6
6
  import type { EventHandlerLike, EventHandlerOptions } from "../eventHandler/eventHandler.core.js";
7
7
  import type { EventSubscription } from "../eventSubscription/eventSubscription.core.js";
8
8
  import type { EventMiddlewareLike, EventMiddlewareOptions, RegisteredEventMiddleware } from "../eventMiddleware/eventMiddleware.type.js";
9
+ import type { RegisteredEventDefinition } from "../eventRegistry/eventRegistry.type.js";
10
+ import type { EventBusMiddlewareItem } from "./eventBus.type.js";
9
11
  /**
10
12
  * Registers an event definition on the given registry.
11
13
  */
12
14
  export declare function busRegister<TType extends EventType, TPayload>(registry: {
13
- register: Function;
14
- }, definition: EventDefinition<TType, TPayload>, ensureUsable: () => void): any;
15
+ register: (definition: EventDefinition<TType, TPayload>) => RegisteredEventDefinition<TType, TPayload>;
16
+ }, definition: EventDefinition<TType, TPayload>, ensureUsable: () => void): RegisteredEventDefinition<TType, TPayload>;
17
+ interface HandlerSource {
18
+ on: <TEvent extends Event = Event>(eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType">) => EventSubscription;
19
+ }
15
20
  /**
16
21
  * Registers a handler on the emitter.
17
22
  */
18
- export declare function busOn<TEvent extends Event = Event>(emitter: {
19
- on: (eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType">) => EventSubscription;
20
- }, eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType"> | undefined, ensureUsable: () => void): EventSubscription;
23
+ export declare function busOn<TEvent extends Event = Event>(emitter: HandlerSource, eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType"> | undefined, ensureUsable: () => void): EventSubscription;
21
24
  /**
22
25
  * Registers a one-time handler.
23
26
  */
24
- export declare function busOnce<TEvent extends Event = Event>(emitter: {
25
- on: (eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType">) => EventSubscription;
26
- }, eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType" | "once"> | undefined, ensureUsable: () => void): EventSubscription;
27
+ export declare function busOnce<TEvent extends Event = Event>(emitter: HandlerSource, eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType" | "once"> | undefined, ensureUsable: () => void): EventSubscription;
27
28
  /**
28
29
  * Registers a wildcard handler.
29
30
  */
30
- export declare function busOnAny<TEvent extends Event = Event>(emitter: {
31
- on: (eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType">) => EventSubscription;
32
- }, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType"> | undefined, ensureUsable: () => void): EventSubscription;
31
+ export declare function busOnAny<TEvent extends Event = Event>(emitter: HandlerSource, handler: EventHandlerLike<TEvent>, options: Omit<EventHandlerOptions, "eventType"> | undefined, ensureUsable: () => void): EventSubscription;
33
32
  /**
34
33
  * Removes a handler.
35
34
  */
@@ -37,11 +36,23 @@ export declare function busOff(emitter: {
37
36
  off: (subscription: EventSubscription) => boolean;
38
37
  }, subscription: EventSubscription, ensureNotDisposed: () => void): boolean;
39
38
  /**
40
- * Adds middleware to the bus.
39
+ * Adds middleware to the bus. The middleware is validated
40
+ * eagerly (invalid middleware or a non-finite priority throw
41
+ * here, not on the next publish).
41
42
  */
42
43
  export declare function busUse(busMiddleware: RegisteredEventMiddleware[], middleware: EventMiddlewareLike, options?: EventMiddlewareOptions): () => void;
44
+ /**
45
+ * Determines whether a value is an already registered middleware
46
+ * (created by createEventMiddleware or a builder helper).
47
+ */
48
+ export declare function isRegisteredEventMiddleware(value: unknown): value is RegisteredEventMiddleware;
43
49
  /**
44
50
  * Normalizes a middleware item into a RegisteredEventMiddleware.
51
+ *
52
+ * `prefix` keeps generated ids stable per source ("bus-mw" for
53
+ * constructor middleware, "publish-mw" for per-publication
54
+ * middleware).
45
55
  */
46
- export declare function registerMiddlewareItem(item: EventMiddlewareLike, index: number): RegisteredEventMiddleware;
56
+ export declare function registerMiddlewareItem(item: EventBusMiddlewareItem, index: number, prefix?: string): RegisteredEventMiddleware;
57
+ export {};
47
58
  //# sourceMappingURL=eventBus.registration.d.ts.map
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Event bus registration and subscription methods for Zudojs.
3
3
  */
4
- import { createEventMiddlewareId, isFunctionEventMiddleware, isObjectEventMiddleware, } from "../eventMiddleware/eventMiddleware.helper.js";
4
+ import { createEventMiddleware, isEventMiddleware, } from "../eventMiddleware/eventMiddleware.helper.js";
5
5
  /**
6
6
  * Registers an event definition on the given registry.
7
7
  */
@@ -39,17 +39,12 @@ export function busOff(emitter, subscription, ensureNotDisposed) {
39
39
  return emitter.off(subscription);
40
40
  }
41
41
  /**
42
- * Adds middleware to the bus.
42
+ * Adds middleware to the bus. The middleware is validated
43
+ * eagerly (invalid middleware or a non-finite priority throw
44
+ * here, not on the next publish).
43
45
  */
44
46
  export function busUse(busMiddleware, middleware, options = {}) {
45
- const id = options.id ?? createEventMiddlewareId();
46
- const registered = {
47
- id,
48
- description: options.description,
49
- priority: options.priority ?? 0,
50
- enabled: options.enabled ?? true,
51
- middleware,
52
- };
47
+ const registered = createEventMiddleware(middleware, options);
53
48
  busMiddleware.push(registered);
54
49
  return () => {
55
50
  const idx = busMiddleware.indexOf(registered);
@@ -58,27 +53,35 @@ export function busUse(busMiddleware, middleware, options = {}) {
58
53
  }
59
54
  };
60
55
  }
56
+ /**
57
+ * Determines whether a value is an already registered middleware
58
+ * (created by createEventMiddleware or a builder helper).
59
+ */
60
+ export function isRegisteredEventMiddleware(value) {
61
+ return (typeof value === "object" &&
62
+ value !== null &&
63
+ typeof value.id === "string" &&
64
+ typeof value.enabled === "boolean" &&
65
+ isEventMiddleware(value.middleware));
66
+ }
61
67
  /**
62
68
  * Normalizes a middleware item into a RegisteredEventMiddleware.
69
+ *
70
+ * `prefix` keeps generated ids stable per source ("bus-mw" for
71
+ * constructor middleware, "publish-mw" for per-publication
72
+ * middleware).
63
73
  */
64
- export function registerMiddlewareItem(item, index) {
65
- const id = `bus-mw-${index}`;
66
- if (isFunctionEventMiddleware(item)) {
67
- return {
68
- id,
69
- priority: 0,
70
- enabled: true,
71
- middleware: item,
72
- };
73
- }
74
- if (isObjectEventMiddleware(item)) {
75
- return {
76
- id,
77
- priority: 0,
78
- enabled: true,
79
- middleware: item,
80
- };
74
+ export function registerMiddlewareItem(item, index, prefix = "bus-mw") {
75
+ if (isRegisteredEventMiddleware(item)) {
76
+ return createEventMiddleware(item.middleware, {
77
+ id: item.id,
78
+ description: item.description,
79
+ priority: item.priority,
80
+ enabled: item.enabled,
81
+ });
81
82
  }
82
- return item;
83
+ return createEventMiddleware(item, {
84
+ id: `${prefix}-${index}`,
85
+ });
83
86
  }
84
87
  //# sourceMappingURL=eventBus.registration.js.map
@@ -3,33 +3,96 @@
3
3
  */
4
4
  import type { Event } from "../eventTypes/eventDefinition.type.js";
5
5
  import type { EventEmitterMode, EventErrorMode } from "../eventEmitter/eventEmitter.type.js";
6
- import type { EventMiddlewareLike } from "../eventMiddleware/eventMiddleware.type.js";
6
+ import type { EventMiddlewareLike, RegisteredEventMiddleware } from "../eventMiddleware/eventMiddleware.type.js";
7
+ import type { DuplicateHandlerIdPolicy, EventRegistryWarning } from "../eventRegistry/eventRegistry.type.js";
8
+ /**
9
+ * Middleware accepted by bus options: a plain middleware function
10
+ * or object, or a registered middleware created with
11
+ * createEventMiddleware() / the builder helpers.
12
+ */
13
+ export type EventBusMiddlewareItem = EventMiddlewareLike | RegisteredEventMiddleware;
14
+ /**
15
+ * Context passed to the bus `onError` hook.
16
+ */
17
+ export interface EventBusErrorContext {
18
+ /**
19
+ * "handler" → a handler failed during a CONTINUE-mode publish
20
+ * "observer" → a bus lifecycle observer threw
21
+ */
22
+ readonly source: "handler" | "observer";
23
+ readonly event?: Event;
24
+ }
7
25
  export interface EventBusOptions {
8
26
  readonly emitter?: {
9
27
  readonly mode?: EventEmitterMode;
10
28
  readonly errorMode?: EventErrorMode;
29
+ /**
30
+ * Deep-freeze events (payload included) before dispatch.
31
+ * Defaults to true.
32
+ */
11
33
  readonly freezeEvents?: boolean;
34
+ /**
35
+ * Maximum handlers per event pattern before a leak warning is
36
+ * emitted (0 disables). Defaults to 100.
37
+ */
38
+ readonly maxListeners?: number;
12
39
  };
13
40
  readonly registry?: {
14
41
  readonly allowDuplicateDefinitions?: boolean;
42
+ /**
43
+ * @deprecated Use `onDuplicateHandlerId: "replace"`.
44
+ */
15
45
  readonly allowDuplicateHandlerIds?: boolean;
46
+ readonly onDuplicateHandlerId?: DuplicateHandlerIdPolicy;
16
47
  };
48
+ /**
49
+ * Reject publishes for event types that were not registered
50
+ * with register(). Defaults to false.
51
+ */
17
52
  readonly requireRegistration?: boolean;
18
- readonly middleware?: readonly EventMiddlewareLike[];
53
+ readonly middleware?: readonly EventBusMiddlewareItem[];
54
+ /**
55
+ * Receives leak warnings. Defaults to console.warn.
56
+ */
57
+ readonly onWarning?: (warning: EventRegistryWarning) => void;
58
+ /**
59
+ * Receives handler errors from CONTINUE-mode publishes and
60
+ * errors thrown by bus/registry observers. Useful for
61
+ * fire-and-forget publishes whose result is never inspected.
62
+ */
63
+ readonly onError?: (error: unknown, context: EventBusErrorContext) => void;
19
64
  }
20
65
  export interface PublishOptions {
21
66
  readonly mode?: EventEmitterMode;
22
67
  readonly errorMode?: EventErrorMode;
23
68
  readonly signal?: AbortSignal;
24
69
  readonly metadata?: Readonly<Record<string, unknown>>;
25
- readonly middleware?: readonly EventMiddlewareLike[];
70
+ readonly middleware?: readonly EventBusMiddlewareItem[];
26
71
  }
27
72
  export interface EventPublishResult<TEvent extends Event = Event> {
28
73
  readonly event: TEvent;
74
+ /**
75
+ * True when at least one handler completed successfully.
76
+ */
29
77
  readonly handled: boolean;
78
+ /**
79
+ * Number of handlers invoked.
80
+ */
30
81
  readonly handlerCount: number;
82
+ /**
83
+ * Number of handlers that completed successfully.
84
+ */
85
+ readonly succeeded: number;
86
+ /**
87
+ * Number of handlers that threw.
88
+ */
89
+ readonly failed: number;
31
90
  readonly results: readonly unknown[];
32
91
  readonly errors: readonly unknown[];
92
+ /**
93
+ * True when a middleware did not call next(), so no handler ran.
94
+ */
95
+ readonly shortCircuited: boolean;
33
96
  readonly middlewareExecutions?: readonly {
34
97
  readonly middlewareId: string;
35
98
  readonly result: unknown;
@@ -37,8 +100,17 @@ export interface EventPublishResult<TEvent extends Event = Event> {
37
100
  }[];
38
101
  }
39
102
  export declare enum EventBusState {
103
+ /**
104
+ * Created, never started. The first publish/subscribe starts
105
+ * the bus automatically.
106
+ */
40
107
  CREATED = "created",
41
108
  ACTIVE = "active",
109
+ /**
110
+ * Stopped with stop(). Publishing and subscribing throw
111
+ * EventBusStoppedError until start() is called again.
112
+ */
113
+ STOPPED = "stopped",
42
114
  DISPOSED = "disposed"
43
115
  }
44
116
  export interface EventBusEvent {
@@ -3,8 +3,17 @@
3
3
  */
4
4
  export var EventBusState;
5
5
  (function (EventBusState) {
6
+ /**
7
+ * Created, never started. The first publish/subscribe starts
8
+ * the bus automatically.
9
+ */
6
10
  EventBusState["CREATED"] = "created";
7
11
  EventBusState["ACTIVE"] = "active";
12
+ /**
13
+ * Stopped with stop(). Publishing and subscribing throw
14
+ * EventBusStoppedError until start() is called again.
15
+ */
16
+ EventBusState["STOPPED"] = "stopped";
8
17
  EventBusState["DISPOSED"] = "disposed";
9
18
  })(EventBusState || (EventBusState = {}));
10
19
  //# sourceMappingURL=eventBus.type.js.map
@@ -6,4 +6,6 @@
6
6
  export * from "./eventBus.type.js";
7
7
  export * from "./eventBus.core.js";
8
8
  export * from "./eventBus.factory.js";
9
+ export { isRegisteredEventMiddleware } from "./eventBus.registration.js";
10
+ export { isEventEmitResult } from "./eventBus.publish.js";
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -6,4 +6,6 @@
6
6
  export * from "./eventBus.type.js";
7
7
  export * from "./eventBus.core.js";
8
8
  export * from "./eventBus.factory.js";
9
+ export { isRegisteredEventMiddleware } from "./eventBus.registration.js";
10
+ export { isEventEmitResult } from "./eventBus.publish.js";
9
11
  //# sourceMappingURL=index.js.map
@@ -1,8 +1,17 @@
1
1
  /**
2
2
  * Event emitter abort error helper for Zudojs.
3
3
  */
4
+ import type { Event } from "../eventTypes/eventDefinition.type.js";
5
+ import { EventDispatchAbortedError } from "../eventErrors/eventError.base.js";
6
+ import type { EventHandlerExecutionResult } from "./eventEmitter.type.js";
4
7
  /**
5
- * Creates an AbortError consistently across runtimes.
8
+ * Creates the error thrown when dispatch is aborted through an
9
+ * AbortSignal. Partial results and errors gathered before the
10
+ * abort are attached to the error.
6
11
  */
7
- export declare function createAbortError(): Error;
12
+ export declare function createAbortError(event?: Event, results?: readonly EventHandlerExecutionResult[], errors?: readonly unknown[]): EventDispatchAbortedError;
13
+ /**
14
+ * Determines whether an error represents an aborted dispatch.
15
+ */
16
+ export declare function isAbortError(error: unknown): boolean;
8
17
  //# sourceMappingURL=eventEmitter.abort.d.ts.map
@@ -1,12 +1,27 @@
1
1
  /**
2
2
  * Event emitter abort error helper for Zudojs.
3
3
  */
4
+ import { EventDispatchAbortedError } from "../eventErrors/eventError.base.js";
4
5
  /**
5
- * Creates an AbortError consistently across runtimes.
6
+ * Creates the error thrown when dispatch is aborted through an
7
+ * AbortSignal. Partial results and errors gathered before the
8
+ * abort are attached to the error.
6
9
  */
7
- export function createAbortError() {
8
- const error = new Error("Event dispatch was aborted.");
9
- error.name = "AbortError";
10
- return error;
10
+ export function createAbortError(event, results = [], errors = []) {
11
+ return new EventDispatchAbortedError("Event dispatch was aborted.", {
12
+ eventType: event?.type,
13
+ eventId: event?.id,
14
+ results,
15
+ errors,
16
+ });
17
+ }
18
+ /**
19
+ * Determines whether an error represents an aborted dispatch.
20
+ */
21
+ export function isAbortError(error) {
22
+ return (error instanceof EventDispatchAbortedError ||
23
+ (typeof error === "object" &&
24
+ error !== null &&
25
+ error.name === "AbortError"));
11
26
  }
12
27
  //# sourceMappingURL=eventEmitter.abort.js.map
@@ -1,34 +1,45 @@
1
1
  /**
2
2
  * Event emitter core class for Zudojs.
3
+ *
4
+ * The emitter dispatches events to handlers. Handlers are stored
5
+ * in an EventHandlerStore (an EventRegistry by default) so that a
6
+ * bus and its registry share one set of handlers.
3
7
  */
4
8
  import type { Event, EventInput } from "../eventTypes/eventDefinition.type.js";
5
9
  import type { EventTypePattern } from "../eventTypes/eventType.type.js";
6
10
  import type { EventHandlerLike, EventHandlerOptions, RegisteredEventHandler } from "../eventHandler/eventHandler.core.js";
7
11
  import type { EventSubscription } from "../eventSubscription/eventSubscription.core.js";
8
12
  import { EventSubscriptionGroup } from "../eventSubscription/eventSubscription.core.js";
13
+ import type { EventHandlerStore } from "../eventRegistry/eventRegistry.type.js";
9
14
  import type { EventEmitterOptions, EmitOptions, EventEmitResult } from "./eventEmitter.type.js";
10
15
  /**
11
16
  * Main local event emitter.
12
17
  */
13
18
  export declare class EventEmitter {
14
- private readonly listeners;
19
+ private readonly store;
15
20
  private readonly options;
16
21
  private disposed;
17
22
  constructor(options?: EventEmitterOptions);
18
23
  on<TEvent extends Event = Event>(eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options?: Omit<EventHandlerOptions, "eventType">): EventSubscription;
19
24
  once<TEvent extends Event = Event>(eventType: EventTypePattern, handler: EventHandlerLike<TEvent>, options?: Omit<EventHandlerOptions, "eventType" | "once">): EventSubscription;
20
25
  onAny<TEvent extends Event = Event>(handler: EventHandlerLike<TEvent>, options?: Omit<EventHandlerOptions, "eventType">): EventSubscription;
26
+ /**
27
+ * Cancels a subscription. Returns true when the subscription
28
+ * was active (and is now cancelled).
29
+ */
21
30
  off(subscription: EventSubscription): boolean;
22
31
  emit<TEvent extends Event>(event: TEvent, options?: EmitOptions): Promise<EventEmitResult<TEvent>>;
23
32
  emitEvent<TPayload>(input: EventInput<TPayload>, options?: EmitOptions): Promise<EventEmitResult<Event<TPayload>>>;
24
33
  get listenerCount(): number;
34
+ /**
35
+ * Returns the handler store backing this emitter.
36
+ */
37
+ getStore(): EventHandlerStore;
25
38
  getRegistrations(): readonly RegisteredEventHandler[];
26
39
  removeAllListeners(): void;
27
40
  createSubscriptionGroup(): EventSubscriptionGroup;
28
41
  dispose(): void;
29
42
  isDisposed(): boolean;
30
- private addRegistration;
31
- private removeHandler;
32
43
  private ensureActive;
33
44
  }
34
45
  /**
@@ -1,9 +1,16 @@
1
1
  /**
2
2
  * Event emitter core class for Zudojs.
3
+ *
4
+ * The emitter dispatches events to handlers. Handlers are stored
5
+ * in an EventHandlerStore (an EventRegistry by default) so that a
6
+ * bus and its registry share one set of handlers.
3
7
  */
4
- import { createEvent } from "../eventTypes/eventDefinition.type.js";
5
- import { createEventHandler, createEventHandlerContext, getMatchingEventHandlers, } from "../eventHandler/eventHandler.core.js";
6
- import { EventSubscriptionGroup, createEventSubscription, } from "../eventSubscription/eventSubscription.core.js";
8
+ import { createEvent, isEvent } from "../eventTypes/eventDefinition.type.js";
9
+ import { deepFreeze } from "../eventTypes/eventPayload.type.js";
10
+ import { createEventHandlerContext } from "../eventHandler/eventHandler.core.js";
11
+ import { EventSubscriptionGroup } from "../eventSubscription/eventSubscription.core.js";
12
+ import { EventRegistry } from "../eventRegistry/eventRegistry.store.js";
13
+ import { EventEmitterDisposedError, InvalidEventError, } from "../eventErrors/eventError.base.js";
7
14
  import { EventEmitterMode, EventErrorMode } from "./eventEmitter.type.js";
8
15
  import { emitSequential } from "./eventEmitter.sequential.js";
9
16
  import { emitParallel } from "./eventEmitter.parallel.js";
@@ -12,7 +19,7 @@ import { createAbortError } from "./eventEmitter.abort.js";
12
19
  * Main local event emitter.
13
20
  */
14
21
  export class EventEmitter {
15
- listeners = new Map();
22
+ store;
16
23
  options;
17
24
  disposed = false;
18
25
  constructor(options = {}) {
@@ -21,14 +28,16 @@ export class EventEmitter {
21
28
  errorMode: options.errorMode ?? EventErrorMode.THROW,
22
29
  freezeEvents: options.freezeEvents ?? true,
23
30
  };
31
+ this.store =
32
+ options.store ??
33
+ new EventRegistry({
34
+ maxHandlersPerPattern: options.maxListeners,
35
+ onWarning: options.onWarning,
36
+ });
24
37
  }
25
38
  on(eventType, handler, options = {}) {
26
39
  this.ensureActive();
27
- const registration = createEventHandler(handler, {
28
- ...options,
29
- eventType,
30
- });
31
- return this.addRegistration(registration);
40
+ return this.store.registerHandler(eventType, handler, options);
32
41
  }
33
42
  once(eventType, handler, options = {}) {
34
43
  return this.on(eventType, handler, {
@@ -39,48 +48,64 @@ export class EventEmitter {
39
48
  onAny(handler, options = {}) {
40
49
  return this.on("*", handler, options);
41
50
  }
51
+ /**
52
+ * Cancels a subscription. Returns true when the subscription
53
+ * was active (and is now cancelled).
54
+ */
42
55
  off(subscription) {
43
56
  this.ensureActive();
44
- const removed = this.listeners.delete(subscription.id);
45
- if (removed && subscription.active) {
46
- subscription.unsubscribe();
47
- }
48
- return removed;
57
+ const wasActive = subscription.active;
58
+ subscription.unsubscribe();
59
+ return wasActive;
49
60
  }
50
61
  async emit(event, options = {}) {
51
62
  this.ensureActive();
63
+ if (!isEvent(event)) {
64
+ throw new InvalidEventError("emit() requires an Event (use emitEvent() for event input).");
65
+ }
52
66
  if (options.signal?.aborted) {
53
- throw createAbortError();
67
+ throw createAbortError(event);
54
68
  }
55
69
  const mode = options.mode ?? this.options.mode;
56
70
  const errorMode = options.errorMode ?? this.options.errorMode;
57
- const handlers = getMatchingEventHandlers(this.getRegistrations(), event);
58
- const context = createEventHandlerContext(event, {
71
+ const dispatched = this.options.freezeEvents ? deepFreeze(event) : event;
72
+ const handlers = this.store.getHandlersForEvent(dispatched);
73
+ const context = createEventHandlerContext(dispatched, {
59
74
  signal: options.signal,
60
75
  metadata: options.metadata,
61
76
  });
77
+ const results = [];
78
+ const errors = [];
62
79
  if (handlers.length === 0) {
63
80
  return {
64
- event,
81
+ event: dispatched,
65
82
  handled: false,
66
- results: [],
67
- errors: [],
83
+ results,
84
+ errors,
85
+ succeeded: 0,
86
+ failed: 0,
68
87
  };
69
88
  }
70
- const results = [];
71
- const errors = [];
72
- const removeOnceHandler = (handlerId) => this.removeHandler(handlerId);
89
+ const hooks = {
90
+ isRegistered: (handlerId) => this.store.hasHandler(handlerId),
91
+ removeOnce: (handlerId) => {
92
+ this.store.unregisterHandler(handlerId);
93
+ },
94
+ };
73
95
  if (mode === EventEmitterMode.PARALLEL) {
74
- await emitParallel(handlers, event, context, errorMode, results, errors, removeOnceHandler);
96
+ await emitParallel(handlers, dispatched, context, errorMode, results, errors, hooks);
75
97
  }
76
98
  else {
77
- await emitSequential(handlers, event, context, errorMode, results, errors, removeOnceHandler);
99
+ await emitSequential(handlers, dispatched, context, errorMode, results, errors, hooks);
78
100
  }
101
+ const succeeded = results.filter((result) => result.ok).length;
79
102
  return {
80
- event,
81
- handled: results.length > 0,
103
+ event: dispatched,
104
+ handled: succeeded > 0,
82
105
  results,
83
106
  errors,
107
+ succeeded,
108
+ failed: results.length - succeeded,
84
109
  };
85
110
  }
86
111
  async emitEvent(input, options = {}) {
@@ -88,18 +113,22 @@ export class EventEmitter {
88
113
  return this.emit(event, options);
89
114
  }
90
115
  get listenerCount() {
91
- return this.listeners.size;
116
+ return this.store.handlerCount;
117
+ }
118
+ /**
119
+ * Returns the handler store backing this emitter.
120
+ */
121
+ getStore() {
122
+ return this.store;
92
123
  }
93
124
  getRegistrations() {
94
- return [...this.listeners.values()].map(({ registration }) => registration);
125
+ return this.store.getHandlers();
95
126
  }
96
127
  removeAllListeners() {
97
128
  this.ensureActive();
98
- const subscriptions = [...this.listeners.values()].map(({ subscription }) => subscription);
99
- for (const subscription of subscriptions) {
100
- subscription.unsubscribe();
129
+ for (const registration of this.store.getHandlers()) {
130
+ this.store.unregisterHandler(registration.id);
101
131
  }
102
- this.listeners.clear();
103
132
  }
104
133
  createSubscriptionGroup() {
105
134
  this.ensureActive();
@@ -115,30 +144,9 @@ export class EventEmitter {
115
144
  isDisposed() {
116
145
  return this.disposed;
117
146
  }
118
- addRegistration(registration) {
119
- const subscription = createEventSubscription(() => {
120
- this.listeners.delete(registration.id);
121
- }, {
122
- id: registration.id,
123
- description: registration.description,
124
- });
125
- this.listeners.set(registration.id, {
126
- registration,
127
- subscription,
128
- });
129
- return subscription;
130
- }
131
- removeHandler(id) {
132
- const listener = this.listeners.get(id);
133
- if (!listener) {
134
- return;
135
- }
136
- this.listeners.delete(id);
137
- listener.subscription.unsubscribe();
138
- }
139
147
  ensureActive() {
140
148
  if (this.disposed) {
141
- throw new Error("EventEmitter has already been disposed.");
149
+ throw new EventEmitterDisposedError();
142
150
  }
143
151
  }
144
152
  }
@@ -1,12 +1,18 @@
1
1
  /**
2
2
  * Parallel event handler dispatch for Zudojs.
3
+ *
4
+ * All handlers start together; an AbortSignal that fires after
5
+ * the handlers have started cannot stop them. Handlers can observe
6
+ * `context.signal` to cooperate. Only a signal that is already
7
+ * aborted when dispatch begins rejects the emit.
3
8
  */
4
9
  import type { Event } from "../eventTypes/eventDefinition.type.js";
5
10
  import type { EventHandlerContext, RegisteredEventHandler } from "../eventHandler/eventHandler.core.js";
6
11
  import type { EventHandlerExecutionResult } from "./eventEmitter.type.js";
7
12
  import { EventErrorMode } from "./eventEmitter.type.js";
13
+ import type { DispatchHooks } from "./eventEmitter.sequential.js";
8
14
  /**
9
15
  * Executes handlers concurrently.
10
16
  */
11
- export declare function emitParallel<TEvent extends Event>(handlers: readonly RegisteredEventHandler<TEvent>[], event: TEvent, context: EventHandlerContext<TEvent>, errorMode: EventErrorMode, results: EventHandlerExecutionResult[], errors: unknown[], onOnceHandler: (handlerId: string) => void): Promise<void>;
17
+ export declare function emitParallel<TEvent extends Event>(handlers: readonly RegisteredEventHandler<TEvent>[], event: TEvent, context: EventHandlerContext<TEvent>, errorMode: EventErrorMode, results: EventHandlerExecutionResult[], errors: unknown[], hooks: DispatchHooks): Promise<void>;
12
18
  //# sourceMappingURL=eventEmitter.parallel.d.ts.map