evnty 4.7.10 → 5.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.
Files changed (44) hide show
  1. package/README.md +191 -70
  2. package/build/callable.cjs +58 -3
  3. package/build/callable.cjs.map +1 -1
  4. package/build/callable.d.ts +19 -1
  5. package/build/callable.js +44 -0
  6. package/build/callable.js.map +1 -1
  7. package/build/event.cjs +199 -0
  8. package/build/event.cjs.map +1 -0
  9. package/build/event.d.ts +362 -0
  10. package/build/event.js +166 -0
  11. package/build/event.js.map +1 -0
  12. package/build/index.cjs +5 -384
  13. package/build/index.cjs.map +1 -1
  14. package/build/index.d.ts +3 -598
  15. package/build/index.js +3 -352
  16. package/build/index.js.map +1 -1
  17. package/build/iterator.cjs +140 -0
  18. package/build/iterator.cjs.map +1 -0
  19. package/build/iterator.d.ts +171 -0
  20. package/build/iterator.js +130 -0
  21. package/build/iterator.js.map +1 -0
  22. package/build/sequence.cjs +32 -49
  23. package/build/sequence.cjs.map +1 -1
  24. package/build/sequence.d.ts +106 -14
  25. package/build/sequence.js +33 -50
  26. package/build/sequence.js.map +1 -1
  27. package/build/signal.cjs +20 -39
  28. package/build/signal.cjs.map +1 -1
  29. package/build/signal.d.ts +86 -17
  30. package/build/signal.js +21 -40
  31. package/build/signal.js.map +1 -1
  32. package/build/types.cjs +11 -0
  33. package/build/types.cjs.map +1 -1
  34. package/build/types.d.ts +18 -1
  35. package/build/types.js +5 -1
  36. package/build/types.js.map +1 -1
  37. package/build/utils.cjs +129 -0
  38. package/build/utils.cjs.map +1 -0
  39. package/build/utils.d.ts +104 -0
  40. package/build/utils.js +105 -0
  41. package/build/utils.js.map +1 -0
  42. package/package.json +33 -32
  43. package/src/__tests__/example.js +2 -2
  44. package/src/index.ts +3 -977
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Downloads][downloads-image]][npm-url]
7
7
  [![Snyk][snyk-image]][snyk-url]
8
8
 
9
- 0-dependency, high-performance, reactive event handling library optimized for both browser and Node.js environments. This library introduces a robust and type-safe abstraction for handling events, reducing boilerplate and increasing code maintainability.
9
+ Async-first, reactive event handling library for complex event flows with three powerful primitives: **Event** (multi-listener broadcast), **Signal** (promise-like coordination), and **Sequence** (async queue). Built for both browser and Node.js with full TypeScript support.
10
10
 
11
11
  <div align="center">
12
12
  <a href="https://github.com/3axap4ehko/evnty">
@@ -14,34 +14,117 @@
14
14
  </a>
15
15
  <br>
16
16
  <br>
17
-
18
17
  </div>
19
18
 
20
19
  ## Table of Contents
21
20
 
