diff --git a/bin/phui.js b/bin/phui.js index 2f28476..41b6ea2 100755 --- a/bin/phui.js +++ b/bin/phui.js @@ -48,8 +48,8 @@ Commands: -h, --help Show this help message ` -const run = (target, args = process.argv.slice(2)) => { - const result = childProcess.spawnSync(target, args, { stdio: "inherit" }) +const run = (target, args = process.argv.slice(2), options = {}) => { + const result = childProcess.spawnSync(target, args, { stdio: "inherit", ...options }) if (result.error) { console.error(result.error.message) process.exit(1) @@ -59,14 +59,25 @@ const run = (target, args = process.argv.slice(2)) => { const scriptPath = fs.realpathSync(__filename) const scriptDir = path.dirname(scriptPath) +const packageRoot = path.join(scriptDir, "..") +const SOLID_PRELOAD = "@opentui/solid/preload" const resolveScriptEntry = () => { if (process.env.PHUI_BIN_PATH) return null - const sourceEntry = path.join(scriptDir, "..", "src", "standalone.ts") + const sourceEntry = path.join(packageRoot, "src", "standalone.ts") if (fs.existsSync(sourceEntry)) return sourceEntry return null } +const runFromSource = (args = process.argv.slice(2)) => { + const sourceEntry = resolveScriptEntry() + if (!sourceEntry) return false + // Same preload `bun run start` uses. Without it, bun does not run the + // Solid JSX transform and the TUI paints the splash then never updates. + run("bun", ["--preload", SOLID_PRELOAD, sourceEntry, ...args], { cwd: packageRoot }) + return true +} + const resolveBinary = () => { const platform = platformMap[os.platform()] const arch = archMap[os.arch()] @@ -95,20 +106,15 @@ if (process.argv[2] === "-v" || process.argv[2] === "--version" || process.argv[ } if (process.argv[2] === "upgrade") { - const sourceEntry = resolveScriptEntry() - const binaryPath = resolveBinary() - - if (sourceEntry) { - run("bun", [sourceEntry, "upgrade"]) - } - - if (binaryPath && fs.existsSync(binaryPath)) { - run(binaryPath, ["upgrade"]) + if (!runFromSource(["upgrade"])) { + const binaryPath = resolveBinary() + if (binaryPath && fs.existsSync(binaryPath)) { + run(binaryPath, ["upgrade"]) + } + console.error("Could not find a phui binary to upgrade.") + console.error(` npm install -g ${packageJson.name}@latest`) + process.exit(1) } - - console.error("Could not find a phui binary to upgrade.") - console.error(` npm install -g ${packageJson.name}@latest`) - process.exit(1) } const isMusl = () => { @@ -141,15 +147,12 @@ if (platform === "linux" && isMusl()) { const binaryPath = resolveBinary() if (!binaryPath || !fs.existsSync(binaryPath)) { - const sourceEntry = resolveScriptEntry() - if (sourceEntry) { - run("bun", [sourceEntry, ...process.argv.slice(2)]) + if (!runFromSource()) { + const fallbackName = `${packageJson.name}-${platform}-${arch}` + console.error(`Could not find the ${fallbackName} binary package for this platform.`) + console.error(`Try reinstalling ${packageJson.name}, or install ${fallbackName} manually.`) + process.exit(1) } - - const fallbackName = `${packageJson.name}-${platform}-${arch}` - console.error(`Could not find the ${fallbackName} binary package for this platform.`) - console.error(`Try reinstalling ${packageJson.name}, or install ${fallbackName} manually.`) - process.exit(1) } run(binaryPath) diff --git a/src/projects/atoms.ts b/src/projects/atoms.ts index 0c81343..fcbda81 100644 --- a/src/projects/atoms.ts +++ b/src/projects/atoms.ts @@ -3,6 +3,7 @@ import * as Atom from "effect/unstable/reactivity/Atom" import { CacheService } from "../services/CacheService.js" import { GitHubService } from "../services/GitHubService.js" import { githubRuntime } from "../services/runtime.js" +import { workspaceSurfaceAtom } from "../workspace/atoms.js" import { runCheckIds, runChecks } from "./checks/index.js" import { checkContext, hasConfiguredRoots, loadProjectsConfig, type ProjectsConfig } from "./config.js" import { fetchProjectGitHubSnapshots } from "./github.js" @@ -52,6 +53,13 @@ export const projectsReportAtom = githubRuntime get(projectsRescanAtom) const scannedAt = new Date() const config = yield* loadProjectsConfig + // Compiling without the Solid transform (and some Switch/Match + // builds) still constructs inactive surfaces. A Projects scan + // fans out `gh` per local repo and freezes boot. Do not fetch + // until this tab is actually selected. + if (get(workspaceSurfaceAtom) !== "projects") { + return { config, report: emptyProjectsReport(scannedAt, config.warnings) } satisfies ProjectsSurfaceState + } if (!hasConfiguredRoots(config)) return { config, report: emptyProjectsReport(scannedAt, config.warnings) } satisfies ProjectsSurfaceState const scan = yield* scanProjects(config, { scannedAt }) diff --git a/test/cliVersion.test.ts b/test/cliVersion.test.ts index 7231610..863d953 100644 --- a/test/cliVersion.test.ts +++ b/test/cliVersion.test.ts @@ -2,6 +2,25 @@ import { describe, expect, test } from "bun:test" import packageJson from "../package.json" with { type: "json" } describe("CLI version", () => { + test("the source fallback launcher uses the Solid JSX preload", async () => { + const text = await Bun.file(new URL("../bin/phui.js", import.meta.url)).text() + expect(text).toContain("--preload") + expect(text).toContain("@opentui/solid/preload") + expect(text).toContain("cwd: packageRoot") + }) + + test("bin/phui.js --version prints the package version", async () => { + const proc = Bun.spawn(["node", "bin/phui.js", "--version"], { + stdout: "pipe", + stderr: "pipe", + cwd: import.meta.dir + "/..", + }) + const [stdout, stderr, exitCode] = await Promise.all([new Response(proc.stdout).text(), new Response(proc.stderr).text(), proc.exited]) + expect(stderr).toBe("") + expect(exitCode).toBe(0) + expect(stdout.trim()).toBe(packageJson.version) + }) + test("bun run src/index.tsx --version prints the package version", async () => { const proc = Bun.spawn(["bun", "--preload", "@opentui/solid/preload", "src/index.tsx", "--version"], { stdout: "pipe",