evnty 1.2.5 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -48
- package/build/index.cjs +24 -7
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +125 -12
- package/build/index.js +18 -7
- package/build/index.js.map +1 -1
- package/package.json +4 -2
- package/src/index.ts +149 -16
package/README.md
CHANGED
|
@@ -57,67 +57,38 @@ Using npm:
|
|
|
57
57
|
npm install evnty
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
type Unsubscribe = () => void;
|
|
64
|
-
type Listener = (...args: any[]) => void;
|
|
65
|
-
type Dispose = () => void;
|
|
66
|
-
type Filter = (...args: any[]) => boolean;
|
|
67
|
-
type Mapper = <T = any>(...args: any[]) => T;
|
|
68
|
-
type Reducer = <T = any>(value: any, ...args: any[]) => T;
|
|
69
|
-
|
|
70
|
-
class Dismiss {
|
|
71
|
-
async after(process: () => MaybePromise<any>): Promise<void>;
|
|
72
|
-
afterTimes(count: number): () => void;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
class Event {
|
|
76
|
-
// Merges multiple events
|
|
77
|
-
static merge(...events: Event[]): Event;
|
|
78
|
-
// Emits event by interval
|
|
79
|
-
static interval(interval: number): Event;
|
|
80
|
-
|
|
81
|
-
readonly size: Number;
|
|
82
|
-
|
|
83
|
-
constructor(dispose?: Dispose);
|
|
84
|
-
lacks(listener: Listener): boolean;
|
|
85
|
-
has(listener: Listener): boolean;
|
|
86
|
-
off(listener: Listener): void;
|
|
87
|
-
on(listener: Listener): Dismiss;
|
|
88
|
-
once(listener: Listener): Dismiss;
|
|
89
|
-
clear(): void;
|
|
90
|
-
toPromise(): Promise<any[]>;
|
|
91
|
-
filter(filter: Filter): Event;
|
|
92
|
-
map(mapper: Mapper): Event;
|
|
93
|
-
reduce(reducer: Reducer, init: any): Event;
|
|
94
|
-
dispose(): Dispose;
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Usage
|
|
60
|
+
## Examples
|
|
99
61
|
|
|
100
62
|
```js
|
|
101
|
-
import
|
|
63
|
+
import createEvent, { Event, once } from 'evnty';
|
|
102
64
|
|
|
103
|
-
|
|
104
|
-
|
|
65
|
+
// Creates a click event
|
|
66
|
+
type Click = { button: string };
|
|
67
|
+
const clickEvent = createEvent<[Click]>();
|
|
68
|
+
const handleClick = ({ button }: Click) => console.log('Clicked button is', button);
|
|
105
69
|
const unsubscribeClick = clickEvent.on(handleClick);
|
|
106
70
|
|
|
107
|
-
|
|
108
|
-
|
|
71
|
+
// Creates a key press event
|
|
72
|
+
type KeyPress = { key: string };
|
|
73
|
+
const keyPressEvent = createEvent<[KeyPress]>();
|
|
74
|
+
const handleKeyPress = ({ key }: KeyPress) => console.log('Key pressed', key);
|
|
109
75
|
const unsubscribeKeyPress = keyPressEvent.on(handleKeyPress);
|
|
110
76
|
|
|
111
|
-
|
|
77
|
+
// Merges click and key press events into input event
|
|
78
|
+
type Input = Click | KeyPress;
|
|
79
|
+
const handleInput = (input: Input) => console.log('Input', input);;
|
|
112
80
|
const inputEvent = Event.merge(clickEvent, keyPressEvent);
|
|
113
81
|
inputEvent.on(handleInput);
|
|
114
82
|
|
|
83
|
+
// Filters a click event to only include left-click events.
|
|
115
84
|
const handleLeftClick = () => console.log('Left button is clicked');
|
|
116
85
|
const leftClickEvent = clickEvent.filter(({ button }) => button === 'left');
|
|
117
86
|
leftClickEvent.on(handleLeftClick);
|
|
118
87
|
|
|
119
|
-
|
|
120
|
-
|
|
88
|
+
// Will press Enter after one second
|
|
89
|
+
setTimeout(keyPressEvent, 1000, { key: 'Enter' });
|
|
90
|
+
// Waits once the first Enter key press event occurs
|
|
91
|
+
await once(keyPressEvent.first(({ key }) => key === 'Enter'));
|
|
121
92
|
|
|
122
93
|
keyPressEvent({ key: 'W' });
|
|
123
94
|
keyPressEvent({ key: 'A' });
|
|
@@ -128,9 +99,14 @@ clickEvent({ button: 'right' });
|
|
|
128
99
|
clickEvent({ button: 'left' });
|
|
129
100
|
clickEvent({ button: 'middle' });
|
|
130
101
|
|
|
102
|
+
// Unsubscribe click listener
|
|
131
103
|
unsubscribeClick();
|
|
132
|
-
|
|
104
|
+
// It does not log anything because of click listener is unsubscribed
|
|
133
105
|
leftClickEvent.off(handleLeftClick);
|
|
106
|
+
|
|
107
|
+
// Unsubscribe key press listener once first Esc key press occur
|
|
108
|
+
unsubscribeKeyPress.after(() => once(keyPressEvent.first(({ key }) => key === 'Esc')));
|
|
109
|
+
// Press Esc to unsubscribe key press listener
|
|
134
110
|
keyPressEvent({ key: 'Esc' });
|
|
135
111
|
```
|
|
136
112
|
|
package/build/index.cjs
CHANGED
|
@@ -9,6 +9,9 @@ function _export(target, all) {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
+
FunctionExt: function() {
|
|
13
|
+
return FunctionExt;
|
|
14
|
+
},
|
|
12
15
|
Dismiss: function() {
|
|
13
16
|
return Dismiss;
|
|
14
17
|
},
|
|
@@ -18,8 +21,11 @@ _export(exports, {
|
|
|
18
21
|
once: function() {
|
|
19
22
|
return once;
|
|
20
23
|
},
|
|
21
|
-
|
|
24
|
+
createEvent: function() {
|
|
22
25
|
return createEvent;
|
|
26
|
+
},
|
|
27
|
+
default: function() {
|
|
28
|
+
return _default;
|
|
23
29
|
}
|
|
24
30
|
});
|
|
25
31
|
class FunctionExt extends Function {
|
|
@@ -29,11 +35,11 @@ class FunctionExt extends Function {
|
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
37
|
class Dismiss extends FunctionExt {
|
|
32
|
-
constructor(
|
|
33
|
-
super(
|
|
38
|
+
constructor(callback){
|
|
39
|
+
super(callback);
|
|
34
40
|
}
|
|
35
|
-
async after(
|
|
36
|
-
await
|
|
41
|
+
async after(task) {
|
|
42
|
+
await task();
|
|
37
43
|
this();
|
|
38
44
|
}
|
|
39
45
|
afterTimes(count) {
|
|
@@ -113,6 +119,16 @@ class Event extends FunctionExt {
|
|
|
113
119
|
const filteredEvent = new Event(dispose);
|
|
114
120
|
return filteredEvent;
|
|
115
121
|
}
|
|
122
|
+
first(filter) {
|
|
123
|
+
const dispose = this.on(async (...args)=>{
|
|
124
|
+
if (filteredEvent.size > 0 && await filter(...args)) {
|
|
125
|
+
dispose();
|
|
126
|
+
await filteredEvent(...args);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
const filteredEvent = new Event(dispose);
|
|
130
|
+
return filteredEvent;
|
|
131
|
+
}
|
|
116
132
|
map(mapper) {
|
|
117
133
|
const dispose = this.on(async (...args)=>{
|
|
118
134
|
if (mappedEvent.size > 0) {
|
|
@@ -138,8 +154,9 @@ class Event extends FunctionExt {
|
|
|
138
154
|
const once = (event)=>{
|
|
139
155
|
return new Promise((resolve)=>event.once((...args)=>resolve(args)));
|
|
140
156
|
};
|
|
141
|
-
|
|
157
|
+
const createEvent = ()=>{
|
|
142
158
|
return new Event();
|
|
143
|
-
}
|
|
159
|
+
};
|
|
160
|
+
const _default = createEvent;
|
|
144
161
|
|
|
145
162
|
//# sourceMappingURL=index.cjs.map
|
package/build/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport interface Listener<T extends unknown[], R> {\n (...args: T): MaybePromise<R | void>;\n}\n\nexport interface Dispose {\n (): void;\n}\n\nexport interface Filter<T extends unknown[]> {\n (...args: T): MaybePromise<boolean>;\n}\n\nexport interface Mapper<T extends unknown[], R> {\n (...args: T): R;\n}\n\nexport interface Reducer<T extends unknown[], R> {\n (value: R, ...args: T): R;\n}\n\nexport type Listeners<T extends unknown[], R> = Listener<T, R>[];\n\nclass FunctionExt extends Function {\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Dismiss {\n (): Promise<void> | void;\n}\n\nexport class Dismiss extends FunctionExt {\n constructor(dismiss: Unsubscribe) {\n super(dismiss);\n }\n async after(process: () => MaybePromise<unknown>) {\n await process();\n this();\n }\n afterTimes(count: number) {\n return () => {\n if (!--count) {\n this();\n }\n };\n }\n}\n\nconst eventEmitter = async <A extends unknown[], R>(listeners: Listeners<A, R>, ...args: A) => {\n return Promise.all(listeners.map((listener) => listener(...args)));\n};\n\nexport interface Event<T extends unknown[], R> {\n (...args: T): Promise<(R | undefined)[]>;\n}\n\ntype UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;\ntype UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;\ntype UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];\ntype UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];\n\nexport class Event<T extends unknown[], R = void> extends FunctionExt {\n static merge<Events extends Event<any[], any>[]>(...events: Events) {\n const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n }\n\n static interval(interval: number) {\n let counter = 0;\n const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));\n const timerId: NodeJS.Timeout = setInterval(() => intervalEvent(counter++), interval);\n return intervalEvent;\n }\n\n private listeners: Listeners<T, R>;\n readonly dispose: Dispose;\n\n constructor(dispose?: Dispose) {\n const listeners: Listeners<T, R> = [];\n const fn = (...args: T) => eventEmitter(listeners, ...args);\n\n super(fn);\n this.listeners = listeners;\n this.dispose = () => {\n this.clear();\n dispose?.();\n };\n }\n\n get size(): number {\n return this.listeners.length;\n }\n\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n off(listener: Listener<T, R>): void {\n let index = this.listeners.indexOf(listener);\n while (~index) {\n this.listeners.splice(index, 1);\n index = this.listeners.indexOf(listener);\n }\n }\n\n on(listener: Listener<T, R>): Dismiss {\n this.listeners.push(listener);\n return new Dismiss(() => this.off(listener));\n }\n\n once(listener: Listener<T, R>): Dismiss {\n const oneTimeListener = (...args: T) => {\n this.off(oneTimeListener);\n return listener(...args);\n };\n return this.on(oneTimeListener);\n }\n\n clear() {\n this.listeners.splice(0);\n }\n\n toPromise(): Promise<T> {\n return new Promise((resolve) => this.once((...args) => resolve(args)));\n }\n\n filter(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n map<R>(mapper: Mapper<T, R>) {\n const dispose = this.on(async (...args) => {\n if (mappedEvent.size > 0) {\n const value = await mapper(...args);\n mappedEvent(value);\n }\n });\n const mappedEvent = new Event(dispose);\n return mappedEvent;\n }\n\n reduce<R>(reducer: Reducer<T, R>, init: R) {\n let value = init;\n const dispose = this.on(async (...args) => {\n if (reducedEvent.size > 0) {\n value = await reducer(value, ...args);\n reducedEvent(value);\n }\n });\n const reducedEvent = new Event(dispose);\n return reducedEvent;\n }\n}\n\nexport const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {\n return new Promise((resolve) => event.once((...args) => resolve(args)));\n};\n\nexport default function createEvent<T extends unknown[], R = void>() {\n return new Event<T, R>();\n}\n"],"names":["Dismiss","Event","once","createEvent","FunctionExt","Function","constructor","func","Object","setPrototypeOf","prototype","dismiss","after","process","afterTimes","count","eventEmitter","listeners","args","Promise","all","map","listener","merge","events","mergedEvent","forEach","event","on","interval","counter","intervalEvent","clearInterval","timerId","setInterval","dispose","fn","clear","size","length","lacks","indexOf","has","off","index","splice","push","oneTimeListener","toPromise","resolve","filter","filteredEvent","mapper","mappedEvent","value","reduce","reducer","init","reducedEvent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport interface Listener<T extends unknown[], R = unknown> {\n (...args: T): MaybePromise<R | void>;\n}\n\nexport interface Dispose {\n (): void;\n}\n\nexport interface Filter<T extends unknown[]> {\n (...args: T): MaybePromise<boolean>;\n}\n\nexport interface Mapper<T extends unknown[], R = unknown> {\n (...args: T): R;\n}\n\nexport interface Reducer<T extends unknown[], R = unknown> {\n (value: R, ...args: T): R;\n}\n\nexport type Listeners<T extends unknown[], R = unknown> = Listener<T, R>[];\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 FunctionExt is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\nexport abstract class FunctionExt extends Function {\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Dismiss {\n (): Promise<void> | void;\n}\n\nexport interface Task {\n (): MaybePromise<unknown>;\n}\n\nexport class Dismiss extends FunctionExt {\n constructor(callback: Unsubscribe) {\n super(callback);\n }\n\n async after(task: Task) {\n await task();\n this();\n }\n\n afterTimes(count: number) {\n return () => {\n if (!--count) {\n this();\n }\n };\n }\n}\n\nconst eventEmitter = async <A extends unknown[], R>(listeners: Listeners<A, R>, ...args: A) => {\n return Promise.all(listeners.map((listener) => listener(...args)));\n};\n\nexport interface Event<T extends unknown[], R> {\n (...args: T): Promise<(R | undefined)[]>;\n}\n\ntype UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;\n\ntype UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;\n\ntype UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];\n\ntype UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];\n\n/**\n * A class representing an anonymous event that can be listened to or triggered.\n * @example\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n *\n * @template T - The tuple of arguments that the event takes.\n * @template R - The return type of the event.\n */\nexport class Event<T extends unknown[], R = void> extends FunctionExt {\n /**\n * Merges multiple events into a single event.\n * @param events - The events to merge.\n * @returns The merged event.\n */\n static merge<Events extends Event<any[], any>[]>(...events: Events) {\n const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n }\n\n /**\n * Creates an event that triggers at a specified interval.\n * @param interval - The interval at which to trigger the event.\n * @returns The interval event.\n */\n static interval(interval: number) {\n let counter = 0;\n const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));\n const timerId: NodeJS.Timeout = setInterval(() => intervalEvent(counter++), interval);\n return intervalEvent;\n }\n\n /**\n * The array of listeners for the event.\n */\n private listeners: Listeners<T, R>;\n\n /**\n * A function that disposes of the event and its listeners.\n */\n readonly dispose: Dispose;\n\n /**\n * Creates a new event.\n * @param dispose - A function to dispose of the event and its listeners.\n */\n constructor(dispose?: Dispose) {\n const listeners: Listeners<T, R> = [];\n const fn = (...args: T) => eventEmitter(listeners, ...args);\n\n super(fn);\n this.listeners = listeners;\n this.dispose = () => {\n this.clear();\n dispose?.();\n };\n }\n\n /**\n * The number of listeners for the event.\n */\n get size(): number {\n return this.listeners.length;\n }\n\n /**\n * Checks if a listener is not registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is not registered, `false` otherwise.\n */\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n /**\n * Checks if a listener is registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is registered, `false` otherwise.\n */\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n /**\n * Removes a listener from the event.\n * @param listener - The listener to remove.\n */\n off(listener: Listener<T, R>): void {\n let index = this.listeners.indexOf(listener);\n while (~index) {\n this.listeners.splice(index, 1);\n index = this.listeners.indexOf(listener);\n }\n }\n\n /**\n * Adds a listener to the event.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n on(listener: Listener<T, R>): Dismiss {\n this.listeners.push(listener);\n return new Dismiss(() => this.off(listener));\n }\n\n /**\n * Adds a listener to the event that will only be called once.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n once(listener: Listener<T, R>): Dismiss {\n const oneTimeListener = (...args: T) => {\n this.off(oneTimeListener);\n return listener(...args);\n };\n return this.on(oneTimeListener);\n }\n\n /**\n * Removes all listeners from the event.\n */\n clear() {\n this.listeners.splice(0);\n }\n\n /**\n * Converts the event to a promise that resolves with the event arguments.\n * @returns A promise that resolves with the event arguments.\n */\n toPromise(): Promise<T> {\n return new Promise((resolve) => this.once((...args) => resolve(args)));\n }\n\n /**\n * Creates a new event that only triggers if the filter function returns `true`.\n * @param filter - The filter function.\n * @returns The filtered event.\n */\n filter(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Creates a new event that only triggers once if the filter function returns `true`.\n * @param filter - The filter function.\n * @returns The filtered event.\n */\n first(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n dispose();\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Creates a new event that maps the event arguments to a new value.\n * @param mapper - The mapper function.\n * @returns The mapped event.\n */\n map<M, MR = unknown>(mapper: Mapper<T, M>) {\n const dispose = this.on(async (...args) => {\n if (mappedEvent.size > 0) {\n const value = await mapper(...args);\n mappedEvent(value);\n }\n });\n const mappedEvent = new Event<[M], MR>(dispose);\n return mappedEvent;\n }\n\n /**\n * Creates a new event that reduces the event arguments to a single value.\n * @param reducer - The reducer function.\n * @param init - The initial value for the reducer.\n * @returns The reduced event.\n */\n reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A) {\n let value = init;\n const dispose = this.on(async (...args) => {\n if (reducedEvent.size > 0) {\n value = await reducer(value, ...args);\n reducedEvent(value);\n }\n });\n const reducedEvent = new Event<[A], AR>(dispose);\n return reducedEvent;\n }\n}\n\n/**\n * Returns a promise that resolves with the arguments passed to the first invocation of the given event.\n * @param event The event to listen for.\n * @returns A promise that resolves with the arguments passed to the first invocation of the given event.\n */\nexport const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {\n return new Promise((resolve) => event.once((...args) => resolve(args)));\n};\n\n/**\n * Creates a new instance of the Event class.\n * @returns {Event<T, R>} A new instance of the Event class.\n * @template T The type of the arguments passed to the event.\n * @template R The return type of the event.\n */\nexport const createEvent = <T extends unknown[], R = void>(): Event<T, R> => {\n return new Event<T, R>();\n};\n\nexport default createEvent;\n\n/**\n * A type helper that extracts the event listener type\n *\n * @template E - The event object type.\n * @template T - The event type extracted from the event object.\n * @template R - The result type returned by the event handler function.\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n"],"names":["FunctionExt","Dismiss","Event","once","createEvent","Function","constructor","func","Object","setPrototypeOf","prototype","callback","after","task","afterTimes","count","eventEmitter","listeners","args","Promise","all","map","listener","merge","events","mergedEvent","forEach","event","on","interval","counter","intervalEvent","clearInterval","timerId","setInterval","dispose","fn","clear","size","length","lacks","indexOf","has","off","index","splice","push","oneTimeListener","toPromise","resolve","filter","filteredEvent","first","mapper","mappedEvent","value","reduce","reducer","init","reducedEvent"],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;
|
|
1
|
+
export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;
|
|
2
2
|
export interface Unsubscribe {
|
|
3
3
|
(): void;
|
|
4
4
|
}
|
|
5
|
-
export interface Listener<T extends unknown[], R> {
|
|
5
|
+
export interface Listener<T extends unknown[], R = unknown> {
|
|
6
6
|
(...args: T): MaybePromise<R | void>;
|
|
7
7
|
}
|
|
8
8
|
export interface Dispose {
|
|
@@ -11,22 +11,31 @@ export interface Dispose {
|
|
|
11
11
|
export interface Filter<T extends unknown[]> {
|
|
12
12
|
(...args: T): MaybePromise<boolean>;
|
|
13
13
|
}
|
|
14
|
-
export interface Mapper<T extends unknown[], R> {
|
|
14
|
+
export interface Mapper<T extends unknown[], R = unknown> {
|
|
15
15
|
(...args: T): R;
|
|
16
16
|
}
|
|
17
|
-
export interface Reducer<T extends unknown[], R> {
|
|
17
|
+
export interface Reducer<T extends unknown[], R = unknown> {
|
|
18
18
|
(value: R, ...args: T): R;
|
|
19
19
|
}
|
|
20
|
-
export type Listeners<T extends unknown[], R> = Listener<T, R>[];
|
|
21
|
-
|
|
20
|
+
export type Listeners<T extends unknown[], R = unknown> = Listener<T, R>[];
|
|
21
|
+
/**
|
|
22
|
+
* An abstract class that extends the built-in Function class. It allows instances of the class
|
|
23
|
+
* to be called as functions. When an instance of FunctionExt is called as a function, it will
|
|
24
|
+
* call the function passed to its constructor with the same arguments.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare abstract class FunctionExt extends Function {
|
|
22
28
|
constructor(func: Function);
|
|
23
29
|
}
|
|
24
30
|
export interface Dismiss {
|
|
25
31
|
(): Promise<void> | void;
|
|
26
32
|
}
|
|
33
|
+
export interface Task {
|
|
34
|
+
(): MaybePromise<unknown>;
|
|
35
|
+
}
|
|
27
36
|
export declare class Dismiss extends FunctionExt {
|
|
28
|
-
constructor(
|
|
29
|
-
after(
|
|
37
|
+
constructor(callback: Unsubscribe);
|
|
38
|
+
after(task: Task): Promise<void>;
|
|
30
39
|
afterTimes(count: number): () => void;
|
|
31
40
|
}
|
|
32
41
|
export interface Event<T extends unknown[], R> {
|
|
@@ -40,24 +49,128 @@ type UnpackAllParameters<T extends Event<unknown[], unknown>[]> = {
|
|
|
40
49
|
type UnpackAllReturn<T extends Event<unknown[], unknown>[]> = {
|
|
41
50
|
[K in keyof T]: UnpackReturn<T[K]>;
|
|
42
51
|
}[number];
|
|
52
|
+
/**
|
|
53
|
+
* A class representing an anonymous event that can be listened to or triggered.
|
|
54
|
+
* @example
|
|
55
|
+
* // Create a click event.
|
|
56
|
+
* const clickEvent = new Event<[x: number, y: number], void>();
|
|
57
|
+
*
|
|
58
|
+
* @template T - The tuple of arguments that the event takes.
|
|
59
|
+
* @template R - The return type of the event.
|
|
60
|
+
*/
|
|
43
61
|
export declare class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
62
|
+
/**
|
|
63
|
+
* Merges multiple events into a single event.
|
|
64
|
+
* @param events - The events to merge.
|
|
65
|
+
* @returns The merged event.
|
|
66
|
+
*/
|
|
44
67
|
static merge<Events extends Event<any[], any>[]>(...events: Events): Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>;
|
|
68
|
+
/**
|
|
69
|
+
* Creates an event that triggers at a specified interval.
|
|
70
|
+
* @param interval - The interval at which to trigger the event.
|
|
71
|
+
* @returns The interval event.
|
|
72
|
+
*/
|
|
45
73
|
static interval(interval: number): Event<[number], void>;
|
|
74
|
+
/**
|
|
75
|
+
* The array of listeners for the event.
|
|
76
|
+
*/
|
|
46
77
|
private listeners;
|
|
78
|
+
/**
|
|
79
|
+
* A function that disposes of the event and its listeners.
|
|
80
|
+
*/
|
|
47
81
|
readonly dispose: Dispose;
|
|
82
|
+
/**
|
|
83
|
+
* Creates a new event.
|
|
84
|
+
* @param dispose - A function to dispose of the event and its listeners.
|
|
85
|
+
*/
|
|
48
86
|
constructor(dispose?: Dispose);
|
|
87
|
+
/**
|
|
88
|
+
* The number of listeners for the event.
|
|
89
|
+
*/
|
|
49
90
|
get size(): number;
|
|
91
|
+
/**
|
|
92
|
+
* Checks if a listener is not registered for the event.
|
|
93
|
+
* @param listener - The listener to check.
|
|
94
|
+
* @returns `true` if the listener is not registered, `false` otherwise.
|
|
95
|
+
*/
|
|
50
96
|
lacks(listener: Listener<T, R>): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Checks if a listener is registered for the event.
|
|
99
|
+
* @param listener - The listener to check.
|
|
100
|
+
* @returns `true` if the listener is registered, `false` otherwise.
|
|
101
|
+
*/
|
|
51
102
|
has(listener: Listener<T, R>): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Removes a listener from the event.
|
|
105
|
+
* @param listener - The listener to remove.
|
|
106
|
+
*/
|
|
52
107
|
off(listener: Listener<T, R>): void;
|
|
108
|
+
/**
|
|
109
|
+
* Adds a listener to the event.
|
|
110
|
+
* @param listener - The listener to add.
|
|
111
|
+
* @returns An object that can be used to remove the listener.
|
|
112
|
+
*/
|
|
53
113
|
on(listener: Listener<T, R>): Dismiss;
|
|
114
|
+
/**
|
|
115
|
+
* Adds a listener to the event that will only be called once.
|
|
116
|
+
* @param listener - The listener to add.
|
|
117
|
+
* @returns An object that can be used to remove the listener.
|
|
118
|
+
*/
|
|
54
119
|
once(listener: Listener<T, R>): Dismiss;
|
|
120
|
+
/**
|
|
121
|
+
* Removes all listeners from the event.
|
|
122
|
+
*/
|
|
55
123
|
clear(): void;
|
|
124
|
+
/**
|
|
125
|
+
* Converts the event to a promise that resolves with the event arguments.
|
|
126
|
+
* @returns A promise that resolves with the event arguments.
|
|
127
|
+
*/
|
|
56
128
|
toPromise(): Promise<T>;
|
|
129
|
+
/**
|
|
130
|
+
* Creates a new event that only triggers if the filter function returns `true`.
|
|
131
|
+
* @param filter - The filter function.
|
|
132
|
+
* @returns The filtered event.
|
|
133
|
+
*/
|
|
57
134
|
filter(filter: Filter<T>): Event<T, R>;
|
|
58
|
-
|
|
59
|
-
|
|
135
|
+
/**
|
|
136
|
+
* Creates a new event that only triggers once if the filter function returns `true`.
|
|
137
|
+
* @param filter - The filter function.
|
|
138
|
+
* @returns The filtered event.
|
|
139
|
+
*/
|
|
140
|
+
first(filter: Filter<T>): Event<T, R>;
|
|
141
|
+
/**
|
|
142
|
+
* Creates a new event that maps the event arguments to a new value.
|
|
143
|
+
* @param mapper - The mapper function.
|
|
144
|
+
* @returns The mapped event.
|
|
145
|
+
*/
|
|
146
|
+
map<M, MR = unknown>(mapper: Mapper<T, M>): Event<[M], MR>;
|
|
147
|
+
/**
|
|
148
|
+
* Creates a new event that reduces the event arguments to a single value.
|
|
149
|
+
* @param reducer - The reducer function.
|
|
150
|
+
* @param init - The initial value for the reducer.
|
|
151
|
+
* @returns The reduced event.
|
|
152
|
+
*/
|
|
153
|
+
reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A): Event<[A], AR>;
|
|
60
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Returns a promise that resolves with the arguments passed to the first invocation of the given event.
|
|
157
|
+
* @param event The event to listen for.
|
|
158
|
+
* @returns A promise that resolves with the arguments passed to the first invocation of the given event.
|
|
159
|
+
*/
|
|
61
160
|
export declare const once: <T extends unknown[], R = void>(event: Event<T, R>) => Promise<T>;
|
|
62
|
-
|
|
63
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Creates a new instance of the Event class.
|
|
163
|
+
* @returns {Event<T, R>} A new instance of the Event class.
|
|
164
|
+
* @template T The type of the arguments passed to the event.
|
|
165
|
+
* @template R The return type of the event.
|
|
166
|
+
*/
|
|
167
|
+
export declare const createEvent: <T extends unknown[], R = void>() => Event<T, R>;
|
|
168
|
+
export default createEvent;
|
|
169
|
+
/**
|
|
170
|
+
* A type helper that extracts the event listener type
|
|
171
|
+
*
|
|
172
|
+
* @template E - The event object type.
|
|
173
|
+
* @template T - The event type extracted from the event object.
|
|
174
|
+
* @template R - The result type returned by the event handler function.
|
|
175
|
+
*/
|
|
176
|
+
export type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;
|
package/build/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
class FunctionExt extends Function {
|
|
1
|
+
export class FunctionExt extends Function {
|
|
2
2
|
constructor(func){
|
|
3
3
|
super();
|
|
4
4
|
return Object.setPrototypeOf(func, new.target.prototype);
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
7
|
export class Dismiss extends FunctionExt {
|
|
8
|
-
constructor(
|
|
9
|
-
super(
|
|
8
|
+
constructor(callback){
|
|
9
|
+
super(callback);
|
|
10
10
|
}
|
|
11
|
-
async after(
|
|
12
|
-
await
|
|
11
|
+
async after(task) {
|
|
12
|
+
await task();
|
|
13
13
|
this();
|
|
14
14
|
}
|
|
15
15
|
afterTimes(count) {
|
|
@@ -89,6 +89,16 @@ export class Event extends FunctionExt {
|
|
|
89
89
|
const filteredEvent = new Event(dispose);
|
|
90
90
|
return filteredEvent;
|
|
91
91
|
}
|
|
92
|
+
first(filter) {
|
|
93
|
+
const dispose = this.on(async (...args)=>{
|
|
94
|
+
if (filteredEvent.size > 0 && await filter(...args)) {
|
|
95
|
+
dispose();
|
|
96
|
+
await filteredEvent(...args);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const filteredEvent = new Event(dispose);
|
|
100
|
+
return filteredEvent;
|
|
101
|
+
}
|
|
92
102
|
map(mapper) {
|
|
93
103
|
const dispose = this.on(async (...args)=>{
|
|
94
104
|
if (mappedEvent.size > 0) {
|
|
@@ -114,8 +124,9 @@ export class Event extends FunctionExt {
|
|
|
114
124
|
export const once = (event)=>{
|
|
115
125
|
return new Promise((resolve)=>event.once((...args)=>resolve(args)));
|
|
116
126
|
};
|
|
117
|
-
export
|
|
127
|
+
export const createEvent = ()=>{
|
|
118
128
|
return new Event();
|
|
119
|
-
}
|
|
129
|
+
};
|
|
130
|
+
export default createEvent;
|
|
120
131
|
|
|
121
132
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport interface Listener<T extends unknown[], R> {\n (...args: T): MaybePromise<R | void>;\n}\n\nexport interface Dispose {\n (): void;\n}\n\nexport interface Filter<T extends unknown[]> {\n (...args: T): MaybePromise<boolean>;\n}\n\nexport interface Mapper<T extends unknown[], R> {\n (...args: T): R;\n}\n\nexport interface Reducer<T extends unknown[], R> {\n (value: R, ...args: T): R;\n}\n\nexport type Listeners<T extends unknown[], R> = Listener<T, R>[];\n\nclass FunctionExt extends Function {\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Dismiss {\n (): Promise<void> | void;\n}\n\nexport class Dismiss extends FunctionExt {\n constructor(dismiss: Unsubscribe) {\n super(dismiss);\n }\n async after(process: () => MaybePromise<unknown>) {\n await process();\n this();\n }\n afterTimes(count: number) {\n return () => {\n if (!--count) {\n this();\n }\n };\n }\n}\n\nconst eventEmitter = async <A extends unknown[], R>(listeners: Listeners<A, R>, ...args: A) => {\n return Promise.all(listeners.map((listener) => listener(...args)));\n};\n\nexport interface Event<T extends unknown[], R> {\n (...args: T): Promise<(R | undefined)[]>;\n}\n\ntype UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;\ntype UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;\ntype UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];\ntype UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];\n\nexport class Event<T extends unknown[], R = void> extends FunctionExt {\n static merge<Events extends Event<any[], any>[]>(...events: Events) {\n const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n }\n\n static interval(interval: number) {\n let counter = 0;\n const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));\n const timerId: NodeJS.Timeout = setInterval(() => intervalEvent(counter++), interval);\n return intervalEvent;\n }\n\n private listeners: Listeners<T, R>;\n readonly dispose: Dispose;\n\n constructor(dispose?: Dispose) {\n const listeners: Listeners<T, R> = [];\n const fn = (...args: T) => eventEmitter(listeners, ...args);\n\n super(fn);\n this.listeners = listeners;\n this.dispose = () => {\n this.clear();\n dispose?.();\n };\n }\n\n get size(): number {\n return this.listeners.length;\n }\n\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n off(listener: Listener<T, R>): void {\n let index = this.listeners.indexOf(listener);\n while (~index) {\n this.listeners.splice(index, 1);\n index = this.listeners.indexOf(listener);\n }\n }\n\n on(listener: Listener<T, R>): Dismiss {\n this.listeners.push(listener);\n return new Dismiss(() => this.off(listener));\n }\n\n once(listener: Listener<T, R>): Dismiss {\n const oneTimeListener = (...args: T) => {\n this.off(oneTimeListener);\n return listener(...args);\n };\n return this.on(oneTimeListener);\n }\n\n clear() {\n this.listeners.splice(0);\n }\n\n toPromise(): Promise<T> {\n return new Promise((resolve) => this.once((...args) => resolve(args)));\n }\n\n filter(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n map<R>(mapper: Mapper<T, R>) {\n const dispose = this.on(async (...args) => {\n if (mappedEvent.size > 0) {\n const value = await mapper(...args);\n mappedEvent(value);\n }\n });\n const mappedEvent = new Event(dispose);\n return mappedEvent;\n }\n\n reduce<R>(reducer: Reducer<T, R>, init: R) {\n let value = init;\n const dispose = this.on(async (...args) => {\n if (reducedEvent.size > 0) {\n value = await reducer(value, ...args);\n reducedEvent(value);\n }\n });\n const reducedEvent = new Event(dispose);\n return reducedEvent;\n }\n}\n\nexport const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {\n return new Promise((resolve) => event.once((...args) => resolve(args)));\n};\n\nexport default function createEvent<T extends unknown[], R = void>() {\n return new Event<T, R>();\n}\n"],"names":["FunctionExt","Function","constructor","func","Object","setPrototypeOf","prototype","Dismiss","dismiss","after","process","afterTimes","count","eventEmitter","listeners","args","Promise","all","map","listener","Event","merge","events","mergedEvent","forEach","event","on","interval","counter","intervalEvent","clearInterval","timerId","setInterval","dispose","fn","clear","size","length","lacks","indexOf","has","off","index","splice","push","once","oneTimeListener","toPromise","resolve","filter","filteredEvent","mapper","mappedEvent","value","reduce","reducer","init","reducedEvent","createEvent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport interface Listener<T extends unknown[], R = unknown> {\n (...args: T): MaybePromise<R | void>;\n}\n\nexport interface Dispose {\n (): void;\n}\n\nexport interface Filter<T extends unknown[]> {\n (...args: T): MaybePromise<boolean>;\n}\n\nexport interface Mapper<T extends unknown[], R = unknown> {\n (...args: T): R;\n}\n\nexport interface Reducer<T extends unknown[], R = unknown> {\n (value: R, ...args: T): R;\n}\n\nexport type Listeners<T extends unknown[], R = unknown> = Listener<T, R>[];\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 FunctionExt is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\nexport abstract class FunctionExt extends Function {\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Dismiss {\n (): Promise<void> | void;\n}\n\nexport interface Task {\n (): MaybePromise<unknown>;\n}\n\nexport class Dismiss extends FunctionExt {\n constructor(callback: Unsubscribe) {\n super(callback);\n }\n\n async after(task: Task) {\n await task();\n this();\n }\n\n afterTimes(count: number) {\n return () => {\n if (!--count) {\n this();\n }\n };\n }\n}\n\nconst eventEmitter = async <A extends unknown[], R>(listeners: Listeners<A, R>, ...args: A) => {\n return Promise.all(listeners.map((listener) => listener(...args)));\n};\n\nexport interface Event<T extends unknown[], R> {\n (...args: T): Promise<(R | undefined)[]>;\n}\n\ntype UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;\n\ntype UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;\n\ntype UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];\n\ntype UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];\n\n/**\n * A class representing an anonymous event that can be listened to or triggered.\n * @example\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n *\n * @template T - The tuple of arguments that the event takes.\n * @template R - The return type of the event.\n */\nexport class Event<T extends unknown[], R = void> extends FunctionExt {\n /**\n * Merges multiple events into a single event.\n * @param events - The events to merge.\n * @returns The merged event.\n */\n static merge<Events extends Event<any[], any>[]>(...events: Events) {\n const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n }\n\n /**\n * Creates an event that triggers at a specified interval.\n * @param interval - The interval at which to trigger the event.\n * @returns The interval event.\n */\n static interval(interval: number) {\n let counter = 0;\n const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));\n const timerId: NodeJS.Timeout = setInterval(() => intervalEvent(counter++), interval);\n return intervalEvent;\n }\n\n /**\n * The array of listeners for the event.\n */\n private listeners: Listeners<T, R>;\n\n /**\n * A function that disposes of the event and its listeners.\n */\n readonly dispose: Dispose;\n\n /**\n * Creates a new event.\n * @param dispose - A function to dispose of the event and its listeners.\n */\n constructor(dispose?: Dispose) {\n const listeners: Listeners<T, R> = [];\n const fn = (...args: T) => eventEmitter(listeners, ...args);\n\n super(fn);\n this.listeners = listeners;\n this.dispose = () => {\n this.clear();\n dispose?.();\n };\n }\n\n /**\n * The number of listeners for the event.\n */\n get size(): number {\n return this.listeners.length;\n }\n\n /**\n * Checks if a listener is not registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is not registered, `false` otherwise.\n */\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n /**\n * Checks if a listener is registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is registered, `false` otherwise.\n */\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n /**\n * Removes a listener from the event.\n * @param listener - The listener to remove.\n */\n off(listener: Listener<T, R>): void {\n let index = this.listeners.indexOf(listener);\n while (~index) {\n this.listeners.splice(index, 1);\n index = this.listeners.indexOf(listener);\n }\n }\n\n /**\n * Adds a listener to the event.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n on(listener: Listener<T, R>): Dismiss {\n this.listeners.push(listener);\n return new Dismiss(() => this.off(listener));\n }\n\n /**\n * Adds a listener to the event that will only be called once.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n once(listener: Listener<T, R>): Dismiss {\n const oneTimeListener = (...args: T) => {\n this.off(oneTimeListener);\n return listener(...args);\n };\n return this.on(oneTimeListener);\n }\n\n /**\n * Removes all listeners from the event.\n */\n clear() {\n this.listeners.splice(0);\n }\n\n /**\n * Converts the event to a promise that resolves with the event arguments.\n * @returns A promise that resolves with the event arguments.\n */\n toPromise(): Promise<T> {\n return new Promise((resolve) => this.once((...args) => resolve(args)));\n }\n\n /**\n * Creates a new event that only triggers if the filter function returns `true`.\n * @param filter - The filter function.\n * @returns The filtered event.\n */\n filter(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Creates a new event that only triggers once if the filter function returns `true`.\n * @param filter - The filter function.\n * @returns The filtered event.\n */\n first(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n dispose();\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Creates a new event that maps the event arguments to a new value.\n * @param mapper - The mapper function.\n * @returns The mapped event.\n */\n map<M, MR = unknown>(mapper: Mapper<T, M>) {\n const dispose = this.on(async (...args) => {\n if (mappedEvent.size > 0) {\n const value = await mapper(...args);\n mappedEvent(value);\n }\n });\n const mappedEvent = new Event<[M], MR>(dispose);\n return mappedEvent;\n }\n\n /**\n * Creates a new event that reduces the event arguments to a single value.\n * @param reducer - The reducer function.\n * @param init - The initial value for the reducer.\n * @returns The reduced event.\n */\n reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A) {\n let value = init;\n const dispose = this.on(async (...args) => {\n if (reducedEvent.size > 0) {\n value = await reducer(value, ...args);\n reducedEvent(value);\n }\n });\n const reducedEvent = new Event<[A], AR>(dispose);\n return reducedEvent;\n }\n}\n\n/**\n * Returns a promise that resolves with the arguments passed to the first invocation of the given event.\n * @param event The event to listen for.\n * @returns A promise that resolves with the arguments passed to the first invocation of the given event.\n */\nexport const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {\n return new Promise((resolve) => event.once((...args) => resolve(args)));\n};\n\n/**\n * Creates a new instance of the Event class.\n * @returns {Event<T, R>} A new instance of the Event class.\n * @template T The type of the arguments passed to the event.\n * @template R The return type of the event.\n */\nexport const createEvent = <T extends unknown[], R = void>(): Event<T, R> => {\n return new Event<T, R>();\n};\n\nexport default createEvent;\n\n/**\n * A type helper that extracts the event listener type\n *\n * @template E - The event object type.\n * @template T - The event type extracted from the event object.\n * @template R - The result type returned by the event handler function.\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n"],"names":["FunctionExt","Function","constructor","func","Object","setPrototypeOf","prototype","Dismiss","callback","after","task","afterTimes","count","eventEmitter","listeners","args","Promise","all","map","listener","Event","merge","events","mergedEvent","forEach","event","on","interval","counter","intervalEvent","clearInterval","timerId","setInterval","dispose","fn","clear","size","length","lacks","indexOf","has","off","index","splice","push","once","oneTimeListener","toPromise","resolve","filter","filteredEvent","first","mapper","mappedEvent","value","reduce","reducer","init","reducedEvent","createEvent"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evnty",
|
|
3
3
|
"description": "0-Deps, simple, fast, for browser and node js anonymous event library",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
7
7
|
"main": "build/index.cjs",
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
"events",
|
|
33
33
|
"emit",
|
|
34
34
|
"emitter",
|
|
35
|
-
"anonymous"
|
|
35
|
+
"anonymous",
|
|
36
|
+
"flow",
|
|
37
|
+
"event-driven"
|
|
36
38
|
],
|
|
37
39
|
"funding": "https://github.com/sponsors/3axap4eHko",
|
|
38
40
|
"author": {
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;
|
|
1
|
+
export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;
|
|
2
2
|
|
|
3
3
|
export interface Unsubscribe {
|
|
4
4
|
(): void;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export interface Listener<T extends unknown[], R> {
|
|
7
|
+
export interface Listener<T extends unknown[], R = unknown> {
|
|
8
8
|
(...args: T): MaybePromise<R | void>;
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -16,17 +16,23 @@ export interface Filter<T extends unknown[]> {
|
|
|
16
16
|
(...args: T): MaybePromise<boolean>;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export interface Mapper<T extends unknown[], R> {
|
|
19
|
+
export interface Mapper<T extends unknown[], R = unknown> {
|
|
20
20
|
(...args: T): R;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export interface Reducer<T extends unknown[], R> {
|
|
23
|
+
export interface Reducer<T extends unknown[], R = unknown> {
|
|
24
24
|
(value: R, ...args: T): R;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export type Listeners<T extends unknown[], R> = Listener<T, R>[];
|
|
27
|
+
export type Listeners<T extends unknown[], R = unknown> = Listener<T, R>[];
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* An abstract class that extends the built-in Function class. It allows instances of the class
|
|
31
|
+
* to be called as functions. When an instance of FunctionExt is called as a function, it will
|
|
32
|
+
* call the function passed to its constructor with the same arguments.
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
export abstract class FunctionExt extends Function {
|
|
30
36
|
constructor(func: Function) {
|
|
31
37
|
super();
|
|
32
38
|
return Object.setPrototypeOf(func, new.target.prototype);
|
|
@@ -37,14 +43,20 @@ export interface Dismiss {
|
|
|
37
43
|
(): Promise<void> | void;
|
|
38
44
|
}
|
|
39
45
|
|
|
46
|
+
export interface Task {
|
|
47
|
+
(): MaybePromise<unknown>;
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
export class Dismiss extends FunctionExt {
|
|
41
|
-
constructor(
|
|
42
|
-
super(
|
|
51
|
+
constructor(callback: Unsubscribe) {
|
|
52
|
+
super(callback);
|
|
43
53
|
}
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
|
|
55
|
+
async after(task: Task) {
|
|
56
|
+
await task();
|
|
46
57
|
this();
|
|
47
58
|
}
|
|
59
|
+
|
|
48
60
|
afterTimes(count: number) {
|
|
49
61
|
return () => {
|
|
50
62
|
if (!--count) {
|
|
@@ -63,17 +75,39 @@ export interface Event<T extends unknown[], R> {
|
|
|
63
75
|
}
|
|
64
76
|
|
|
65
77
|
type UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;
|
|
78
|
+
|
|
66
79
|
type UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;
|
|
80
|
+
|
|
67
81
|
type UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];
|
|
82
|
+
|
|
68
83
|
type UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];
|
|
69
84
|
|
|
85
|
+
/**
|
|
86
|
+
* A class representing an anonymous event that can be listened to or triggered.
|
|
87
|
+
* @example
|
|
88
|
+
* // Create a click event.
|
|
89
|
+
* const clickEvent = new Event<[x: number, y: number], void>();
|
|
90
|
+
*
|
|
91
|
+
* @template T - The tuple of arguments that the event takes.
|
|
92
|
+
* @template R - The return type of the event.
|
|
93
|
+
*/
|
|
70
94
|
export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
95
|
+
/**
|
|
96
|
+
* Merges multiple events into a single event.
|
|
97
|
+
* @param events - The events to merge.
|
|
98
|
+
* @returns The merged event.
|
|
99
|
+
*/
|
|
71
100
|
static merge<Events extends Event<any[], any>[]>(...events: Events) {
|
|
72
101
|
const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();
|
|
73
102
|
events.forEach((event) => event.on(mergedEvent));
|
|
74
103
|
return mergedEvent;
|
|
75
104
|
}
|
|
76
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Creates an event that triggers at a specified interval.
|
|
108
|
+
* @param interval - The interval at which to trigger the event.
|
|
109
|
+
* @returns The interval event.
|
|
110
|
+
*/
|
|
77
111
|
static interval(interval: number) {
|
|
78
112
|
let counter = 0;
|
|
79
113
|
const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));
|
|
@@ -81,9 +115,20 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
81
115
|
return intervalEvent;
|
|
82
116
|
}
|
|
83
117
|
|
|
118
|
+
/**
|
|
119
|
+
* The array of listeners for the event.
|
|
120
|
+
*/
|
|
84
121
|
private listeners: Listeners<T, R>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* A function that disposes of the event and its listeners.
|
|
125
|
+
*/
|
|
85
126
|
readonly dispose: Dispose;
|
|
86
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Creates a new event.
|
|
130
|
+
* @param dispose - A function to dispose of the event and its listeners.
|
|
131
|
+
*/
|
|
87
132
|
constructor(dispose?: Dispose) {
|
|
88
133
|
const listeners: Listeners<T, R> = [];
|
|
89
134
|
const fn = (...args: T) => eventEmitter(listeners, ...args);
|
|
@@ -96,18 +141,35 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
96
141
|
};
|
|
97
142
|
}
|
|
98
143
|
|
|
144
|
+
/**
|
|
145
|
+
* The number of listeners for the event.
|
|
146
|
+
*/
|
|
99
147
|
get size(): number {
|
|
100
148
|
return this.listeners.length;
|
|
101
149
|
}
|
|
102
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Checks if a listener is not registered for the event.
|
|
153
|
+
* @param listener - The listener to check.
|
|
154
|
+
* @returns `true` if the listener is not registered, `false` otherwise.
|
|
155
|
+
*/
|
|
103
156
|
lacks(listener: Listener<T, R>): boolean {
|
|
104
157
|
return this.listeners.indexOf(listener) === -1;
|
|
105
158
|
}
|
|
106
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Checks if a listener is registered for the event.
|
|
162
|
+
* @param listener - The listener to check.
|
|
163
|
+
* @returns `true` if the listener is registered, `false` otherwise.
|
|
164
|
+
*/
|
|
107
165
|
has(listener: Listener<T, R>): boolean {
|
|
108
166
|
return this.listeners.indexOf(listener) !== -1;
|
|
109
167
|
}
|
|
110
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Removes a listener from the event.
|
|
171
|
+
* @param listener - The listener to remove.
|
|
172
|
+
*/
|
|
111
173
|
off(listener: Listener<T, R>): void {
|
|
112
174
|
let index = this.listeners.indexOf(listener);
|
|
113
175
|
while (~index) {
|
|
@@ -116,11 +178,21 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
116
178
|
}
|
|
117
179
|
}
|
|
118
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Adds a listener to the event.
|
|
183
|
+
* @param listener - The listener to add.
|
|
184
|
+
* @returns An object that can be used to remove the listener.
|
|
185
|
+
*/
|
|
119
186
|
on(listener: Listener<T, R>): Dismiss {
|
|
120
187
|
this.listeners.push(listener);
|
|
121
188
|
return new Dismiss(() => this.off(listener));
|
|
122
189
|
}
|
|
123
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Adds a listener to the event that will only be called once.
|
|
193
|
+
* @param listener - The listener to add.
|
|
194
|
+
* @returns An object that can be used to remove the listener.
|
|
195
|
+
*/
|
|
124
196
|
once(listener: Listener<T, R>): Dismiss {
|
|
125
197
|
const oneTimeListener = (...args: T) => {
|
|
126
198
|
this.off(oneTimeListener);
|
|
@@ -129,14 +201,26 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
129
201
|
return this.on(oneTimeListener);
|
|
130
202
|
}
|
|
131
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Removes all listeners from the event.
|
|
206
|
+
*/
|
|
132
207
|
clear() {
|
|
133
208
|
this.listeners.splice(0);
|
|
134
209
|
}
|
|
135
210
|
|
|
211
|
+
/**
|
|
212
|
+
* Converts the event to a promise that resolves with the event arguments.
|
|
213
|
+
* @returns A promise that resolves with the event arguments.
|
|
214
|
+
*/
|
|
136
215
|
toPromise(): Promise<T> {
|
|
137
216
|
return new Promise((resolve) => this.once((...args) => resolve(args)));
|
|
138
217
|
}
|
|
139
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Creates a new event that only triggers if the filter function returns `true`.
|
|
221
|
+
* @param filter - The filter function.
|
|
222
|
+
* @returns The filtered event.
|
|
223
|
+
*/
|
|
140
224
|
filter(filter: Filter<T>) {
|
|
141
225
|
const dispose = this.on(async (...args) => {
|
|
142
226
|
if (filteredEvent.size > 0 && (await filter(...args))) {
|
|
@@ -147,18 +231,45 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
147
231
|
return filteredEvent;
|
|
148
232
|
}
|
|
149
233
|
|
|
150
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Creates a new event that only triggers once if the filter function returns `true`.
|
|
236
|
+
* @param filter - The filter function.
|
|
237
|
+
* @returns The filtered event.
|
|
238
|
+
*/
|
|
239
|
+
first(filter: Filter<T>) {
|
|
240
|
+
const dispose = this.on(async (...args) => {
|
|
241
|
+
if (filteredEvent.size > 0 && (await filter(...args))) {
|
|
242
|
+
dispose();
|
|
243
|
+
await filteredEvent(...args);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
const filteredEvent = new Event<T, R>(dispose);
|
|
247
|
+
return filteredEvent;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Creates a new event that maps the event arguments to a new value.
|
|
252
|
+
* @param mapper - The mapper function.
|
|
253
|
+
* @returns The mapped event.
|
|
254
|
+
*/
|
|
255
|
+
map<M, MR = unknown>(mapper: Mapper<T, M>) {
|
|
151
256
|
const dispose = this.on(async (...args) => {
|
|
152
257
|
if (mappedEvent.size > 0) {
|
|
153
258
|
const value = await mapper(...args);
|
|
154
259
|
mappedEvent(value);
|
|
155
260
|
}
|
|
156
261
|
});
|
|
157
|
-
const mappedEvent = new Event(dispose);
|
|
262
|
+
const mappedEvent = new Event<[M], MR>(dispose);
|
|
158
263
|
return mappedEvent;
|
|
159
264
|
}
|
|
160
265
|
|
|
161
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Creates a new event that reduces the event arguments to a single value.
|
|
268
|
+
* @param reducer - The reducer function.
|
|
269
|
+
* @param init - The initial value for the reducer.
|
|
270
|
+
* @returns The reduced event.
|
|
271
|
+
*/
|
|
272
|
+
reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A) {
|
|
162
273
|
let value = init;
|
|
163
274
|
const dispose = this.on(async (...args) => {
|
|
164
275
|
if (reducedEvent.size > 0) {
|
|
@@ -166,15 +277,37 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
166
277
|
reducedEvent(value);
|
|
167
278
|
}
|
|
168
279
|
});
|
|
169
|
-
const reducedEvent = new Event(dispose);
|
|
280
|
+
const reducedEvent = new Event<[A], AR>(dispose);
|
|
170
281
|
return reducedEvent;
|
|
171
282
|
}
|
|
172
283
|
}
|
|
173
284
|
|
|
285
|
+
/**
|
|
286
|
+
* Returns a promise that resolves with the arguments passed to the first invocation of the given event.
|
|
287
|
+
* @param event The event to listen for.
|
|
288
|
+
* @returns A promise that resolves with the arguments passed to the first invocation of the given event.
|
|
289
|
+
*/
|
|
174
290
|
export const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {
|
|
175
291
|
return new Promise((resolve) => event.once((...args) => resolve(args)));
|
|
176
292
|
};
|
|
177
293
|
|
|
178
|
-
|
|
294
|
+
/**
|
|
295
|
+
* Creates a new instance of the Event class.
|
|
296
|
+
* @returns {Event<T, R>} A new instance of the Event class.
|
|
297
|
+
* @template T The type of the arguments passed to the event.
|
|
298
|
+
* @template R The return type of the event.
|
|
299
|
+
*/
|
|
300
|
+
export const createEvent = <T extends unknown[], R = void>(): Event<T, R> => {
|
|
179
301
|
return new Event<T, R>();
|
|
180
|
-
}
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
export default createEvent;
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* A type helper that extracts the event listener type
|
|
308
|
+
*
|
|
309
|
+
* @template E - The event object type.
|
|
310
|
+
* @template T - The event type extracted from the event object.
|
|
311
|
+
* @template R - The result type returned by the event handler function.
|
|
312
|
+
*/
|
|
313
|
+
export type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;
|