21
+ - [Core Concepts](#core-concepts)
22
22
  - [Motivation](#motivation)
23
23
  - [Features](#features)
24
24
  - [Platform Support](#platform-support)
25
25
  - [Installing](#installing)
26
26
  - [Documentation](https://3axap4ehko.github.io/evnty/)
27
27
  - [Examples](#examples)
28
- - [Migration](#migration)
29
28
  - [License](#license)
30
29
 
30
+ ## Core Concepts
31
+
32
+ Evnty provides three complementary async primitives, each designed for specific patterns:
33
+
34
+ ### 🔊 Event - Multi-Listener Broadcasting
35
+ Events allow multiple listeners to react to values. All registered listeners are called for each emission.
36
+
37
+ ```typescript
38
+ const clickEvent = createEvent<{ x: number, y: number }>();
39
+
40
+ // Multiple listeners can subscribe
41
+ clickEvent.on(({ x, y }) => console.log(`Click at ${x},${y}`));
42
+ clickEvent.on(({ x, y }) => updateUI(x, y));
43
+
44
+ // All listeners receive the value
45
+ clickEvent({ x: 100, y: 200 });
46
+ ```
47
+
48
+ **Use Event when:**
49
+ - Multiple components need to react to the same occurrence
50
+ - You need pub/sub or observer pattern
51
+ - Listeners should persist across multiple emissions
52
+
53
+ ### 📡 Signal - Promise-Based Coordination
54
+ Signals are for coordinating async operations. When a value is sent, ALL waiting consumers receive it (broadcast).
55
+
56
+ ```typescript
57
+ const signal = new Signal<string>();
58
+
59
+ // Multiple consumers can wait
60
+ const promise1 = signal.next();
61
+ const promise2 = signal.next();
62
+
63
+ // Send value - all waiting consumers receive it
64
+ signal('data');
65
+ const [result1, result2] = await Promise.all([promise1, promise2]);
66
+ // result1 === 'data' && result2 === 'data'
67
+ ```
68
+
69
+ **Use Signal when:**
70
+ - You need one-time notifications
71
+ - Multiple async operations need the same trigger
72
+ - Implementing async coordination patterns
73
+
74
+ ### 📦 Sequence - Async Queue (FIFO)
75
+ Sequences are FIFO queues for single-consumer scenarios. Values are consumed in order, with backpressure support.
76
+
77
+ ```typescript
78
+ const taskQueue = new Sequence<Task>();
79
+
80
+ // Producer adds tasks
81
+ taskQueue(task1);
82
+ taskQueue(task2);
83
+ taskQueue(task3);
84
+
85
+ // Single consumer processes in order
86
+ for await (const task of taskQueue) {
87
+ await processTask(task); // task1, then task2, then task3
88
+ }
89
+ ```
90
+
91
+ **Use Sequence when:**
92
+ - You need ordered processing (FIFO)
93
+ - Only one consumer should handle each value
94
+ - You want backpressure control with `reserve()`
95
+
96
+ ### Key Differences
97
+
98
+ | | Event | Signal | Sequence |
99
+ |---|---|---|---|
100
+ | **Consumers** | Multiple persistent listeners | Multiple one-time receivers | Single consumer |
101
+ | **Delivery** | All listeners called | All waiting get same value | Each value consumed once |
102
+ | **Pattern** | Pub/Sub | Broadcast coordination | Queue/Stream |
103
+ | **Persistence** | Listeners stay registered | Resolves once per `next()` | Values queued until consumed |
104
+
31
105
  ## Motivation
32
106
 
33
- In traditional event handling in TypeScript, events are often represented as strings, and there's no easy way to apply functional transformations like filtering or mapping directly on the event data. This approach lacks type safety, and chaining operations require additional boilerplate, making the code verbose and less maintainable.
107
+ Traditional event handling in JavaScript/TypeScript has limitations:
108
+ - String-based event names lack type safety
109
+ - No built-in async coordination primitives
110
+ - Missing functional transformations for event streams
111
+ - Complex patterns require extensive boilerplate
34
112
 
35
- The proposed library introduces a robust `Event` abstraction that encapsulates event data and provides a suite of functional methods like `map`, `filter`, `reduce`, `debounce`, etc., allowing for a more declarative and type-safe approach to event handling. This design facilitates method chaining and composition, making the code more readable and maintainable. For instance, it allows developers to create new events by transforming or filtering existing ones, thus promoting code reusability and modularity.
113
+ Evnty solves these problems by providing:
114
+ - **Type-safe events** with full TypeScript inference
115
+ - **Three specialized primitives** for different async patterns
116
+ - **Rich functional operators** (map, filter, reduce, debounce, batch, etc.)
117
+ - **Composable abstractions** that work together seamlessly
36
118
 
37
119
  ## Features
38
120
 
39
- - Modern: Supports Promises and module systems ESM and CommonJS
40
- - Zero Dependencies: Utilizes native features for optimal performance.
41
- - Full TypeScript Support: Ensures type safety and improves developer experience.
42
- - Functional Programming Techniques: Offers map, filter, reduce, expand, and more for event handling.
43
- - Flexible Environment Support: Works seamlessly in both the browser and Node.js, including service workers.
44
- - Performance Optimized: Competes with and exceeds other well-known libraries like EventEmitter3 and EventEmitter2 in performance benchmarks.
121
+ - **Async-First Design**: Built from the ground up for asynchronous event handling with full Promise support
122
+ - **Functional Programming**: Rich set of operators including map, filter, reduce, debounce, batch, and expand for event stream transformations
123
+ - **Type-Safe**: Full TypeScript support with strong typing and inference throughout the event pipeline
124
+ - **Async Iteration**: Events can be consumed as async iterables using for-await-of loops
125
+ - **Event Composition**: Merge, combine, and transform multiple event streams into new events
126
+ - **Minimal Dependencies**: Lightweight with only essential dependencies for optimal bundle size
127
+ - **Universal**: Works seamlessly in both browser and Node.js environments, including service workers
45
128
 
46
129
  ## Platform Support
47
130
 
@@ -78,71 +161,109 @@ npm install evnty
78
161
 
79
162
  ## Examples
80
163
 
81
- ```js
82
- import { createEvent, Event } from 'evnty';
83
-
84
- // Creates a click event
85
- type Click = { button: string };
86
- const clickEvent = createEvent<Click>();
87
- const handleClick = ({ button }: Click) => console.log('Clicked button is', button);
88
- const unsubscribeClick = clickEvent.on(handleClick);
89
-
90
- // Creates a key press event
91
- type KeyPress = { key: string };
92
- const keyPressEvent = createEvent<KeyPress>();
93
- const handleKeyPress = ({ key }: KeyPress) => console.log('Key pressed', key);
94
- const unsubscribeKeyPress = keyPressEvent.on(handleKeyPress);
95
-
96
- // Merges click and key press events into input event
97
- type Input = Click | KeyPress;
98
- const handleInput = (input: Input) => console.log('Input', input);;
99
- const inputEvent = Event.merge(clickEvent, keyPressEvent);
100
- inputEvent.on(handleInput);
101
-
102
- // Filters a click event to only include left-click events.
103
- const handleLeftClick = () => console.log('Left button is clicked');
104
- const leftClickEvent = clickEvent.filter(({ button }) => button === 'left');
105
- leftClickEvent.on(handleLeftClick);
106
-
107
- // Will press Enter after one second
108
- setTimeout(keyPressEvent, 1000, { key: 'Enter' });
109
- // Waits once the first Enter key press event occurs
110
- await keyPressEvent.first(({ key }) => key === 'Enter').onceAsync();
111
-
112
- keyPressEvent({ key: 'W' });
113
- keyPressEvent({ key: 'A' });
114
- keyPressEvent({ key: 'S' });
115
- keyPressEvent({ key: 'D' });
116
-
117
- clickEvent({ button: 'right' });
118
- clickEvent({ button: 'left' });
119
- clickEvent({ button: 'middle' });
120
-
121
- // Unsubscribe click listener
122
- unsubscribeClick();
123
- // It does not log anything because of click listener is unsubscribed
124
- leftClickEvent.off(handleLeftClick);
125
-
126
- // Unsubscribe key press listener once first Esc key press occur
127
- unsubscribeKeyPress.after(() => keyPressEvent
128
- .first(({ key }) => key === 'Esc')
129
- .onceAsync()
130
- );
131
- // Press Esc to unsubscribe key press listener
132
- keyPressEvent({ key: 'Esc' });
133
-
134
- const messageEvent = createEvent();
135
- const messagesBatchEvent = messageEvent.debounce(100);
136
-
137
- const messageEvent = createEvent();
138
- const messagesBatchEvent = messageEvent.batch(100);
164
+ ### Event - Multi-Listener Pattern
165
+ ```typescript
166
+ import { createEvent } from 'evnty';
167
+
168
+ // Create a typed event
169
+ const userEvent = createEvent<{ id: number, name: string }>();
170
+
171
+ // Multiple listeners
172
+ userEvent.on(user => console.log('Logger:', user));
173
+ userEvent.on(user => updateUI(user));
174
+ userEvent.on(user => saveToCache(user));
175
+
176
+ // Emit - all listeners are called
177
+ userEvent({ id: 1, name: 'Alice' });
178
+
179
+ // Functional transformations
180
+ const adminEvent = userEvent
181
+ .filter(user => user.id < 100)
182
+ .map(user => ({ ...user, role: 'admin' }));
183
+
184
+ // Async iteration
185
+ for await (const user of userEvent) {
186
+ console.log('User event:', user);
187
+ }
188
+ ```
189
+
190
+ ### Signal - Async Coordination
191
+ ```typescript
192
+ import { Signal } from 'evnty';
193
+
194
+ // Coordinate multiple async operations
195
+ const dataSignal = new Signal<Buffer>();
196
+
197
+ // Multiple operations wait for the same data
198
+ async function processA() {
199
+ const data = await dataSignal.next();
200
+ // Process data in way A
201
+ }
202
+
203
+ async function processB() {
204
+ const data = await dataSignal.next();
205
+ // Process data in way B
206
+ }
207
+
208
+ // Start both processors
209
+ Promise.all([processA(), processB()]);
210
+
211
+ // Both receive the same data when it arrives
212
+ dataSignal(Buffer.from('shared data'));
213
+ ```
214
+
215
+ ### Sequence - Task Queue
216
+ ```typescript
217
+ import { Sequence } from 'evnty';
218
+
219
+ // Create a task queue
220
+ const taskQueue = new Sequence<() => Promise<void>>();
221
+
222
+ // Single consumer processes tasks in order
223
+ (async () => {
224
+ for await (const task of taskQueue) {
225
+ await task();
226
+ console.log('Task completed');
227
+ }
228
+ })();
229
+
230
+ // Multiple producers add tasks
231
+ taskQueue(async () => fetchData());
232
+ taskQueue(async () => processData());
233
+ taskQueue(async () => saveResults());
234
+
235
+ // Backpressure control
236
+ await taskQueue.reserve(10); // Wait until queue has ≤10 items
237
+ taskQueue(async () => nonUrgentTask());
238
+ ```
239
+
240
+ ### Combining Primitives
241
+ ```typescript
242
+ // Event + Signal for request/response pattern
243
+ const requestEvent = createEvent<Request>();
244
+ const responseSignal = new Signal<Response>();
245
+
246
+ requestEvent.on(async (req) => {
247
+ const response = await handleRequest(req);
248
+ responseSignal(response);
249
+ });
250
+
251
+ // Event + Sequence for buffered processing
252
+ const dataEvent = createEvent<Data>();
253
+ const processQueue = new Sequence<Data>();
254
+
255
+ dataEvent.on(data => processQueue(data));
139
256
 
257
+ // Process with controlled concurrency
258
+ for await (const data of processQueue) {
259
+ await processWithRateLimit(data);
260
+ }
140
261
  ```
141
262
 
142
263
  ## License
143
264
 
144
265
  License [The MIT License](./LICENSE)
145
- Copyright (c) 2024 Ivan Zakharchanka
266
+ Copyright (c) 2025 Ivan Zakharchanka
146
267
 
147
268
  [npm-url]: https://www.npmjs.com/package/evnty
148
269
  [downloads-image]: https://img.shields.io/npm/dw/evnty.svg?maxAge=43200
@@ -2,16 +2,71 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "Callable", {
6
- enumerable: true,
7
- get: function() {
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get AsyncCallable () {
13
+ return AsyncCallable;
14
+ },
15
+ get Callable () {
8
16
  return Callable;
17
+ },
18
+ get CallableAsyncIterator () {
19
+ return CallableAsyncIterator;
9
20
  }
10
21
  });
11
22
  class Callable {
23
+ static{
24
+ Object.setPrototypeOf(Callable.prototype, Function.prototype);
25
+ }
12
26
  constructor(func){
13
27
  return Object.setPrototypeOf(func, new.target.prototype);
14
28
  }
15
29
  }
30
+ class AsyncCallable extends Callable {
31
+ constructor(func){
32
+ super(func);
33
+ }
34
+ catch(onrejected) {
35
+ return this.next().catch(onrejected);
36
+ }
37
+ finally(onfinally) {
38
+ return this.next().finally(onfinally);
39
+ }
40
+ then(onfulfilled, onrejected) {
41
+ return this.next().then(onfulfilled, onrejected);
42
+ }
43
+ }
44
+ class CallableAsyncIterator extends AsyncCallable {
45
+ [Symbol.asyncIterator]() {
46
+ return {
47
+ next: async ()=>{
48
+ try {
49
+ const value = await this.next();
50
+ return {
51
+ value,
52
+ done: false
53
+ };
54
+ } catch {
55
+ return {
56
+ value: undefined,
57
+ done: true
58
+ };
59
+ }
60
+ },
61
+ return: ()=>{
62
+ this[Symbol.dispose]();
63
+ return Promise.resolve({
64
+ value: undefined,
65
+ done: true
66
+ });
67
+ }
68
+ };
69
+ }
70
+ }
16
71
 
17
72
  //# sourceMappingURL=callable.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/callable.ts"],"sourcesContent":["import { Fn } from './types.js';\n/**\n * @internal\n */\nexport interface Callable<T extends unknown[], R> {\n (...args: T): R;\n}\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of Callable is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\n\nexport abstract class Callable<T, R> {\n constructor(func: Fn<T, R>) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n"],"names":["Callable","constructor","func","Object","setPrototypeOf","prototype"],"mappings":";;;;+BAesBA;;;eAAAA;;;AAAf,MAAeA;IACpBC,YAAYC,IAAc,CAAE;QAE1B,OAAOC,OAAOC,cAAc,CAACF,MAAM,WAAWG,SAAS;IACzD;AACF"}
1
+ {"version":3,"sources":["../src/callable.ts"],"sourcesContent":["import { Fn, Promiseable } from './types.js';\n/**\n * @internal\n */\nexport interface Callable<T extends unknown[], R> {\n (...args: T): R;\n}\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of Callable is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\n\nexport abstract class Callable<T, R> {\n static {\n Object.setPrototypeOf(Callable.prototype, Function.prototype);\n }\n\n constructor(func: Fn<T, R>) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\n/**\n * @internal\n */\nexport abstract class AsyncCallable<T, R> extends Callable<[T], R> implements Promiseable<T>, Promise<T> {\n constructor(func: Fn<[T], R>) {\n super(func);\n }\n\n abstract [Symbol.toStringTag]: string;\n abstract next(): Promise<T>;\n\n catch<OK = never>(onrejected?: ((reason: any) => OK | PromiseLike<OK>) | null): Promise<T | OK> {\n return this.next().catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<T> {\n return this.next().finally(onfinally);\n }\n\n then<OK = T, ERR = never>(\n onfulfilled?: ((value: T) => OK | PromiseLike<OK>) | null,\n onrejected?: ((reason: unknown) => ERR | PromiseLike<ERR>) | null,\n ): Promise<OK | ERR> {\n return this.next().then(onfulfilled, onrejected);\n }\n}\n\n/**\n * @internal\n */\nexport abstract class CallableAsyncIterator<T, R> extends AsyncCallable<T, R> implements Promiseable<T>, Promise<T>, AsyncIterable<T>, Disposable {\n [Symbol.asyncIterator](): AsyncIterator<T, void, void> {\n return {\n next: async () => {\n try {\n const value = await this.next();\n return { value, done: false };\n } catch {\n return { value: undefined, done: true };\n }\n },\n return: () => {\n this[Symbol.dispose]();\n return Promise.resolve({ value: undefined, done: true });\n },\n };\n }\n abstract [Symbol.dispose](): void;\n}\n"],"names":["AsyncCallable","Callable","CallableAsyncIterator","Object","setPrototypeOf","prototype","Function","func","catch","onrejected","next","finally","onfinally","then","onfulfilled","Symbol","asyncIterator","value","done","undefined","return","dispose","Promise","resolve"],"mappings":";;;;;;;;;;;QA6BsBA;eAAAA;;QAdAC;eAAAA;;QAyCAC;eAAAA;;;AAzCf,MAAeD;IACpB,MAAO;QACLE,OAAOC,cAAc,CAACH,SAASI,SAAS,EAAEC,SAASD,SAAS;IAC9D,CAAC;IAED,YAAYE,IAAc,CAAE;QAE1B,OAAOJ,OAAOC,cAAc,CAACG,MAAM,WAAWF,SAAS;IACzD;AACF;AAKO,MAAeL,sBAA4BC;IAChD,YAAYM,IAAgB,CAAE;QAC5B,KAAK,CAACA;IACR;IAKAC,MAAkBC,UAA2D,EAAmB;QAC9F,OAAO,IAAI,CAACC,IAAI,GAAGF,KAAK,CAACC;IAC3B;IAEAE,QAAQC,SAA+B,EAAc;QACnD,OAAO,IAAI,CAACF,IAAI,GAAGC,OAAO,CAACC;IAC7B;IAEAC,KACEC,WAAyD,EACzDL,UAAiE,EAC9C;QACnB,OAAO,IAAI,CAACC,IAAI,GAAGG,IAAI,CAACC,aAAaL;IACvC;AACF;AAKO,MAAeP,8BAAoCF;IACxD,CAACe,OAAOC,aAAa,CAAC,GAAiC;QACrD,OAAO;YACLN,MAAM;gBACJ,IAAI;oBACF,MAAMO,QAAQ,MAAM,IAAI,CAACP,IAAI;oBAC7B,OAAO;wBAAEO;wBAAOC,MAAM;oBAAM;gBAC9B,EAAE,OAAM;oBACN,OAAO;wBAAED,OAAOE;wBAAWD,MAAM;oBAAK;gBACxC;YACF;YACAE,QAAQ;gBACN,IAAI,CAACL,OAAOM,OAAO,CAAC;gBACpB,OAAOC,QAAQC,OAAO,CAAC;oBAAEN,OAAOE;oBAAWD,MAAM;gBAAK;YACxD;QACF;IACF;AAEF"}
@@ -1,4 +1,4 @@
1
- import { Fn } from './types.js';
1
+ import { Fn, Promiseable } from './types.js';
2
2
  /**
3
3
  * @internal
4
4
  */
@@ -14,3 +14,21 @@ export interface Callable<T extends unknown[], R> {
14
14
  export declare abstract class Callable<T, R> {
15
15
  constructor(func: Fn<T, R>);
16
16
  }
17
+ /**
18
+ * @internal
19
+ */
20
+ export declare abstract class AsyncCallable<T, R> extends Callable<[T], R> implements Promiseable<T>, Promise<T> {
21
+ constructor(func: Fn<[T], R>);
22
+ abstract [Symbol.toStringTag]: string;
23
+ abstract next(): Promise<T>;
24
+ catch<OK = never>(onrejected?: ((reason: any) => OK | PromiseLike<OK>) | null): Promise<T | OK>;
25
+ finally(onfinally?: (() => void) | null): Promise<T>;
26
+ then<OK = T, ERR = never>(onfulfilled?: ((value: T) => OK | PromiseLike<OK>) | null, onrejected?: ((reason: unknown) => ERR | PromiseLike<ERR>) | null): Promise<OK | ERR>;
27
+ }
28
+ /**
29
+ * @internal
30
+ */
31
+ export declare abstract class CallableAsyncIterator<T, R> extends AsyncCallable<T, R> implements Promiseable<T>, Promise<T>, AsyncIterable<T>, Disposable {
32
+ [Symbol.asyncIterator](): AsyncIterator<T, void, void>;
33
+ abstract [Symbol.dispose](): void;
34
+ }
package/build/callable.js CHANGED
@@ -1,7 +1,51 @@
1
1
  export class Callable {
2
+ static{
3
+ Object.setPrototypeOf(Callable.prototype, Function.prototype);
4
+ }
2
5
  constructor(func){
3
6
  return Object.setPrototypeOf(func, new.target.prototype);
4
7
  }
5
8
  }
9
+ export class AsyncCallable extends Callable {
10
+ constructor(func){
11
+ super(func);
12
+ }
13
+ catch(onrejected) {
14
+ return this.next().catch(onrejected);
15
+ }
16
+ finally(onfinally) {
17
+ return this.next().finally(onfinally);
18
+ }
19
+ then(onfulfilled, onrejected) {
20
+ return this.next().then(onfulfilled, onrejected);
21
+ }
22
+ }
23
+ export class CallableAsyncIterator extends AsyncCallable {
24
+ [Symbol.asyncIterator]() {
25
+ return {
26
+ next: async ()=>{
27
+ try {
28
+ const value = await this.next();
29
+ return {
30
+ value,
31
+ done: false
32
+ };
33
+ } catch {
34
+ return {
35
+ value: undefined,
36
+ done: true
37
+ };
38
+ }
39
+ },
40
+ return: ()=>{
41
+ this[Symbol.dispose]();
42
+ return Promise.resolve({
43
+ value: undefined,
44
+ done: true
45
+ });
46
+ }
47
+ };
48
+ }
49
+ }
6
50
 
7
51
  //# sourceMappingURL=callable.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/callable.ts"],"sourcesContent":["import { Fn } from './types.js';\n/**\n * @internal\n */\nexport interface Callable<T extends unknown[], R> {\n (...args: T): R;\n}\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of Callable is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\n\nexport abstract class Callable<T, R> {\n constructor(func: Fn<T, R>) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n"],"names":["Callable","constructor","func","Object","setPrototypeOf","prototype"],"mappings":"AAeA,OAAO,MAAeA;IACpBC,YAAYC,IAAc,CAAE;QAE1B,OAAOC,OAAOC,cAAc,CAACF,MAAM,WAAWG,SAAS;IACzD;AACF"}
1
+ {"version":3,"sources":["../src/callable.ts"],"sourcesContent":["import { Fn, Promiseable } from './types.js';\n/**\n * @internal\n */\nexport interface Callable<T extends unknown[], R> {\n (...args: T): R;\n}\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of Callable is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\n\nexport abstract class Callable<T, R> {\n static {\n Object.setPrototypeOf(Callable.prototype, Function.prototype);\n }\n\n constructor(func: Fn<T, R>) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\n/**\n * @internal\n */\nexport abstract class AsyncCallable<T, R> extends Callable<[T], R> implements Promiseable<T>, Promise<T> {\n constructor(func: Fn<[T], R>) {\n super(func);\n }\n\n abstract [Symbol.toStringTag]: string;\n abstract next(): Promise<T>;\n\n catch<OK = never>(onrejected?: ((reason: any) => OK | PromiseLike<OK>) | null): Promise<T | OK> {\n return this.next().catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<T> {\n return this.next().finally(onfinally);\n }\n\n then<OK = T, ERR = never>(\n onfulfilled?: ((value: T) => OK | PromiseLike<OK>) | null,\n onrejected?: ((reason: unknown) => ERR | PromiseLike<ERR>) | null,\n ): Promise<OK | ERR> {\n return this.next().then(onfulfilled, onrejected);\n }\n}\n\n/**\n * @internal\n */\nexport abstract class CallableAsyncIterator<T, R> extends AsyncCallable<T, R> implements Promiseable<T>, Promise<T>, AsyncIterable<T>, Disposable {\n [Symbol.asyncIterator](): AsyncIterator<T, void, void> {\n return {\n next: async () => {\n try {\n const value = await this.next();\n return { value, done: false };\n } catch {\n return { value: undefined, done: true };\n }\n },\n return: () => {\n this[Symbol.dispose]();\n return Promise.resolve({ value: undefined, done: true });\n },\n };\n }\n abstract [Symbol.dispose](): void;\n}\n"],"names":["Callable","Object","setPrototypeOf","prototype","Function","func","AsyncCallable","catch","onrejected","next","finally","onfinally","then","onfulfilled","CallableAsyncIterator","Symbol","asyncIterator","value","done","undefined","return","dispose","Promise","resolve"],"mappings":"AAeA,OAAO,MAAeA;IACpB,MAAO;QACLC,OAAOC,cAAc,CAACF,SAASG,SAAS,EAAEC,SAASD,SAAS;IAC9D,CAAC;IAED,YAAYE,IAAc,CAAE;QAE1B,OAAOJ,OAAOC,cAAc,CAACG,MAAM,WAAWF,SAAS;IACzD;AACF;AAKA,OAAO,MAAeG,sBAA4BN;IAChD,YAAYK,IAAgB,CAAE;QAC5B,KAAK,CAACA;IACR;IAKAE,MAAkBC,UAA2D,EAAmB;QAC9F,OAAO,IAAI,CAACC,IAAI,GAAGF,KAAK,CAACC;IAC3B;IAEAE,QAAQC,SAA+B,EAAc;QACnD,OAAO,IAAI,CAACF,IAAI,GAAGC,OAAO,CAACC;IAC7B;IAEAC,KACEC,WAAyD,EACzDL,UAAiE,EAC9C;QACnB,OAAO,IAAI,CAACC,IAAI,GAAGG,IAAI,CAACC,aAAaL;IACvC;AACF;AAKA,OAAO,MAAeM,8BAAoCR;IACxD,CAACS,OAAOC,aAAa,CAAC,GAAiC;QACrD,OAAO;YACLP,MAAM;gBACJ,IAAI;oBACF,MAAMQ,QAAQ,MAAM,IAAI,CAACR,IAAI;oBAC7B,OAAO;wBAAEQ;wBAAOC,MAAM;oBAAM;gBAC9B,EAAE,OAAM;oBACN,OAAO;wBAAED,OAAOE;wBAAWD,MAAM;oBAAK;gBACxC;YACF;YACAE,QAAQ;gBACN,IAAI,CAACL,OAAOM,OAAO,CAAC;gBACpB,OAAOC,QAAQC,OAAO,CAAC;oBAAEN,OAAOE;oBAAWD,MAAM;gBAAK;YACxD;QACF;IACF;AAEF"}