evnty 5.0.0 → 5.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/README.md +28 -28
- package/build/async.cjs +101 -0
- package/build/async.cjs.map +1 -0
- package/build/async.d.ts +37 -0
- package/build/async.js +83 -0
- package/build/async.js.map +1 -0
- package/build/broadcast.cjs +205 -0
- package/build/broadcast.cjs.map +1 -0
- package/build/broadcast.d.ts +164 -0
- package/build/broadcast.js +184 -0
- package/build/broadcast.js.map +1 -0
- package/build/dispatch-result.cjs +154 -0
- package/build/dispatch-result.cjs.map +1 -0
- package/build/dispatch-result.d.ts +49 -0
- package/build/dispatch-result.js +127 -0
- package/build/dispatch-result.js.map +1 -0
- package/build/event.cjs +92 -127
- package/build/event.cjs.map +1 -1
- package/build/event.d.ts +92 -167
- package/build/event.js +90 -122
- package/build/event.js.map +1 -1
- package/build/index.cjs +3 -1
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +3 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/iterator.cjs +578 -91
- package/build/iterator.cjs.map +1 -1
- package/build/iterator.d.ts +178 -7
- package/build/iterator.js +579 -92
- package/build/iterator.js.map +1 -1
- package/build/listener-registry.cjs +114 -0
- package/build/listener-registry.cjs.map +1 -0
- package/build/listener-registry.d.ts +54 -0
- package/build/listener-registry.js +104 -0
- package/build/listener-registry.js.map +1 -0
- package/build/ring-buffer.cjs +171 -0
- package/build/ring-buffer.cjs.map +1 -0
- package/build/ring-buffer.d.ts +80 -0
- package/build/ring-buffer.js +161 -0
- package/build/ring-buffer.js.map +1 -0
- package/build/sequence.cjs +34 -35
- package/build/sequence.cjs.map +1 -1
- package/build/sequence.d.ts +38 -24
- package/build/sequence.js +34 -35
- package/build/sequence.js.map +1 -1
- package/build/signal.cjs +26 -35
- package/build/signal.cjs.map +1 -1
- package/build/signal.d.ts +36 -39
- package/build/signal.js +26 -35
- package/build/signal.js.map +1 -1
- package/build/types.cjs +0 -11
- package/build/types.cjs.map +1 -1
- package/build/types.d.ts +86 -9
- package/build/types.js +1 -5
- package/build/types.js.map +1 -1
- package/build/utils.cjs +202 -22
- package/build/utils.cjs.map +1 -1
- package/build/utils.d.ts +85 -26
- package/build/utils.js +181 -22
- package/build/utils.js.map +1 -1
- package/package.json +27 -25
- package/src/__tests__/example.js +19 -24
- package/src/index.ts +3 -1
- package/build/callable.cjs +0 -72
- package/build/callable.cjs.map +0 -1
- package/build/callable.d.ts +0 -34
- package/build/callable.js +0 -51
- package/build/callable.js.map +0 -1
package/build/event.d.ts
CHANGED
|
@@ -1,131 +1,89 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Callback, Listener, FilterFunction, Predicate, Mapper, Reducer, Action, Fn, Emitter, MaybePromise, Promiseable } from './types.js';
|
|
2
|
+
import { Signal } from './signal.js';
|
|
3
|
+
import { DispatchResult } from './dispatch-result.js';
|
|
4
|
+
export type Unsubscribe = Action;
|
|
3
5
|
/**
|
|
4
|
-
* Represents an unsubscribe function that can be called to remove a listener.
|
|
5
|
-
* Provides additional utilities for chaining and conditional unsubscription.
|
|
6
|
-
*
|
|
7
6
|
* @internal
|
|
8
7
|
*/
|
|
9
|
-
export declare class
|
|
10
|
-
private _done;
|
|
11
|
-
constructor(callback: Callback);
|
|
12
|
-
get done(): boolean;
|
|
13
|
-
/**
|
|
14
|
-
* Creates a new unsubscribe function that executes the given callback before this unsubscribe.
|
|
15
|
-
*
|
|
16
|
-
* @param callback - The callback to execute before unsubscribing.
|
|
17
|
-
* @returns {Unsubscribe} A new Unsubscribe instance.
|
|
18
|
-
*/
|
|
19
|
-
pre(callback: Callback): Unsubscribe;
|
|
20
|
-
/**
|
|
21
|
-
* Creates a new unsubscribe function that executes the given callback after this unsubscribe.
|
|
22
|
-
*
|
|
23
|
-
* @param callback - The callback to execute after unsubscribing.
|
|
24
|
-
* @returns {Unsubscribe} A new Unsubscribe instance.
|
|
25
|
-
*/
|
|
26
|
-
post(callback: Callback): Unsubscribe;
|
|
27
|
-
/**
|
|
28
|
-
* Creates a new unsubscribe function that only executes after being called a specified number of times.
|
|
29
|
-
*
|
|
30
|
-
* @param count - The number of times this must be called before actually unsubscribing.
|
|
31
|
-
* @returns {Unsubscribe} A new Unsubscribe instance.
|
|
32
|
-
*/
|
|
33
|
-
countdown(count: number): Unsubscribe;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Wraps an array of values or promises (typically listener results) and provides batch resolution.
|
|
37
|
-
*
|
|
38
|
-
* @template T
|
|
39
|
-
*/
|
|
40
|
-
export declare class EventResult<T> implements PromiseLike<T[]> {
|
|
8
|
+
export declare class EventIterator<T> implements AsyncIterator<T, void, void> {
|
|
41
9
|
#private;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
*/
|
|
46
|
-
constructor(results: MaybePromise<T>[]);
|
|
47
|
-
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): PromiseLike<TResult1 | TResult2>;
|
|
48
|
-
/**
|
|
49
|
-
* Resolves all listener results, rejecting if any promise rejects.
|
|
50
|
-
*
|
|
51
|
-
* @returns {Promise<T[]>} A promise that fulfills with an array of all resolved values.
|
|
52
|
-
*/
|
|
53
|
-
all(): Promise<T[]>;
|
|
54
|
-
/**
|
|
55
|
-
* Waits for all listener results to settle, regardless of fulfillment or rejection.
|
|
56
|
-
*
|
|
57
|
-
* @returns {Promise<PromiseSettledResult<T>[]>} A promise that fulfills with an array of each result's settled status and value/reason.
|
|
58
|
-
*/
|
|
59
|
-
settled(): Promise<PromiseSettledResult<T>[]>;
|
|
10
|
+
constructor(signal: Signal<T>);
|
|
11
|
+
next(): Promise<IteratorResult<T, void>>;
|
|
12
|
+
return(): Promise<IteratorResult<T, void>>;
|
|
60
13
|
}
|
|
61
14
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* Key characteristics:
|
|
67
|
-
* - Multiple listeners - all are called for each emission
|
|
68
|
-
* - Listeners can return values collected in EventResult
|
|
69
|
-
* - Supports async listeners and async iteration
|
|
70
|
-
* - Provides lifecycle hooks for listener management
|
|
71
|
-
* - Memory efficient using RingBuffer for storage
|
|
15
|
+
* Multi-listener event emitter with async support.
|
|
16
|
+
* All registered listeners are called for each emission, and their return
|
|
17
|
+
* values are collected in a DispatchResult. Supports async iteration and
|
|
18
|
+
* an `onDispose` callback for cleanup.
|
|
72
19
|
*
|
|
73
20
|
* Differs from:
|
|
74
|
-
* - Signal:
|
|
75
|
-
* - Sequence:
|
|
21
|
+
* - Signal: Event has persistent listeners; Signal is promise-based (receive per round)
|
|
22
|
+
* - Sequence: Event broadcasts to all listeners; Sequence is a single-consumer queue
|
|
76
23
|
*
|
|
77
24
|
* @template T - The type of value emitted to listeners (event payload)
|
|
78
25
|
* @template R - The return type of listener functions
|
|
79
26
|
*/
|
|
80
|
-
export declare class Event<T = unknown, R = unknown>
|
|
81
|
-
|
|
82
|
-
* The ring buffer containing all registered listeners for the event.
|
|
83
|
-
*/
|
|
84
|
-
private listeners;
|
|
85
|
-
/**
|
|
86
|
-
* The ring buffer containing hook listeners that respond to listener lifecycle events.
|
|
87
|
-
*/
|
|
88
|
-
private hooks;
|
|
89
|
-
/**
|
|
90
|
-
* Flag indicating whether this event has been disposed.
|
|
91
|
-
*/
|
|
92
|
-
private _disposed;
|
|
93
|
-
/**
|
|
94
|
-
* A function that disposes of the event and its listeners.
|
|
95
|
-
*/
|
|
96
|
-
readonly dispose: Callback;
|
|
27
|
+
export declare class Event<T = unknown, R = unknown> implements Emitter<T, DispatchResult<void | R>>, Promiseable<T>, Promise<T>, Disposable, AsyncIterable<T> {
|
|
28
|
+
#private;
|
|
97
29
|
readonly [Symbol.toStringTag] = "Event";
|
|
98
30
|
/**
|
|
99
31
|
* Creates a new event.
|
|
100
32
|
*
|
|
101
|
-
* @param
|
|
33
|
+
* @param onDispose - A function to call on the event disposal.
|
|
102
34
|
*
|
|
35
|
+
* @example
|
|
103
36
|
* ```typescript
|
|
104
37
|
* // Create a click event.
|
|
105
38
|
* const clickEvent = new Event<[x: number, y: number], void>();
|
|
106
39
|
* clickEvent.on(([x, y]) => console.log(`Clicked at ${x}, ${y}`));
|
|
40
|
+
* clickEvent.emit([10, 20]);
|
|
107
41
|
* ```
|
|
108
42
|
*/
|
|
109
|
-
constructor(
|
|
43
|
+
constructor(onDispose?: Callback);
|
|
110
44
|
/**
|
|
111
|
-
*
|
|
45
|
+
* Returns a bound emit function for use as a callback.
|
|
46
|
+
* Useful for passing to other APIs that expect a function.
|
|
112
47
|
*
|
|
113
|
-
* @
|
|
114
|
-
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const event = new Event<string>();
|
|
51
|
+
* someApi.onMessage(event.sink);
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
get sink(): Fn<[T], DispatchResult<void | R>>;
|
|
55
|
+
/**
|
|
56
|
+
* DOM EventListener interface compatibility.
|
|
57
|
+
* Allows the event to be used directly with addEventListener.
|
|
58
|
+
*/
|
|
59
|
+
handleEvent(event: T): void;
|
|
60
|
+
/**
|
|
61
|
+
* The number of listeners for the event.
|
|
115
62
|
*/
|
|
116
63
|
get size(): number;
|
|
117
64
|
/**
|
|
118
|
-
*
|
|
65
|
+
* Emits a value to all registered listeners.
|
|
66
|
+
* Each listener is called with the value and their return values are collected.
|
|
67
|
+
*
|
|
68
|
+
* @param value - The value to emit to all listeners.
|
|
69
|
+
* @returns A DispatchResult containing all listener return values.
|
|
119
70
|
*
|
|
120
|
-
* @
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const event = new Event<string, number>();
|
|
74
|
+
* event.on(str => str.length);
|
|
75
|
+
* const result = event.emit('hello');
|
|
76
|
+
* await result.all(); // [5]
|
|
77
|
+
* ```
|
|
121
78
|
*/
|
|
122
|
-
|
|
79
|
+
emit(value: T): DispatchResult<void | R>;
|
|
123
80
|
/**
|
|
124
81
|
* Checks if the given listener is NOT registered for this event.
|
|
125
82
|
*
|
|
126
83
|
* @param listener - The listener function to check against the registered listeners.
|
|
127
|
-
* @returns
|
|
84
|
+
* @returns `true` if the listener is not already registered; otherwise, `false`.
|
|
128
85
|
*
|
|
86
|
+
* @example
|
|
129
87
|
* ```typescript
|
|
130
88
|
* // Check if a listener is not already added
|
|
131
89
|
* if (event.lacks(myListener)) {
|
|
@@ -138,8 +96,9 @@ export declare class Event<T = unknown, R = unknown> extends CallableAsyncIterat
|
|
|
138
96
|
* Checks if the given listener is registered for this event.
|
|
139
97
|
*
|
|
140
98
|
* @param listener - The listener function to check.
|
|
141
|
-
* @returns
|
|
99
|
+
* @returns `true` if the listener is currently registered; otherwise, `false`.
|
|
142
100
|
*
|
|
101
|
+
* @example
|
|
143
102
|
* ```typescript
|
|
144
103
|
* // Verify if a listener is registered
|
|
145
104
|
* if (event.has(myListener)) {
|
|
@@ -152,8 +111,9 @@ export declare class Event<T = unknown, R = unknown> extends CallableAsyncIterat
|
|
|
152
111
|
* Removes a specific listener from this event.
|
|
153
112
|
*
|
|
154
113
|
* @param listener - The listener to remove.
|
|
155
|
-
* @returns
|
|
114
|
+
* @returns The event instance for chaining.
|
|
156
115
|
*
|
|
116
|
+
* @example
|
|
157
117
|
* ```typescript
|
|
158
118
|
* // Remove a listener
|
|
159
119
|
* event.off(myListener);
|
|
@@ -161,14 +121,13 @@ export declare class Event<T = unknown, R = unknown> extends CallableAsyncIterat
|
|
|
161
121
|
*/
|
|
162
122
|
off(listener: Listener<T, R>): this;
|
|
163
123
|
/**
|
|
164
|
-
* Registers a listener that
|
|
165
|
-
* This is the primary method for adding event handlers that will react to the event being triggered.
|
|
124
|
+
* Registers a listener that is called on every emission.
|
|
166
125
|
*
|
|
167
126
|
* @param listener - The function to call when the event occurs.
|
|
168
|
-
* @returns
|
|
127
|
+
* @returns A function that removes this listener when called.
|
|
169
128
|
*
|
|
129
|
+
* @example
|
|
170
130
|
* ```typescript
|
|
171
|
-
* // Add a listener to an event
|
|
172
131
|
* const unsubscribe = event.on((data) => {
|
|
173
132
|
* console.log('Event data:', data);
|
|
174
133
|
* });
|
|
@@ -176,75 +135,54 @@ export declare class Event<T = unknown, R = unknown> extends CallableAsyncIterat
|
|
|
176
135
|
*/
|
|
177
136
|
on(listener: Listener<T, R>): Unsubscribe;
|
|
178
137
|
/**
|
|
179
|
-
*
|
|
180
|
-
* This method is useful for one-time notifications or single-trigger scenarios.
|
|
138
|
+
* Registers a listener that is called only once on the next emission, then auto-removed.
|
|
181
139
|
*
|
|
182
140
|
* @param listener - The listener to trigger once.
|
|
183
|
-
* @returns
|
|
141
|
+
* @returns A function that removes this listener when called (if it hasn't fired yet).
|
|
184
142
|
*
|
|
143
|
+
* @example
|
|
185
144
|
* ```typescript
|
|
186
|
-
*
|
|
187
|
-
* const onceUnsubscribe = event.once((data) => {
|
|
145
|
+
* const cancel = event.once((data) => {
|
|
188
146
|
* console.log('Received data once:', data);
|
|
189
147
|
* });
|
|
190
148
|
* ```
|
|
191
149
|
*/
|
|
192
150
|
once(listener: Listener<T, R>): Unsubscribe;
|
|
193
151
|
/**
|
|
194
|
-
* Removes all listeners from the event
|
|
195
|
-
*
|
|
152
|
+
* Removes all listeners from the event.
|
|
153
|
+
* Does not dispose the event - new listeners can still be added after clearing.
|
|
196
154
|
*
|
|
197
|
-
* @returns
|
|
198
|
-
*
|
|
199
|
-
* ```typescript
|
|
200
|
-
* const myEvent = new Event();
|
|
201
|
-
* myEvent.on(data => console.log(data));
|
|
202
|
-
* myEvent.clear(); // Clears all listeners
|
|
203
|
-
* ```
|
|
155
|
+
* @returns The event instance for chaining.
|
|
204
156
|
*/
|
|
205
157
|
clear(): this;
|
|
206
158
|
/**
|
|
207
|
-
* Waits for the next
|
|
208
|
-
* This method allows the event to be used as a promise that resolves with the next emitted value.
|
|
159
|
+
* Waits for the next emission and returns the emitted value.
|
|
209
160
|
*
|
|
210
|
-
* @returns
|
|
161
|
+
* @returns A promise that resolves with the next emitted value.
|
|
211
162
|
*/
|
|
212
|
-
|
|
163
|
+
receive(): Promise<T>;
|
|
164
|
+
then<OK = T, ERR = never>(onfulfilled?: Fn<[T], MaybePromise<OK>> | null, onrejected?: Fn<[unknown], MaybePromise<ERR>> | null): Promise<OK | ERR>;
|
|
165
|
+
catch<ERR = never>(onrejected?: Fn<[unknown], MaybePromise<ERR>> | null): Promise<T | ERR>;
|
|
166
|
+
finally(onfinally?: Action | null): Promise<T>;
|
|
213
167
|
/**
|
|
214
|
-
* Waits for the
|
|
168
|
+
* Waits for the next emission via `receive()` and wraps the outcome in a
|
|
169
|
+
* `PromiseSettledResult` - always resolves, never rejects.
|
|
215
170
|
*
|
|
216
|
-
* @returns
|
|
171
|
+
* @returns A promise that resolves with the settled result.
|
|
217
172
|
*
|
|
218
173
|
* @example
|
|
219
174
|
* ```typescript
|
|
220
175
|
* const result = await event.settle();
|
|
221
176
|
* if (result.status === 'fulfilled') {
|
|
222
|
-
* console.log('
|
|
177
|
+
* console.log('Value:', result.value);
|
|
223
178
|
* } else {
|
|
224
|
-
* console.error('
|
|
179
|
+
* console.error('Reason:', result.reason);
|
|
225
180
|
* }
|
|
226
181
|
* ```
|
|
227
182
|
*/
|
|
228
183
|
settle(): Promise<PromiseSettledResult<T>>;
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
*
|
|
232
|
-
* @returns {AsyncIterator<T>} An async iterator that yields values as they are emitted by this event.
|
|
233
|
-
*
|
|
234
|
-
* ```typescript
|
|
235
|
-
* // Assuming an event that emits numbers
|
|
236
|
-
* const numberEvent = new Event<number>();
|
|
237
|
-
* (async () => {
|
|
238
|
-
* for await (const num of numberEvent) {
|
|
239
|
-
* console.log('Number:', num);
|
|
240
|
-
* }
|
|
241
|
-
* })();
|
|
242
|
-
* await numberEvent(1);
|
|
243
|
-
* await numberEvent(2);
|
|
244
|
-
* await numberEvent(3);
|
|
245
|
-
* ```
|
|
246
|
-
*/
|
|
247
|
-
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
184
|
+
[Symbol.asyncIterator](): AsyncIterator<T, void, void>;
|
|
185
|
+
dispose(): void;
|
|
248
186
|
[Symbol.dispose](): void;
|
|
249
187
|
}
|
|
250
188
|
export type EventParameters<T> = T extends Event<infer P, any> ? P : never;
|
|
@@ -256,18 +194,14 @@ export type AllEventsResults<T extends Event<any, any>[]> = {
|
|
|
256
194
|
[K in keyof T]: EventReturn<T[K]>;
|
|
257
195
|
}[number];
|
|
258
196
|
/**
|
|
259
|
-
* Merges multiple events into a single event
|
|
260
|
-
*
|
|
261
|
-
* and results of the merged event are derived from the input events, providing a flexible way to
|
|
262
|
-
* handle multiple sources of events in a unified manner.
|
|
197
|
+
* Merges multiple events into a single event that triggers whenever any source triggers.
|
|
198
|
+
* Disposing the merged event unsubscribes from all sources.
|
|
263
199
|
*
|
|
264
|
-
* @
|
|
265
|
-
* @
|
|
266
|
-
* @returns {Event<AllEventsParameters<Events>, AllEventsResults<Events>>} Returns a new `Event` instance
|
|
267
|
-
* that triggers with the parameters and results of any of the merged input events.
|
|
200
|
+
* @param events - The events to merge.
|
|
201
|
+
* @returns A new Event that forwards emissions from all sources.
|
|
268
202
|
*
|
|
203
|
+
* @example
|
|
269
204
|
* ```typescript
|
|
270
|
-
* // Merging mouse and keyboard events into a single event
|
|
271
205
|
* const mouseEvent = createEvent<MouseEvent>();
|
|
272
206
|
* const keyboardEvent = createEvent<KeyboardEvent>();
|
|
273
207
|
* const inputEvent = merge(mouseEvent, keyboardEvent);
|
|
@@ -276,18 +210,14 @@ export type AllEventsResults<T extends Event<any, any>[]> = {
|
|
|
276
210
|
*/
|
|
277
211
|
export declare const merge: <Events extends Event<any, any>[]>(...events: Events) => Event<AllEventsParameters<Events>, AllEventsResults<Events>>;
|
|
278
212
|
/**
|
|
279
|
-
* Creates a periodic event that
|
|
280
|
-
*
|
|
281
|
-
* for creating time-based triggers within an application, such as updating UI elements, polling,
|
|
282
|
-
* or any other timed operation.
|
|
213
|
+
* Creates a periodic event that emits an incrementing counter (starting from 0) at a fixed interval.
|
|
214
|
+
* Disposing the event clears the interval.
|
|
283
215
|
*
|
|
284
|
-
* @
|
|
285
|
-
* @
|
|
286
|
-
* @returns {Event<number, R>} An `Event` instance that triggers at the specified interval,
|
|
287
|
-
* emitting an incrementing counter value.
|
|
216
|
+
* @param interval - The interval in milliseconds.
|
|
217
|
+
* @returns An Event that triggers at the specified interval.
|
|
288
218
|
*
|
|
219
|
+
* @example
|
|
289
220
|
* ```typescript
|
|
290
|
-
* // Creating an interval event that logs a message every second
|
|
291
221
|
* const tickEvent = createInterval(1000);
|
|
292
222
|
* tickEvent.on(tickNumber => console.log('Tick:', tickNumber));
|
|
293
223
|
* ```
|
|
@@ -295,23 +225,18 @@ export declare const merge: <Events extends Event<any, any>[]>(...events: Events
|
|
|
295
225
|
export declare const createInterval: <R = unknown>(interval: number) => Event<number, R>;
|
|
296
226
|
/**
|
|
297
227
|
* Creates a new Event instance for multi-listener event handling.
|
|
298
|
-
* This is the primary way to create events in the library.
|
|
299
|
-
*
|
|
300
|
-
* @template T - The type of value emitted to listeners (event payload)
|
|
301
|
-
* @template R - The return type of listener functions (collected in EventResult)
|
|
302
|
-
* @returns {Event<T, R>} A new Event instance ready for listener registration
|
|
303
228
|
*
|
|
229
|
+
* @example
|
|
304
230
|
* ```typescript
|
|
305
|
-
* // Create an event that accepts a string payload
|
|
306
231
|
* const messageEvent = createEvent<string>();
|
|
307
232
|
* messageEvent.on(msg => console.log('Received:', msg));
|
|
308
|
-
* messageEvent('Hello'); // All listeners receive 'Hello'
|
|
233
|
+
* messageEvent.emit('Hello'); // All listeners receive 'Hello'
|
|
309
234
|
*
|
|
310
|
-
* //
|
|
235
|
+
* // Listeners can return values, collected via DispatchResult
|
|
311
236
|
* const validateEvent = createEvent<string, boolean>();
|
|
312
237
|
* validateEvent.on(str => str.length > 0);
|
|
313
238
|
* validateEvent.on(str => str.length < 100);
|
|
314
|
-
* const results = await validateEvent('test'); //
|
|
239
|
+
* const results = await validateEvent.emit('test').all(); // [true, true]
|
|
315
240
|
* ```
|
|
316
241
|
*/
|
|
317
242
|
export declare const createEvent: <T = unknown, R = unknown>() => Event<T, R>;
|
package/build/event.js
CHANGED
|
@@ -1,162 +1,130 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
export class
|
|
6
|
-
|
|
7
|
-
constructor(
|
|
8
|
-
|
|
9
|
-
this._done = true;
|
|
10
|
-
await callback();
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
get done() {
|
|
14
|
-
return this._done;
|
|
15
|
-
}
|
|
16
|
-
pre(callback) {
|
|
17
|
-
return new Unsubscribe(async ()=>{
|
|
18
|
-
await callback();
|
|
19
|
-
await this();
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
post(callback) {
|
|
23
|
-
return new Unsubscribe(async ()=>{
|
|
24
|
-
await this();
|
|
25
|
-
await callback();
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
countdown(count) {
|
|
29
|
-
return new Unsubscribe(async ()=>{
|
|
30
|
-
if (!--count) {
|
|
31
|
-
await this();
|
|
32
|
-
}
|
|
33
|
-
});
|
|
1
|
+
import { Disposer } from "./async.js";
|
|
2
|
+
import { Signal } from "./signal.js";
|
|
3
|
+
import { ListenerRegistry } from "./listener-registry.js";
|
|
4
|
+
import { DispatchResult } from "./dispatch-result.js";
|
|
5
|
+
export class EventIterator {
|
|
6
|
+
#signal;
|
|
7
|
+
constructor(signal){
|
|
8
|
+
this.#signal = signal;
|
|
34
9
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
10
|
+
async next() {
|
|
11
|
+
try {
|
|
12
|
+
const value = await this.#signal.receive();
|
|
13
|
+
return {
|
|
14
|
+
value,
|
|
15
|
+
done: false
|
|
16
|
+
};
|
|
17
|
+
} catch {
|
|
18
|
+
return {
|
|
19
|
+
value: undefined,
|
|
20
|
+
done: true
|
|
21
|
+
};
|
|
22
|
+
}
|
|
47
23
|
}
|
|
48
|
-
|
|
49
|
-
return
|
|
24
|
+
async return() {
|
|
25
|
+
return {
|
|
26
|
+
value: undefined,
|
|
27
|
+
done: true
|
|
28
|
+
};
|
|
50
29
|
}
|
|
51
30
|
}
|
|
52
|
-
export class Event
|
|
53
|
-
listeners;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
31
|
+
export class Event {
|
|
32
|
+
#listeners = new ListenerRegistry();
|
|
33
|
+
#signal = new Signal();
|
|
34
|
+
#disposer;
|
|
35
|
+
#onDispose;
|
|
36
|
+
#sink;
|
|
57
37
|
[Symbol.toStringTag] = 'Event';
|
|
58
|
-
constructor(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
void this.clear();
|
|
68
|
-
void dispose?.();
|
|
69
|
-
};
|
|
38
|
+
constructor(onDispose){
|
|
39
|
+
this.#onDispose = onDispose;
|
|
40
|
+
this.#disposer = new Disposer(this);
|
|
41
|
+
}
|
|
42
|
+
get sink() {
|
|
43
|
+
return this.#sink ??= this.emit.bind(this);
|
|
44
|
+
}
|
|
45
|
+
handleEvent(event) {
|
|
46
|
+
this.emit(event);
|
|
70
47
|
}
|
|
71
48
|
get size() {
|
|
72
|
-
return this
|
|
49
|
+
return this.#listeners.size;
|
|
73
50
|
}
|
|
74
|
-
|
|
75
|
-
|
|
51
|
+
emit(value) {
|
|
52
|
+
this.#signal.emit(value);
|
|
53
|
+
return new DispatchResult(this.#listeners.dispatch(value));
|
|
76
54
|
}
|
|
77
55
|
lacks(listener) {
|
|
78
|
-
return !this
|
|
56
|
+
return !this.#listeners.has(listener);
|
|
79
57
|
}
|
|
80
58
|
has(listener) {
|
|
81
|
-
return this
|
|
59
|
+
return this.#listeners.has(listener);
|
|
82
60
|
}
|
|
83
61
|
off(listener) {
|
|
84
|
-
|
|
85
|
-
[
|
|
86
|
-
...this.hooks
|
|
87
|
-
].forEach((hook)=>hook(listener, HookType.Remove));
|
|
88
|
-
}
|
|
62
|
+
this.#listeners.off(listener);
|
|
89
63
|
return this;
|
|
90
64
|
}
|
|
91
65
|
on(listener) {
|
|
92
|
-
this
|
|
93
|
-
|
|
94
|
-
[
|
|
95
|
-
...this.hooks
|
|
96
|
-
].forEach((hook)=>hook(listener, HookType.Add));
|
|
97
|
-
}
|
|
98
|
-
return new Unsubscribe(()=>{
|
|
99
|
-
void this.off(listener);
|
|
100
|
-
});
|
|
66
|
+
this.#listeners.on(listener);
|
|
67
|
+
return ()=>void this.off(listener);
|
|
101
68
|
}
|
|
102
69
|
once(listener) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return listener(event);
|
|
106
|
-
};
|
|
107
|
-
return this.on(oneTimeListener);
|
|
70
|
+
this.#listeners.once(listener);
|
|
71
|
+
return ()=>void this.off(listener);
|
|
108
72
|
}
|
|
109
73
|
clear() {
|
|
110
|
-
this
|
|
111
|
-
if (this.hooks.length) {
|
|
112
|
-
[
|
|
113
|
-
...this.hooks
|
|
114
|
-
].forEach((hook)=>hook(undefined, HookType.Remove));
|
|
115
|
-
}
|
|
74
|
+
this.#listeners.clear();
|
|
116
75
|
return this;
|
|
117
76
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
77
|
+
receive() {
|
|
78
|
+
return this.#signal.receive();
|
|
79
|
+
}
|
|
80
|
+
then(onfulfilled, onrejected) {
|
|
81
|
+
return this.receive().then(onfulfilled, onrejected);
|
|
82
|
+
}
|
|
83
|
+
catch(onrejected) {
|
|
84
|
+
return this.receive().catch(onrejected);
|
|
85
|
+
}
|
|
86
|
+
finally(onfinally) {
|
|
87
|
+
return this.receive().finally(onfinally);
|
|
124
88
|
}
|
|
125
|
-
|
|
126
|
-
return
|
|
127
|
-
|
|
128
|
-
|
|
89
|
+
settle() {
|
|
90
|
+
return this.receive().then((value)=>({
|
|
91
|
+
status: 'fulfilled',
|
|
92
|
+
value
|
|
93
|
+
}), (reason)=>({
|
|
94
|
+
status: 'rejected',
|
|
95
|
+
reason
|
|
96
|
+
}));
|
|
129
97
|
}
|
|
130
98
|
[Symbol.asyncIterator]() {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
};
|
|
136
|
-
this.listeners.push(emitEvent);
|
|
137
|
-
const hook = (target = emitEvent, action)=>{
|
|
138
|
-
if (target === emitEvent && action === HookType.Remove) {
|
|
139
|
-
ctrl.abort('done');
|
|
140
|
-
this.listeners.removeFirst(emitEvent);
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
this.hooks.push(hook);
|
|
144
|
-
return sequence[Symbol.asyncIterator]();
|
|
99
|
+
return new EventIterator(this.#signal);
|
|
100
|
+
}
|
|
101
|
+
dispose() {
|
|
102
|
+
this[Symbol.dispose]();
|
|
145
103
|
}
|
|
146
104
|
[Symbol.dispose]() {
|
|
147
|
-
|
|
105
|
+
if (this.#disposer[Symbol.dispose]()) {
|
|
106
|
+
this.#signal[Symbol.dispose]();
|
|
107
|
+
this.#listeners.clear();
|
|
108
|
+
void this.#onDispose?.();
|
|
109
|
+
}
|
|
148
110
|
}
|
|
149
111
|
}
|
|
150
112
|
export const merge = (...events)=>{
|
|
151
|
-
const mergedEvent = new Event()
|
|
152
|
-
|
|
113
|
+
const mergedEvent = new Event(()=>{
|
|
114
|
+
for (const event of events){
|
|
115
|
+
event.off(mergedEvent.sink);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
for (const event of events){
|
|
119
|
+
event.on(mergedEvent.sink);
|
|
120
|
+
}
|
|
153
121
|
return mergedEvent;
|
|
154
122
|
};
|
|
155
123
|
export const createInterval = (interval)=>{
|
|
156
124
|
let counter = 0;
|
|
157
125
|
const intervalEvent = new Event(()=>clearInterval(timerId));
|
|
158
126
|
const timerId = setInterval(()=>{
|
|
159
|
-
|
|
127
|
+
intervalEvent.emit(counter++);
|
|
160
128
|
}, interval);
|
|
161
129
|
return intervalEvent;
|
|
162
130
|
};
|