events-ex 2.3.0 → 2.4.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 (122) hide show
  1. package/.babelrc +1 -1
  2. package/CHANGELOG.md +25 -0
  3. package/README.cn.md +114 -3
  4. package/README.md +106 -5
  5. package/coverage/all-off.js.html +133 -0
  6. package/coverage/base.css +224 -0
  7. package/coverage/block-navigation.js +87 -0
  8. package/coverage/clover.xml +572 -0
  9. package/coverage/consts.js.html +154 -0
  10. package/coverage/default-methods.js.html +2068 -0
  11. package/coverage/event-emitter.js.html +121 -0
  12. package/coverage/event.js.html +286 -0
  13. package/coverage/eventable.js.html +355 -0
  14. package/coverage/favicon.png +0 -0
  15. package/coverage/has-listeners.js.html +166 -0
  16. package/coverage/index.html +281 -0
  17. package/coverage/lcov-report/all-off.js.html +133 -0
  18. package/coverage/lcov-report/base.css +224 -0
  19. package/coverage/lcov-report/block-navigation.js +87 -0
  20. package/coverage/lcov-report/consts.js.html +154 -0
  21. package/coverage/lcov-report/default-methods.js.html +2068 -0
  22. package/coverage/lcov-report/event-emitter.js.html +121 -0
  23. package/coverage/lcov-report/event.js.html +286 -0
  24. package/coverage/lcov-report/eventable.js.html +355 -0
  25. package/coverage/lcov-report/favicon.png +0 -0
  26. package/coverage/lcov-report/has-listeners.js.html +166 -0
  27. package/coverage/lcov-report/index.html +281 -0
  28. package/coverage/lcov-report/once-promise.js.html +325 -0
  29. package/coverage/lcov-report/pipe-async.js.html +385 -0
  30. package/coverage/lcov-report/pipe.js.html +244 -0
  31. package/coverage/lcov-report/prettify.css +1 -0
  32. package/coverage/lcov-report/prettify.js +2 -0
  33. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  34. package/coverage/lcov-report/sorter.js +210 -0
  35. package/coverage/lcov-report/unify.js.html +259 -0
  36. package/coverage/lcov-report/wrap-event-emitter.js.html +223 -0
  37. package/coverage/lcov.info +1201 -0
  38. package/coverage/once-promise.js.html +325 -0
  39. package/coverage/pipe-async.js.html +385 -0
  40. package/coverage/pipe.js.html +244 -0
  41. package/coverage/prettify.css +1 -0
  42. package/coverage/prettify.js +2 -0
  43. package/coverage/sort-arrow-sprite.png +0 -0
  44. package/coverage/sorter.js +210 -0
  45. package/coverage/unify.js.html +259 -0
  46. package/coverage/wrap-event-emitter.js.html +223 -0
  47. package/docs/README.md +106 -5
  48. package/docs/all-off/functions/allOff.md +1 -1
  49. package/docs/consts/README.md +4 -0
  50. package/docs/consts/functions/createAbortError.md +18 -0
  51. package/docs/consts/variables/RegExpEventSymbol.md +1 -1
  52. package/docs/consts/variables/states.md +2 -2
  53. package/docs/default-methods/functions/getEventableMethods.md +34 -18
  54. package/docs/event/classes/Event.md +23 -13
  55. package/docs/event-emitter/classes/EventEmitter-1.md +2 -2
  56. package/docs/event-emitter/classes/EventEmitter.md +28 -28
  57. package/docs/eventable/functions/eventable.md +1 -1
  58. package/docs/has-listeners/functions/hasListeners.md +2 -2
  59. package/docs/index/README.md +12 -0
  60. package/docs/modules.md +1 -0
  61. package/docs/once-promise/README.md +17 -0
  62. package/docs/once-promise/functions/oncePromise.md +60 -0
  63. package/docs/pipe/functions/pipe.md +3 -3
  64. package/docs/pipe-async/functions/pipeAsync.md +3 -3
  65. package/docs/unify/functions/unify.md +1 -1
  66. package/docs/util/array-remove/functions/remove.md +1 -1
  67. package/docs/util/object-for-each/functions/forEach.md +1 -1
  68. package/docs/util/string-pad/functions/pad.md +1 -1
  69. package/docs/util/to-int/functions/toInt.md +1 -1
  70. package/docs/util/valid-callable/functions/validCallable.md +1 -1
  71. package/docs/util/valid-object/functions/validObject.md +1 -1
  72. package/docs/wrap-event-emitter/functions/wrapEventEmitter.md +3 -3
  73. package/docs/wrap-event-emitter/variables/methods.md +1 -1
  74. package/lib/all-off.mjs +16 -0
  75. package/lib/consts.d.ts +7 -1
  76. package/lib/consts.js +17 -2
  77. package/lib/consts.mjs +23 -0
  78. package/lib/default-methods.d.ts +12 -4
  79. package/lib/default-methods.js +174 -22
  80. package/lib/default-methods.mjs +661 -0
  81. package/lib/event-emitter.mjs +12 -0
  82. package/lib/event.d.ts +10 -4
  83. package/lib/event.js +6 -0
  84. package/lib/event.mjs +67 -0
  85. package/lib/eventable.d.ts +1 -1
  86. package/lib/eventable.mjs +90 -0
  87. package/lib/has-listeners.d.ts +1 -1
  88. package/lib/has-listeners.mjs +27 -0
  89. package/lib/index.d.ts +1 -0
  90. package/lib/index.js +12 -0
  91. package/lib/index.mjs +16 -0
  92. package/lib/once-promise.d.ts +23 -0
  93. package/lib/once-promise.js +82 -0
  94. package/lib/once-promise.mjs +80 -0
  95. package/lib/pipe-async.d.ts +4 -2
  96. package/lib/pipe-async.js +16 -3
  97. package/lib/pipe-async.mjs +100 -0
  98. package/lib/pipe.d.ts +1 -1
  99. package/lib/pipe.mjs +53 -0
  100. package/lib/unify.js +1 -1
  101. package/lib/unify.mjs +58 -0
  102. package/lib/util/array-remove.mjs +16 -0
  103. package/lib/util/object-for-each.mjs +20 -0
  104. package/lib/util/promise-any.mjs +45 -0
  105. package/lib/util/string-pad.mjs +19 -0
  106. package/lib/util/to-int.mjs +9 -0
  107. package/lib/util/valid-callable.mjs +6 -0
  108. package/lib/util/valid-object.mjs +8 -0
  109. package/lib/wrap-event-emitter.d.ts +1 -1
  110. package/lib/wrap-event-emitter.mjs +46 -0
  111. package/package.json +29 -20
  112. package/scripts/copy-to-mjs.mjs +79 -0
  113. package/src/consts.js +10 -0
  114. package/src/default-methods.js +169 -24
  115. package/src/event.js +6 -0
  116. package/src/index.js +1 -0
  117. package/src/once-promise.js +80 -0
  118. package/src/pipe-async.js +16 -3
  119. package/src/unify.js +1 -1
  120. package/tsconfig.json +2 -1
  121. package/vitest.config.js +61 -0
  122. package/.mocharc.yml +0 -3
