import Echo, { type BroadcastDriver, type EchoOptions } from "laravel-echo"; import Pusher from "pusher-js"; import type { ConfigDefaults } from "../types"; let echoInstance: Echo | null = null; let echoConfig: EchoOptions | null = null; const getEchoInstance = (): Echo => { if (echoInstance) { return echoInstance as Echo; } if (!echoConfig) { throw new Error( "Echo has not been configured. Please call `configureEcho()`.", ); } echoConfig.Pusher ??= Pusher; echoInstance = new Echo(echoConfig); return echoInstance as Echo; }; /** * Configure the Echo instance with sensible defaults. * * @link https://laravel.com/docs/broadcasting#client-side-installation */ export const configureEcho = ( config: EchoOptions, ): void => { const defaults: ConfigDefaults = { reverb: { broadcaster: "reverb", key: import.meta.env.VITE_REVERB_APP_KEY, wsHost: import.meta.env.VITE_REVERB_HOST, wsPort: import.meta.env.VITE_REVERB_PORT, wssPort: import.meta.env.VITE_REVERB_PORT, forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? "https") === "https", enabledTransports: ["ws", "wss"], }, pusher: { broadcaster: "pusher", key: import.meta.env.VITE_PUSHER_APP_KEY, cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER, forceTLS: true, wsHost: import.meta.env.VITE_PUSHER_HOST, wsPort: import.meta.env.VITE_PUSHER_PORT, wssPort: import.meta.env.VITE_PUSHER_PORT, enabledTransports: ["ws", "wss"], }, "socket.io": { broadcaster: "socket.io", host: import.meta.env.VITE_SOCKET_IO_HOST, }, null: { broadcaster: "null", }, ably: { broadcaster: "pusher", key: import.meta.env.VITE_ABLY_PUBLIC_KEY, wsHost: "realtime-pusher.ably.io", wsPort: 443, disableStats: true, encrypted: true, }, }; echoConfig = { ...defaults[config.broadcaster], ...config, } as EchoOptions; // Reset the instance if it was already created if (echoInstance) { echoInstance = null; } }; export const echo = (): Echo => getEchoInstance(); export const echoIsConfigured = () => echoConfig !== null;