Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
49 changes: 49 additions & 0 deletions apps/desktop/src/dev-desktop-tauri-noreload.test.ts
Original file line number Diff line number Diff line change
@@ -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: <repo>/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<string, string> };
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");
});
});

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
13 changes: 13 additions & 0 deletions scripts/dev-desktop-tauri-noreload.sh
Original file line number Diff line number Diff line change
@@ -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 "$@"