import useSWRMutation from "swr/mutation"; import { useSWRConfig } from "swr"; import type { PreviewUrlResponse, RunStatusResponse, } from "@qltysh/fabro-api-client"; import { apiJsonMutation } from "./api-client"; import { queryKeys } from "./query-keys"; import type { LifecycleAction, LifecycleActionError } from "./run-actions"; import { archiveRun, cancelRun, isLifecycleActionError, unarchiveRun, } from "./run-actions"; export type PreviewRunArg = { port: number; expires_in_secs: number; }; export type PreviewMutationResult = { intent: "preview"; url: string; }; export type LifecycleMutationResult = | { intent: LifecycleAction; ok: true; run: RunStatusResponse; } | { intent: LifecycleAction; ok: false; error: LifecycleActionError | null; }; export function usePreviewRun(id: string | undefined) { return useSWRMutation( id ? queryKeys.runs.preview(id) : null, async (key: string, { arg }: { arg: PreviewRunArg }): Promise => { const result = await apiJsonMutation(key, { arg }); return { intent: "preview", url: result.url }; }, ); } export function useCancelRun(id: string | undefined) { return useLifecycleMutation(id, "cancel", cancelRun); } export function useArchiveRun(id: string | undefined) { return useLifecycleMutation(id, "archive", archiveRun); } export function useUnarchiveRun(id: string | undefined) { return useLifecycleMutation(id, "unarchive", unarchiveRun); } function useLifecycleMutation( id: string | undefined, intent: LifecycleAction, action: (id: string) => Promise, ) { const { mutate } = useSWRConfig(); const key = id ? queryKeys.runs[intent](id) : null; return useSWRMutation( key, async (): Promise => { if (!id) { return { intent, ok: false, error: null }; } try { return { intent, ok: true, run: await action(id) }; } catch (error) { return { intent, ok: false, error: isLifecycleActionError(error) ? error : null, }; } }, { onSuccess: (result) => { if (!id || !result.ok) return; void mutate(queryKeys.runs.detail(id)); void mutate(queryKeys.boards.runs()); void mutate(queryKeys.runs.billing(id)); }, }, ); } export function useToggleDemoMode() { const { mutate } = useSWRConfig(); return useSWRMutation( queryKeys.demo.toggle(), async (key: string, { arg }: { arg: { enabled: boolean } }) => { await apiJsonMutation(key, { arg }); }, { onSuccess: () => { void mutate(queryKeys.auth.me()); }, }, ); } export function useLoginDevToken() { return useSWRMutation( "/auth/login/dev-token", async (key: string, { arg }: { arg: { token: string } }) => { const response = await fetch(key, { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify(arg), }); if (!response.ok) { throw new Error(response.statusText || `HTTP ${response.status}`); } return response.json() as Promise<{ ok: boolean }>; }, ); }