'use client'; import { FirestorePermissionError } from '@/firebase/errors'; /** * Defines the shape of all possible events and their corresponding payload types. * This centralizes event definitions for type safety across the application. */ export interface AppEvents { 'permission-error': FirestorePermissionError; } // A generic type for a callback function. type Callback = (data: T) => void; /** * A strongly-typed pub/sub event emitter. * It uses a generic type T that extends a record of event names to payload types. */ function createEventEmitter>() { // The events object stores arrays of callbacks, keyed by event name. // The types ensure that a callback for a specific event matches its payload type. const events: { [K in keyof T]?: Array> } = {}; return { /** * Subscribe to an event. * @param eventName The name of the event to subscribe to. * @param callback The function to call when the event is emitted. */ on(eventName: K, callback: Callback) { if (!events[eventName]) { events[eventName] = []; } events[eventName]?.push(callback); }, /** * Unsubscribe from an event. * @param eventName The name of the event to unsubscribe from. * @param callback The specific callback to remove. */ off(eventName: K, callback: Callback) { if (!events[eventName]) { return; } events[eventName] = events[eventName]?.filter(cb => cb !== callback); }, /** * Publish an event to all subscribers. * @param eventName The name of the event to emit. * @param data The data payload that corresponds to the event's type. */ emit(eventName: K, data: T[K]) { if (!events[eventName]) { return; } events[eventName]?.forEach(callback => callback(data)); }, }; } // Create and export a singleton instance of the emitter, typed with our AppEvents interface. export const errorEmitter = createEventEmitter();