evnty 3.0.39 → 4.0.0-rc-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 CHANGED
@@ -1,13 +1,21 @@
1
- Copyright (c) 2023-present Ivan Zakharchanka
1
+ The MIT License (MIT)
2
2
 
3
- Licensed under the Apache License, Version 2.0 (the "License");
4
- you may not use this file except in compliance with the License.
5
- You may obtain a copy of the License at
3
+ Copyright (c) 2019-2024 Ivan Zakharchanka
6
4
 
7
- http://www.apache.org/licenses/LICENSE-2.0
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:
8
11
 
9
- Unless required by applicable law or agreed to in writing, software
10
- distributed under the License is distributed on an "AS IS" BASIS,
11
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- See the License for the specific language governing permissions and
13
- limitations under the License.
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 CHANGED
@@ -14,19 +14,40 @@
14
14
  - [Features](#features)
15
15
  - [Platform Support](#platform-support)
16
16
  - [Installing](#installing)
17
- - [Usage](#usage)
18
- - [createEvent](#createevent)
19
- - [filter](#filter)
20
- - [map](#map)
21
- - [reduce](#reduce)
22
- - [expand](#expand)
23
- - [orchestrate](#orchestrate)
24
- - [debounce](#debounce)
25
- - [batch](#batch)
26
- - [generator](#generator)
27
- - [queue](#queue)
28
- - [merge](#merge)
29
- - [createInterval](#createinterval)
17
+ - [API](#api)
18
+ - [Event](#event)
19
+ - [constructor(dispose?: Callback)](#constructordispose-callback)
20
+ - [error(): Event<unknown>](#error-eventunknown)
21
+ - [size(): number](#size-number)
22
+ - [lacks(listener: Listener<T, R>): boolean](#lackslistener-listenert-r-boolean)
23
+ - [has(listener: Listener<T, R>): boolean](#haslistener-listenert-r-boolean)
24
+ - [off(listener: Listener<T, R>): this](#offlistener-listenert-r-this)
25
+ - [on(listener: Listener<T, R>): Unsubscribe](#onlistener-listenert-r-unsubscribe)
26
+ - [once(listener: Listener<T, R>): Unsubscribe](#oncelistener-listenert-r-unsubscribe)
27
+ - [clear(): this](#clear-this)
28
+ - [then(onfulfilled, onrejected): Promise<TResult1 | TResult2>](#thenonfulfilled-onrejected-promisetresult1--tresult2)
29
+ - [promise(): Promise<T>](#promise-promiset)
30
+ - [Symbol.asyncIterator(): AsyncIterator<T>](#symbolasynciterator-asynciteratort)
31
+ - [pipe(generator): Event<PT, R>](#pipegenerator-eventpt-r)
32
+ - [generator(generator): AsyncGenerator<Awaited<PT>, void, unknown>](#generatorgenerator-asyncgeneratorawaitedpt-void-unknown)
33
+ - [filter(predicate: Predicate<T, P>): Event<P, R>](#filterpredicate-predicatet-p-eventp-r)
34
+ - [filter(filter: FilterFunction<T>): Event<P, R>](#filterfilter-filterfunctiont-eventp-r)
35
+ - [filter(filter: Filter<T, P>): Event<P, R>](#filterfilter-filtert-p-eventp-r)
36
+ - [first(predicate: Predicate<T, P>): Event<P, R>](#firstpredicate-predicatet-p-eventp-r)
37
+ - [first(filter: FilterFunction<T>): Event<P, R>](#firstfilter-filterfunctiont-eventp-r)
38
+ - [first(filter: Filter<T, P>): Event<P, R>](#firstfilter-filtert-p-eventp-r)
39
+ - [map(mapper: Mapper<T, M>): Event<Awaited<M>, MR>](#mapmapper-mappert-m-eventawaitedm-mr)
40
+ - [reduce(reducer: Reducer<T, A>, init?: A): Event<Awaited<A>, AR>](#reducereducer-reducert-a-init-a-eventawaiteda-ar)
41
+ - [reduce(reducer: Reducer<T, A>, ...init: unknown[]): Event<Awaited<A>, AR>](#reducereducer-reducert-a-init-unknown-eventawaiteda-ar)
42
+ - [expand(expander: Expander<T, ET[]>): Event<Awaited<ET>, ER>](#expandexpander-expandert-et-eventawaitedet-er)
43
+ - [orchestrate(conductor: Event<any, any>): Event<T, R>](#orchestrateconductor-eventany-any-eventt-r)
44
+ - [debounce(interval: number): Event<Awaited<T>, unknown>](#debounceinterval-number-eventawaitedt-unknown)
45
+ - [throttle(interval: number): Event<Awaited<T>, unknown>](#throttleinterval-number-eventawaitedt-unknown)
46
+ - [batch(interval: number, size?: number): Event<T[], R>](#batchinterval-number-size-number-eventt-r)
47
+ - [queue(): Queue<T>](#queue-queuet)
48
+ - [merge(...events: Events): Event<AllEventsParameters<Events>, AllEventsResults<Events>>](#mergeevents-events-eventalleventsparametersevents-alleventsresultsevents)
49
+ - [createInterval(interval: number): Event<number, R>](#createintervalinterval-number-eventnumber-r)
50
+ - [createEvent(): Event<T, R>](#createevent-eventt-r)
30
51
  - [Examples](#examples)
31
52
  - [Migration](#migration)
32
53
  - [License](#license)
@@ -79,66 +100,277 @@ Using npm:
79
100
  npm install evnty
80
101
  ```
81
102
 
82
- ## Usage
103
+ ## API
83
104
 
84
- ### createEvent
105
+ ### `Event`
85
106
 
86
- Creates a new event instance.
107
+ A class representing an anonymous event that can be listened to or triggered.
87
108
 
88
- ```ts
89
- import { createEvent, Event } from 'evnty';
109
+ - @template T - The event type.
110
+ - @template R - The return type of the event.
90
111
 
91
- type ClickEvent = { x: number; y: number; button: number };
92
- const clickEvent = createEvent<ClickEvent>();
112
+ #### `constructor(dispose?: Callback)`
93
113
 
94
- type KeyPressEvent = { key: string };
95
- const keyPressEvent = createEvent<KeyPressEvent>();
114
+ Creates a new event.
96
115
 
97
- type ChangeEvent = { target: HTMLInputElement };
98
- const changeEvent = createEvent<ChangeEvent>();
99
- document.querySelector('input').addEventListener('change', changeEvent);
116
+ - @param dispose - A function to call on the event disposal.
117
+
118
+ ```typescript
119
+ // Create a click event.
120
+ const clickEvent = new Event<[x: number, y: number], void>();
121
+ clickEvent.on(([x, y]) => console.log(`Clicked at ${x}, ${y}`));
122
+ ```
123
+
124
+ #### `error(): Event<unknown>`
125
+
126
+ Error event that emits errors.
127
+
128
+ - @returns {Event<unknown>} The error event.
129
+
130
+ #### `size(): number`
131
+
132
+ The number of listeners for the event.
133
+
134
+ - @readonly
135
+ - @type {number}
136
+
137
+ #### `lacks(listener: Listener<T, R>): boolean`
138
+
139
+ Checks if the given listener is NOT registered for this event.
140
+
141
+ - @param listener - The listener function to check against the registered listeners.
142
+ - @returns `true` if the listener is not already registered; otherwise, `false`.
143
+
144
+ ```typescript
145
+ // Check if a listener is not already added
146
+ if (event.lacks(myListener)) {
147
+ event.on(myListener);
148
+ }
149
+ ```
150
+
151
+ #### `has(listener: Listener<T, R>): boolean`
152
+
153
+ Checks if the given listener is registered for this event.
154
+
155
+ - @param listener - The listener function to check.
156
+ - @returns `true` if the listener is currently registered; otherwise, `false`.
157
+
158
+ ```typescript
159
+ // Verify if a listener is registered
160
+ if (event.has(myListener)) {
161
+ console.log('Listener is already registered');
162
+ }
163
+ ```
164
+
165
+ #### `off(listener: Listener<T, R>): this`
166
+
167
+ Removes a specific listener from this event.
168
+
169
+ - @param listener - The listener to remove.
170
+ - @returns The event instance, allowing for method chaining.
171
+
172
+ ```typescript
173
+ // Remove a listener
174
+ event.off(myListener);
175
+ ```
176
+
177
+ #### `on(listener: Listener<T, R>): Unsubscribe`
178
+
179
+ Registers a listener that gets triggered whenever the event is emitted.
180
+ This is the primary method for adding event handlers that will react to the event being triggered.
181
+
182
+ - @param listener - The function to call when the event occurs.
183
+ - @returns An object that can be used to unsubscribe the listener, ensuring easy cleanup.
184
+
185
+ ```typescript
186
+ // Add a listener to an event
187
+ const unsubscribe = event.on((data) => {
188
+ console.log('Event data:', data);
189
+ });
190
+ ```
191
+
192
+ #### `once(listener: Listener<T, R>): Unsubscribe`
193
+
194
+ Adds a listener that will be called only once the next time the event is emitted.
195
+ This method is useful for one-time notifications or single-trigger scenarios.
196
+
197
+ - @param listener - The listener to trigger once.
198
+ - @returns An object that can be used to remove the listener if the event has not yet occurred.
199
+
200
+ ```typescript
201
+ // Register a one-time listener
202
+ const onceUnsubscribe = event.once((data) => {
203
+ console.log('Received data once:', data);
204
+ });
205
+ ```
206
+
207
+ #### `clear(): this`
208
+
209
+ Removes all listeners from the event, effectively resetting it. This is useful when you need to
210
+ cleanly dispose of all event handlers to prevent memory leaks or unwanted triggerings after certain conditions.
211
+
212
+ - @returns {this} The instance of the event, allowing for method chaining.
213
+
214
+ ```typescript
215
+ const myEvent = new Event();
216
+ myEvent.on((data) => console.log(data));
217
+ myEvent.clear(); // Clears all listeners
218
+ ```
219
+
220
+ #### `then(onfulfilled, onrejected): Promise<TResult1 | TResult2>`
221
+
222
+ Enables the `Event` to be used in a Promise chain, resolving with the first emitted value.
223
+
224
+ - @template TResult1 - The type of the fulfilled value returned by `onfulfilled` (defaults to the event's type).
225
+ - @template TResult2 - The type of the rejected value returned by `onrejected` (defaults to `never`).
226
+ - @param onfulfilled - A function called when the event emits its first value.
227
+ - @param onrejected - A function called if an error occurs before the event emits.
228
+ - @returns A Promise that resolves with the result of `onfulfilled` or `onrejected`.
229
+
230
+ ```typescript
231
+ const clickEvent = new Event<[number, number]>();
232
+ await clickEvent;
233
+ ```
234
+
235
+ #### `promise(): Promise<T>`
236
+
237
+ A promise that resolves with the first emitted value from this event.
238
+
239
+ - @returns {Promise<T>} The promise value.
240
+
241
+ #### `Symbol.asyncIterator(): AsyncIterator<T>`
242
+
243
+ Makes this event iterable using `for await...of` loops.
244
+
245
+ - @returns An async iterator that yields values as they are emitted by this event.
246
+
247
+ ```typescript
248
+ // Assuming an event that emits numbers
249
+ const numberEvent = new Event<number>();
250
+ (async () => {
251
+ for await (const num of numberEvent) {
252
+ console.log('Number:', num);
253
+ }
254
+ })();
255
+ await numberEvent(1);
256
+ await numberEvent(2);
257
+ await numberEvent(3);
100
258
  ```
101
259
 
102
- ### filter
260
+ #### `pipe(generator): Event<PT, R>`
261
+
262
+ Transforms the event's values using a generator function, creating a new `Event` that emits the transformed values.
263
+
264
+ - @template PT - The type of values emitted by the transformed `Event`.
265
+ - @template PR - The return type of the listeners of the transformed `Event`.
266
+ - @param generator - A function that takes the original event's value and returns a generator (sync or async) that yields the transformed values.
267
+ - @returns A new `Event` instance that emits the transformed values.
268
+
269
+ ```typescript
270
+ const numbersEvent = new Event<number>();
271
+ const evenNumbersEvent = numbersEvent.pipe(function* (value) {
272
+ if (value % 2 === 0) {
273
+ yield value;
274
+ }
275
+ });
276
+ evenNumbersEvent.on((evenNumber) => console.log(evenNumber));
277
+ await numbersEvent(1);
278
+ await numbersEvent(2);
279
+ await numbersEvent(3);
280
+ ```
281
+
282
+ #### `generator(generator): AsyncGenerator<Awaited<PT>, void, unknown>`
283
+
284
+ Creates an async generator that yields values as they are emitted by this event.
285
+
286
+ - @template PT - The type of values yielded by the async generator.
287
+ - @param generator - An optional function that takes the original event's value and returns a generator (sync or async)
288
+ that yields values to include in the async generator.
289
+ - @returns An async generator that yields values from this event as they occur.
290
+
291
+ ```typescript
292
+ const numbersEvent = new Event<number>();
293
+ const evenNumbersEvent = numbersEvent.pipe(function* (value) {
294
+ if (value % 2 === 0) {
295
+ yield value;
296
+ }
297
+ });
298
+ evenNumbersEvent.on((evenNumber) => console.log(evenNumber));
299
+ await numbersEvent(1);
300
+ await numbersEvent(2);
301
+ await numbersEvent(3);
302
+ ```
103
303
 
104
- Returns a new event that will only be triggered once the provided filter function returns `true`.
105
- Supports predicate type guard function and filter function as a more concise variant.
304
+ #### `filter(predicate: Predicate<T, P>): Event<P, R>`
106
305
 
107
- ```ts
108
- import { Predicate } from 'evnty';
306
+ #### `filter(filter: FilterFunction<T>): Event<P, R>`
109
307
 
110
- type SpacePressEvent = KeyPressEvent & { key: 'Space' };
111
- type LeftClickEvent = ClickEvent & { button: 1 };
308
+ #### `filter(filter: Filter<T, P>): Event<P, R>`
112
309
 
113
- const spacePressPredicate: Predicate<KeyPressEvent, SpacePressEvent> = (keyPressEvent): keyPressEvent is SpacePressEvent => keyPressEvent.key === 'Space';
114
- // event type is inferred from the predicate function
115
- const spacePressPredicatedEvent = keyPressEvent.filter(spacePredicate);
116
- // event type is inferred from the explicitly specified type
117
- const spacePressFilteredEvent = keyPressEvent.filter<SpacePressEvent>(({ key }) => key === 'Space');
310
+ Filters events, creating a new event that only triggers when the provided filter function returns `true`.
311
+ This method can be used to selectively process events that meet certain criteria.
118
312
 
119
- const leftClickPredicate: Predicate<ClickEvent, LeftClickEvent> = (mouseClickEvent): mouseClickEvent is LeftClickEvent => mouseClickEvent.button === 1;
120
- // event type is inferred from the predicate function
121
- const leftClickPredicatedEvent = clickEvent.filter(leftClickPredicate);
122
- // event type is inferred from the explicitly specified type
123
- const leftClickFilteredEvent = keyPressEvent.filter<LeftClickEvent>(({ button }) => button === 1);
313
+ - @param {Filter<T, P>} predicate The filter function or predicate to apply to each event.
314
+ - @returns {Event<P, R>} A new event that only triggers for filtered events.
315
+
316
+ ```typescript
317
+ const keyPressedEvent = new Event<string>();
318
+ const enterPressedEvent = keyPressedEvent.filter((key) => key === 'Enter');
319
+ enterPressedEvent.on(() => console.log('Enter key was pressed.'));
124
320
  ```
125
321
 
126
- ### map
322
+ #### `first(predicate: Predicate<T, P>): Event<P, R>`
323
+
324
+ #### `first(filter: FilterFunction<T>): Event<P, R>`
325
+
326
+ #### `first(filter: Filter<T, P>): Event<P, R>`
127
327
 
128
- Returns a new event that maps the values of this event using the provided mapper function.
328
+ Creates a new event that will only be triggered once when the provided filter function returns `true`.
329
+ This method is useful for handling one-time conditions in a stream of events.
129
330
 
130
- ```ts
131
- const point = { x: 100, y: 100 };
132
- const distanceClickEvent = clickEvent.map((click) => (click.x - point.x) ** 2 + (click.y - point.y) ** 2);
133
- const lowerCaseKeyPressEvent = keyPressEvent.map(({ key }) => key.toLowerCase());
134
- const trimmedChangeEvent = changeEvent.map((event) => event.target.value.trim());
331
+ - @param {Filter<T, P>} predicate - The filter function or predicate.
332
+ - @returns {Event<P, R>} A new event that will be triggered only once when the filter condition is met.
333
+
334
+ ```typescript
335
+ const sizeChangeEvent = new Event<number>();
336
+ const sizeReachedEvent = sizeChangeEvent.first((size) => size > 1024);
337
+ sizeReachedEvent.on(() => console.log('Size threshold exceeded.'));
338
+ ```
339
+
340
+ #### `map(mapper: Mapper<T, M>): Event<Awaited<M>, MR>`
341
+
342
+ Transforms the data emitted by this event using a mapping function. Each emitted event is processed by the `mapper`
343
+ function, which returns a new value that is then emitted by the returned `Event` instance. This is useful for data transformation
344
+ or adapting the event's data structure.
345
+
346
+ - @template M The type of data that the mapper function will produce.
347
+ - @template MR The type of data emitted by the mapped event, usually related to or the same as `M`.
348
+ - @param {Mapper<T, M>} mapper A function that takes the original event data and returns the transformed data.
349
+ - @returns {Event<M, MR>} A new `Event` instance that emits the mapped values.
350
+
351
+ ```typescript
352
+ // Assuming an event that emits numbers, create a new event that emits their squares.
353
+ const numberEvent = new Event<number>();
354
+ const squaredEvent = numberEvent.map(num => num num);
355
+ squaredEvent.on(squared => console.log('Squared number:', squared));
356
+ await numberEvent(5); // Logs: "Squared number: 25"
135
357
  ```
136
358
 
137
- ### reduce
359
+ #### `reduce(reducer: Reducer<T, A>, init?: A): Event<Awaited<A>, AR>`
360
+
361
+ #### `reduce(reducer: Reducer<T, A>, ...init: unknown[]): Event<Awaited<A>, AR>`
362
+
363
+ Accumulates the values emitted by this event using a reducer function, starting from an initial value. The reducer
364
+ function takes the accumulated value and the latest emitted event data, then returns a new accumulated value. This
365
+ new value is then emitted by the returned `Event` instance. This is particularly useful for accumulating state over time.
138
366
 
139
- Returns a new event that reduces the emitted values using the provided reducer function.
367
+ - @template A The type of the accumulator value.
368
+ - @template AR The type of data emitted by the reduced event, usually the same as `A`.
369
+ - @param {Reducer<T, A>} reducer A function that takes the current accumulated value and the new event data, returning the new accumulated value.
370
+ - @param {A} init The initial value of the accumulator.
371
+ - @returns {Event<A, AR>} A new `Event` instance that emits the reduced value.
140
372
 
141
- ```ts
373
+ ```typescript
142
374
  const sumEvent = numberEvent.reduce((a, b) => a + b, 0);
143
375
  sumEvent.on((sum) => console.log(sum)); // 1, 3, 6
144
376
  await sumEvent(1);
@@ -146,133 +378,177 @@ await sumEvent(2);
146
378
  await sumEvent(3);
147
379
  ```
148
380
 
149
- ### expand
381
+ #### `expand(expander: Expander<T, ET[]>): Event<Awaited<ET>, ER>`
150
382
 
151
383
  Transforms each event's data into multiple events using an expander function. The expander function takes
152
384
  the original event's data and returns an array of new data elements, each of which will be emitted individually
153
385
  by the returned `Event` instance. This method is useful for scenarios where an event's data can naturally
154
386
  be expanded into multiple, separate pieces of data which should each trigger further processing independently.
155
387
 
156
- ```ts
388
+ - @template ET - The type of data elements in the array returned by the expander function.
389
+ - @template ER - The type of responses emitted by the expanded event, usually related to or the same as `ET`.
390
+ - @param {Expander<T, ET[]>} expander - A function that takes the original event data and returns an array of new data elements.
391
+ - @returns {Event<ET, ER>} - A new `Event` instance that emits each value from the array returned by the expander function.
392
+
393
+ ```typescript
157
394
  // Assuming an event that emits a sentence, create a new event that emits each word from the sentence separately.
158
395
  const sentenceEvent = new Event<string>();
159
- const wordEvent = sentenceEvent.expand(sentence => sentence.split(' '));
160
- wordEvent.on(word => console.log('Word:', word));
396
+ const wordEvent = sentenceEvent.expand((sentence) => sentence.split(' '));
397
+ wordEvent.on((word) => console.log('Word:', word));
161
398
  await sentenceEvent('Hello world'); // Logs: "Word: Hello", "Word: world"
162
399
  ```
163
400
 
164
- ### orchestrate
401
+ #### `orchestrate(conductor: Event<any, any>): Event<T, R>`
165
402
 
166
403
  Creates a new event that emits values based on a conductor event. The orchestrated event will emit the last value
167
404
  captured from the original event each time the conductor event is triggered. This method is useful for synchronizing
168
405
  events, where the emission of one event controls the timing of another.
169
406
 
170
- ```ts
407
+ - @template T The type of data emitted by the original event.
408
+ - @template R The type of data emitted by the orchestrated event, usually the same as `T`.
409
+ - @param {Event<unknown, unknown>} conductor An event that signals when the orchestrated event should emit.
410
+ - @returns {Event<T, R>} An orchestrated event that emits values based on the conductor's trigger.
411
+
412
+ ```typescript
171
413
  const rightClickPositionEvent = mouseMoveEvent.orchestrate(mouseRightClickEvent);
414
+ ```
172
415
 
416
+ ```typescript
173
417
  // An event that emits whenever a "tick" event occurs.
174
418
  const tickEvent = new Event<void>();
175
419
  const dataEvent = new Event<string>();
176
420
  const synchronizedEvent = dataEvent.orchestrate(tickEvent);
177
- synchronizedEvent.on(data => console.log('Data on tick:', data));
421
+ synchronizedEvent.on((data) => console.log('Data on tick:', data));
178
422
  await dataEvent('Hello');
179
423
  await dataEvent('World!');
180
424
  await tickEvent(); // Logs: "Data on tick: World!"
181
425
  ```
182
426
 
183
- ### debounce
427
+ #### `debounce(interval: number): Event<Awaited<T>, unknown>`
184
428
 
185
429
  Creates a debounced event that delays triggering until after a specified interval has elapsed
186
430
  following the last time it was invoked. This method is particularly useful for limiting the rate
187
431
  at which a function is executed. Common use cases include handling rapid user inputs, window resizing,
188
432
  or scroll events.
189
433
 
190
- ```ts
191
- const searchEvent = changeEvent.debounce(100);
192
- searchEvent.value.on(text => searchAPI(text)); // 'text'
193
- searchEvent.error.on(error => console.error(error));
194
- await searchEvent('t');
195
- await searchEvent('te');
196
- await searchEvent('tex');
197
- await searchEvent('text');
434
+ - @param {number} interval - The amount of time to wait (in milliseconds) before firing the debounced event.
435
+ - @returns {Event<T, R>} An event of debounced events.
436
+
437
+ ```typescript
438
+ const debouncedEvent = textInputEvent.debounce(100);
439
+ debouncedEvent.on((str) => console.log(str)); // only 'text' is emitted
440
+ await event('t');
441
+ await event('te');
442
+ await event('tex');
443
+ await event('text');
198
444
  ```
199
445
 
200
- ### batch
446
+ #### `throttle(interval: number): Event<Awaited<T>, unknown>`
201
447
 
202
- Aggregates multiple event emissions into batches and emits the batched events either at specified
203
- time intervals or when the batch reaches a predefined size. This method is useful for grouping
204
- a high volume of events into manageable chunks, such as logging or processing data in bulk.
448
+ Creates a throttled event that emits values at most once per specified interval.
205
449
 
206
- ```ts
207
- const sendData = changeEvent.batch(100, 5);
208
- sendData.value.on(data => console.log(data)); // ['data1', 'data2', 'data3', 'data4']
209
- sendData.error.on(error => console.error(error)); //
210
- await sendData('data1');
211
- await sendData('data2');
212
- await sendData('data3');
213
- await sendData('data4');
450
+ This is useful for controlling the rate of event emissions, especially for high-frequency events.
451
+ The throttled event will immediately emit the first value, and then only emit subsequent values
452
+ if the specified interval has passed since the last emission.
453
+
454
+ - @param interval - The time interval (in milliseconds) between allowed emissions.
455
+ - @returns A new Event that emits throttled values.
456
+
457
+ ```typescript
458
+ const scrollEvent = new Event();
459
+ const throttledScroll = scrollEvent.throttle(100); // Emit at most every 100ms
460
+ throttledScroll.on(() => console.log('Throttled scroll event'));
214
461
  ```
215
462
 
216
- ### generator
217
- Transforms an event into an AsyncIterable that yields values as they are emitted by the event. This allows for the consumption
218
- of event data using async iteration mechanisms. The iterator generated will yield all emitted values until the event
219
- signals it should no longer be active.
463
+ #### `batch(interval: number, size?: number): Event<T[], R>`
220
464
 
221
- ```ts
222
- // Assuming an event that emits numbers
223
- const numberEvent = new Event<number>();
224
- const numberIterable = numberEvent.generator();
465
+ Aggregates multiple event emissions into batches and emits the batched events either at specified
466
+ time intervals or when the batch reaches a predefined size. This method is useful for grouping
467
+ a high volume of events into manageable chunks, such as logging or processing data in bulk.
225
468
 
226
- await numberEvent(1);
227
- await numberEvent(2);
228
- await numberEvent(3);
469
+ - @param {number} interval - The time in milliseconds between batch emissions.
470
+ - @param {number} [size] - Optional. The maximum size of each batch. If specified, triggers a batch emission
471
+ once the batch reaches this size, regardless of the interval.
472
+ - @returns {Event<T[], R>} An event of the batched results.
229
473
 
230
- for await (const num of numberIterable) {
231
- console.log('Number:', num);
232
- }
474
+ ```typescript
475
+ // Batch messages for bulk processing every 1 second or when 10 messages are collected
476
+ const messageEvent = createEvent<string, void>();
477
+ const batchedMessageEvent = messageEvent.batch(1000, 10);
478
+ batchedMessageEvent.on((messages) => console.log('Batched Messages:', messages));
233
479
  ```
234
480
 
235
- ### queue
481
+ #### `queue(): Queue<T>`
236
482
 
237
483
  Creates a queue from the event, where each emitted value is sequentially processed. The returned object allows popping elements
238
484
  from the queue, ensuring that elements are handled one at a time. This method is ideal for scenarios where order and sequential processing are critical.
239
485
 
240
- ```ts
486
+ - @returns {Queue<T>} An object representing the queue. The 'pop' method retrieves the next element from the queue, while 'stop' halts further processing.
487
+
488
+ ```typescript
241
489
  // Queueing tasks for sequential execution
242
490
  const taskEvent = new Event<string>();
243
491
  const taskQueue = taskEvent.queue();
492
+ (async () => {
493
+ console.log('Processing:', await taskQueue.pop()); // Processing: Task 1
494
+ console.log('Processing:', await taskQueue.pop()); // Processing: Task 2
495
+ })();
244
496
  await taskEvent('Task 1');
245
497
  await taskEvent('Task 2');
246
- console.log('Processing:', await taskQueue.pop()); // Processing: Task 1
247
- console.log('Processing:', await taskQueue.pop()); // Processing: Task 2
248
498
  ```
249
499
 
250
- ### merge
500
+ ### `merge(...events: Events): Event<AllEventsParameters<Events>, AllEventsResults<Events>>`
251
501
 
252
502
  Merges multiple events into a single event. This function takes any number of `Event` instances
253
503
  and returns a new `Event` that triggers whenever any of the input events trigger. The parameters
254
504
  and results of the merged event are derived from the input events, providing a flexible way to
255
505
  handle multiple sources of events in a unified manner.
256
506
 
507
+ - @template Events - An array of `Event` instances.
508
+ - @param {...Events} events - A rest parameter that takes multiple events to be merged.
509
+ - @returns {Event<AllEventsParameters<Events>, AllEventsResults<Events>>} - Returns a new `Event` instance
510
+ that triggers with the parameters and results of any of the merged input events.
257
511
 
258
- ```ts
259
- import { merge } from 'evnty';
260
-
512
+ ```typescript
261
513
  // Merging mouse and keyboard events into a single event
262
514
  const mouseEvent = createEvent<MouseEvent>();
263
515
  const keyboardEvent = createEvent<KeyboardEvent>();
264
516
  const inputEvent = merge(mouseEvent, keyboardEvent);
265
- inputEvent.on(event => console.log('Input event:', event));
517
+ inputEvent.on((event) => console.log('Input event:', event));
518
+ ```
519
+
520
+ ### `createInterval(interval: number): Event<number, R>`
521
+
522
+ Creates a periodic event that triggers at a specified interval. The event will automatically emit
523
+ an incrementing counter value each time it triggers, starting from zero. This function is useful
524
+ for creating time-based triggers within an application, such as updating UI elements, polling,
525
+ or any other timed operation.
526
+
527
+ - @template R - The return type of the event handler function, defaulting to `void`.
528
+ - @param {number} interval - The interval in milliseconds at which the event should trigger.
529
+ - @returns {Event<number, R>} - An `Event` instance that triggers at the specified interval,
530
+ emitting an incrementing counter value.
531
+
532
+ ```typescript
533
+ // Creating an interval event that logs a message every second
534
+ const tickEvent = createInterval(1000);
535
+ tickEvent.on((tickNumber) => console.log('Tick:', tickNumber));
266
536
  ```
267
537
 
268
- ### createInterval
538
+ ### `createEvent(): Event<T, R>`
269
539
 
270
- Creates an event that triggers at a specified interval.
540
+ Creates a new instance of the `Event` class, which allows for the registration of event handlers that get called when the event is emitted.
541
+ This factory function simplifies the creation of events by encapsulating the instantiation logic, providing a clean and simple API for event creation.
271
542
 
272
- ```ts
273
- import { createInterval } from 'evnty';
543
+ - @typeParam T - The tuple of argument types that the event will accept.
544
+ - @typeParam R - The return type of the event handler function, which is emitted after processing the event data.
545
+ - @returns {Event<T, R>} - A new instance of the `Event` class, ready to have listeners added to it.
274
546
 
275
- const everySecondEvent = createInterval(1000);
547
+ ```typescript
548
+ // Create a new event that accepts a string and returns the string length
549
+ const myEvent = createEvent<string, number>();
550
+ myEvent.on((str: string) => str.length);
551
+ myEvent('hello').then((results) => console.log(results)); // Logs: [5]
276
552
  ```
277
553
 
278
554
  ## Examples
@@ -338,16 +614,10 @@ const messagesBatchEvent = messageEvent.batch(100);
338
614
 
339
615
  ```
340
616
 
341
- ## Migration
342
-
343
- ### From v1 to v2
344
-
345
- A breaking change has been made: events no longer accept a list of arguments. Now, each event accepts a single argument, so simply wrap your arguments in an object. This decision was taken to leverage the benefits of predicate type guards.
346
-
347
617
  ## License
348
618
 
349
- License [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0)
350
- Copyright (c) 2021-present Ivan Zakharchanka
619
+ License [MIT](./LICENSE)
620
+ Copyright (c) 2024 Ivan Zakharchanka
351
621
 
352
622
  [npm-url]: https://www.npmjs.com/package/evnty
353
623
  [downloads-image]: https://img.shields.io/npm/dw/evnty.svg?maxAge=43200