@@ -0,0 +1,223 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for wrap-event-emitter.js</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="prettify.css" />
9
+ <link rel="stylesheet" href="base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="index.html">All files</a> wrap-event-emitter.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">100% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>13/13</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">100% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>6/6</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>2/2</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">100% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>13/13</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line high'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
113
+ <span class="cline-any cline-neutral">&nbsp;</span>
114
+ <span class="cline-any cline-neutral">&nbsp;</span>
115
+ <span class="cline-any cline-yes">33x</span>
116
+ <span class="cline-any cline-yes">33x</span>
117
+ <span class="cline-any cline-neutral">&nbsp;</span>
118
+ <span class="cline-any cline-yes">33x</span>
119
+ <span class="cline-any cline-neutral">&nbsp;</span>
120
+ <span class="cline-any cline-neutral">&nbsp;</span>
121
+ <span class="cline-any cline-neutral">&nbsp;</span>
122
+ <span class="cline-any cline-neutral">&nbsp;</span>
123
+ <span class="cline-any cline-yes">33x</span>
124
+ <span class="cline-any cline-neutral">&nbsp;</span>
125
+ <span class="cline-any cline-neutral">&nbsp;</span>
126
+ <span class="cline-any cline-neutral">&nbsp;</span>
127
+ <span class="cline-any cline-neutral">&nbsp;</span>
128
+ <span class="cline-any cline-neutral">&nbsp;</span>
129
+ <span class="cline-any cline-neutral">&nbsp;</span>
130
+ <span class="cline-any cline-neutral">&nbsp;</span>
131
+ <span class="cline-any cline-neutral">&nbsp;</span>
132
+ <span class="cline-any cline-neutral">&nbsp;</span>
133
+ <span class="cline-any cline-neutral">&nbsp;</span>
134
+ <span class="cline-any cline-neutral">&nbsp;</span>
135
+ <span class="cline-any cline-yes">33x</span>
136
+ <span class="cline-any cline-yes">33x</span>
137
+ <span class="cline-any cline-yes">396x</span>
138
+ <span class="cline-any cline-neutral">&nbsp;</span>
139
+ <span class="cline-any cline-neutral">&nbsp;</span>
140
+ <span class="cline-any cline-yes">33x</span>
141
+ <span class="cline-any cline-neutral">&nbsp;</span>
142
+ <span class="cline-any cline-neutral">&nbsp;</span>
143
+ <span class="cline-any cline-neutral">&nbsp;</span>
144
+ <span class="cline-any cline-neutral">&nbsp;</span>
145
+ <span class="cline-any cline-neutral">&nbsp;</span>
146
+ <span class="cline-any cline-neutral">&nbsp;</span>
147
+ <span class="cline-any cline-neutral">&nbsp;</span>
148
+ <span class="cline-any cline-neutral">&nbsp;</span>
149
+ <span class="cline-any cline-yes">192x</span>
150
+ <span class="cline-any cline-yes">192x</span>
151
+ <span class="cline-any cline-yes">192x</span>
152
+ <span class="cline-any cline-yes">2x</span>
153
+ <span class="cline-any cline-neutral">&nbsp;</span>
154
+ <span class="cline-any cline-yes">192x</span>
155
+ <span class="cline-any cline-neutral">&nbsp;</span>
156
+ <span class="cline-any cline-neutral">&nbsp;</span>
157
+ <span class="cline-any cline-neutral">&nbsp;</span>
158
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import {defineProperty} from 'util-ex'
159
+ import eventable from './eventable'
160
+ &nbsp;
161
+ const create = Object.create;
162
+ const defineProperties = Object.defineProperties;
163
+ &nbsp;
164
+ export const methods = eventable().methods;
165
+ &nbsp;
166
+ /**
167
+ * Minimal set of core methods to be injected into an existing object.
168
+ */
169
+ const descriptors = {
170
+ on: { value: methods.on },
171
+ once: { value: methods.once },
172
+ off: { value: methods.off },
173
+ emit: { value: methods.emit },
174
+ emitAsync: { value: methods.emitAsync },
175
+ setEmitterOptions: { value: methods.setEmitterOptions },
176
+ };
177
+ &nbsp;
178
+ /**
179
+ * Full set of all available methods from eventable for standalone instances.
180
+ */
181
+ const fullDescriptors = {};
182
+ Object.keys(methods).forEach(key =&gt; {
183
+ fullDescriptors[key] = { value: methods[key] };
184
+ });
185
+ &nbsp;
186
+ const base = defineProperties({}, fullDescriptors);
187
+ &nbsp;
188
+ /**
189
+ * Create or inject the eventable instance into the object
190
+ * @param {Object} [o] the optional instance to eventable
191
+ * @param {Object} [options] optional configuration for the emitter
192
+ * @returns o or new Event instance
193
+ */
194
+ export function wrapEventEmitter(o, options) {
195
+ const result = o == null ? create(base) : defineProperties(Object(o), descriptors)
196
+ defineProperty(result, '_events', {})
197
+ if (options &amp;&amp; options.emitterOptions) {
198
+ result.setEmitterOptions(options.emitterOptions)
199
+ }
200
+ return result
201
+ };
202
+ &nbsp;
203
+ export default wrapEventEmitter
204
+ &nbsp;</pre></td></tr></table></pre>
205
+
206
+ <div class='push'></div><!-- for sticky footer -->
207
+ </div><!-- /wrapper -->
208
+ <div class='footer quiet pad2 space-top1 center small'>
209
+ Code coverage generated by
210
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
211
+ at 2026-07-07T07:31:06.609Z
212
+ </div>
213
+ <script src="prettify.js"></script>
214
+ <script>
215
+ window.onload = function () {
216
+ prettyPrint();
217
+ };
218
+ </script>
219
+ <script src="sorter.js"></script>
220
+ <script src="block-navigation.js"></script>
221
+ </body>
222
+ </html>
223
+
package/docs/README.md CHANGED
@@ -18,8 +18,9 @@ Browser-friendly enhanced event emitter [ability][Ability] and class. It's modif
18
18
  * **Configurable Concurrency**: Choose between **Serial** (default) and **Parallel** execution for async listeners.
