History

Prepare datamodel for multi-environment (#1765)

Julius Marminge committed 7 months ago

Commit b96308f1 parent 72b7f90121 files · +10206 −4969Browse files

Showing the changes to apps/web/src/lib/gitReactQuery.ts (1 of 121 files). Show all

Unified · Split

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