This repository has been archived by the owner on Jan 28, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from elderapo/from-event-emitter
feat(*): fromEventEmitter
- Loading branch information
Showing
16 changed files
with
1,179 additions
and
680 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
src/examples/**/*.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { EventEmitter } from "events"; | ||
|
||
export type RemoveEventListener = () => void; | ||
export type EventHandler = (payload: any) => void; | ||
|
||
export enum InternalEventEmitterEvent { | ||
NewListener = "newListener", | ||
RemoveListener = "removeListener" | ||
} | ||
|
||
export type InternalEventEmitterEvents = { | ||
[InternalEventEmitterEvent.NewListener]: EventHandler; | ||
[InternalEventEmitterEvent.RemoveListener]: { event: any; listener: EventHandler }; | ||
}; | ||
|
||
export class TypedEventEmitter< | ||
T, | ||
Events extends InternalEventEmitterEvents & T = InternalEventEmitterEvents & T | ||
> { | ||
constructor(private internalEventEmitter: EventEmitter = new EventEmitter()) { | ||
this.interceptEmit(); | ||
} | ||
|
||
static fromEventEmitter<T>(eventEmitter: EventEmitter): TypedEventEmitter<T> { | ||
return new TypedEventEmitter<T>(eventEmitter); | ||
} | ||
|
||
public on<Event extends keyof Events>( | ||
event: Event, | ||
listener: (payload: Events[Event]) => void | ||
): RemoveEventListener { | ||
this.internalEventEmitter.on(this.castTypedEventToEvent(event), listener); | ||
return () => this.removeListener(event, listener); | ||
} | ||
|
||
public once<Event extends keyof Events>( | ||
event: Event, | ||
listener: (payload: Events[Event]) => void | ||
): RemoveEventListener { | ||
this.internalEventEmitter.once(this.castTypedEventToEvent(event), listener); | ||
return () => this.removeListener(event, listener); | ||
} | ||
|
||
public prependListener<Event extends keyof Events>( | ||
event: Event, | ||
listener: (payload: Events[Event]) => void | ||
): RemoveEventListener { | ||
this.internalEventEmitter.prependListener(this.castTypedEventToEvent(event), listener); | ||
return () => this.removeListener(event, listener); | ||
} | ||
|
||
public prependOnceListener<Event extends keyof Events>( | ||
event: Event, | ||
listener: (payload: Events[Event]) => void | ||
): RemoveEventListener { | ||
this.internalEventEmitter.prependOnceListener(this.castTypedEventToEvent(event), listener); | ||
return () => this.removeListener(event, listener); | ||
} | ||
|
||
public removeListener<Event extends keyof Events>( | ||
event: Event, | ||
listenerFunc: (payload: Events[Event]) => void | ||
): void { | ||
this.internalEventEmitter.removeListener(this.castTypedEventToEvent(event), listenerFunc); | ||
} | ||
|
||
public removeAllListeners<Event extends keyof Events>(event?: Event): void { | ||
if (typeof event === "undefined") { | ||
this.internalEventEmitter.removeAllListeners(); | ||
return; | ||
} | ||
|
||
this.internalEventEmitter.removeAllListeners(this.castTypedEventToEvent(event)); | ||
} | ||
|
||
public setMaxListeners(n: number): void { | ||
this.internalEventEmitter.setMaxListeners(n); | ||
} | ||
|
||
public getMaxListeners(): number { | ||
return this.internalEventEmitter.getMaxListeners(); | ||
} | ||
|
||
public listeners<Event extends keyof Events>(event: Event): EventHandler[] { | ||
return this.internalEventEmitter.listeners(this.castTypedEventToEvent(event)) as EventHandler[]; | ||
} | ||
|
||
public emit<Event extends keyof Events>(event: Event, payload: Events[Event]): void { | ||
this.internalEventEmitter.emit(this.castTypedEventToEvent(event), payload); | ||
} | ||
|
||
public eventIdentifiers(): Array<keyof Events> { | ||
return this.internalEventEmitter.eventNames().map(eventIndetifier => { | ||
if (typeof eventIndetifier === "symbol") { | ||
return eventIndetifier; | ||
} | ||
|
||
const n = parseFloat(eventIndetifier); | ||
|
||
return Number.isNaN(n) ? eventIndetifier : n; | ||
}) as Array<keyof Events>; | ||
} | ||
|
||
public listenerCount<Event extends keyof Events>(event: Event): number { | ||
return this.internalEventEmitter.listenerCount(this.castTypedEventToEvent(event)); | ||
} | ||
|
||
private castTypedEventToEvent<Event extends keyof Events>(event: Event): string | symbol { | ||
return event as string | symbol; | ||
} | ||
|
||
private interceptEmit() { | ||
let originalFunc: Function = this.internalEventEmitter.emit.bind(this.internalEventEmitter); | ||
|
||
this.internalEventEmitter.emit = (...args: any[]) => { | ||
if (args[0] === InternalEventEmitterEvent.RemoveListener) { | ||
return originalFunc(args[0], { | ||
event: args[1], | ||
listener: args[2] | ||
}); | ||
} | ||
return originalFunc(...args); | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { TypedEventEmitter } from "../TypedEventEmitter"; | ||
|
||
enum Event { | ||
SomeEvent0, | ||
SomeEvent1, | ||
SomeEvent_StringKey = "lalala" | ||
} | ||
|
||
type Events = { | ||
[Event.SomeEvent0]: string; | ||
[Event.SomeEvent1]: number; | ||
[Event.SomeEvent_StringKey]: { name: string; age: number }; | ||
}; | ||
|
||
const ee = new TypedEventEmitter<Events>(); | ||
|
||
const removeListener0 = ee.on(Event.SomeEvent0, payload => {}); // payload type === string | ||
const removeListener1 = ee.once(Event.SomeEvent1, payload => {}); // payload type === number | ||
const removeListener2 = ee.prependListener(Event.SomeEvent_StringKey, payload => {}); // payload type === { name: string; age: number } | ||
const removeListener3 = ee.prependOnceListener(Event.SomeEvent_StringKey, payload => {}); // payload type === { name: string; age: number } | ||
|
||
ee.emit(Event.SomeEvent0, "string"); // ok | ||
// ee.emit(Event.SomeEvent0, 1); // wrong type - TS error | ||
|
||
ee.emit(Event.SomeEvent1, 666); // ok | ||
// ee.emit(Event.SomeEvent1, "aaa"); // wrong type - TS error | ||
|
||
ee.emit(Event.SomeEvent_StringKey, { name: "Tomek", age: 123 }); // ok | ||
// ee.emit(Event.SomeEvent_StringKey, {}); // wrong type - TS error | ||
|
||
removeListener0(); // pretty self explanatory :) | ||
removeListener1(); | ||
removeListener2(); | ||
removeListener3(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { TypedEventEmitter } from "../TypedEventEmitter"; | ||
|
||
// Process extends from EventEmitter | ||
global.process.on("uncaughtException", ex => { | ||
console.log("Caught from eventEmitter", ex.message); | ||
}); | ||
|
||
enum ProcessEvent { | ||
UncaughtException = "uncaughtException" | ||
} | ||
|
||
type ProcessEvents = { | ||
[ProcessEvent.UncaughtException]: Error; | ||
}; | ||
|
||
const typedEventEmitter = TypedEventEmitter.fromEventEmitter<ProcessEvents>(global.process); | ||
|
||
typedEventEmitter.on(ProcessEvent.UncaughtException, ex => { | ||
console.log("Caught from typedEventEmitter", ex.message); // type ex === Error | ||
}); | ||
|
||
throw new Error("Hehuheuheueh"); |
Oops, something went wrong.