import { EventMap, Listener } from 'strict-event-emitter' import { Interceptor, ExtractEventNames } from './Interceptor' export interface BatchInterceptorOptions< InterceptorList extends ReadonlyArray> > { name: string interceptors: InterceptorList } export type ExtractEventMapType< InterceptorList extends ReadonlyArray> > = InterceptorList extends ReadonlyArray ? InterceptorType extends Interceptor ? EventMap : never : never /** * A batch interceptor that exposes a single interface * to apply and operate with multiple interceptors at once. */ export class BatchInterceptor< InterceptorList extends ReadonlyArray>, Events extends EventMap = ExtractEventMapType > extends Interceptor { static symbol: symbol private interceptors: InterceptorList constructor(options: BatchInterceptorOptions) { BatchInterceptor.symbol = Symbol(options.name) super(BatchInterceptor.symbol) this.interceptors = options.interceptors } protected setup() { const logger = this.logger.extend('setup') logger.info('applying all %d interceptors...', this.interceptors.length) for (const interceptor of this.interceptors) { logger.info('applying "%s" interceptor...', interceptor.constructor.name) interceptor.apply() logger.info('adding interceptor dispose subscription') this.subscriptions.push(() => interceptor.dispose()) } } public on>( event: EventName, listener: Listener ): this { // Instead of adding a listener to the batch interceptor, // propagate the listener to each of the individual interceptors. for (const interceptor of this.interceptors) { interceptor.on(event, listener) } return this } public once>( event: EventName, listener: Listener ): this { for (const interceptor of this.interceptors) { interceptor.once(event, listener) } return this } public off>( event: EventName, listener: Listener ): this { for (const interceptor of this.interceptors) { interceptor.off(event, listener) } return this } public removeAllListeners>( event?: EventName | undefined ): this { for (const interceptors of this.interceptors) { interceptors.removeAllListeners(event) } return this } }