fix: build @fusion/core and @fusion/engine dist in desktop packaging

The packaged desktop "Local" runtime dynamically imports @fusion/engine, whose
tsc dist is gitignored. desktop-windows.yml built only `@fusion/desktop build`
(no root `pnpm build`), so it packaged an empty engine/dist and the app crashed
on Local mode with ERR_MODULE_NOT_FOUND for app.asar/node_modules/@fusion/engine.

Make the desktop build self-contained (build core then engine before packaging)
and add the parity `pnpm build` step to desktop-windows.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-01 19:34:11 -07:00
parent 8bb18d9d61
commit 3aef6dd5cf
4 changed files with 47 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Fix desktop app crashing on "Local" mode startup with a missing-module error.
category: fix
dev: The desktop build now compiles @fusion/core and @fusion/engine tsc dist (both gitignored) so the packaged embedded Local runtime's `import("@fusion/engine")` resolves. Previously only release.yml's root `pnpm build` produced these; desktop-windows.yml packaged an empty engine/dist and crashed with ERR_MODULE_NOT_FOUND for app.asar/node_modules/@fusion/engine. `@fusion/desktop build` is now self-contained (build.ts → ensureEmbeddedRuntimeBuild), and desktop-windows.yml gained the `pnpm build` parity step.

View File

@@ -22,6 +22,16 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
# FNXC:WindowsDesktopPackaging 2026-07-01-19:45:
# Mirror release.yml: build every workspace package's tsc dist (incl.
# @fusion/core and @fusion/engine, which are gitignored) before packaging.
# Without this the embedded Local runtime's `import("@fusion/engine")`
# resolves to an empty dist and the app crashes with ERR_MODULE_NOT_FOUND.
# `@fusion/desktop build` now also self-builds these, so this is belt-and-
# suspenders parity that additionally covers any other workspace runtime dep.
- name: Build workspace
run: pnpm build
- name: Build desktop package
run: pnpm --filter @fusion/desktop build

View File

@@ -1,7 +1,7 @@
import { build } from "esbuild";
import { cp, mkdir, rm, stat } from "node:fs/promises";
import { join } from "node:path";
import { buildDashboard, buildDashboardClient, packageRoot, workspaceRoot } from "./workspace-tools";
import { buildCore, buildDashboard, buildDashboardClient, buildEngine, packageRoot, workspaceRoot } from "./workspace-tools";
const dashboardRoot = join(workspaceRoot, "packages", "dashboard");
const dashboardClientDir = join(dashboardRoot, "dist", "client");
const dashboardRegistryManifestSource = join(dashboardRoot, "src", "registry-manifest.json");
@@ -97,10 +97,27 @@ async function copyDashboardClient(): Promise<void> {
await cp(dashboardClientDir, desktopClientDistDir, { recursive: true });
}
// FNXC:DesktopBuild 2026-07-01-19:45:
// Compile the workspace @fusion/* packages the embedded "Local" runtime imports
// at runtime (@fusion/core, @fusion/engine) so `@fusion/desktop build` alone
// produces a complete, packageable tree — no separate root `pnpm build` required.
// engine/dist and core/dist are tsc-emitted + gitignored; without this the
// desktop-windows.yml workflow_dispatch build shipped an empty engine/dist and
// the packaged app crashed on Local mode with ERR_MODULE_NOT_FOUND for
// ...app.asar/node_modules/@fusion/engine. Core must build before engine
// (engine depends on @fusion/core). Dashboard + its runtime plugins + plugin-sdk
// are already built by ensureDashboardBuild().
async function ensureEmbeddedRuntimeBuild(): Promise<void> {
console.log("[desktop:build] Building @fusion/core and @fusion/engine runtime dist...");
await buildCore();
await buildEngine();
}
async function main(): Promise<void> {
await rm(desktopDistDir, { recursive: true, force: true });
await mkdir(desktopDistDir, { recursive: true });
await ensureEmbeddedRuntimeBuild();
await ensureDashboardBuild();
await buildElectronEntrypoints();
await copyDashboardClient();

View File

@@ -46,6 +46,18 @@ export async function buildCore(): Promise<void> {
await runWorkspaceBin("tsc", [], resolve(workspaceRoot, "packages", "core"));
}
// FNXC:DesktopBuild 2026-07-01-19:45:
// The packaged desktop "Local" runtime dynamically imports @fusion/engine
// (local-runtime.ts createDashboardServerDefault). Engine's runtime code is
// tsc-emitted into packages/engine/dist and gitignored, so a workflow that runs
// only `@fusion/desktop build` (e.g. desktop-windows.yml, which lacked the root
// `pnpm build`) shipped an empty engine/dist. The packaged app then crashed on
// Local mode with `ERR_MODULE_NOT_FOUND ...app.asar/node_modules/@fusion/engine`.
// Engine depends on @fusion/core, so callers must build core first.
export async function buildEngine(): Promise<void> {
await runWorkspaceBin("tsc", [], resolve(workspaceRoot, "packages", "engine"));
}
async function buildPackage(relativePath: string): Promise<void> {
await runWorkspaceBin("tsc", [], resolve(workspaceRoot, relativePath));
}