import { WebSocket } from "partysocket"; import * as React from "react"; export type BrevitySocketOptions = { maxReconnectionDelay?: number; minReconnectionDelay?: number; reconnectionDelayGrowFactor?: number; minUptime?: number; connectionTimeout?: number; maxRetries?: number; maxEnqueuedMessages?: number; startClosed?: boolean; debug?: boolean; }; type UseBrevitySocketOptions = BrevitySocketOptions & { appId: string; host?: string; tags?: string[]; onMessage: (event: WebSocketEventMap["message"]) => void; }; // A React hook that wraps PartySocket export function useBrevitySocket(options: UseBrevitySocketOptions) { const [tags, setTags] = React.useState(options.tags ?? []); const { onMessage, host = "realtime.devize.com", appId, ...brevitySocketOptions } = options; React.useEffect(() => { if (Array.isArray(options.tags) && options.tags.length) { setTags((previousTags) => { const unique = new Set([...previousTags, ...options.tags!]); return Array.from(unique).sort(); }); } }, [options.tags?.join(",")]); React.useEffect(() => { document.addEventListener("REGISTER_TAGS", (c: CustomEvent) => { const tags = c.detail; if (Array.isArray(tags) && tags.length) { setTags((previousTags) => { const unique = new Set([...previousTags, ...tags]); return Array.from(unique).sort(); }); } }); }, []); React.useEffect(() => { if (!tags || !tags?.length) { return; } const params = new URLSearchParams(); tags.forEach((tag) => params.append("tags", tag)); const ws = new WebSocket( `wss://${host}/api/v1/subscribe/${appId}?${params}`, undefined, brevitySocketOptions, ); const handleMessage = (e: MessageEvent) => { const data = JSON.parse(e.data); onMessage(data); document.dispatchEvent(new CustomEvent("REALTIME", { detail: data })); }; ws.addEventListener("message", handleMessage); return () => { ws.removeEventListener("message", handleMessage); ws.close(); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [appId, tags?.join(",")]); }