From 8839fd733c126ff7187c0966ba83fe7e95a625c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Sep 2025 15:34:05 +0200 Subject: [PATCH 1/2] Fix stackId null handling in frontend API calls - Fix URL parameter parsing converting null to "null" string - Update branchChanges methods to convert "null" string to null - Update type signatures to accept string | null for stackId - Update mock backend validation to accept null stackId values Co-authored-by: Byron <63622+Byron@users.noreply.github.com> --- .../desktop/cypress/e2e/support/mock/changes.ts | 4 ++-- .../src/lib/stacks/stackService.svelte.ts | 17 ++++++++++------- .../routes/[projectId]/workspace/+page.svelte | 10 ++++++++-- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/apps/desktop/cypress/e2e/support/mock/changes.ts b/apps/desktop/cypress/e2e/support/mock/changes.ts index 6c3c4467be..1d54571ecb 100644 --- a/apps/desktop/cypress/e2e/support/mock/changes.ts +++ b/apps/desktop/cypress/e2e/support/mock/changes.ts @@ -147,7 +147,7 @@ export function isGetCommitChangesParams(args: unknown): args is GetCommitChange export type GetBranchChangesParams = { projectId: string; - stackId?: string; + stackId?: string | null; branch: string; }; @@ -157,7 +157,7 @@ export function isGetBranchChangesParams(args: unknown): args is GetBranchChange args !== null && 'projectId' in args && typeof args['projectId'] === 'string' && - (typeof (args as any).stackId === 'string' || (args as any).stackId === undefined) && + (typeof (args as any).stackId === 'string' || (args as any).stackId === undefined || (args as any).stackId === null) && 'branch' in args && typeof args['branch'] === 'string' ); diff --git a/apps/desktop/src/lib/stacks/stackService.svelte.ts b/apps/desktop/src/lib/stacks/stackService.svelte.ts index 3897b7fbb4..28a75c8d8a 100644 --- a/apps/desktop/src/lib/stacks/stackService.svelte.ts +++ b/apps/desktop/src/lib/stacks/stackService.svelte.ts @@ -602,11 +602,12 @@ export class StackService { * If the branch is part of a stack and if the stackId is provided, this will include only the changes up to the next branch in the stack. * Otherwise, if stackId is not provided, this will include all changes as compared to the target branch */ - branchChanges(args: { projectId: string; stackId?: string; branch: BranchRef }) { + branchChanges(args: { projectId: string; stackId?: string | null; branch: BranchRef }) { return this.api.endpoints.branchChanges.useQuery( { projectId: args.projectId, - stackId: args.stackId, + // Handle case where URL parameters convert null to "null" string + stackId: args.stackId === 'null' ? null : args.stackId, branch: args.branch }, { @@ -618,11 +619,12 @@ export class StackService { ); } - branchChange(args: { projectId: string; stackId?: string; branch: BranchRef; path: string }) { + branchChange(args: { projectId: string; stackId?: string | null; branch: BranchRef; path: string }) { return this.api.endpoints.branchChanges.useQuery( { projectId: args.projectId, - stackId: args.stackId, + // Handle case where URL parameters convert null to "null" string + stackId: args.stackId === 'null' ? null : args.stackId, branch: args.branch }, { transform: (result) => changesSelectors.selectById(result.changes, args.path) } @@ -631,14 +633,15 @@ export class StackService { async branchChangesByPaths(args: { projectId: string; - stackId?: string; + stackId?: string | null; branch: BranchRef; paths: string[]; }) { const result = await this.api.endpoints.branchChanges.fetch( { projectId: args.projectId, - stackId: args.stackId, + // Handle case where URL parameters convert null to "null" string + stackId: args.stackId === 'null' ? null : args.stackId, branch: args.branch }, { transform: (result) => selectChangesByPaths(result.changes, args.paths) } @@ -1185,7 +1188,7 @@ function injectEndpoints(api: ClientState['backendApi'], uiState: UiState) { }), branchChanges: build.query< { changes: EntityState; stats: TreeStats }, - { projectId: string; stackId?: string; branch: BranchRef } + { projectId: string; stackId?: string | null; branch: BranchRef } >({ extraOptions: { command: 'changes_in_branch' }, query: (args) => args, diff --git a/apps/desktop/src/routes/[projectId]/workspace/+page.svelte b/apps/desktop/src/routes/[projectId]/workspace/+page.svelte index 1852c3dd4d..ece41c6ba8 100644 --- a/apps/desktop/src/routes/[projectId]/workspace/+page.svelte +++ b/apps/desktop/src/routes/[projectId]/workspace/+page.svelte @@ -17,7 +17,13 @@ const stackId = $derived(projectState.stackId.current); // Check for stackId in URL query parameters - const urlStackId = $derived(page.url.searchParams.get('stackId')); + // Note: URLSearchParams.get() returns strings, so "null" becomes the string "null" + // We need to convert it back to actual null for proper API handling + const urlStackId = $derived((() => { + const param = page.url.searchParams.get('stackId'); + // Convert string "null" back to actual null + return param === 'null' ? null : param; + })()); let scrollToStackId = $state(undefined); const firstStackResult = $derived(stackService.stackAt(projectId, 0)); @@ -29,7 +35,7 @@ }); $effect(() => { - if (urlStackId) { + if (urlStackId !== null) { projectState.stackId.set(urlStackId); scrollToStackId = urlStackId; } else if (stackId === undefined && firstStack) { From d441f041603fd42ed773744e6441a1b5ef754b0e Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 16 Sep 2025 15:34:23 +0200 Subject: [PATCH 2/2] refactor - linting --- apps/desktop/cypress/e2e/support/mock/changes.ts | 4 +++- apps/desktop/src/lib/stacks/stackService.svelte.ts | 7 ++++++- .../src/routes/[projectId]/workspace/+page.svelte | 12 +++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/desktop/cypress/e2e/support/mock/changes.ts b/apps/desktop/cypress/e2e/support/mock/changes.ts index 1d54571ecb..5220ad365f 100644 --- a/apps/desktop/cypress/e2e/support/mock/changes.ts +++ b/apps/desktop/cypress/e2e/support/mock/changes.ts @@ -157,7 +157,9 @@ export function isGetBranchChangesParams(args: unknown): args is GetBranchChange args !== null && 'projectId' in args && typeof args['projectId'] === 'string' && - (typeof (args as any).stackId === 'string' || (args as any).stackId === undefined || (args as any).stackId === null) && + (typeof (args as any).stackId === 'string' || + (args as any).stackId === undefined || + (args as any).stackId === null) && 'branch' in args && typeof args['branch'] === 'string' ); diff --git a/apps/desktop/src/lib/stacks/stackService.svelte.ts b/apps/desktop/src/lib/stacks/stackService.svelte.ts index 28a75c8d8a..e09ca95b61 100644 --- a/apps/desktop/src/lib/stacks/stackService.svelte.ts +++ b/apps/desktop/src/lib/stacks/stackService.svelte.ts @@ -619,7 +619,12 @@ export class StackService { ); } - branchChange(args: { projectId: string; stackId?: string | null; branch: BranchRef; path: string }) { + branchChange(args: { + projectId: string; + stackId?: string | null; + branch: BranchRef; + path: string; + }) { return this.api.endpoints.branchChanges.useQuery( { projectId: args.projectId, diff --git a/apps/desktop/src/routes/[projectId]/workspace/+page.svelte b/apps/desktop/src/routes/[projectId]/workspace/+page.svelte index ece41c6ba8..bb6fcd1b6d 100644 --- a/apps/desktop/src/routes/[projectId]/workspace/+page.svelte +++ b/apps/desktop/src/routes/[projectId]/workspace/+page.svelte @@ -19,11 +19,13 @@ // Check for stackId in URL query parameters // Note: URLSearchParams.get() returns strings, so "null" becomes the string "null" // We need to convert it back to actual null for proper API handling - const urlStackId = $derived((() => { - const param = page.url.searchParams.get('stackId'); - // Convert string "null" back to actual null - return param === 'null' ? null : param; - })()); + const urlStackId = $derived( + (() => { + const param = page.url.searchParams.get('stackId'); + // Convert string "null" back to actual null + return param === 'null' ? null : param; + })() + ); let scrollToStackId = $state(undefined); const firstStackResult = $derived(stackService.stackAt(projectId, 0));