From e88ef5189aa19a139084f4e98f9a09696b834429 Mon Sep 17 00:00:00 2001 From: coach007 Date: Thu, 9 Jul 2026 22:54:32 +0200 Subject: [PATCH] fix(web): persist project action preview settings --- apps/web/src/components/ChatView.tsx | 17 ++---------- apps/web/src/projectScripts.test.ts | 41 ++++++++++++++++++++++++++++ apps/web/src/projectScripts.ts | 25 +++++++++++++++++ 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index f5ea5bb1eba..216cce8e8ca 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -144,6 +144,7 @@ import { stackedThreadToast, toastManager } from "./ui/toast"; import { decodeProjectScriptKeybindingRule } from "~/lib/projectScriptKeybindings"; import { type NewProjectScriptInput } from "./ProjectScriptsControl"; import { + buildProjectScript, commandForProjectScript, nextProjectScriptId, projectScriptIdFromCommand, @@ -2603,13 +2604,7 @@ function ChatViewContent(props: ChatViewProps) { input.name, activeProject.scripts.map((script) => script.id), ); - const nextScript: ProjectScript = { - id: nextId, - name: input.name, - command: input.command, - icon: input.icon, - runOnWorktreeCreate: input.runOnWorktreeCreate, - }; + const nextScript = buildProjectScript(nextId, input); const nextScripts = input.runOnWorktreeCreate ? [ ...activeProject.scripts.map((script) => @@ -2643,13 +2638,7 @@ function ChatViewContent(props: ChatViewProps) { return AsyncResult.failure(Cause.fail(new Error("Script not found."))); } - const updatedScript: ProjectScript = { - ...existingScript, - name: input.name, - command: input.command, - icon: input.icon, - runOnWorktreeCreate: input.runOnWorktreeCreate, - }; + const updatedScript = buildProjectScript(existingScript.id, input); const nextScripts = activeProject.scripts.map((script) => script.id === scriptId ? updatedScript diff --git a/apps/web/src/projectScripts.test.ts b/apps/web/src/projectScripts.test.ts index 3597b714c77..1f7a6bfaa9f 100644 --- a/apps/web/src/projectScripts.test.ts +++ b/apps/web/src/projectScripts.test.ts @@ -6,6 +6,7 @@ import { } from "@t3tools/shared/projectScripts"; import { + buildProjectScript, commandForProjectScript, nextProjectScriptId, primaryProjectScript, @@ -13,6 +14,46 @@ import { } from "./projectScripts"; describe("projectScripts helpers", () => { + it("builds scripts with preview settings", () => { + expect( + buildProjectScript("dev", { + name: "Dev server", + command: "pnpm dev", + icon: "debug", + runOnWorktreeCreate: false, + previewUrl: "http://localhost:5733", + autoOpenPreview: true, + }), + ).toEqual({ + id: "dev", + name: "Dev server", + command: "pnpm dev", + icon: "debug", + runOnWorktreeCreate: false, + previewUrl: "http://localhost:5733", + autoOpenPreview: true, + }); + }); + + it("omits preview settings when no preview URL is configured", () => { + expect( + buildProjectScript("test", { + name: "Test", + command: "pnpm test", + icon: "test", + runOnWorktreeCreate: false, + previewUrl: null, + autoOpenPreview: false, + }), + ).toEqual({ + id: "test", + name: "Test", + command: "pnpm test", + icon: "test", + runOnWorktreeCreate: false, + }); + }); + it("builds and parses script run commands", () => { const command = commandForProjectScript("lint"); expect(command).toBe("script.lint.run"); diff --git a/apps/web/src/projectScripts.ts b/apps/web/src/projectScripts.ts index f0aeead1411..e3efc9e3a33 100644 --- a/apps/web/src/projectScripts.ts +++ b/apps/web/src/projectScripts.ts @@ -7,6 +7,31 @@ import { import * as Schema from "effect/Schema"; const isScriptRunCommand = Schema.is(SCRIPT_RUN_COMMAND_PATTERN); +export interface ProjectScriptInput { + readonly name: ProjectScript["name"]; + readonly command: ProjectScript["command"]; + readonly icon: ProjectScript["icon"]; + readonly runOnWorktreeCreate: ProjectScript["runOnWorktreeCreate"]; + readonly previewUrl: Exclude | null; + readonly autoOpenPreview: boolean; +} + +export function buildProjectScript(id: string, input: ProjectScriptInput): ProjectScript { + return { + id, + name: input.name, + command: input.command, + icon: input.icon, + runOnWorktreeCreate: input.runOnWorktreeCreate, + ...(input.previewUrl === null + ? {} + : { + previewUrl: input.previewUrl, + autoOpenPreview: input.autoOpenPreview, + }), + }; +} + function normalizeScriptId(value: string): string { const cleaned = value .trim()