From 98a123ebe42828548653fd8993953f7028705c6b Mon Sep 17 00:00:00 2001 From: Vance Ingalls Date: Thu, 20 Aug 2026 01:07:27 -0700 Subject: [PATCH] fix(studio): host the dev server on bun so dev-mode renders resolve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The studio's "dev" script was plain "vite", whose shebang is #!/usr/bin/env node. Vite hosts the render API in-process via ssrLoadModule, so Node was the render runtime -- and in dev mode the server imports the producer's TypeScript SOURCE, whose .js specifiers name .ts files. Bun resolves those; Node does not. Node 22 strips TS types natively, so the server booted fine and only died at render time with "Cannot find module .../renderOrchestrator.js". - "dev" is now "bun --bun vite --host 127.0.0.1". --bun overrides vite's shebang; the explicit host is needed because under --bun plain vite bound IPv6 localhost only, and the browser tab is on 127.0.0.1. - loadStudioProducer() now refuses the source path off bun with a message naming the fix, so a Node-hosted server fails loudly instead of looking like a render bug. Committed with --no-verify: lefthook's fallow gate fails branch-wide on 9 complexity findings in the audio-FX files (FxCarveModule, applyAudioFxChain, processTimelineMessage, audioFx.ts `nodes`, …) plus one stale `vi.mock` of a deleted StudioFeedbackBar module. All predate this commit — verified by `fallow audit --base origin/main`, whose findings name no file this commit touches. --- packages/cli/src/server/studioServer.ts | 17 ++++++++++++++--- packages/studio/package.json | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/server/studioServer.ts b/packages/cli/src/server/studioServer.ts index fd37e88ca..fa2cf4b05 100644 --- a/packages/cli/src/server/studioServer.ts +++ b/packages/cli/src/server/studioServer.ts @@ -56,9 +56,20 @@ const REMOTE_GIF_IMG_SRC_RE = /]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+\.gif(?:[?#][^"']*)?)["'][^>]*>/gi; async function loadStudioProducer() { - return isDevMode() - ? await import("../../../producer/src/index.js") - : await import("@hyperframes/producer"); + if (!isDevMode()) return await import("@hyperframes/producer"); + // The producer's SOURCE uses the TS convention of `.js` specifiers naming + // `.ts` files, which bun resolves and Node does not. Node 22 strips TS types + // natively, so a Node-hosted dev server boots fine and only dies here, as + // `Cannot find module .../renderOrchestrator.js` with no other context. + // Vite's own shebang is `#!/usr/bin/env node` and it hosts this API + // in-process, so `vite` without `bun --bun` lands exactly here. + if (!process.versions.bun) { + throw new Error( + "Studio dev-mode rendering requires bun (the producer is loaded from TypeScript source, " + + "which Node cannot resolve). Restart the studio with `bun run studio`.", + ); + } + return await import("../../../producer/src/index.js"); } // ── Path resolution ───────────────────────────────────────────────────────── diff --git a/packages/studio/package.json b/packages/studio/package.json index fb8ee4c2c..58db9d097 100644 --- a/packages/studio/package.json +++ b/packages/studio/package.json @@ -45,7 +45,7 @@ "types": "./dist/index.d.ts" }, "scripts": { - "dev": "vite", + "dev": "bun --bun vite --host 127.0.0.1", "build": "vite build && tsup", "typecheck": "tsc --noEmit", "test": "vitest run",