fabro/apps/fabro-web/app/lib/board-events.ts
Bryan Helmkamp d4104be841
refactor(web): simplify SWR event plumbing
Share SSE subscription management, reuse query key builders, and remove duplicate route mapping/error helpers from the SWR refactor.
2026-04-25 07:37:17 -04:00

65 lines
1.6 KiB
TypeScript

import { useEffect } from "react";
import { useSWRConfig } from "swr";
import { queryKeys } from "./query-keys";
import {
createBrowserEventSource,
subscribeToSharedEventSource,
type EventPayload,
type EventSourceLike,
type MutateFn,
type SharedEventSubscription,
} from "./sse";
const BOARD_STATUS_EVENTS = new Set([
"run.submitted",
"run.queued",
"run.starting",
"run.running",
"run.removing",
"run.paused",
"run.unpaused",
"run.blocked",
"run.unblocked",
"run.completed",
"run.failed",
"run.archived",
"run.unarchived",
"interview.started",
"interview.completed",
"interview.timeout",
"interview.interrupted",
]);
const subscriptions = new Map<string, SharedEventSubscription>();
const BOARD_SUBSCRIPTION_KEY = "board";
export function shouldRefreshBoardForEvent(event: string) {
return BOARD_STATUS_EVENTS.has(event);
}
export function subscribeToBoardEvents(
mutate: MutateFn,
eventSourceFactory: (url: string) => EventSourceLike = createBrowserEventSource,
{ debounceMs = 500 }: { debounceMs?: number } = {},
): () => void {
return subscribeToSharedEventSource<EventPayload>({
subscriptions,
subscriptionKey: BOARD_SUBSCRIPTION_KEY,
url: queryKeys.system.attach(),
mutate,
eventSourceFactory,
debounceMs,
resolveInvalidation: (payload) => ({
keys: payload.event && shouldRefreshBoardForEvent(payload.event)
? [queryKeys.boards.runs()]
: [],
}),
});
}
export function useBoardEvents() {
const { mutate } = useSWRConfig();
useEffect(() => subscribeToBoardEvents(mutate as MutateFn), [mutate]);
}