diff --git a/src/flare.ts b/src/flare.ts index 2544646..845b571 100644 --- a/src/flare.ts +++ b/src/flare.ts @@ -7,14 +7,9 @@ import { FlareMiddleware, } from './types'; -type HandlerOptions = { - handler: FlareHandler; - options: FlareCatchOptions; -}; - export class Flare> { - private handlerOptions: { - [K in keyof E]?: Set>; + private handlerOptionsStore: { + [K in keyof E]?: Set>; } = {}; private interceptors: FlareInterceptor[] = []; @@ -41,32 +36,10 @@ export class Flare> { return Promise.resolve(`Event "${String(event)}" was stopped by middleware.`); } - const handlers = this.handlerOptions[event]; - if (!handlers) return Promise.resolve(`No handlers found for event "${String(event)}".`); + const handlerOptionsSet = this.handlerOptionsStore[event]; + if (!handlerOptionsSet) return Promise.resolve(`No handlers found for event "${String(event)}".`); - const { strategy = FlareFireStrategy.Parallel, timeout, haltOnError = false } = options; - - if (strategy === FlareFireStrategy.Parallel) { - await Promise.allSettled( - Array.from(handlers).map(async (handler) => { - try { - await this.execute(event, handler, newPayload, timeout); - } catch (err) { - // TODO: handle or log exception - if (haltOnError) throw err; - } - }) - ); - } else { - for (const handler of handlers) { - try { - await this.execute(event, handler, newPayload, timeout); - } catch (err) { - // TODO: handle or log exception - if (haltOnError) break; - } - } - } + await this.handleExecute(event, newPayload, options, handlerOptionsSet); this.handleAfterInterceptors(event, newPayload); } @@ -76,12 +49,12 @@ export class Flare> { handler: FlareHandler, options: FlareCatchOptions = {}, ): () => void { - if (!this.handlerOptions[event]) { - this.handlerOptions[event] = new Set(); + if (!this.handlerOptionsStore[event]) { + this.handlerOptionsStore[event] = new Set(); } - this.handlerOptions[event].add({ - handler: handler, + this.handlerOptionsStore[event].add({ + handler, options }) @@ -92,27 +65,26 @@ export class Flare> { event: K, handler: FlareHandler, ): void { - const handlers = this.handlerOptions[event]; - if (!handlers) return; + const handlerOptionsSet = this.handlerOptionsStore[event]; + if (!handlerOptionsSet) return; - for (const h of handlers) { - if (h.handler === handler) { - handlers.delete(h); + for (const handlerOptions of handlerOptionsSet) { + if (handlerOptions.handler === handler) { + handlerOptionsSet.delete(handlerOptions); break; } } } releaseAll(): void { - for (const event in this.handlerOptions) { - if (!Object.prototype.hasOwnProperty.call(this.handlerOptions, event)) continue; - const handlers = this.handlerOptions[event]; - handlers?.clear(); + for (const event in this.handlerOptionsStore) { + if (!Object.prototype.hasOwnProperty.call(this.handlerOptionsStore, event)) continue; + this.handlerOptionsStore[event]?.clear(); } - this.handlerOptions = {}; + this.handlerOptionsStore = {}; } - // ==================== internals ==================== + // ==================== handle methods ==================== private handleBeforeInterceptors(event: K, payload: E[K]) { for (const interceptor of this.interceptors) { @@ -162,11 +134,45 @@ export class Flare> { }; } + private async handleExecute( + event: K, + newPayload: E[K], + fireOptions: FlareFireOptions, + handlerOptionsSet: Set> + ) { + const { strategy = FlareFireStrategy.Parallel, timeout, haltOnError = false } = fireOptions; + + if (strategy === FlareFireStrategy.Parallel) { + await Promise.allSettled( + Array.from(handlerOptionsSet).map(async (handlerOptions) => { + try { + await this.execute(event, newPayload, timeout, handlerOptions); + } catch (err) { + // TODO: handle or log exception + if (haltOnError) throw err; + } + }) + ); + } else { + for (const handlerOptions of handlerOptionsSet) { + try { + await this.execute(event, newPayload, timeout, handlerOptions); + } catch (err) { + // TODO: handle or log exception + if (haltOnError) break; + } + } + } + } + + // ==================== internal methods ==================== + private async execute( event: K, - handlerOptions: HandlerOptions, payload: E[K], - timeout?: number): Promise { + timeout: number | undefined, + handlerOptions: HandlerOptionsPair + ): Promise { try { if (!timeout) return this.call(handlerOptions.handler, payload); @@ -174,7 +180,7 @@ export class Flare> { return Promise.race([this.call(handlerOptions.handler, payload), timeoutPromise]); } finally { if (handlerOptions.options.once) { - this.handlerOptions[event]?.delete(handlerOptions); + this.handlerOptionsStore[event]?.delete(handlerOptions); } } }; @@ -193,3 +199,8 @@ export class Flare> { } } } + +interface HandlerOptionsPair { + handler: FlareHandler; + options: FlareCatchOptions; +};