import { MutMapEx } from "./map" import { TupleTail } from "./types" /** Type safe event */ export class TEvent { #fns = new Set<(...args: A) => void>() #onces = new Set<(...args: A) => void>() /** Emit the event */ emit(...args: A) { for (const fn of this.#fns) { new Promise(res => { fn(...args) res() }) } for (const once of this.#onces) { this.#fns.delete(once) } this.#onces.clear() } /** Register event */ on(f: (...args: A) => void) { this.#fns.add(f) } /** Register event and only trigger once*/ once(f: (...args: A) => void) { this.#fns.add(f) this.#onces.add(f) } /** Unregister */ off(f: (...args: A) => void) { this.#fns.delete(f) this.#onces.delete(f) } } /** Event pool */ export class PEvents { #regs = MutMapEx(new Map>()) /** Emit the event */ emit(name: N, ...args: A): void /** Emit the event */ emit(name: T[0], ...args: TupleTail): void /** Emit the event */ emit(name: T['name'], ...args: T['args']): void emit(name: string, ...args: unknown[]) { this.#regs.get(name)?.emit(...args) } /** Register event */ on(name: N, fn: (...args: A) => unknown): void /** Register event */ on(name: T[0], fn: (...args: TupleTail) => unknown): void /** Register event */ on(name: T['name'], fn: (...args: T['args']) => unknown): void on(name: string, f: (...args: unknown[]) => unknown) { const e = this.#regs.getOrAdd(name, () => new TEvent) e.on(f) } /** Register event and only trigger once*/ once(name: N, fn: (...args: A) => unknown): void /** Register event and only trigger once*/ once(name: T[0], fn: (...args: TupleTail) => unknown): void /** Register event and only trigger once*/ once(name: T['name'], fn: (...args: T['args']) => unknown): void once(name: string, f: (...args: unknown[]) => unknown) { const e = this.#regs.getOrAdd(name, () => new TEvent) e.once(f) } /** Unregister */ off(name: N, fn: (...args: A) => unknown): void /** Unregister */ off(name: T[0], fn: (...args: TupleTail) => unknown): void /** Unregister */ off(name: T['name'], fn: (...args: T['args']) => unknown): void off(name: string, f: (...args: unknown[]) => unknown) { this.#regs.get(name)?.off(f) } }