/* * Copyright 2025 coze-dev Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import EventEmitter from 'eventemitter3'; interface EventWithData { event: EventEmitter.EventNames; args: Parameters>>; } type ValidEventTypes = EventEmitter.ValidEventTypes; export class GlobalEventBus { private eventEmitter = new EventEmitter(); private started = true; private buffer: EventWithData[] = []; private static instances = new Map>(); static create(key: string): GlobalEventBus { if (GlobalEventBus.instances.has(key)) { return GlobalEventBus.instances.get(key) as unknown as GlobalEventBus; } const instance = new GlobalEventBus(); GlobalEventBus.instances.set( key, instance as unknown as GlobalEventBus, ); return instance; } /** * trigger event * @param event name * @param args parameter */ emit

>( event: P, ...args: Parameters> ) { if (!this.started) { this.buffer.push({ event, args, }); return; } this.eventEmitter.emit(event, ...args); } /** * subscribe to events * @param event name * @param fn event callback */ on

>( event: P, fn: EventEmitter.EventListener, ) { this.eventEmitter.on(event, fn); } /** * unsubscribe from the event * @param event name * @param fn event callback */ off

>( event: P, fn: EventEmitter.EventListener, ) { this.eventEmitter.off(event, fn); } /** * Turn on the cached event subscriber, and when turned on, the callbacks corresponding to the events received when closed will be fired one by one in sequence */ start() { this.started = true; for (const { event, args } of this.buffer) { this.emit(event, ...args); } } /** * Close the cached event subscriber. Events received during shutdown will be cached and delayed until the next time it is turned on */ stop() { this.started = false; } /** * Clears the cached events of the event subscriber so that the callback corresponding to the event received at stop is not triggered when starting again */ clear() { this.buffer = []; } }