@firesystem/core
Version:
Virtual File System core interfaces and types
110 lines (91 loc) • 2.66 kB
text/typescript
import type { Disposable } from "../types/Common";
import type {
IEventEmitter,
ITypedEventEmitter,
} from "../interfaces/IEventEmitter";
/**
* Simple event emitter implementation that file systems can use
* Implementations are free to use their own event system
*/
export class EventEmitter implements IEventEmitter {
private events = new Map<string | symbol, Set<Function>>();
on(event: string | symbol, handler: (...args: any[]) => void): Disposable {
if (!this.events.has(event)) {
this.events.set(event, new Set());
}
this.events.get(event)!.add(handler);
return {
dispose: () => this.off(event, handler),
};
}
once(event: string | symbol, handler: (...args: any[]) => void): Disposable {
const wrappedHandler = (...args: any[]) => {
handler(...args);
this.off(event, wrappedHandler);
};
return this.on(event, wrappedHandler);
}
emit(event: string | symbol, ...args: any[]): boolean {
const handlers = this.events.get(event);
if (!handlers || handlers.size === 0) {
return false;
}
handlers.forEach((handler) => {
try {
handler(...args);
} catch (error) {
console.error(`Error in event handler for ${String(event)}:`, error);
}
});
return true;
}
off(event: string | symbol, handler?: (...args: any[]) => void): void {
if (!handler) {
this.events.delete(event);
return;
}
const handlers = this.events.get(event);
if (handlers) {
handlers.delete(handler);
if (handlers.size === 0) {
this.events.delete(event);
}
}
}
removeAllListeners(event?: string | symbol): void {
if (event) {
this.events.delete(event);
} else {
this.events.clear();
}
}
}
/**
* Typed event emitter implementation
*/
export class TypedEventEmitter<T extends Record<string, any>>
implements ITypedEventEmitter<T>
{
private emitter = new EventEmitter();
on<K extends keyof T>(
event: K,
handler: (payload: T[K]) => void,
): Disposable {
return this.emitter.on(event as string, handler);
}
once<K extends keyof T>(
event: K,
handler: (payload: T[K]) => void,
): Disposable {
return this.emitter.once(event as string, handler);
}
emit<K extends keyof T>(event: K, payload: T[K]): boolean {
return this.emitter.emit(event as string, payload);
}
off<K extends keyof T>(event: K, handler?: (payload: T[K]) => void): void {
this.emitter.off(event as string, handler);
}
removeAllListeners<K extends keyof T>(event?: K): void {
this.emitter.removeAllListeners(event as string);
}
}