import type { KeyAsString } from 'type-fest'; import type ImmerChangeset from '../changeset/immer-changeset'; import type { Changeset } from '../types/changeset'; export type OnSetCallback< T extends Changeset, DTO extends Record, > = (key: KeyAsString, value: unknown, changeset: T) => void; interface EventMap> { set: Map>; } type MapValue< T extends ImmerChangeset, DTO extends Record, K extends KeyAsString>, > = EventMap[K] extends Map ? Callback : never; export default class ChangesetEventEmitter< T extends ImmerChangeset, DTO extends Record, > { private events: EventMap = { set: new Map(), }; public constructor(private changeset: T) {} public emitOnSet>(key: K, value: DTO[K]) { this.events['set'].forEach((callback) => callback(key, value, this.changeset), ); } on>>( event: K, callback: MapValue, ): Symbol { const uniqueId = Symbol(); this.events[event].set(uniqueId, callback as never); return uniqueId; } off>>( event: K, uniqueId: Symbol, ): void { this.events[event].delete(uniqueId); } }