170 lines · 5.4 KB · TypeScript
RawDownload
import type { GitStackedAction } from "@t3tools/contracts";import { mutationOptions, queryOptions, type QueryClient } from "@tanstack/react-query";import { ensureNativeApi } from "../nativeApi"; const GIT_STATUS_STALE_TIME_MS = 5_000;const GIT_STATUS_REFETCH_INTERVAL_MS = 15_000;const GIT_BRANCHES_STALE_TIME_MS = 15_000;const GIT_BRANCHES_REFETCH_INTERVAL_MS = 60_000; export const gitQueryKeys = {  all: ["git"] as const,  status: (cwd: string | null) => ["git", "status", cwd] as const,  branches: (cwd: string | null) => ["git", "branches", cwd] as const,}; export const gitMutationKeys = {  init: (cwd: string | null) => ["git", "mutation", "init", cwd] as const,  checkout: (cwd: string | null) => ["git", "mutation", "checkout", cwd] as const,  runStackedAction: (cwd: string | null) => ["git", "mutation", "run-stacked-action", cwd] as const,  pull: (cwd: string | null) => ["git", "mutation", "pull", cwd] as const,}; export function invalidateGitQueries(queryClient: QueryClient) {  return queryClient.invalidateQueries({ queryKey: gitQueryKeys.all });} export function gitStatusQueryOptions(cwd: string | null) {  return queryOptions({    queryKey: gitQueryKeys.status(cwd),    queryFn: async () => {      const api = ensureNativeApi();      if (!cwd) throw new Error("Git status is unavailable.");      return api.git.status({ cwd });    },    enabled: cwd !== null,    staleTime: GIT_STATUS_STALE_TIME_MS,    refetchOnWindowFocus: "always",    refetchOnReconnect: "always",    refetchInterval: GIT_STATUS_REFETCH_INTERVAL_MS,  });} export function gitBranchesQueryOptions(cwd: string | null) {  return queryOptions({    queryKey: gitQueryKeys.branches(cwd),    queryFn: async () => {      const api = ensureNativeApi();      if (!cwd) throw new Error("Git branches are unavailable.");      return api.git.listBranches({ cwd });    },    enabled: cwd !== null,    staleTime: GIT_BRANCHES_STALE_TIME_MS,    refetchOnWindowFocus: true,    refetchOnReconnect: true,    refetchInterval: GIT_BRANCHES_REFETCH_INTERVAL_MS,  });} export function gitInitMutationOptions(input: { cwd: string | null; queryClient: QueryClient }) {  return mutationOptions({    mutationKey: gitMutationKeys.init(input.cwd),    mutationFn: async () => {      const api = ensureNativeApi();      if (!input.cwd) throw new Error("Git init is unavailable.");      return api.git.init({ cwd: input.cwd });    },    onSuccess: async () => {      await invalidateGitQueries(input.queryClient);    },  });} export function gitCheckoutMutationOptions(input: {  cwd: string | null;  queryClient: QueryClient;}) {  return mutationOptions({    mutationKey: gitMutationKeys.checkout(input.cwd),    mutationFn: async (branch: string) => {      const api = ensureNativeApi();      if (!input.cwd) throw new Error("Git checkout is unavailable.");      return api.git.checkout({ cwd: input.cwd, branch });    },    onSuccess: async () => {      await invalidateGitQueries(input.queryClient);    },  });} export function gitRunStackedActionMutationOptions(input: {  cwd: string | null;  queryClient: QueryClient;}) {  return mutationOptions({    mutationKey: gitMutationKeys.runStackedAction(input.cwd),    mutationFn: async ({      action,      commitMessage,      featureBranch,    }: {      action: GitStackedAction;      commitMessage?: string;      featureBranch?: boolean;    }) => {      const api = ensureNativeApi();      if (!input.cwd) throw new Error("Git action is unavailable.");      return api.git.runStackedAction({        cwd: input.cwd,        action,        ...(commitMessage ? { commitMessage } : {}),        ...(featureBranch ? { featureBranch } : {}),      });    },    onSettled: async () => {      await invalidateGitQueries(input.queryClient);    },  });} export function gitPullMutationOptions(input: { cwd: string | null; queryClient: QueryClient }) {  return mutationOptions({    mutationKey: gitMutationKeys.pull(input.cwd),    mutationFn: async () => {      const api = ensureNativeApi();      if (!input.cwd) throw new Error("Git pull is unavailable.");      return api.git.pull({ cwd: input.cwd });    },    onSettled: async () => {      await invalidateGitQueries(input.queryClient);    },  });} export function gitCreateWorktreeMutationOptions(input: { queryClient: QueryClient }) {  return mutationOptions({    mutationFn: async ({      cwd,      branch,      newBranch,      path,    }: {      cwd: string;      branch: string;      newBranch: string;      path?: string | null;    }) => {      const api = ensureNativeApi();      if (!cwd) throw new Error("Git worktree creation is unavailable.");      return api.git.createWorktree({ cwd, branch, newBranch, path: path ?? null });    },    mutationKey: ["git", "mutation", "create-worktree"] as const,    onSettled: async () => {      await invalidateGitQueries(input.queryClient);    },  });} export function gitRemoveWorktreeMutationOptions(input: { queryClient: QueryClient }) {  return mutationOptions({    mutationFn: async ({ cwd, path, force }: { cwd: string; path: string; force?: boolean }) => {      const api = ensureNativeApi();      if (!cwd) throw new Error("Git worktree removal is unavailable.");      return api.git.removeWorktree({ cwd, path, force });    },    mutationKey: ["git", "mutation", "remove-worktree"] as const,    onSettled: async () => {      await invalidateGitQueries(input.queryClient);    },  });}