diff --git a/apps/desktop/README.md b/apps/desktop/README.md index 3a6bec2..884ba7f 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -11,6 +11,7 @@ bun run --filter @forge/desktop dev bun run --filter @forge/desktop dev:singleport bun run dev:desktop:tauri bun run dev:desktop:tauri:oneshot +bun run dev:desktop:tauri:noreload bun run --filter @forge/desktop build bun run --filter @forge/desktop test bun run --filter @forge/desktop typecheck @@ -24,6 +25,7 @@ Notes: - The desktop UI talks to the backend via HTTP `/api/*` (single origin), not Tauri `invoke()`. - `bun run dev:desktop:tauri` is the recommended way to start Tauri in dev (it starts the watcher + `cargo tauri dev`). - `bun run dev:desktop:tauri:oneshot` runs a one-time frontend build then starts Tauri (no watch, single process after startup). +- `bun run dev:desktop:tauri:noreload` runs a one-time frontend build and starts Tauri with its watcher disabled (`cargo tauri dev --no-watch`). ## Plans diff --git a/apps/desktop/src/dev-desktop-tauri-noreload.test.ts b/apps/desktop/src/dev-desktop-tauri-noreload.test.ts new file mode 100644 index 0000000..77c7213 --- /dev/null +++ b/apps/desktop/src/dev-desktop-tauri-noreload.test.ts @@ -0,0 +1,49 @@ +import { existsSync, readFileSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { describe, expect, it } from "vitest"; + +function getRepoRootFromThisFile(): string { + // This file lives at: /apps/desktop/src/*.ts + const here = dirname(fileURLToPath(import.meta.url)); + return resolve(here, "../../.."); +} + +describe("desktop: tauri no-reload dev entrypoint", () => { + it("exposes a bun script alias for the no-reload workflow", () => { + // Given the repo root package.json + const repoRoot = getRepoRootFromThisFile(); + const packageJsonPath = join(repoRoot, "package.json"); + + // When reading scripts.dev:desktop:tauri:noreload + const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8")) as { scripts?: Record }; + const command = pkg.scripts?.["dev:desktop:tauri:noreload"]; + + // Then it points at the wrapper script + expect(command).toBe("./scripts/dev-desktop-tauri-noreload.sh"); + }); + + it("provides a wrapper script that disables both frontend and tauri watchers", () => { + // Given the expected wrapper script path + const repoRoot = getRepoRootFromThisFile(); + const scriptPath = join(repoRoot, "scripts/dev-desktop-tauri-noreload.sh"); + + // When checking the script exists + const exists = existsSync(scriptPath); + + // Then it should exist + expect(exists).toBe(true); + if (!exists) { + return; + } + + // When reading its contents + const body = readFileSync(scriptPath, "utf8"); + + // Then it should invoke the existing dev script with flags to avoid reloads + expect(body).toContain("dev-desktop-tauri.sh"); + expect(body).toContain("--oneshot"); + expect(body).toContain("--no-watch"); + }); +}); + diff --git a/package.json b/package.json index fdacf4d..1943b99 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "dev:desktop": "bun run --filter @forge/desktop dev", "dev:desktop:tauri": "./scripts/dev-desktop-tauri.sh", "dev:desktop:tauri:oneshot": "FORGE_DESKTOP_ONESHOT=1 ./scripts/dev-desktop-tauri.sh", + "dev:desktop:tauri:noreload": "./scripts/dev-desktop-tauri-noreload.sh", "docs:check": "bun scripts/docs-check.mjs", "architecture:check": "bun scripts/architecture-check.mjs" }, diff --git a/scripts/dev-desktop-tauri-noreload.sh b/scripts/dev-desktop-tauri-noreload.sh new file mode 100755 index 0000000..bfffac1 --- /dev/null +++ b/scripts/dev-desktop-tauri-noreload.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +readonly ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +readonly DEV_SCRIPT="$ROOT/scripts/dev-desktop-tauri.sh" + +# Usage: +# ./scripts/dev-desktop-tauri-noreload.sh [tauri args...] +# +# Runs Forge Desktop without disruptive reloads: +# - frontend: builds once (no `vite build --watch`) +# - tauri/rust: disables the watcher (`cargo tauri dev --no-watch`) +exec "$DEV_SCRIPT" --oneshot --no-watch "$@"