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.
- package/.babelrc +1 -1
- package/CHANGELOG.md +25 -0
- package/README.cn.md +114 -3
- package/README.md +106 -5
- package/coverage/all-off.js.html +133 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +572 -0
- package/coverage/consts.js.html +154 -0
- package/coverage/default-methods.js.html +2068 -0
- package/coverage/event-emitter.js.html +121 -0
- package/coverage/event.js.html +286 -0
- package/coverage/eventable.js.html +355 -0
- package/coverage/favicon.png +0 -0
- package/coverage/has-listeners.js.html +166 -0
- package/coverage/index.html +281 -0
- package/coverage/lcov-report/all-off.js.html +133 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/consts.js.html +154 -0
- package/coverage/lcov-report/default-methods.js.html +2068 -0
- package/coverage/lcov-report/event-emitter.js.html +121 -0
- package/coverage/lcov-report/event.js.html +286 -0
- package/coverage/lcov-report/eventable.js.html +355 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/has-listeners.js.html +166 -0
- package/coverage/lcov-report/index.html +281 -0
- package/coverage/lcov-report/once-promise.js.html +325 -0
- package/coverage/lcov-report/pipe-async.js.html +385 -0
- package/coverage/lcov-report/pipe.js.html +244 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov-report/unify.js.html +259 -0
- package/coverage/lcov-report/wrap-event-emitter.js.html +223 -0
- package/coverage/lcov.info +1201 -0
- package/coverage/once-promise.js.html +325 -0
- package/coverage/pipe-async.js.html +385 -0
- package/coverage/pipe.js.html +244 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/coverage/unify.js.html +259 -0
- package/coverage/wrap-event-emitter.js.html +223 -0
- package/docs/README.md +106 -5
- package/docs/all-off/functions/allOff.md +1 -1
- package/docs/consts/README.md +4 -0
- package/docs/consts/functions/createAbortError.md +18 -0
- package/docs/consts/variables/RegExpEventSymbol.md +1 -1
- package/docs/consts/variables/states.md +2 -2
- package/docs/default-methods/functions/getEventableMethods.md +34 -18
- package/docs/event/classes/Event.md +23 -13
- package/docs/event-emitter/classes/EventEmitter-1.md +2 -2
- package/docs/event-emitter/classes/EventEmitter.md +28 -28
- package/docs/eventable/functions/eventable.md +1 -1
- package/docs/has-listeners/functions/hasListeners.md +2 -2
- package/docs/index/README.md +12 -0
- package/docs/modules.md +1 -0
- package/docs/once-promise/README.md +17 -0
- package/docs/once-promise/functions/oncePromise.md +60 -0
- package/docs/pipe/functions/pipe.md +3 -3
- package/docs/pipe-async/functions/pipeAsync.md +3 -3
- package/docs/unify/functions/unify.md +1 -1
- package/docs/util/array-remove/functions/remove.md +1 -1
- package/docs/util/object-for-each/functions/forEach.md +1 -1
- package/docs/util/string-pad/functions/pad.md +1 -1
- package/docs/util/to-int/functions/toInt.md +1 -1
- package/docs/util/valid-callable/functions/validCallable.md +1 -1
- package/docs/util/valid-object/functions/validObject.md +1 -1
- package/docs/wrap-event-emitter/functions/wrapEventEmitter.md +3 -3
- package/docs/wrap-event-emitter/variables/methods.md +1 -1
- package/lib/all-off.mjs +16 -0
- package/lib/consts.d.ts +7 -1
- package/lib/consts.js +17 -2
- package/lib/consts.mjs +23 -0
- package/lib/default-methods.d.ts +12 -4
- package/lib/default-methods.js +174 -22
- package/lib/default-methods.mjs +661 -0
- package/lib/event-emitter.mjs +12 -0
- package/lib/event.d.ts +10 -4
- package/lib/event.js +6 -0
- package/lib/event.mjs +67 -0
- package/lib/eventable.d.ts +1 -1
- package/lib/eventable.mjs +90 -0
- package/lib/has-listeners.d.ts +1 -1
- package/lib/has-listeners.mjs +27 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +12 -0
- package/lib/index.mjs +16 -0
- package/lib/once-promise.d.ts +23 -0
- package/lib/once-promise.js +82 -0
- package/lib/once-promise.mjs +80 -0
- package/lib/pipe-async.d.ts +4 -2
- package/lib/pipe-async.js +16 -3
- package/lib/pipe-async.mjs +100 -0
- package/lib/pipe.d.ts +1 -1
- package/lib/pipe.mjs +53 -0
- package/lib/unify.js +1 -1
- package/lib/unify.mjs +58 -0
- package/lib/util/array-remove.mjs +16 -0
- package/lib/util/object-for-each.mjs +20 -0
- package/lib/util/promise-any.mjs +45 -0
- package/lib/util/string-pad.mjs +19 -0
- package/lib/util/to-int.mjs +9 -0
- package/lib/util/valid-callable.mjs +6 -0
- package/lib/util/valid-object.mjs +8 -0
- package/lib/wrap-event-emitter.d.ts +1 -1
- package/lib/wrap-event-emitter.mjs +46 -0
- package/package.json +29 -20
- package/scripts/copy-to-mjs.mjs +79 -0
- package/src/consts.js +10 -0
- package/src/default-methods.js +169 -24
- package/src/event.js +6 -0
- package/src/index.js +1 -0
- package/src/once-promise.js +80 -0
- package/src/pipe-async.js +16 -3
- package/src/unify.js +1 -1
- package/tsconfig.json +2 -1
- package/vitest.config.js +61 -0
- package/.mocharc.yml +0 -3
package/lib/event.d.ts
CHANGED
|
@@ -25,19 +25,25 @@ export class Event {
|
|
|
25
25
|
* @type {Object}
|
|
26
26
|
* @public
|
|
27
27
|
*/
|
|
28
|
-
public target:
|
|
28
|
+
public target: Object | undefined;
|
|
29
29
|
/**
|
|
30
30
|
* Whether stop the bubbling event
|
|
31
31
|
* @type {boolean}
|
|
32
32
|
* @public
|
|
33
33
|
*/
|
|
34
|
-
public stopped: boolean;
|
|
34
|
+
public stopped: boolean | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the event emission was aborted via AbortSignal.
|
|
37
|
+
* @type {boolean}
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
public aborted: boolean | undefined;
|
|
35
41
|
/**
|
|
36
42
|
* Whether a result has been resolved (for 'first' result mode)
|
|
37
43
|
* @type {boolean}
|
|
38
44
|
* @public
|
|
39
45
|
*/
|
|
40
|
-
public resolved: boolean;
|
|
46
|
+
public resolved: boolean | undefined;
|
|
41
47
|
/**
|
|
42
48
|
* Keep your event result here if any.
|
|
43
49
|
* @type {*}
|
|
@@ -49,7 +55,7 @@ export class Event {
|
|
|
49
55
|
* @type {string}
|
|
50
56
|
* @public
|
|
51
57
|
*/
|
|
52
|
-
public type: string;
|
|
58
|
+
public type: string | undefined;
|
|
53
59
|
/**
|
|
54
60
|
* Ends the event and returns the result.
|
|
55
61
|
* @returns {*} The result of the event.
|
package/lib/event.js
CHANGED
|
@@ -37,6 +37,12 @@ Event.prototype.init = function (target, type) {
|
|
|
37
37
|
* @public
|
|
38
38
|
*/
|
|
39
39
|
this.stopped = false;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the event emission was aborted via AbortSignal.
|
|
42
|
+
* @type {boolean}
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
this.aborted = false;
|
|
40
46
|
/**
|
|
41
47
|
* Whether a result has been resolved (for 'first' result mode)
|
|
42
48
|
* @type {boolean}
|
package/lib/event.mjs
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a new Event object instance that contains information about the event, such as the target element and the return value of the event.
|
|
3
|
+
* @class
|
|
4
|
+
* @classdesc Event Object that contains information about the event, such as the target element and the return value of the event.
|
|
5
|
+
* @param {import('./event-emitter').EventEmitter} target - Who trigger the event
|
|
6
|
+
* @returns {Event} - The new Event instance.
|
|
7
|
+
*/
|
|
8
|
+
export function Event(target, type) {
|
|
9
|
+
if (!(this instanceof Event)) {
|
|
10
|
+
const evt = new Event(target, type)
|
|
11
|
+
return evt
|
|
12
|
+
}
|
|
13
|
+
this.init(target, type)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Initializes the event with the target object.
|
|
18
|
+
* @param {import('./event-emitter').EventEmitter} target - The target object for the event.
|
|
19
|
+
*/
|
|
20
|
+
Event.prototype.init = function(target, type) {
|
|
21
|
+
/**
|
|
22
|
+
* Who trigger the event
|
|
23
|
+
* @type {Object}
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
this.target = target
|
|
27
|
+
/**
|
|
28
|
+
* Whether stop the bubbling event
|
|
29
|
+
* @type {boolean}
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
this.stopped = false
|
|
33
|
+
/**
|
|
34
|
+
* Whether the event emission was aborted via AbortSignal.
|
|
35
|
+
* @type {boolean}
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
this.aborted = false
|
|
39
|
+
/**
|
|
40
|
+
* Whether a result has been resolved (for 'first' result mode)
|
|
41
|
+
* @type {boolean}
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
this.resolved = false
|
|
45
|
+
/**
|
|
46
|
+
* Keep your event result here if any.
|
|
47
|
+
* @type {*}
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
this.result = undefined
|
|
51
|
+
/**
|
|
52
|
+
* The type of the event.
|
|
53
|
+
* @type {string}
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
this.type = type;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Ends the event and returns the result.
|
|
61
|
+
* @returns {*} The result of the event.
|
|
62
|
+
*/
|
|
63
|
+
Event.prototype.end = function() {
|
|
64
|
+
return this.result
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default Event
|
package/lib/eventable.d.ts
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
* }
|
|
46
46
|
* });
|
|
47
47
|
*/
|
|
48
|
-
export const eventable: <T extends Function | (new (...args: any[]) => any)>(targetClass?: T, options?: import("custom-ability").AbilityOptions) => T & typeof getEventableClass & (T extends new (...args: any[]) => any ? InstanceType<T> : T);
|
|
48
|
+
export const eventable: <T extends Function | (new (...args: any[]) => any)>(targetClass?: T | undefined, options?: import("custom-ability").AbilityOptions) => T & typeof getEventableClass & (T extends new (...args: any[]) => any ? InstanceType<T> : T);
|
|
49
49
|
export default eventable;
|
|
50
50
|
/**
|
|
51
51
|
* Creates an Eventable class with event-emitting capabilities.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {createAbilityInjector} from 'custom-ability'
|
|
2
|
+
import defineProperty from 'util-ex/lib/defineProperty'
|
|
3
|
+
import defaultMethods from './default-methods.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates an Eventable class with event-emitting capabilities.
|
|
7
|
+
*
|
|
8
|
+
* @param {Function} [aClass] - The target class to which event capabilities will be injected.
|
|
9
|
+
* If not provided, a new base class (`Eventable`) is created and used.
|
|
10
|
+
* @returns {Function} A class with event-emitting capabilities.
|
|
11
|
+
*/
|
|
12
|
+
function getEventableClass(aClass) {
|
|
13
|
+
/**
|
|
14
|
+
* Base Eventable class that provides event-related functionality.
|
|
15
|
+
* @class
|
|
16
|
+
*/
|
|
17
|
+
function Eventable() {}
|
|
18
|
+
|
|
19
|
+
if (aClass == null) {aClass = Eventable}
|
|
20
|
+
const methods = defaultMethods(aClass);
|
|
21
|
+
defineProperty(Eventable, 'methods', methods);
|
|
22
|
+
|
|
23
|
+
Eventable.defaultMaxListeners = 10;
|
|
24
|
+
Eventable.listenerCount = methods.listenerCount;
|
|
25
|
+
Eventable.prototype.listenerCount = methods.listenerCount;
|
|
26
|
+
Eventable.prototype.emit = methods.emit;
|
|
27
|
+
Eventable.prototype.emitAsync = methods.emitAsync;
|
|
28
|
+
Eventable.prototype.configure = methods.configure;
|
|
29
|
+
Eventable.prototype.parallel = methods.parallel;
|
|
30
|
+
Eventable.prototype.setEmitterOptions = methods.setEmitterOptions;
|
|
31
|
+
Eventable.prototype.on = methods.on;
|
|
32
|
+
Eventable.prototype.addListener = methods.on;
|
|
33
|
+
Eventable.prototype.off = methods.off;
|
|
34
|
+
Eventable.prototype.removeListener = methods.off;
|
|
35
|
+
Eventable.prototype.removeAllListeners = methods.removeAllListeners;
|
|
36
|
+
Eventable.prototype.once = methods.once;
|
|
37
|
+
Eventable.prototype.setMaxListeners = methods.setMaxListeners;
|
|
38
|
+
Eventable.prototype.listeners = methods.listeners;
|
|
39
|
+
return Eventable;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Adds event-emitting capabilities to a class by injecting necessary methods and properties.
|
|
44
|
+
*
|
|
45
|
+
* This function uses `createAbilityInjector` from `custom-ability` to inject event-related methods
|
|
46
|
+
* into the target class. The injected methods include standard EventEmitter functionality such as
|
|
47
|
+
* `on`, `off`, `emit`, `emitAsync`, `once`, `listeners`, `@listenerCount` and more. It also ensures compatibility with Node.js `EventEmitter`
|
|
48
|
+
* by including methods like `listenerCount`, `setMaxListeners`, `addListener`, `removeListener`, and `removeAllListeners`.
|
|
49
|
+
*
|
|
50
|
+
* @function eventable
|
|
51
|
+
* @param {Class} [aClass] - The target class to which event capabilities will be injected. if no class is provided, a new class with eventable will be created.
|
|
52
|
+
* @param {Object} [options] - Optional configuration for the injection process:
|
|
53
|
+
* * `include` (string[]|string): Specifies which methods should be added.
|
|
54
|
+
* Static methods should use the prefix '@'.
|
|
55
|
+
* * `exclude` (string[]|string): Specifies which methods should not be added.
|
|
56
|
+
* Static methods should use the prefix '@'.
|
|
57
|
+
* * `methods` (Object): Custom methods to override or extend the default behavior.
|
|
58
|
+
* Use `this.super()` to call the original method and `this.self` to access the original context.
|
|
59
|
+
* * `classMethods` (Object): Custom static methods to be added to the class.
|
|
60
|
+
* @returns {Class} The same `aClass` class with event capabilities injected. The return value is the modified `aClass` itself.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* import { eventable } from 'events-ex';
|
|
64
|
+
*
|
|
65
|
+
* class MyClass {}
|
|
66
|
+
*
|
|
67
|
+
* // Inject only specific methods: 'on', 'off', 'emit', 'emitAsync', and the static 'listenerCount'
|
|
68
|
+
* eventable(MyClass, { include: ['on', 'off', 'emit', 'emitAsync', '@listenerCount'] });
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* import { eventable } from 'events-ex';
|
|
72
|
+
*
|
|
73
|
+
* class OtherClass {
|
|
74
|
+
* exec() {
|
|
75
|
+
* console.log("Original exec");
|
|
76
|
+
* }
|
|
77
|
+
* }
|
|
78
|
+
*
|
|
79
|
+
* // Inject event capabilities and override the `exec` method
|
|
80
|
+
* eventable(OtherClass, {
|
|
81
|
+
* methods: {
|
|
82
|
+
* exec() {
|
|
83
|
+
* console.log("New exec");
|
|
84
|
+
* this.super(); // Calls the original `exec` method
|
|
85
|
+
* }
|
|
86
|
+
* }
|
|
87
|
+
* });
|
|
88
|
+
*/
|
|
89
|
+
export const eventable = createAbilityInjector(getEventableClass, true);
|
|
90
|
+
export default eventable;
|
package/lib/has-listeners.d.ts
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
* - If `type` is not provided, returns whether the object has any event listeners.
|
|
9
9
|
* @throws {TypeError} Throws a TypeError if `obj` is null or undefined.
|
|
10
10
|
*/
|
|
11
|
-
export function hasListeners(obj:
|
|
11
|
+
export function hasListeners(obj: Object, type?: string): boolean;
|
|
12
12
|
export default hasListeners;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
import {isEmptyObject} from 'util-ex'
|
|
3
|
+
|
|
4
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
5
|
+
|
|
6
|
+
function isValue(v) {
|
|
7
|
+
return v!== null && v!== undefined
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Checks if an object has event listeners.
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} obj - The object to check. Must not be null or undefined.
|
|
14
|
+
* @param {string} [type] - Optional parameter specifying the event type. If provided, checks for the existence of listeners for this specific type.
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
* - If `type` is provided, returns whether listeners for the specified event type exist.
|
|
17
|
+
* - If `type` is not provided, returns whether the object has any event listeners.
|
|
18
|
+
* @throws {TypeError} Throws a TypeError if `obj` is null or undefined.
|
|
19
|
+
*/
|
|
20
|
+
export function hasListeners(obj, type) {
|
|
21
|
+
if (!isValue(obj)) {throw new TypeError("Cannot use null or undefined")}
|
|
22
|
+
|
|
23
|
+
const result = type != null ? hasOwnProperty.call(obj, '_events') && obj._events[type] : obj.hasOwnProperty('_events') && !isEmptyObject(obj._events);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default hasListeners
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -101,6 +101,18 @@ Object.keys(_pipeAsync).forEach(function (key) {
|
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
103
|
});
|
|
104
|
+
var _oncePromise = require("./once-promise");
|
|
105
|
+
Object.keys(_oncePromise).forEach(function (key) {
|
|
106
|
+
if (key === "default" || key === "__esModule") return;
|
|
107
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
108
|
+
if (key in exports && exports[key] === _oncePromise[key]) return;
|
|
109
|
+
Object.defineProperty(exports, key, {
|
|
110
|
+
enumerable: true,
|
|
111
|
+
get: function () {
|
|
112
|
+
return _oncePromise[key];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
104
116
|
var _unify = require("./unify");
|
|
105
117
|
Object.keys(_unify).forEach(function (key) {
|
|
106
118
|
if (key === "default" || key === "__esModule") return;
|
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @sourceType: module
|
|
2
|
+
import {EventEmitter} from './event-emitter.mjs'
|
|
3
|
+
|
|
4
|
+
export * from './all-off.mjs'
|
|
5
|
+
export * from './consts.mjs'
|
|
6
|
+
export * from './event.mjs'
|
|
7
|
+
export * from './eventable.mjs'
|
|
8
|
+
export * from './event-emitter.mjs'
|
|
9
|
+
export * from './has-listeners.mjs'
|
|
10
|
+
export * from './pipe.mjs'
|
|
11
|
+
export * from './pipe-async.mjs'
|
|
12
|
+
export * from './once-promise.mjs'
|
|
13
|
+
export * from './unify.mjs'
|
|
14
|
+
export * from './wrap-event-emitter.mjs'
|
|
15
|
+
|
|
16
|
+
export default EventEmitter;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a Promise that resolves with the Event object when the specified event is emitted on the given emitter.
|
|
3
|
+
* If an 'error' event is emitted (and the waiting event is not 'error'), the promise rejects by default.
|
|
4
|
+
* If the provided AbortSignal is aborted, the promise rejects with an AbortError.
|
|
5
|
+
*
|
|
6
|
+
* Note: The resolved Event object's `result` field may not be the final value if other listeners have not yet run.
|
|
7
|
+
* For the definitive emit return value, use `emit()` or `emitAsync()` directly.
|
|
8
|
+
*
|
|
9
|
+
* @param {import('./event-emitter').EventEmitter} emitter - The event emitter to listen on.
|
|
10
|
+
* @param {string|RegExp} type - The event type to wait for.
|
|
11
|
+
* @param {Object} [options] - Optional configuration.
|
|
12
|
+
* @param {AbortSignal} [options.signal] - An AbortSignal to cancel the wait.
|
|
13
|
+
* @param {boolean|null} [options.raiseError] - Controls behavior when an 'error' event is emitted:
|
|
14
|
+
* - `true` / `undefined` (default): The promise rejects with the error.
|
|
15
|
+
* - `false`: The promise resolves with the error object instead of rejecting.
|
|
16
|
+
* @returns {Promise<import('./event').Event>} - A promise that resolves with the Event object.
|
|
17
|
+
* @throws {TypeError} - If emitter is not a valid event emitter object.
|
|
18
|
+
*/
|
|
19
|
+
export function oncePromise(emitter: import("./event-emitter").EventEmitter, type: string | RegExp, options?: {
|
|
20
|
+
signal?: any;
|
|
21
|
+
raiseError?: boolean | null | undefined;
|
|
22
|
+
}): Promise<import("./event").Event>;
|
|
23
|
+
export default oncePromise;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
exports.oncePromise = oncePromise;
|
|
8
|
+
var _validObject = _interopRequireDefault(require("./util/valid-object"));
|
|
9
|
+
var _consts = require("./consts");
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
// @sourceType: module
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns a Promise that resolves with the Event object when the specified event is emitted on the given emitter.
|
|
15
|
+
* If an 'error' event is emitted (and the waiting event is not 'error'), the promise rejects by default.
|
|
16
|
+
* If the provided AbortSignal is aborted, the promise rejects with an AbortError.
|
|
17
|
+
*
|
|
18
|
+
* Note: The resolved Event object's `result` field may not be the final value if other listeners have not yet run.
|
|
19
|
+
* For the definitive emit return value, use `emit()` or `emitAsync()` directly.
|
|
20
|
+
*
|
|
21
|
+
* @param {import('./event-emitter').EventEmitter} emitter - The event emitter to listen on.
|
|
22
|
+
* @param {string|RegExp} type - The event type to wait for.
|
|
23
|
+
* @param {Object} [options] - Optional configuration.
|
|
24
|
+
* @param {AbortSignal} [options.signal] - An AbortSignal to cancel the wait.
|
|
25
|
+
* @param {boolean|null} [options.raiseError] - Controls behavior when an 'error' event is emitted:
|
|
26
|
+
* - `true` / `undefined` (default): The promise rejects with the error.
|
|
27
|
+
* - `false`: The promise resolves with the error object instead of rejecting.
|
|
28
|
+
* @returns {Promise<import('./event').Event>} - A promise that resolves with the Event object.
|
|
29
|
+
* @throws {TypeError} - If emitter is not a valid event emitter object.
|
|
30
|
+
*/
|
|
31
|
+
function oncePromise(emitter, type, options) {
|
|
32
|
+
(0, _validObject.default)(emitter);
|
|
33
|
+
const signal = options && options.signal;
|
|
34
|
+
const raiseError = options && options.raiseError;
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
let onAbort = null;
|
|
37
|
+
let aborted = false;
|
|
38
|
+
const cleanup = () => {
|
|
39
|
+
emitter.off(type, onEvent);
|
|
40
|
+
if (type !== 'error') {
|
|
41
|
+
emitter.off('error', onError);
|
|
42
|
+
}
|
|
43
|
+
if (signal && onAbort) {
|
|
44
|
+
signal.removeEventListener('abort', onAbort);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
if (signal) {
|
|
48
|
+
if (signal.aborted) {
|
|
49
|
+
reject((0, _consts.createAbortError)());
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
onAbort = () => {
|
|
53
|
+
/* v8 ignore next — defensive guard, { once: true } ensures callback fires at most once */
|
|
54
|
+
if (!aborted) {
|
|
55
|
+
aborted = true;
|
|
56
|
+
cleanup();
|
|
57
|
+
reject((0, _consts.createAbortError)());
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
signal.addEventListener('abort', onAbort, {
|
|
61
|
+
once: true
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function onEvent() {
|
|
65
|
+
cleanup();
|
|
66
|
+
resolve(this); // resolve with the Event object
|
|
67
|
+
}
|
|
68
|
+
function onError(err) {
|
|
69
|
+
cleanup();
|
|
70
|
+
if (raiseError === false) {
|
|
71
|
+
resolve(err); // resolve with the error instead of rejecting
|
|
72
|
+
} else {
|
|
73
|
+
reject(err); // true | null | undefined → reject
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
emitter.on(type, onEvent);
|
|
77
|
+
if (type !== 'error') {
|
|
78
|
+
emitter.on('error', onError);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
var _default = exports.default = oncePromise;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// @sourceType: module
|
|
2
|
+
import validObject from './util/valid-object.mjs'
|
|
3
|
+
import {createAbortError} from './consts.mjs'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a Promise that resolves with the Event object when the specified event is emitted on the given emitter.
|
|
7
|
+
* If an 'error' event is emitted (and the waiting event is not 'error'), the promise rejects by default.
|
|
8
|
+
* If the provided AbortSignal is aborted, the promise rejects with an AbortError.
|
|
9
|
+
*
|
|
10
|
+
* Note: The resolved Event object's `result` field may not be the final value if other listeners have not yet run.
|
|
11
|
+
* For the definitive emit return value, use `emit()` or `emitAsync()` directly.
|
|
12
|
+
*
|
|
13
|
+
* @param {import('./event-emitter').EventEmitter} emitter - The event emitter to listen on.
|
|
14
|
+
* @param {string|RegExp} type - The event type to wait for.
|
|
15
|
+
* @param {Object} [options] - Optional configuration.
|
|
16
|
+
* @param {AbortSignal} [options.signal] - An AbortSignal to cancel the wait.
|
|
17
|
+
* @param {boolean|null} [options.raiseError] - Controls behavior when an 'error' event is emitted:
|
|
18
|
+
* - `true` / `undefined` (default): The promise rejects with the error.
|
|
19
|
+
* - `false`: The promise resolves with the error object instead of rejecting.
|
|
20
|
+
* @returns {Promise<import('./event').Event>} - A promise that resolves with the Event object.
|
|
21
|
+
* @throws {TypeError} - If emitter is not a valid event emitter object.
|
|
22
|
+
*/
|
|
23
|
+
export function oncePromise(emitter, type, options) {
|
|
24
|
+
validObject(emitter)
|
|
25
|
+
|
|
26
|
+
const signal = options && options.signal
|
|
27
|
+
const raiseError = options && options.raiseError
|
|
28
|
+
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
let onAbort = null
|
|
31
|
+
let aborted = false
|
|
32
|
+
|
|
33
|
+
const cleanup = () => {
|
|
34
|
+
emitter.off(type, onEvent)
|
|
35
|
+
if (type !== 'error') {
|
|
36
|
+
emitter.off('error', onError)
|
|
37
|
+
}
|
|
38
|
+
if (signal && onAbort) {
|
|
39
|
+
signal.removeEventListener('abort', onAbort)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (signal) {
|
|
44
|
+
if (signal.aborted) {
|
|
45
|
+
reject(createAbortError())
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
onAbort = () => {
|
|
49
|
+
/* v8 ignore next — defensive guard, { once: true } ensures callback fires at most once */
|
|
50
|
+
if (!aborted) {
|
|
51
|
+
aborted = true
|
|
52
|
+
cleanup()
|
|
53
|
+
reject(createAbortError())
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
signal.addEventListener('abort', onAbort, { once: true })
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function onEvent() {
|
|
60
|
+
cleanup()
|
|
61
|
+
resolve(this) // resolve with the Event object
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function onError(err) {
|
|
65
|
+
cleanup()
|
|
66
|
+
if (raiseError === false) {
|
|
67
|
+
resolve(err) // resolve with the error instead of rejecting
|
|
68
|
+
} else {
|
|
69
|
+
reject(err) // true | null | undefined → reject
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
emitter.on(type, onEvent)
|
|
74
|
+
if (type !== 'error') {
|
|
75
|
+
emitter.on('error', onError)
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export default oncePromise
|
package/lib/pipe-async.d.ts
CHANGED
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* @param {string} [name='emitAsync'] - The name of the event to pipe (defaults to 'emitAsync').
|
|
7
7
|
* @param {Object} [options] - Configuration for the pipeline.
|
|
8
8
|
* @param {string} [options.asyncMode='serial'] - The mode of propagation ('serial' or 'parallel').
|
|
9
|
-
* @param {string} [options.resultMode] - Strategy for aggregating results from the pipe chain ('
|
|
9
|
+
* @param {string} [options.resultMode='last'] - Strategy for aggregating results from the pipe chain ('last', 'first', 'collect').
|
|
10
|
+
* @param {AbortSignal} [options.signal] - An AbortSignal to cancel forwarding to remaining pipe targets (serial mode only).
|
|
11
|
+
* Can also be set on the source emitter via `configure({ signal })`.
|
|
10
12
|
* @returns {Object} - An object with a `close` method that removes the pipeline between the two event emitters.
|
|
11
13
|
* @throws {TypeError} - If either of the arguments is not an event emitter object.
|
|
12
14
|
*/
|
|
13
|
-
export function pipeAsync(e1: import("./event-emitter").EventEmitter, e2: import("./event-emitter").EventEmitter, ...args: any[]):
|
|
15
|
+
export function pipeAsync(e1: import("./event-emitter").EventEmitter, e2: import("./event-emitter").EventEmitter, ...args: any[]): Object;
|
|
14
16
|
export default pipeAsync;
|
package/lib/pipe-async.js
CHANGED
|
@@ -23,7 +23,9 @@ const emit = _wrapEventEmitter.methods.emitAsync;
|
|
|
23
23
|
* @param {string} [name='emitAsync'] - The name of the event to pipe (defaults to 'emitAsync').
|
|
24
24
|
* @param {Object} [options] - Configuration for the pipeline.
|
|
25
25
|
* @param {string} [options.asyncMode='serial'] - The mode of propagation ('serial' or 'parallel').
|
|
26
|
-
* @param {string} [options.resultMode] - Strategy for aggregating results from the pipe chain ('
|
|
26
|
+
* @param {string} [options.resultMode='last'] - Strategy for aggregating results from the pipe chain ('last', 'first', 'collect').
|
|
27
|
+
* @param {AbortSignal} [options.signal] - An AbortSignal to cancel forwarding to remaining pipe targets (serial mode only).
|
|
28
|
+
* Can also be set on the source emitter via `configure({ signal })`.
|
|
27
29
|
* @returns {Object} - An object with a `close` method that removes the pipeline between the two event emitters.
|
|
28
30
|
* @throws {TypeError} - If either of the arguments is not an event emitter object.
|
|
29
31
|
*/
|
|
@@ -67,6 +69,9 @@ function pipeAsync(e1, e2 /* , name, options */) {
|
|
|
67
69
|
const fn = target[name] || target.emitAsync || emit;
|
|
68
70
|
return fn.apply(target, args);
|
|
69
71
|
};
|
|
72
|
+
|
|
73
|
+
// Read signal from source emitter's runtime options, if configured
|
|
74
|
+
const signal = this._eeRuntimeOptions && this._eeRuntimeOptions.signal;
|
|
70
75
|
if (asyncMode === 'parallel') {
|
|
71
76
|
const promises = [emit.apply(this, arguments)];
|
|
72
77
|
for (let i = 0; i < data.length; ++i) {
|
|
@@ -75,17 +80,25 @@ function pipeAsync(e1, e2 /* , name, options */) {
|
|
|
75
80
|
const results = await Promise.all(promises);
|
|
76
81
|
if (resultMode === 'collect') return results;
|
|
77
82
|
if (resultMode === 'first') return results.find(r => r !== undefined);
|
|
78
|
-
|
|
83
|
+
// Default: 'last' — return last non-undefined result in the pipe chain
|
|
84
|
+
for (let i = results.length - 1; i >= 0; i--) {
|
|
85
|
+
if (results[i] !== undefined) return results[i];
|
|
86
|
+
}
|
|
79
87
|
} else {
|
|
80
88
|
const mainResult = await emit.apply(this, arguments);
|
|
81
89
|
const allResults = [mainResult];
|
|
82
90
|
for (let i = 0; i < data.length; ++i) {
|
|
91
|
+
// Check signal before forwarding to each pipe target in serial mode
|
|
92
|
+
if (signal && signal.aborted) break;
|
|
83
93
|
const res = await forward(data[i], arguments);
|
|
84
94
|
allResults.push(res);
|
|
85
95
|
}
|
|
86
96
|
if (resultMode === 'collect') return allResults;
|
|
87
97
|
if (resultMode === 'first') return allResults.find(r => r !== undefined);
|
|
88
|
-
|
|
98
|
+
// Default: 'last' — return last non-undefined result in the pipe chain
|
|
99
|
+
for (let i = allResults.length - 1; i >= 0; i--) {
|
|
100
|
+
if (allResults[i] !== undefined) return allResults[i];
|
|
101
|
+
}
|
|
89
102
|
}
|
|
90
103
|
};
|
|
91
104
|
(0, _defineProperty.default)(e1, name, desc.value, desc);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import defineProperty from 'util-ex/lib/defineProperty'
|
|
2
|
+
|
|
3
|
+
import {methods} from './wrap-event-emitter.mjs'
|
|
4
|
+
import arrRemove from './util/array-remove.mjs'
|
|
5
|
+
import validObject from './util/valid-object.mjs'
|
|
6
|
+
|
|
7
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty
|
|
8
|
+
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
|
|
9
|
+
const arrFrom = Array.from
|
|
10
|
+
const emit = methods.emitAsync
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates a pipeline between two event emitters, so that any events emitted by the first emitter are also emitted by the second emitter.
|
|
14
|
+
*
|
|
15
|
+
* @param {import('./event-emitter').EventEmitter} e1 - The first event emitter.
|
|
16
|
+
* @param {import('./event-emitter').EventEmitter} e2 - The second event emitter.
|
|
17
|
+
* @param {string} [name='emitAsync'] - The name of the event to pipe (defaults to 'emitAsync').
|
|
18
|
+
* @param {Object} [options] - Configuration for the pipeline.
|
|
19
|
+
* @param {string} [options.asyncMode='serial'] - The mode of propagation ('serial' or 'parallel').
|
|
20
|
+
* @param {string} [options.resultMode='last'] - Strategy for aggregating results from the pipe chain ('last', 'first', 'collect').
|
|
21
|
+
* @param {AbortSignal} [options.signal] - An AbortSignal to cancel forwarding to remaining pipe targets (serial mode only).
|
|
22
|
+
* Can also be set on the source emitter via `configure({ signal })`.
|
|
23
|
+
* @returns {Object} - An object with a `close` method that removes the pipeline between the two event emitters.
|
|
24
|
+
* @throws {TypeError} - If either of the arguments is not an event emitter object.
|
|
25
|
+
*/
|
|
26
|
+
export function pipeAsync(e1, e2/* , name, options */) {
|
|
27
|
+
let pipes
|
|
28
|
+
|
|
29
|
+
(validObject(e1) && validObject(e2))
|
|
30
|
+
let name = arguments[2]
|
|
31
|
+
let options = arguments[3]
|
|
32
|
+
if (typeof name === 'object') {
|
|
33
|
+
options = name
|
|
34
|
+
name = undefined
|
|
35
|
+
}
|
|
36
|
+
if (name === undefined) {name = 'emitAsync'}
|
|
37
|
+
if (!options) {options = {}}
|
|
38
|
+
|
|
39
|
+
const result = {
|
|
40
|
+
close() { arrRemove.call(pipes, e2) }
|
|
41
|
+
};
|
|
42
|
+
if (hasOwnProperty.call(e1, '__eePipes__')) {
|
|
43
|
+
(pipes = e1.__eePipes__).push(e2)
|
|
44
|
+
return result
|
|
45
|
+
}
|
|
46
|
+
defineProperty(e1, '__eePipes__', pipes = [e2])
|
|
47
|
+
let desc = getOwnPropertyDescriptor(e1, name)
|
|
48
|
+
if (!desc) {
|
|
49
|
+
desc = {}
|
|
50
|
+
} else {
|
|
51
|
+
delete desc.get
|
|
52
|
+
delete desc.set
|
|
53
|
+
}
|
|
54
|
+
desc.value = async function () {
|
|
55
|
+
const data = arrFrom(pipes)
|
|
56
|
+
const asyncMode = options.asyncMode || 'serial'
|
|
57
|
+
const resultMode = options.resultMode
|
|
58
|
+
|
|
59
|
+
const forward = async (target, args) => {
|
|
60
|
+
const fn = target[name] || target.emitAsync || emit
|
|
61
|
+
return fn.apply(target, args)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Read signal from source emitter's runtime options, if configured
|
|
65
|
+
const signal = this._eeRuntimeOptions && this._eeRuntimeOptions.signal
|
|
66
|
+
|
|
67
|
+
if (asyncMode === 'parallel') {
|
|
68
|
+
const promises = [emit.apply(this, arguments)]
|
|
69
|
+
for (let i = 0; i < data.length; ++i) {
|
|
70
|
+
promises.push(forward(data[i], arguments))
|
|
71
|
+
}
|
|
72
|
+
const results = await Promise.all(promises)
|
|
73
|
+
if (resultMode === 'collect') return results
|
|
74
|
+
if (resultMode === 'first') return results.find(r => r !== undefined)
|
|
75
|
+
// Default: 'last' — return last non-undefined result in the pipe chain
|
|
76
|
+
for (let i = results.length - 1; i >= 0; i--) {
|
|
77
|
+
if (results[i] !== undefined) return results[i]
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
const mainResult = await emit.apply(this, arguments)
|
|
81
|
+
const allResults = [mainResult]
|
|
82
|
+
for (let i = 0; i < data.length; ++i) {
|
|
83
|
+
// Check signal before forwarding to each pipe target in serial mode
|
|
84
|
+
if (signal && signal.aborted) break
|
|
85
|
+
const res = await forward(data[i], arguments)
|
|
86
|
+
allResults.push(res)
|
|
87
|
+
}
|
|
88
|
+
if (resultMode === 'collect') return allResults
|
|
89
|
+
if (resultMode === 'first') return allResults.find(r => r !== undefined)
|
|
90
|
+
// Default: 'last' — return last non-undefined result in the pipe chain
|
|
91
|
+
for (let i = allResults.length - 1; i >= 0; i--) {
|
|
92
|
+
if (allResults[i] !== undefined) return allResults[i]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
defineProperty(e1, name, desc.value, desc)
|
|
97
|
+
return result
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export default pipeAsync
|
package/lib/pipe.d.ts
CHANGED
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
* @returns {Object} - An object with a `close` method that removes the pipeline between the two event emitters.
|
|
8
8
|
* @throws {TypeError} - If either of the arguments is not an event emitter object.
|
|
9
9
|
*/
|
|
10
|
-
export function pipe(e1: import("./event-emitter").EventEmitter, e2: import("./event-emitter").EventEmitter, ...args: any[]):
|
|
10
|
+
export function pipe(e1: import("./event-emitter").EventEmitter, e2: import("./event-emitter").EventEmitter, ...args: any[]): Object;
|
|
11
11
|
export default pipe;
|