19
19
  * **Result Aggregation**: Strategies to gather return values: `last` (default), `first` (first success), and `collect` (all results).
20
20
  * **Fluent API Proxies**: Use `.parallel()` and `.configure()` for transient, side-effect-free execution context.
21
+ * **AbortSignal Support**: Cancel async event emissions via `configure({ signal })` or `oncePromise` with an `AbortSignal`.
21
22
  * **Architecture**: Rewritten core for improved performance and flexibility while maintaining broad compatibility.
22
- * **Event Utilities**: Built-in support for `pipe`, `pipeAsync`, `unify`, `allOff`, and `hasListeners`.
23
+ * **Event Utilities**: Built-in support for `pipe`, `pipeAsync`, `oncePromise`, `unify`, `allOff`, and `hasListeners`.
23
24
 
24
25
  ### Differences
25
26
 
@@ -28,6 +29,7 @@ Browser-friendly enhanced event emitter [ability][Ability] and class. It's modif
28
29
  + the `event object` as listener's "this" object:
29
30
  * `result`: If set, the result is returned to the `Event Emitter`.
30
31
  * `stopped`: If set to `true`, it prevents the remaining listeners from being executed.
32
+ * `aborted`: (Async only) `true` if the emission was cancelled by an `AbortSignal`.
31
33
  * `target`: The `Event Emitter` object, which was originally the `this` object.
