Showing the changes to apps/web/src/lib/gitReactQuery.ts (1 of 121 files). Show all
Unified · Split
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | import { |
| 2 | + type EnvironmentId, | |
| 2 | 3 | type GitActionProgressEvent, |
| 3 | 4 | type GitStackedAction, |
| 4 | 5 | type ThreadId, |
| @@ -9,8 +10,8 @@ import { · 4 unmodified lines | ||
| 9 | 10 | queryOptions, |
| 10 | 11 | type QueryClient, |
| 11 | 12 | } from "@tanstack/react-query"; |
| 12 | −import { ensureNativeApi } from "../nativeApi"; | |
| 13 | −import { getWsRpcClient } from "../wsRpcClient"; | |
| 13 | +import { ensureEnvironmentApi } from "../environmentApi"; | |
| 14 | +import { getWsRpcClientForEnvironment } from "../wsRpcClient"; | |
| 14 | 15 | |
| 15 | 16 | const GIT_BRANCHES_STALE_TIME_MS = 15_000; |
| 16 | 17 | const GIT_BRANCHES_REFETCH_INTERVAL_MS = 60_000; |
| @@ -18,38 +19,52 @@ const GIT_BRANCHES_PAGE_SIZE = 100; · 1 unmodified line | ||
| 18 | 19 | |
| 19 | 20 | export const gitQueryKeys = { |
| 20 | 21 | all: ["git"] as const, |
| 21 | − branches: (cwd: string | null) => ["git", "branches", cwd] as const, | |
| 22 | − branchSearch: (cwd: string | null, query: string) => | |
| 23 | − ["git", "branches", cwd, "search", query] as const, | |
| 22 | + branches: (environmentId: EnvironmentId | null, cwd: string | null) => | |
| 23 | + ["git", "branches", environmentId ?? null, cwd] as const, | |
| 24 | + branchSearch: (environmentId: EnvironmentId | null, cwd: string | null, query: string) => | |
| 25 | + ["git", "branches", environmentId ?? null, cwd, "search", query] as const, | |
| 24 | 26 | }; |
| 25 | 27 | |
| 26 | 28 | export const gitMutationKeys = { |
| 27 | − init: (cwd: string | null) => ["git", "mutation", "init", cwd] as const, | |
| 28 | − checkout: (cwd: string | null) => ["git", "mutation", "checkout", cwd] as const, | |
| 29 | − runStackedAction: (cwd: string | null) => ["git", "mutation", "run-stacked-action", cwd] as const, | |
| 30 | − pull: (cwd: string | null) => ["git", "mutation", "pull", cwd] as const, | |
| 31 | − preparePullRequestThread: (cwd: string | null) => | |
| 32 | − ["git", "mutation", "prepare-pull-request-thread", cwd] as const, | |
| 29 | + init: (environmentId: EnvironmentId | null, cwd: string | null) => | |
| 30 | + ["git", "mutation", "init", environmentId ?? null, cwd] as const, | |
| 31 | + checkout: (environmentId: EnvironmentId | null, cwd: string | null) => | |
| 32 | + ["git", "mutation", "checkout", environmentId ?? null, cwd] as const, | |
| 33 | + runStackedAction: (environmentId: EnvironmentId | null, cwd: string | null) => | |
| 34 | + ["git", "mutation", "run-stacked-action", environmentId ?? null, cwd] as const, | |
| 35 | + pull: (environmentId: EnvironmentId | null, cwd: string | null) => | |
| 36 | + ["git", "mutation", "pull", environmentId ?? null, cwd] as const, | |
| 37 | + preparePullRequestThread: (environmentId: EnvironmentId | null, cwd: string | null) => | |
| 38 | + ["git", "mutation", "prepare-pull-request-thread", environmentId ?? null, cwd] as const, | |
| 33 | 39 | }; |
| 34 | 40 | |
| 35 | −export function invalidateGitQueries(queryClient: QueryClient, input?: { cwd?: string | null }) { | |
| 41 | +export function invalidateGitQueries( | |
| 42 | + queryClient: QueryClient, | |
| 43 | + input?: { environmentId?: EnvironmentId | null; cwd?: string | null }, | |
| 44 | +) { | |
| 45 | + const environmentId = input?.environmentId ?? null; | |
| 36 | 46 | const cwd = input?.cwd ?? null; |
| 37 | 47 | if (cwd !== null) { |
| 38 | − return queryClient.invalidateQueries({ queryKey: gitQueryKeys.branches(cwd) }); | |
| 48 | + return queryClient.invalidateQueries({ queryKey: gitQueryKeys.branches(environmentId, cwd) }); | |
| 39 | 49 | } |
| 40 | 50 | |
| 41 | 51 | return queryClient.invalidateQueries({ queryKey: gitQueryKeys.all }); |
| 42 | 52 | } |
| 43 | 53 | |
| 44 | −function invalidateGitBranchQueries(queryClient: QueryClient, cwd: string | null) { | |
| 54 | +function invalidateGitBranchQueries( | |
| 55 | + queryClient: QueryClient, | |
| 56 | + environmentId: EnvironmentId | null, | |
| 57 | + cwd: string | null, | |
| 58 | +) { | |
| 45 | 59 | if (cwd === null) { |
| 46 | 60 | return Promise.resolve(); |
| 47 | 61 | } |
| 48 | 62 | |
| 49 | − return queryClient.invalidateQueries({ queryKey: gitQueryKeys.branches(cwd) }); | |
| 63 | + return queryClient.invalidateQueries({ queryKey: gitQueryKeys.branches(environmentId, cwd) }); | |
| 50 | 64 | } |
| 51 | 65 | |
| 52 | 66 | export function gitBranchSearchInfiniteQueryOptions(input: { |
| 67 | + environmentId: EnvironmentId | null; | |
| 53 | 68 | cwd: string | null; |
| 54 | 69 | query: string; |
| 55 | 70 | enabled?: boolean; |
| @@ -57,11 +72,12 @@ export function gitBranchSearchInfiniteQueryOptions(input: { · 1 unmodified line | ||
| 57 | 72 | const normalizedQuery = input.query.trim(); |
| 58 | 73 | |
| 59 | 74 | return infiniteQueryOptions({ |
| 60 | − queryKey: gitQueryKeys.branchSearch(input.cwd, normalizedQuery), | |
| 75 | + queryKey: gitQueryKeys.branchSearch(input.environmentId, input.cwd, normalizedQuery), | |
| 61 | 76 | initialPageParam: 0, |
| 62 | 77 | queryFn: async ({ pageParam }) => { |
| 63 | − const api = ensureNativeApi(); | |
| 64 | 78 | if (!input.cwd) throw new Error("Git branches are unavailable."); |
| 79 | + if (!input.environmentId) throw new Error("Git branches are unavailable."); | |
| 80 | + const api = ensureEnvironmentApi(input.environmentId); | |
| 65 | 81 | return api.git.listBranches({ |
| 66 | 82 | cwd: input.cwd, |
| 67 | 83 | ...(normalizedQuery.length > 0 ? { query: normalizedQuery } : {}), |
| @@ -79,62 +95,75 @@ export function gitBranchSearchInfiniteQueryOptions(input: { · 11 unmodified lines | ||
| 79 | 95 | } |
| 80 | 96 | |
| 81 | 97 | export function gitResolvePullRequestQueryOptions(input: { |
| 98 | + environmentId: EnvironmentId | null; | |
| 82 | 99 | cwd: string | null; |
| 83 | 100 | reference: string | null; |
| 84 | 101 | }) { |
| 85 | 102 | return queryOptions({ |
| 86 | − queryKey: ["git", "pull-request", input.cwd, input.reference] as const, | |
| 103 | + queryKey: [ | |
| 104 | + "git", | |
| 105 | + "pull-request", | |
| 106 | + input.environmentId ?? null, | |
| 107 | + input.cwd, | |
| 108 | + input.reference, | |
| 109 | + ] as const, | |
| 87 | 110 | queryFn: async () => { |
| 88 | − const api = ensureNativeApi(); | |
| 89 | − if (!input.cwd || !input.reference) { | |
| 111 | + if (!input.cwd || !input.reference || !input.environmentId) { | |
| 90 | 112 | throw new Error("Pull request lookup is unavailable."); |
| 91 | 113 | } |
| 114 | + const api = ensureEnvironmentApi(input.environmentId); | |
| 92 | 115 | return api.git.resolvePullRequest({ cwd: input.cwd, reference: input.reference }); |
| 93 | 116 | }, |
| 94 | − enabled: input.cwd !== null && input.reference !== null, | |
| 117 | + enabled: input.environmentId !== null && input.cwd !== null && input.reference !== null, | |
| 95 | 118 | staleTime: 30_000, |
| 96 | 119 | refetchOnWindowFocus: false, |
| 97 | 120 | refetchOnReconnect: false, |
| 98 | 121 | }); |
| 99 | 122 | } |
| 100 | 123 | |
| 101 | −export function gitInitMutationOptions(input: { cwd: string | null; queryClient: QueryClient }) { | |
| 124 | +export function gitInitMutationOptions(input: { | |
| 125 | + environmentId: EnvironmentId | null; | |
| 126 | + cwd: string | null; | |
| 127 | + queryClient: QueryClient; | |
| 128 | +}) { | |
| 102 | 129 | return mutationOptions({ |
| 103 | − mutationKey: gitMutationKeys.init(input.cwd), | |
| 130 | + mutationKey: gitMutationKeys.init(input.environmentId, input.cwd), | |
| 104 | 131 | mutationFn: async () => { |
| 105 | − const api = ensureNativeApi(); | |
| 106 | − if (!input.cwd) throw new Error("Git init is unavailable."); | |
| 132 | + if (!input.cwd || !input.environmentId) throw new Error("Git init is unavailable."); | |
| 133 | + const api = ensureEnvironmentApi(input.environmentId); | |
| 107 | 134 | return api.git.init({ cwd: input.cwd }); |
| 108 | 135 | }, |
| 109 | 136 | onSettled: async () => { |
| 110 | − await invalidateGitBranchQueries(input.queryClient, input.cwd); | |
| 137 | + await invalidateGitBranchQueries(input.queryClient, input.environmentId, input.cwd); | |
| 111 | 138 | }, |
| 112 | 139 | }); |
| 113 | 140 | } |
| 114 | 141 | |
| 115 | 142 | export function gitCheckoutMutationOptions(input: { |
| 143 | + environmentId: EnvironmentId | null; | |
| 116 | 144 | cwd: string | null; |
| 117 | 145 | queryClient: QueryClient; |
| 118 | 146 | }) { |
| 119 | 147 | return mutationOptions({ |
| 120 | − mutationKey: gitMutationKeys.checkout(input.cwd), | |
| 148 | + mutationKey: gitMutationKeys.checkout(input.environmentId, input.cwd), | |
| 121 | 149 | mutationFn: async (branch: string) => { |
| 122 | − const api = ensureNativeApi(); | |
| 123 | − if (!input.cwd) throw new Error("Git checkout is unavailable."); | |
| 150 | + if (!input.cwd || !input.environmentId) throw new Error("Git checkout is unavailable."); | |
| 151 | + const api = ensureEnvironmentApi(input.environmentId); | |
| 124 | 152 | return api.git.checkout({ cwd: input.cwd, branch }); |
| 125 | 153 | }, |
| 126 | 154 | onSettled: async () => { |
| 127 | − await invalidateGitBranchQueries(input.queryClient, input.cwd); | |
| 155 | + await invalidateGitBranchQueries(input.queryClient, input.environmentId, input.cwd); | |
| 128 | 156 | }, |
| 129 | 157 | }); |
| 130 | 158 | } |
| 131 | 159 | |
| 132 | 160 | export function gitRunStackedActionMutationOptions(input: { |
| 161 | + environmentId: EnvironmentId | null; | |
| 133 | 162 | cwd: string | null; |
| 134 | 163 | queryClient: QueryClient; |
| 135 | 164 | }) { |
| 136 | 165 | return mutationOptions({ |
| 137 | − mutationKey: gitMutationKeys.runStackedAction(input.cwd), | |
| 166 | + mutationKey: gitMutationKeys.runStackedAction(input.environmentId, input.cwd), | |
| 138 | 167 | mutationFn: async ({ |
| 139 | 168 | actionId, |
| 140 | 169 | action, |
| @@ -150,8 +179,8 @@ export function gitRunStackedActionMutationOptions(input: { · 9 unmodified lines | ||
| 150 | 179 | filePaths?: string[]; |
| 151 | 180 | onProgress?: (event: GitActionProgressEvent) => void; |
| 152 | 181 | }) => { |
| 153 | − if (!input.cwd) throw new Error("Git action is unavailable."); | |
| 154 | − return getWsRpcClient().git.runStackedAction( | |
| 182 | + if (!input.cwd || !input.environmentId) throw new Error("Git action is unavailable."); | |
| 183 | + return getWsRpcClientForEnvironment(input.environmentId).git.runStackedAction( | |
| 155 | 184 | { |
| 156 | 185 | action, |
| 157 | 186 | actionId, |
| @@ -164,62 +193,85 @@ export function gitRunStackedActionMutationOptions(input: { · 6 unmodified lines | ||
| 164 | 193 | ); |
| 165 | 194 | }, |
| 166 | 195 | onSuccess: async () => { |
| 167 | − await invalidateGitBranchQueries(input.queryClient, input.cwd); | |
| 196 | + await invalidateGitBranchQueries(input.queryClient, input.environmentId, input.cwd); | |
| 168 | 197 | }, |
| 169 | 198 | }); |
| 170 | 199 | } |
| 171 | 200 | |
| 172 | −export function gitPullMutationOptions(input: { cwd: string | null; queryClient: QueryClient }) { | |
| 201 | +export function gitPullMutationOptions(input: { | |
| 202 | + environmentId: EnvironmentId | null; | |
| 203 | + cwd: string | null; | |
| 204 | + queryClient: QueryClient; | |
| 205 | +}) { | |
| 173 | 206 | return mutationOptions({ |
| 174 | − mutationKey: gitMutationKeys.pull(input.cwd), | |
| 207 | + mutationKey: gitMutationKeys.pull(input.environmentId, input.cwd), | |
| 175 | 208 | mutationFn: async () => { |
| 176 | − const api = ensureNativeApi(); | |
| 177 | − if (!input.cwd) throw new Error("Git pull is unavailable."); | |
| 209 | + if (!input.cwd || !input.environmentId) throw new Error("Git pull is unavailable."); | |
| 210 | + const api = ensureEnvironmentApi(input.environmentId); | |
| 178 | 211 | return api.git.pull({ cwd: input.cwd }); |
| 179 | 212 | }, |
| 180 | 213 | onSuccess: async () => { |
| 181 | − await invalidateGitBranchQueries(input.queryClient, input.cwd); | |
| 214 | + await invalidateGitBranchQueries(input.queryClient, input.environmentId, input.cwd); | |
| 182 | 215 | }, |
| 183 | 216 | }); |
| 184 | 217 | } |
| 185 | 218 | |
| 186 | −export function gitCreateWorktreeMutationOptions(input: { queryClient: QueryClient }) { | |
| 219 | +export function gitCreateWorktreeMutationOptions(input: { | |
| 220 | + environmentId: EnvironmentId | null; | |
| 221 | + queryClient: QueryClient; | |
| 222 | +}) { | |
| 187 | 223 | return mutationOptions({ |
| 188 | − mutationKey: ["git", "mutation", "create-worktree"] as const, | |
| 224 | + mutationKey: ["git", "mutation", "create-worktree", input.environmentId ?? null] as const, | |
| 189 | 225 | mutationFn: ( |
| 190 | − args: Parameters<ReturnType<typeof ensureNativeApi>["git"]["createWorktree"]>[0], | |
| 191 | − ) => ensureNativeApi().git.createWorktree(args), | |
| 226 | + args: Parameters<ReturnType<typeof ensureEnvironmentApi>["git"]["createWorktree"]>[0], | |
| 227 | + ) => { | |
| 228 | + if (!input.environmentId) { | |
| 229 | + throw new Error("Worktree creation is unavailable."); | |
| 230 | + } | |
| 231 | + return ensureEnvironmentApi(input.environmentId).git.createWorktree(args); | |
| 232 | + }, | |
| 192 | 233 | onSuccess: async () => { |
| 193 | − await invalidateGitQueries(input.queryClient); | |
| 234 | + await invalidateGitQueries(input.queryClient, { environmentId: input.environmentId }); | |
| 194 | 235 | }, |
| 195 | 236 | }); |
| 196 | 237 | } |
| 197 | 238 | |
| 198 | −export function gitRemoveWorktreeMutationOptions(input: { queryClient: QueryClient }) { | |
| 239 | +export function gitRemoveWorktreeMutationOptions(input: { | |
| 240 | + environmentId: EnvironmentId | null; | |
| 241 | + queryClient: QueryClient; | |
| 242 | +}) { | |
| 199 | 243 | return mutationOptions({ |
| 200 | − mutationKey: ["git", "mutation", "remove-worktree"] as const, | |
| 244 | + mutationKey: ["git", "mutation", "remove-worktree", input.environmentId ?? null] as const, | |
| 201 | 245 | mutationFn: ( |
| 202 | − args: Parameters<ReturnType<typeof ensureNativeApi>["git"]["removeWorktree"]>[0], | |
| 203 | − ) => ensureNativeApi().git.removeWorktree(args), | |
| 246 | + args: Parameters<ReturnType<typeof ensureEnvironmentApi>["git"]["removeWorktree"]>[0], | |
| 247 | + ) => { | |
| 248 | + if (!input.environmentId) { | |
| 249 | + throw new Error("Worktree removal is unavailable."); | |
| 250 | + } | |
| 251 | + return ensureEnvironmentApi(input.environmentId).git.removeWorktree(args); | |
| 252 | + }, | |
| 204 | 253 | onSuccess: async () => { |
| 205 | − await invalidateGitQueries(input.queryClient); | |
| 254 | + await invalidateGitQueries(input.queryClient, { environmentId: input.environmentId }); | |
| 206 | 255 | }, |
| 207 | 256 | }); |
| 208 | 257 | } |
| 209 | 258 | |
| 210 | 259 | export function gitPreparePullRequestThreadMutationOptions(input: { |
| 260 | + environmentId: EnvironmentId | null; | |
| 211 | 261 | cwd: string | null; |
| 212 | 262 | queryClient: QueryClient; |
| 213 | 263 | }) { |
| 214 | 264 | return mutationOptions({ |
| 215 | − mutationKey: gitMutationKeys.preparePullRequestThread(input.cwd), | |
| 265 | + mutationKey: gitMutationKeys.preparePullRequestThread(input.environmentId, input.cwd), | |
| 216 | 266 | mutationFn: async (args: { |
| 217 | 267 | reference: string; |
| 218 | 268 | mode: "local" | "worktree"; |
| 219 | 269 | threadId?: ThreadId; |
| 220 | 270 | }) => { |
| 221 | − const api = ensureNativeApi(); | |
| 222 | − if (!input.cwd) throw new Error("Pull request thread preparation is unavailable."); | |
| 271 | + if (!input.cwd || !input.environmentId) { | |
| 272 | + throw new Error("Pull request thread preparation is unavailable."); | |
| 273 | + } | |
| 274 | + const api = ensureEnvironmentApi(input.environmentId); | |
| 223 | 275 | return api.git.preparePullRequestThread({ |
| 224 | 276 | cwd: input.cwd, |
| 225 | 277 | reference: args.reference, |
| @@ -228,7 +280,7 @@ export function gitPreparePullRequestThreadMutationOptions(input: { · 2 unmodified lines | ||
| 228 | 280 | }); |
| 229 | 281 | }, |
| 230 | 282 | onSuccess: async () => { |
| 231 | − await invalidateGitBranchQueries(input.queryClient, input.cwd); | |
| 283 | + await invalidateGitBranchQueries(input.queryClient, input.environmentId, input.cwd); | |
| 232 | 284 | }, |
| 233 | 285 | }); |
| 234 | 286 | } |