@irrelon/emitter 6.1.0 → 6.2.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/doc/index.html CHANGED
@@ -56,7 +56,7 @@
56
56
  <br class="clear">
57
57
 
58
58
  <footer>
59
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Tue Jan 22 2019 14:10:25 GMT+0000 (GMT)
59
+ Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.4</a> on Tue Sep 23 2025 16:47:15 GMT+0100 (Western European Summer Time)
60
60
  </footer>
61
61
 
62
62
  <script> prettyPrint(); </script>
@@ -1,12 +1,12 @@
1
1
  /*global document */
2
- (function() {
3
- var source = document.getElementsByClassName('prettyprint source linenums');
4
- var i = 0;
5
- var lineNumber = 0;
6
- var lineId;
7
- var lines;
8
- var totalLines;
9
- var anchorHash;
2
+ (() => {
3
+ const source = document.getElementsByClassName('prettyprint source linenums');
4
+ let i = 0;
5
+ let lineNumber = 0;
6
+ let lineId;
7
+ let lines;
8
+ let totalLines;
9
+ let anchorHash;
10
10
 
11
11
  if (source && source[0]) {
12
12
  anchorHash = document.location.hash.substring(1);
@@ -15,7 +15,7 @@
15
15
 
16
16
  for (; i < totalLines; i++) {
17
17
  lineNumber++;
18
- lineId = 'line' + lineNumber;
18
+ lineId = `line${lineNumber}`;
19
19
  lines[i].id = lineId;
20
20
  if (lineId === anchorHash) {
21
21
  lines[i].className += ' selected';
@@ -273,7 +273,7 @@ tr > th:last-child { border-right: 1px solid #ddd; }
273
273
  margin: 0;
274
274
  }
275
275
 
276
- .prettyprint
276
+ .source
277
277
  {
278
278
  border: 1px solid #ddd;
279
279
  width: 80%;
@@ -284,7 +284,7 @@ tr > th:last-child { border-right: 1px solid #ddd; }
284
284
  width: inherit;
285
285
  }
286
286
 
287
- .prettyprint code
287
+ .source code
288
288
  {
289
289
  font-size: 100%;
290
290
  line-height: 18px;
package/package.json CHANGED
@@ -1,59 +1,61 @@
1
1
  {
2
- "author": "Rob Evans - Irrelon Software Limited",
3
- "name": "@irrelon/emitter",
4
- "description": "Simple JavaScript event emitter with some powerful features.",
5
- "version": "6.1.0",
6
- "keywords": [
7
- "javascript",
8
- "browser",
9
- "node",
10
- "client-side",
11
- "server-side",
12
- "emitter",
13
- "events",
14
- "on",
15
- "off",
16
- "once",
17
- "listener"
18
- ],
19
- "devDependencies": {
20
- "@eslint/js": "^9.5.0",
21
- "@trivago/prettier-plugin-sort-imports": "^4.3.0",
22
- "@types/jest": "^29.5.12",
23
- "@types/node": "^18.7.23",
24
- "chokidar": "^3.5.3",
25
- "eslint": "^9.5.0",
26
- "globals": "^15.6.0",
27
- "jest": "^29.7.0",
28
- "minimatch": "^7.4.2",
29
- "prettier": "^3.3.2",
30
- "ts-jest": "^29.1.5",
31
- "typescript": "^5.5.2",
32
- "typescript-eslint": "^7.14.1"
33
- },
34
- "engines": {
35
- "node": "*"
36
- },
37
- "scripts": {
38
- "build": "tsc -p tsconfig-esm.json && tsc -p tsconfig-cjs.json && sh ./fixup.sh",
39
- "build-watch": "tsc --watch",
40
- "fixPaths": "npx @irrelon/fix-paths --write",
41
- "test": "NODE_OPTIONS=--experimental-vm-modules npx jest --testMatch \"**/*.test.(js|ts)\"",
42
- "test-watch": "NODE_OPTIONS=--experimental-vm-modules npx jest --testMatch \"**/*.test.(js|ts)\" --watchAll"
43
- },
44
- "repository": {
45
- "type": "git",
46
- "url": "git://github.com/irrelon/emitter.git"
47
- },
48
- "main": "dist/cjs/src/Emitter.js",
49
- "module": "dist/esm/src/Emitter.js",
50
- "exports": {
51
- ".": {
52
- "import": "./dist/esm/src/Emitter.js",
53
- "require": "./dist/cjs/src/Emitter.js"
54
- }
55
- },
56
- "bugs": {
57
- "url": "https://github.com/irrelon/emitter/issues"
58
- }
2
+ "author": "Rob Evans - Irrelon Software Limited",
3
+ "name": "@irrelon/emitter",
4
+ "description": "Simple JavaScript event emitter with some powerful features.",
5
+ "version": "6.2.0",
6
+ "keywords": [
7
+ "javascript",
8
+ "browser",
9
+ "node",
10
+ "client-side",
11
+ "server-side",
12
+ "emitter",
13
+ "events",
14
+ "on",
15
+ "off",
16
+ "once",
17
+ "listener"
18
+ ],
19
+ "devDependencies": {
20
+ "@eslint/js": "^9.36.0",
21
+ "@trivago/prettier-plugin-sort-imports": "^5.2.2",
22
+ "@types/jest": "^30.0.0",
23
+ "@types/node": "^24.5.2",
24
+ "chokidar": "^3.5.3",
25
+ "eslint": "^9.36.0",
26
+ "jest": "^30.1.3",
27
+ "minimatch": "^10.0.3",
28
+ "prettier": "^3.6.2",
29
+ "ts-jest": "^29.4.4",
30
+ "typescript": "^5.9.2",
31
+ "typescript-eslint": "^8.44.1"
32
+ },
33
+ "engines": {
34
+ "node": "*"
35
+ },
36
+ "scripts": {
37
+ "build": "tsc -p tsconfig-esm.json && tsc -p tsconfig-cjs.json && sh ./fixup.sh",
38
+ "build-watch": "tsc --watch",
39
+ "fixPaths": "npx @irrelon/fix-paths --write",
40
+ "test": "NODE_OPTIONS=--experimental-vm-modules npx jest --testMatch \"**/*.test.(js|ts)\"",
41
+ "test-watch": "NODE_OPTIONS=--experimental-vm-modules npx jest --testMatch \"**/*.test.(js|ts)\" --watchAll"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git://github.com/irrelon/emitter.git"
46
+ },
47
+ "main": "dist/cjs/src/Emitter.js",
48
+ "module": "dist/esm/src/Emitter.js",
49
+ "exports": {
50
+ ".": {
51
+ "import": "./dist/esm/src/Emitter.js",
52
+ "require": "./dist/cjs/src/Emitter.js"
53
+ }
54
+ },
55
+ "bugs": {
56
+ "url": "https://github.com/irrelon/emitter/issues"
57
+ },
58
+ "dependencies": {
59
+ "jsdoc": "^4.0.4"
60
+ }
59
61
  }
package/readme.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Irrelon Emitter
2
2
 
3
+ ### What Is It?
4
+ It's an event emitter that supports some very powerful and useful features.
5
+
6
+ ### Why Not Just Use window.dispatchEvent()?
7
+ This library is more flexible and operates in both Node.js and the browser with the same interface.
8
+ This is useful because it allows you to maintain the same code patterns on both the backend and frontend of your application.
9
+
10
+ This event emitter also supports many more features than the basic event system built into browsers.
11
+
3
12
  ## Usage
4
13
 
5
14
  ### JavaScript
@@ -43,7 +52,7 @@ interface MyEvents {
43
52
  // Pass your interface to the Emitter instantiation
44
53
  const emitter = new Emitter<MyEvents>();
45
54
 
46
- // This will show a typescript error because the
55
+ // This will show a typescript error because the
47
56
  // first argument of the event1 listener should be
48
57
  // a string, and the listener should return a number
49
58
  // instead of void.
@@ -0,0 +1,290 @@
1
+ export type AnyFunction<ReturnType = any> = (...args: any[]) => ReturnType;
2
+ export type AnyConstructor = new (...args: any[]) => any;
3
+ export declare enum ListenerReturnFlag {
4
+ none = "!+_NONE",
5
+ cancel = "!+_CANCEL"
6
+ }
7
+ export type EventListenerCallback<EventCallbackFunctionSignature extends AnyFunction = AnyFunction> = (...args: Parameters<EventCallbackFunctionSignature>) => ReturnType<EventCallbackFunctionSignature>;
8
+ export interface EventStaticEmitterObject<EventCallbackFunctionSignature extends AnyFunction = AnyFunction> {
9
+ id: string;
10
+ args: Parameters<EventCallbackFunctionSignature>;
11
+ }
12
+ export interface EmitterAnyEventsInterface {
13
+ [key: string]: AnyFunction;
14
+ }
15
+ export type EmitterEventsInterface<T> = {
16
+ [K in keyof T]: T[K];
17
+ };
18
+ export interface WithStar {
19
+ "*"?: (eventName: string, ...args: any[]) => void;
20
+ }
21
+ export type EmitterEventsWithStar<T> = EmitterEventsInterface<T> & WithStar;
22
+ /**
23
+ * Creates a new class with the ability to emit events.
24
+ */
25
+ export declare class Emitter<EventsInterface extends EmitterEventsWithStar<EventsInterface> = EmitterAnyEventsInterface> {
26
+ _eventsEmitting: boolean;
27
+ _eventRemovalQueue: any[];
28
+ _eventListeners?: {
29
+ [EventName in keyof EventsInterface]?: Record<string, EventListenerCallback<EventsInterface[EventName]>[]>;
30
+ };
31
+ _eventStaticEmitters: {
32
+ [EventName in keyof EventsInterface]?: EventStaticEmitterObject<EventsInterface[EventName]>[];
33
+ };
34
+ _eventsAllowDefer: boolean;
35
+ _eventsDeferTimeouts: Record<any, number>;
36
+ _dispatchWindowEventsEnabled: boolean;
37
+ _dispatchPrefix?: string;
38
+ constructor(dispatchPrefix?: string, shouldDispatchWindowEvents?: boolean);
39
+ dispatchWindowEventsEnabled(shouldDispatchWindowEvents: boolean): void;
40
+ /**
41
+ * Attach an event listener to the passed event only if the passed
42
+ * id matches the id for the event being fired.
43
+ * @param eventName The name of the event to listen for.
44
+ * @param id The id to match against.
45
+ * @param listener The method to call when the event is fired.
46
+ * @returns The emitter instance.
47
+ */
48
+ _on<EventName extends keyof EventsInterface>(eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>): this;
49
+ /**
50
+ * Attach an event listener to the passed event only if the passed
51
+ * id matches the document id for the event being fired.
52
+ * @param eventName The name of the event to listen for.
53
+ * @param id The id to match against.
54
+ * @param listener The method to call when the event is fired.
55
+ * @returns The emitter instance.
56
+ */
57
+ _once<EventName extends keyof EventsInterface>(eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>): this;
58
+ /**
59
+ * Cancels an event listener based on an event name, id and listener function.
60
+ * @param eventName The event to cancel listener for.
61
+ * @param id The ID of the event to cancel listening for.
62
+ * @param listener The event listener function used in the on()
63
+ * or once() call to cancel.
64
+ * @returns The emitter instance.
65
+ */
66
+ _off<EventName extends keyof EventsInterface>(eventName: EventName, id: string, listener?: EventListenerCallback<EventsInterface[EventName]>): this;
67
+ /**
68
+ * Creates an event listener that listens for any and all events
69
+ * emitted.
70
+ */
71
+ onAny(listener: EventListenerCallback): void;
72
+ /**
73
+ * Attach an event listener to the passed event only if the passed
74
+ * id matches the document id for the event being fired.
75
+ * @param eventName The name of the event to listen for.
76
+ * @param id The id to match against.
77
+ * @param listener The method to call when the event is fired.
78
+ * @returns The emitter instance.
79
+ */
80
+ on<EventName extends keyof EventsInterface>(eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>): this;
81
+ on<EventName extends keyof EventsInterface>(eventName: EventName, listener: EventListenerCallback<EventsInterface[EventName]>): this;
82
+ /**
83
+ * Attach an event listener to the passed event only if the passed
84
+ * id matches the document id for the event being fired.
85
+ * @param eventName The name of the event to listen for.
86
+ * @param id The id to match against.
87
+ * @param listener
88
+ * @returns The emitter instance.
89
+ */
90
+ once<EventName extends keyof EventsInterface>(eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>): this;
91
+ once<EventName extends keyof EventsInterface>(eventName: EventName, listener: EventListenerCallback<EventsInterface[EventName]>): this;
92
+ /**
93
+ * Overwrites any previous event listeners so that if the event fires, only
94
+ * the listener you pass will be called. If you pass an id along with the
95
+ * listener, only listeners for the id will be overwritten. This is similar
96
+ * to calling `.off(eventName)` then `on(eventName, listener)` since
97
+ * `off(eventName)` will cancel any previous event listeners for the passed
98
+ * event name.
99
+ * @param eventName The name of the event to listen for.
100
+ * @param id The id to match against.
101
+ * @param listener The method to call when the event is fired.
102
+ * @returns The emitter instance.
103
+ */
104
+ overwrite<EventName extends keyof EventsInterface>(eventName: EventName, id: string, listener: EventListenerCallback<EventsInterface[EventName]>): this;
105
+ overwrite<EventName extends keyof EventsInterface>(eventName: EventName, listener: EventListenerCallback<EventsInterface[EventName]>): this;
106
+ /**
107
+ * Removes an event listener that listens for any and all events
108
+ * emitted.
109
+ */
110
+ offAny(listener: EventListenerCallback): void;
111
+ /**
112
+ * Cancels an event listener based on an event name, id and listener function.
113
+ * @param eventName The event to cancel listener for.
114
+ * @param id The ID of the event to cancel listening for.
115
+ * @param listener The event listener function used in the on()
116
+ * or once() call to cancel.
117
+ * @returns The emitter instance.
118
+ */
119
+ off<EventName extends keyof EventsInterface>(eventName: EventName, id: string, listener?: EventListenerCallback<EventsInterface[EventName]>): this;
120
+ off<EventName extends keyof EventsInterface>(eventName: EventName, listener?: EventListenerCallback<EventsInterface[EventName]>): this;
121
+ off<EventName extends keyof EventsInterface>(eventName: EventName): this;
122
+ _emitToSingleListener<EventName extends keyof EventsInterface>(listener: EventListenerCallback<EventsInterface[EventName]>, data: Parameters<EventsInterface[EventName]>): ReturnType<EventsInterface[EventName]> | ListenerReturnFlag;
123
+ _emitToArrayOfListeners<EventName extends keyof EventsInterface>(arr: EventListenerCallback<EventsInterface[EventName]>[], data: Parameters<EventsInterface[EventName]>): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[];
124
+ /**
125
+ * Dispatches an event originating in our emitter to the browser's
126
+ * window object.
127
+ * @param eventName The name of the event to emit. This gets prefixed with the
128
+ * dispatch prefix if one is set.
129
+ * @param data
130
+ */
131
+ _emitToWindowDispatch<EventName extends keyof EventsInterface>(eventName: EventName, data: any): void;
132
+ /**
133
+ * Call an event listener by name. The `rpc()` function differs from `emit()` in
134
+ * that it will only call and return data from the first event listener for the
135
+ * event rather than all event listeners. If you have more than one event listener
136
+ * assigned to the event, all others except the first will be ignored and will
137
+ * not receive the event.
138
+ * @param eventName The name of the event to call the listener for.
139
+ * @param {...any} data The arguments to send to the listening method.
140
+ * If you are sending multiple arguments, separate them with a comma so
141
+ * that they are received by the function as separate arguments.
142
+ * @return {number}
143
+ * @example #Call the Event Listener
144
+ * // Emit the event named "hello"
145
+ * myEntity.emit('hello');
146
+ * @example #Call the Event Listener With Data Object
147
+ * // Emit the event named "hello"
148
+ * myEntity.emit('hello', {moo: true});
149
+ * @example #Call the Event Listener With Multiple Data Values
150
+ * // Emit the event named "hello"
151
+ * myEntity.emit('hello', {moo: true}, 'someString');
152
+ * @example #Register the Listener for Event Data
153
+ * // Set a listener to listen for the data (multiple values emitted
154
+ * // from an event are passed as function arguments)
155
+ * myEntity.on('hello', function (arg1, arg2) {
156
+ * console.log("Arguments:", arg1, arg2);
157
+ * return "foo";
158
+ * }
159
+ *
160
+ * // Emit the event named "hello"
161
+ * const result = myEntity.emit('hello', 'data1', 'data2');
162
+ * console.log("Result:", result);
163
+ *
164
+ * // The console output is:
165
+ * // Arguments: data1 data2
166
+ * // Result: "foo"
167
+ */
168
+ rpc<EventName extends keyof EventsInterface>(eventName: EventName, ...data: Parameters<EventsInterface[EventName]>): ReturnType<EventsInterface[EventName]> | ListenerReturnFlag;
169
+ rpcId<EventName extends keyof EventsInterface>(eventName: EventName, id: string, ...data: Parameters<EventsInterface[EventName]>): ReturnType<EventsInterface[EventName]> | ListenerReturnFlag;
170
+ /**
171
+ * Emit an event by name.
172
+ * @param eventName The name of the event to emit.
173
+ * @param {...any} data The arguments to send to any listening methods.
174
+ * If you are sending multiple arguments, separate them with a comma so
175
+ * that they are received by the function as separate arguments.
176
+ * @return {any[]} An array of all return values from all the listeners for the event.
177
+ * @example #Emit an Event
178
+ * // Emit the event named "hello"
179
+ * myEntity.emit('hello');
180
+ * @example #Emit an Event With Data Object
181
+ * // Emit the event named "hello"
182
+ * myEntity.emit('hello', {moo: true});
183
+ * @example #Emit an Event With Multiple Data Values
184
+ * // Emit the event named "hello"
185
+ * myEntity.emit('hello', {moo: true}, 'someString');
186
+ * @example #Listen for Event Data
187
+ * // Set a listener to listen for the data (multiple values emitted
188
+ * // from an event are passed as function arguments)
189
+ * myEntity.on('hello', function (arg1, arg2) {
190
+ * console.log("Arguments:", arg1, arg2);
191
+ * return "foo";
192
+ * }
193
+ *
194
+ * // Emit the event named "hello"
195
+ * // The result is returned as an array of all return values
196
+ * // from all the listeners for the event
197
+ * const result = myEntity.emit('hello', 'data1', 'data2');
198
+ * console.log("Result:", result);
199
+ *
200
+ * // The console output is:
201
+ * // Arguments: data1 data2
202
+ * // Result: ["foo"]
203
+ */
204
+ emit<EventName extends keyof EventsInterface>(eventName: EventName, ...data: Parameters<EventsInterface[EventName]>): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[];
205
+ /**
206
+ * Emits an event by name and id.
207
+ * @param eventName The name of the event to emit.
208
+ * @param id The id of the event to emit.
209
+ * @param {...any} data The arguments to send to any listening methods.
210
+ * If you are sending multiple arguments, separate them with a comma so
211
+ * that they are received by the function as separate arguments.
212
+ * @return {any[]} An array of all return values from all the listeners for the event.
213
+ */
214
+ emitId<EventName extends keyof EventsInterface>(eventName: EventName, id: string, ...data: Parameters<EventsInterface[EventName]>): (ReturnType<EventsInterface[EventName]> | ListenerReturnFlag)[];
215
+ /**
216
+ * Creates a persistent event. Once emitStatic() has been called, a
217
+ * persistent event is registered. Any existing event listeners will
218
+ * be called just like when you call emit(), however, any new
219
+ * listeners that are registered for this event via on() will also be
220
+ * called as soon as they are added.
221
+ * @param eventName The name of the event to emit.
222
+ * @param {...any} data Optional arguments to emit with the event.
223
+ * @returns The emitter instance.
224
+ * @private
225
+ */
226
+ emitStatic<EventName extends keyof EventsInterface>(eventName: EventName, ...data: Parameters<EventsInterface[EventName]>): this;
227
+ /**
228
+ * Creates a persistent emitter record that will fire a listener if
229
+ * one is added for this event after the emitStatic() call has been
230
+ * made.
231
+ * @param eventName The name of the event to emit.
232
+ * @param id The id of the event to emit.
233
+ * @param {...any} data Optional arguments to emit with the event.
234
+ * @returns The emitter instance.
235
+ * @private
236
+ */
237
+ emitStaticId<EventName extends keyof EventsInterface>(eventName: EventName, id: string, ...data: Parameters<EventsInterface[EventName]>): this;
238
+ /**
239
+ * Handles removing emitters, is an internal method not called directly.
240
+ * @param eventName The event to remove static emitter for.
241
+ * @returns The emitter instance.
242
+ * @private
243
+ */
244
+ cancelStatic<EventName extends keyof EventsInterface>(eventName: EventName): this;
245
+ /**
246
+ * Checks if an event has any event listeners or not.
247
+ * @param eventName The name of the event to check for.
248
+ * @returns True if one or more event listeners are registered for
249
+ * the event. False if none are found.
250
+ */
251
+ willEmit<EventName extends keyof EventsInterface>(eventName: EventName): boolean;
252
+ /**
253
+ * Checks if an event has any event listeners or not based on the passed id.
254
+ * @param eventName The name of the event to check for.
255
+ * @param id The event ID to check for.
256
+ * @returns True if one or more event listeners are registered for
257
+ * the event. False if none are found.
258
+ */
259
+ willEmitId<EventName extends keyof EventsInterface>(eventName: EventName, id: string): boolean;
260
+ /**
261
+ * Queues an event to be fired. This has automatic de-bouncing so that any
262
+ * events of the same type that occur within 100 milliseconds of a previous
263
+ * one will all be wrapped into a single emit rather than emitting tons of
264
+ * events for lots of chained inserts etc. Only the data from the last
265
+ * de-bounced event will be emitted.
266
+ * @param eventName The name of the event to emit.
267
+ * @param {...any} data Optional arguments to emit with the event.
268
+ * @returns The emitter instance.
269
+ */
270
+ deferEmit<EventName extends keyof EventsInterface>(eventName: EventName, ...data: Parameters<EventsInterface[EventName]>): this;
271
+ /**
272
+ * Returns true if the result from an emit() call passed as the first
273
+ * argument contains a cancellation flag.
274
+ * @param resultArr
275
+ */
276
+ didCancel(resultArr: (unknown | ListenerReturnFlag)[]): boolean;
277
+ /**
278
+ * If events are cleared with the off() method while the event emitter is
279
+ * actively processing any events then the off() calls get added to a
280
+ * queue to be executed after the event emitter is finished. This stops
281
+ * errors that might occur by potentially mutating the event listener array
282
+ * while the emitter is running through them. This method is called after
283
+ * the event emitter is finished processing.
284
+ * @private
285
+ */
286
+ _processRemovalQueue(): void;
287
+ }
288
+ export declare function makeEmitter<EventsInterface extends EmitterEventsWithStar<EventsInterface> = EmitterAnyEventsInterface>(obj: boolean): Emitter<EventsInterface>;
289
+ export declare function makeEmitter<EventsInterface extends EmitterEventsWithStar<EventsInterface> = EmitterAnyEventsInterface>(obj: Record<string, unknown>, prototypeMode: boolean): Emitter<EventsInterface>;
290
+ export declare function makeEmitter<EventsInterface extends EmitterEventsWithStar<EventsInterface> = EmitterAnyEventsInterface>(obj: AnyConstructor): Emitter<EventsInterface>;