32
34
  * `type`: triggered event type(name).
33
35
  * `resolved`: (Async only) Indicates if a successful result has been found in `first` mode.
@@ -43,7 +45,7 @@ Browser-friendly enhanced event emitter [ability][Ability] and class. It's modif
43
45
  * `collect`: Returns an array of all results in registration order.
44
46
  * **Fluent Configuration**: Use `.parallel()` or `.configure({...})` for one-time customized async emits.
45
47
  * **Listener APIs**: `on/once(event: string|RegExp, listener, index?: number|'first'|'last')`
46
- * 📌 **Index Parameter** (Optional): Insertion position in the listener array.
48
+ * 📌 **Index Parameter** (Optional): Insertion position in the listener array.
47
49
  * `'first'` (`-Infinity`): Stays in the **Head** zone. The first listener added as `'first'` is placed at the very front.
48
50
  * `'last'` (`Infinity`): Stays in the **Tail** zone. The first listener added as `'last'` will always remain at the absolute end.
49
51
  * `number`: Relative index within the **Body** zone.
@@ -63,7 +65,7 @@ Browser-friendly enhanced event emitter [ability][Ability] and class. It's modif
63
65
  * `pipeAsync(source, target, options)`: Async forwarding with configurable concurrency and aggregation.
64
66
  * `unify(emitter1, emitter2)`: Bi-directional synchronization.
65
67
 
66
- Note: The listener throw error should not broke the notification, but it will emit error(`emit('error', error, 'notify', eventName, listener, args)`) after notification.
68
+ Note: A listener's throw error does not break the notification flow—caught errors are collected and then re-emitted as an `'error'` event after all listeners run. **Exception**: If the error is thrown inside an `'error'` event listener itself, it propagates directly as a thrown exception (sync) or a rejected promise (async), preventing infinite recursion / stack overflow. This applies to both `emit()` and `emitAsync()`.
67
69
 
68
70
  ### Installation
69
71
 
@@ -174,6 +176,44 @@ const allResults = await ee.parallel('collect').emitAsync('task');
174
176
  const firstResult = await ee.parallel('first').emitAsync('task');
