42 lines · 1.7 KB
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect, useRef } from "react";
import { getPullMergeFix } from "~/fns/mergefix";
import type { QueryClient } from "@tanstack/react-query";

export type MergeFix = Awaited<ReturnType<typeof getPullMergeFix>>;
export type PullParams = { owner: string; repo: string; number: number };

const POLL_MS = 4000;
export const MERGE_FIX_ACTIVE = new Set(["queued", "running", "applying"]);

export const mergeFixQueryKey = ({ owner, repo, number }: PullParams) => ["merge-fix", owner, repo, number] as const;

export async function refreshMergeFix(queryClient: QueryClient, params: PullParams): Promise<void> {
  await queryClient.invalidateQueries({ queryKey: mergeFixQueryKey(params) });
}

/** Seeds from the route loader, polls while a run is active and reports once it settles. */
export function useMergeFix(params: PullParams, initial: MergeFix, onSettled: (fix: MergeFix) => void) {
  const queryClient = useQueryClient();
  const query = useQuery({
    queryKey: mergeFixQueryKey(params),
    queryFn: () => getPullMergeFix({ data: params }),
    initialData: initial,
    refetchInterval: (state) => {
      const fix = state.state.data;
      return fix && MERGE_FIX_ACTIVE.has(fix.status) ? POLL_MS : false;
    },
  });
  const fix = query.data;
  const active = fix !== null && MERGE_FIX_ACTIVE.has(fix.status);
  const wasActive = useRef(active);
  const latestOnSettled = useRef(onSettled);
  latestOnSettled.current = onSettled;
  useEffect(() => {
    if (wasActive.current && !active) latestOnSettled.current(fix);
    wasActive.current = active;
  }, [active, fix]);

  return { fix, refresh: () => refreshMergeFix(queryClient, params) };