-
Notifications
You must be signed in to change notification settings - Fork 0
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 #120 from ksv90/dev
feat: types changed
- Loading branch information
Showing
5 changed files
with
98 additions
and
84 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
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,54 @@ | ||
import { IEventNotifier, NotifierListener, NotifyOptions } from './types'; | ||
|
||
export class EventNotifier<TNotifierData extends object> implements IEventNotifier<TNotifierData> { | ||
readonly #listenerMap = new Map<keyof TNotifierData, Map<NotifierListener, NotifyOptions | undefined>>(); | ||
|
||
public emit<TName extends keyof TNotifierData>(name: TName, data: TNotifierData[TName]): void { | ||
this.#listenerMap.get(name)?.forEach((options, listener, map) => { | ||
if (options?.once) map.delete(listener); | ||
void listener(data); | ||
}); | ||
} | ||
|
||
public on<TName extends keyof TNotifierData>( | ||
name: TName, | ||
listener: NotifierListener<TNotifierData[TName]>, | ||
options?: NotifyOptions, | ||
): void { | ||
let listeners = this.#listenerMap.get(name); | ||
if (!listeners) { | ||
listeners = new Map<NotifierListener, NotifyOptions>(); | ||
this.#listenerMap.set(name, listeners); | ||
} | ||
listeners.set(listener, options); | ||
} | ||
|
||
public off<TName extends keyof TNotifierData>(name: TName, listener: NotifierListener<TNotifierData[TName]>): void { | ||
const listeners = this.#listenerMap.get(name); | ||
listeners?.delete(listener); | ||
} | ||
|
||
public once<TName extends keyof TNotifierData>( | ||
name: TName, | ||
listener: NotifierListener<TNotifierData[TName]>, | ||
options?: Omit<NotifyOptions, 'once'>, | ||
) { | ||
this.on(name, listener, { ...options, once: true }); | ||
} | ||
|
||
public hasListener<TName extends keyof TNotifierData>( | ||
name: TName, | ||
listener: NotifierListener<TNotifierData[TName]>, | ||
): boolean { | ||
const listeners = this.#listenerMap.get(name); | ||
return !!listeners && listeners.has(listener); | ||
} | ||
|
||
public deleteListeners<TName extends keyof TNotifierData>(name: TName): void { | ||
this.#listenerMap.delete(name); | ||
} | ||
|
||
public clearAll(): void { | ||
this.#listenerMap.clear(); | ||
} | ||
} |
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 |
---|---|---|
@@ -1,69 +1,2 @@ | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export type EventNotifierListener<TData = any> = (data: TData extends object ? TData : object) => void | Promise<void>; | ||
|
||
export type NotifyType<TType> = { type: TType }; | ||
|
||
export type NotifyListenerOptions = { | ||
readonly once?: boolean; | ||
}; | ||
|
||
export class EventNotifier<TEventNotifierData extends Record<string, object | undefined>> { | ||
protected listenerMap = new Map< | ||
keyof TEventNotifierData, | ||
Map<EventNotifierListener, NotifyListenerOptions | undefined> | ||
>(); | ||
|
||
public emit<TType extends keyof TEventNotifierData>( | ||
event: TEventNotifierData[TType] extends object ? NotifyType<TType> & TEventNotifierData[TType] : NotifyType<TType>, | ||
): void { | ||
const { type, ...data } = event; | ||
this.listenerMap.get(type)?.forEach((options, listener, map) => { | ||
if (options?.once) map.delete(listener); | ||
void listener(data); | ||
}); | ||
} | ||
|
||
public on<TType extends keyof TEventNotifierData>( | ||
type: TType, | ||
listener: EventNotifierListener<TEventNotifierData[TType]>, | ||
options?: NotifyListenerOptions, | ||
): void { | ||
const listeners = this.listenerMap.get(type) ?? new Map<EventNotifierListener, NotifyListenerOptions>(); | ||
listeners.set(listener, options); | ||
this.listenerMap.set(type, listeners); | ||
} | ||
|
||
public off<TType extends keyof TEventNotifierData>( | ||
type: TType, | ||
listener: EventNotifierListener<TEventNotifierData[TType]>, | ||
): void { | ||
this.listenerMap.get(type)?.forEach((_, currentListener, map) => { | ||
if (currentListener !== listener) return; | ||
map.delete(listener); | ||
}); | ||
} | ||
|
||
public once<TType extends keyof TEventNotifierData>( | ||
type: TType, | ||
listener: EventNotifierListener<TEventNotifierData[TType]>, | ||
options?: Omit<NotifyListenerOptions, 'once'>, | ||
) { | ||
this.on(type, listener, { ...options, once: true }); | ||
} | ||
|
||
public has<TType extends keyof TEventNotifierData>( | ||
type: TType, | ||
listener: EventNotifierListener<TEventNotifierData[TType]>, | ||
): boolean { | ||
const listeners = this.listenerMap.get(type); | ||
return !!listeners && listeners.has(listener); | ||
} | ||
|
||
public delete<TType extends keyof TEventNotifierData>(type: TType): void { | ||
this.listenerMap.delete(type); | ||
} | ||
|
||
public clear(): void { | ||
this.listenerMap.clear(); | ||
} | ||
} | ||
export * from './eventNotifier'; | ||
export * from './types'; |
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,12 @@ | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export type NotifierListener<TData = any> = (data: TData) => void | Promise<void>; | ||
|
||
export type NotifyOptions = { | ||
readonly once?: boolean; | ||
}; | ||
|
||
export interface IEventNotifier<TNotifierData extends object> { | ||
on<TName extends keyof TNotifierData>(name: TName, listener: NotifierListener<TNotifierData[TName]>): void; | ||
once<TName extends keyof TNotifierData>(name: TName, listener: NotifierListener<TNotifierData[TName]>): void; | ||
off<TName extends keyof TNotifierData>(name: TName, listener: NotifierListener<TNotifierData[TName]>): void; | ||
} |