(
event: EventType,
args: Partial<AnyEventArgs<T>>,
meta?: EntityMetadata<T>,
)
| 54 | meta?: EntityMetadata<T>, |
| 55 | ): Promise<unknown>; |
| 56 | dispatchEvent<T extends object>( |
| 57 | event: EventType, |
| 58 | args: Partial<AnyEventArgs<T>>, |
| 59 | meta?: EntityMetadata<T>, |
| 60 | ): Promise<unknown> | unknown { |
| 61 | const listeners: AsyncFunction[] = []; |
| 62 | const entity = (args as EventArgs<T>).entity; |
| 63 | |
| 64 | // execute lifecycle hooks first |
| 65 | meta ??= (entity as AnyEntity)?.__meta; |
| 66 | const hooks = (meta?.hooks[event] || []) as AsyncFunction[]; |
| 67 | listeners.push( |
| 68 | ...hooks.map(hook => { |
| 69 | const prototypeHook = meta?.prototype[hook as unknown as EntityKey<T>]; |
| 70 | const handler = typeof hook === 'function' ? hook : (entity[hook] ?? (prototypeHook as AsyncFunction)); |
| 71 | return handler.bind(entity); |
| 72 | }), |
| 73 | ); |
| 74 | |
| 75 | for (const listener of this.#listeners[event] ?? new Set()) { |
| 76 | const entities = this.#entities.get(listener)!; |
| 77 | |
| 78 | if (entities.size === 0 || !entity || entities.has(entity.constructor.name)) { |
| 79 | listeners.push(listener[event]!.bind(listener) as AsyncFunction); |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | if (event === EventType.onInit) { |
| 84 | for (const listener of listeners) { |
| 85 | void listener(args); |
| 86 | } |
| 87 | |
| 88 | return; |
| 89 | } |
| 90 | |
| 91 | return Utils.runSerial(listeners, listener => listener(args)); |
| 92 | } |
| 93 | |
| 94 | /** Checks whether there are any listeners (hooks or subscribers) for the given event type and entity. */ |
| 95 | hasListeners<T>(event: EventType, meta: EntityMetadata<T>): boolean { |
no test coverage detected