175
177
  ```
176
178
 
179
+ #### AbortSignal Support (Async Only)
180
+
181
+ Cancel async event emissions using the standard `AbortSignal` via `configure({ signal })` or `oncePromise` options.
182
+
183
+ ```js
184
+ const emitter = new EventEmitter();
185
+ const controller = new AbortController();
186
+
187
+ emitter.on('task', async () => {
188
+ await sleep(500);
189
+ return 'done';
190
+ });
191
+
192
+ // emitAsync: pass signal via configure
193
+ setTimeout(() => controller.abort(), 200); // cancel after 200ms
194
+ try {
195
+ await emitter.configure({ signal: controller.signal }).emitAsync('task');
196
+ } catch (err) {
197
+ console.log(err.name); // 'AbortError'
198
+ }
199
+
200
+ // oncePromise: pass signal directly via options
201
+ const c2 = new AbortController();
202
+ setTimeout(() => c2.abort(), 100);
203
+ try {
204
+ await oncePromise(emitter, 'ready', { signal: c2.signal });
205
+ } catch (err) {
206
+ console.log(err.name); // 'AbortError'
207
+ }
208
+ ```
209
+
210
+ **Behavior**:
211
+
212
+ - **Serial mode**: Checks `signal.aborted` before each listener, throws `AbortError` immediately when triggered. When `raiseError` is explicitly set (`true`/`false`/`null`), uses `Promise.race` to interrupt an actively running listener as well.
213
+ - **Parallel mode**: Races listener execution against the signal via `Promise.race`. Throws `AbortError` when the signal wins.
214
+ - **pipeAsync**: In serial mode, checks the source's signal before forwarding to each pipe target; skips remaining targets if aborted.
215
+ - `Event` objects have an `aborted` field (independent of `stopped`) to track cancellation state.
216
+
177
217
  ### Advanced Features
178
218
 
179
219
  #### Async Concurrency Engine (For `emitAsync` Only)
@@ -185,6 +225,11 @@ const firstResult = await ee.parallel('first').emitAsync('task');
185
225
  | **`resultMode`** | `'last'` | **(Default)** Returns the result of the last listener (or last to finish). |
186
226
  | | `'first'` | Returns the first **non-undefined** and **successful** result. Skips errors. |
187
227
  | | `'collect'` | Returns an array of all results in registration order. |
228
+ | **`signal`** | `AbortSignal` | An `AbortSignal` from an `AbortController` to cancel async event emission. Only passed via `configure()`, not stored on the instance. |
229
+ | **`raiseError`** | `true` | Throws all listener errors immediately. Parallel mode aggregates multiple errors into an `AggregateError`. |
230
+ | | `false` | Silently swallows listener errors. Used with `signal` to interrupt an executing listener in serial mode (added `Promise.race`). |
231
+ | | `null` | **(Default for sync `emit`)** For `'error'` events only: throws if there are no error listeners (Node.js default behavior). |
232
+ | | `undefined` | **(Default)** Same as `false` for `emitAsync`. Keeps existing behavior unchanged. |
188
233
 
189
234
  #### Proxy Isolation (Fluent API)
190
235
 
@@ -252,11 +297,67 @@ hasListeners(emitter, 'foo'); // true
252
297
  Creates an asynchronous pipeline.
253
298
 
254
299
  - `options.asyncMode`: Propagation mode (`'serial' | 'parallel'`).
255
- - `options.resultMode`: Aggregation strategy.
300
+ - `options.resultMode`: Aggregation strategy (`'last'` default | `'first'` | `'collect'`).
301
+
302
+ #### oncePromise(emitter, type[, options]) _(events-ex/once-promise)_
303
+
304
+ Returns a `Promise` that resolves with the **Event object** when the specified event is emitted on the given emitter.
305
+ If an `error` event is emitted (and the waiting event is not `error`), the promise rejects.
306
+ If the provided `AbortSignal` is aborted, the promise rejects with an `AbortError`.
307
+
308
+ - `emitter` _(EventEmitter)_: The event emitter to listen on.
309
+ - `type` _(string | RegExp)_: The event type to wait for. Supports regex for matching multiple events.
310
+ - `options` _(Object)_: Optional configuration.
311
+ - `signal` _(AbortSignal)_: An AbortSignal to cancel the wait.
312
+ - `raiseError` _(boolean|null)_: Controls behavior when an `'error'` event is emitted on the emitter.
313
+ - `true` / `undefined` **(default)**: The promise rejects with the error.
314
+ - `false`: The promise resolves with the error object instead of rejecting.
315
+ - Returns: `Promise<Event>` — resolves with the Event object, which provides `type`, `target`, etc.
316
+
317
+ > Note: The resolved Event object's `result` field may not be the final value if other listeners have not yet run. For the definitive emit return value, use `emit()` or `emitAsync()` directly.
318
+
319
+ ```js
320
+ import {oncePromise, EventEmitter} from 'events-ex';
321
+
322
+ const ee = new EventEmitter();
323
+
324
+ // Wait for a data event
325
+ setTimeout(() => ee.emit('data', { id: 1 }), 100);
326
+ const evt = await oncePromise(ee, 'data');
327
+ console.log(evt.type); // 'data'
328
+ console.log(evt.target); // the emitter
329
+
330
+ // Wait for a regex-matched event – evt.type reveals the actual event
331
+ setTimeout(() => ee.emit('user.login', { name: 'Alice' }), 100);
332
+ const evt2 = await oncePromise(ee, /^user\./);
333
+ console.log(evt2.type); // 'user.login' (not the regex)
334
+
335
+ // Error handling: rejects on error (unless waiting for 'error')
336
+ try {
337
+ await oncePromise(ee, 'data');
338
+ } catch (err) {
339
+ console.error('Error occurred:', err);
340
+ }
341
+
342
+ // Waiting for 'error' event resolves normally
343
+ ee.emit('error', new Error('expected'));
344
+ await oncePromise(ee, 'error'); // resolves, not rejects
345
+
346
+ // Use AbortSignal for timeout cancellation
347
+ const controller = new AbortController();
348
+ setTimeout(() => controller.abort(), 5000);
349
+ try {
350
+ const evt = await oncePromise(ee, 'response', { signal: controller.signal });
351
+ } catch (err) {
352
+ if (err.name === 'AbortError') {
353
+ console.log('timed out or cancelled');
354
+ }
355
+ }
356
+ ```
256
357
 
257
358
  #### setEmitterOptions(options)
258
359
 
259
- Configures instance-wide defaults for `asyncMode`, `resultMode`, and `maxListeners`.
360
+ Configures instance-wide defaults for `asyncMode`, `resultMode`, `maxListeners`, and `raiseError`.
260
361
 
261
362
  [event-emitter]: https://github.com/medikoo/event-emitter
262
363
  [Ability]: https://github.com/snowyu/custom-ability.js
@@ -8,7 +8,7 @@
8
8
 
9
9
  > **allOff**(`emitter`, `type?`): [`EventEmitter`](../../event-emitter/classes/EventEmitter.md)
10
10
 
11
- Defined in: [src/all-off.js:12](https://github.com/snowyu/events-ex.js/blob/53cfb5bb3f7229cb549e99d410c0d6d39665eb0a/src/all-off.js#L12)
11
+ Defined in: [src/all-off.js:12](https://github.com/snowyu/events-ex.js/blob/1738d9bce8d1eae4826213336afe3c0c8e5fa482/src/all-off.js#L12)
12
12
 
13
13
  Removes all listeners for a specific event or all events from an event emitter.
14
14
 
@@ -10,3 +10,7 @@
10
10
 
11
11
  - [RegExpEventSymbol](variables/RegExpEventSymbol.md)
12
12
  - [states](variables/states.md)
13
+
14
+ ## Functions
15
+
16
+ - [createAbortError](functions/createAbortError.md)
@@ -0,0 +1,18 @@
1
+ [**events-ex**](../../README.md)
2
+
3
+ ***
4
+
5
+ [events-ex](../../modules.md) / [consts](../README.md) / createAbortError
6
+
7
+ # Function: createAbortError()
8
+
9
+ > **createAbortError**(): `Error`
10
+
11
+ Defined in: [src/consts.js:21](https://github.com/snowyu/events-ex.js/blob/1738d9bce8d1eae4826213336afe3c0c8e5fa482/src/consts.js#L21)
12
+
13
+ Creates an AbortError with name 'AbortError'.
14
+ Ensures a fresh Error instance each call for proper stack traces.
15
+
16
+ ## Returns
17
+
18
+ `Error`
@@ -8,4 +8,4 @@
8
8
 
9
9
  > `const` **RegExpEventSymbol**: `symbol` \| `"@@RegExpEvent"`
10
10
 
11
- Defined in: [src/consts.js:13](https://github.com/snowyu/events-ex.js/blob/53cfb5bb3f7229cb549e99d410c0d6d39665eb0a/src/consts.js#L13)
11
+ Defined in: [src/consts.js:14](https://github.com/snowyu/events-ex.js/blob/1738d9bce8d1eae4826213336afe3c0c8e5fa482/src/consts.js#L14)
@@ -8,7 +8,7 @@
8
8
 
9
9
  > `const` **states**: `object`
10
10
 
11
- Defined in: [src/consts.js:6](https://github.com/snowyu/events-ex.js/blob/53cfb5bb3f7229cb549e99d410c0d6d39665eb0a/src/consts.js#L6)
11
+ Defined in: [src/consts.js:6](https://github.com/snowyu/events-ex.js/blob/1738d9bce8d1eae4826213336afe3c0c8e5fa482/src/consts.js#L6)
12
12
 
13
13
  ## Type Declaration
14
14
 
@@ -18,7 +18,7 @@ Defined in: [src/consts.js:6](https://github.com/snowyu/events-ex.js/blob/53cfb5
18
18
 
19
19
  ### CONTINUE
20
20
 
21
- > **CONTINUE**: `any`
21
+ > **CONTINUE**: `undefined`
22
22
 
23
23
  ### DONE
24
24
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  > **getEventableMethods**(`aClass`): `object`
10
10
 
11
- Defined in: [src/default-methods.js:15](https://github.com/snowyu/events-ex.js/blob/53cfb5bb3f7229cb549e99d410c0d6d39665eb0a/src/default-methods.js#L15)
11
+ Defined in: [src/default-methods.js:15](https://github.com/snowyu/events-ex.js/blob/1738d9bce8d1eae4826213336afe3c0c8e5fa482/src/default-methods.js#L15)
12
12
 
13
13
  ## Parameters
14
14
 
@@ -36,12 +36,28 @@ Configuration options for event emission.
36
36
 
37
37
  The mode of asynchronous emission ('serial' or 'parallel').
38
38
 
39
+ ###### raiseError?
40
+
41
+ `boolean` \| `null`
42
+
43
+ Controls error handling behavior:
44
+ - `true`: Always throw listener errors immediately.
45
+ - `false`: Silently swallow listener errors.
46
+ - `null`: Throw only for 'error' events with no error listeners (Node.js default).
47
+ - `undefined` (default): Same as `false` for emitAsync.
48
+
39
49
  ###### resultMode?
40
50
 
41
51
  `string`
42
52
 
43
53
  The strategy for handling multiple return values ('last', 'first', 'collect').
44
54
 
55
+ ###### signal?
56
+
57
+ `any`
58
+
59
+ An AbortSignal to cancel async event emission.
60
+
45
61
  #### Returns
46
62
 
47
63
  [`EventEmitter`](../../event-emitter/classes/EventEmitter.md)
@@ -130,9 +146,9 @@ Removes a listener function from the specified event type.
130
146
 
131
147
  ##### type
132
148
 
133
- The event type to remove the listener from.
149
+ `string` \| `RegExp`
134
150
 
135
- `string` | `RegExp`
151
+ The event type to remove the listener from.
136
152
 
137
153
  ##### listener
138
154
 
@@ -160,9 +176,9 @@ Adds a listener function to the specified event type.
160
176
 
161
177
  ##### type
162
178
 
163
- The event type to listen for.
179
+ `string` \| `RegExp`
164
180
 
165
- `string` | `RegExp`
181
+ The event type to listen for.
166
182
 
167
183
  ##### listener
168
184
 
@@ -172,14 +188,14 @@ The listener function to be called when the event is emitted.
172
188
 
173
189
  ##### index?
174
190
 
175
- The index at which to insert the listener.
191
+ `number` \| `"first"` \| `"last"`
192
+
193
+ The index at which to insert the listener.
176
194
  - 'first' or -Infinity: Adds to the "Head" zone. The first listener added as 'first' is placed at the very front.
177
195
  - 'last' or Infinity: Adds to the "Tail" zone. The first listener added as 'last' will always be the very last one to execute.
178
196
  - number: Inserts at the specified index within the "Body" (normal) zone.
179
197
  If not specified, the listener is added to the end of the "Body" zone.
180
198
 
181
- `number` | `"first"` | `"last"`
182
-
183
199
  #### Returns
184
200
 
185
201
  [`EventEmitter`](../../event-emitter/classes/EventEmitter.md)
@@ -200,9 +216,9 @@ Adds a one-time listener function to the specified event type.
200
216
 
201
217
  ##### type
202
218
 
203
- The event type to listen for.
219
+ `string` \| `RegExp`
204
220
 
205
- `string` | `RegExp`
221
+ The event type to listen for.
206
222
 
207
223
  ##### listener
208
224
 
@@ -212,14 +228,14 @@ The listener function to be called once when the event is emitted.
212
228
 
213
229
  ##### index?
214
230
 
231
+ `number` \| `"first"` \| `"last"`
232
+
215
233
  The index at which to insert the listener.
216
234
  - 'first' or -Infinity: Adds to the "Head" zone. The first listener added as 'first' is placed at the very front.
217
235
  - 'last' or Infinity: Adds to the "Tail" zone. The first listener added as 'last' will always be the very last one to execute.
218
236
  - number: Inserts at the specified index within the "Body" (normal) zone.
219
237
  If not specified, the listener is added to the end of the "Body" zone.
220
238
 
221
- `number` | `"first"` | `"last"`
222
-
223
239
  #### Returns
224
240
 
225
241
  [`EventEmitter`](../../event-emitter/classes/EventEmitter.md)
@@ -260,9 +276,9 @@ Removes all listener functions from the specified event type.
260
276
 
261
277
  ##### type
262
278
 
263
- The event type to remove the listener from.
279
+ `string` \| `RegExp`
264
280
 
265
- `string` | `RegExp`
281
+ The event type to remove the listener from.
266
282
 
267
283
  #### Returns
268
284
 
@@ -284,9 +300,9 @@ Sets the configuration options for the EventEmitter instance.
284
300
 
285
301
  ##### options
286
302
 
287
- `any`
303
+ `Object`
288
304
 
289
- Configuration options for the emitter (e.g., asyncMode, resultMode, maxListeners).
305
+ Configuration options for the emitter (e.g., asyncMode, resultMode, maxListeners, raiseError).
290
306
 
291
307
  #### Returns
292
308
 
@@ -296,7 +312,7 @@ The EventEmitter instance for chaining.
296
312
 
297
313
  ### setMaxListeners()
298
314
 
299
- > **setMaxListeners**(`n`): \{ configure(options: \{ asyncMode?: string; resultMode?: string; \}): EventEmitter; parallel(resultMode?: string): EventEmitter; setEmitterOptions(options: any): EventEmitter; ... 8 more ...; removeAllListeners(type: string \| RegExp): EventEmitter; \}
315
+ > **setMaxListeners**(`n`): \{ configure(options: \{ asyncMode?: string \| undefined; resultMode?: string \| undefined; signal?: any; raiseError?: boolean \| null \| undefined; \}): EventEmitter; parallel(resultMode?: string \| undefined): EventEmitter; ... 9 more ...; removeAllListeners(type: string \| RegExp): EventEmitter; \}
300
316
 
301
317
  #### Parameters
302
318
 
@@ -306,4 +322,4 @@ The EventEmitter instance for chaining.
306
322
 
307
323
  #### Returns
308
324
 
309
- \{ configure(options: \{ asyncMode?: string; resultMode?: string; \}): EventEmitter; parallel(resultMode?: string): EventEmitter; setEmitterOptions(options: any): EventEmitter; ... 8 more ...; removeAllListeners(type: string \| RegExp): EventEmitter; \}
325
+ \{ configure(options: \{ asyncMode?: string \| undefined; resultMode?: string \| undefined; signal?: any; raiseError?: boolean \| null \| undefined; \}): EventEmitter; parallel(resultMode?: string \| undefined): EventEmitter; ... 9 more ...; removeAllListeners(type: string \| RegExp): EventEmitter; \}