import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental"; import type { QueryClient } from "@tanstack/react-query"; /** Prefix for same-origin BroadcastChannel names (suffixed with authenticated user id). */ export const QUERY_BROADCAST_CHANNEL_PREFIX = "seahaven-admin-query"; let unsubscribe: (() => void) | null = null; let activeUserId: string | number | null = null; /** Builds the account-scoped channel name for cross-tab QueryClient sync. */ export function queryBroadcastChannelForUser(userId: string | number): string { return `${QUERY_BROADCAST_CHANNEL_PREFIX}:${String(userId)}`; } function disposeBroadcast(): void { unsubscribe?.(); unsubscribe = null; activeUserId = null; } function canUseBroadcast(): boolean { return typeof window !== "undefined" && import.meta.env.MODE !== "test"; } /** * Starts (or switches) account-scoped QueryClient broadcast. * Disposes any prior subscription; clears the cache when the authenticated user changes. * No-op for the BroadcastChannel outside the browser and during Vitest runs. */ export function startQueryBroadcast(queryClient: QueryClient, userId: string | number): void { if (activeUserId === userId) { return; } const previousUserId = activeUserId; disposeBroadcast(); if (previousUserId != null && previousUserId !== userId) { queryClient.clear(); } activeUserId = userId; if (!canUseBroadcast()) { return; } unsubscribe = broadcastQueryClient({ queryClient, broadcastChannel: queryBroadcastChannelForUser(userId), }); } /** * Tears down the broadcaster and clears the entire QueryClient cache (logout / 401). */ export function stopQueryBroadcast(queryClient: QueryClient): void { disposeBroadcast(); queryClient.clear(); }