fix(core,cli): make standalone binary actually run
Bun's --compile binary previously crashed at startup because:
1. node:sqlite isn't implemented in Bun 1.3.8 (require returns
undefined; import throws "No such built-in module")
2. ink imports react-devtools-core inside its reconciler; even though
gated by isDev(), the bundled module path failed to resolve at
runtime
Fixes:
- Add packages/core/src/sqlite-adapter.ts: a thin DatabaseSync wrapper
that picks bun:sqlite under Bun and node:sqlite under Node via
createRequire (so the bundler doesn't statically pull in either).
Drop-in for the three core files that import DatabaseSync.
- Install react-devtools-core as a workspace devDependency so it
resolves at bundle time. The dev-only code path is still gated by
DEV=true, so it stays inert in production.
- Revert the prior --external react-devtools-core flag (no longer
needed and was causing a different runtime error).
- Mark node-pty external in tsup so esbuild stops choking on the
homebridge fork's conditional native require()s
(build/Release/conpty.node etc.) when bundling for the npm package.
- Update bundle-output test: the bundle now contains both
bun:sqlite and node:sqlite specifiers (loaded via createRequire).
Verified end-to-end: dist/fn dashboard -p 0 starts cleanly (no PTY,
sqlite, or devtools errors). Core tests 3038/3038, CLI tests 826/826
(up from 822/826 baseline).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -338,10 +338,6 @@ function compileBinary(outFile: string, target: string, isCrossCompile: boolean)
|
||||
target,
|
||||
"--minify",
|
||||
"--conditions=source",
|
||||
// ink imports react-devtools-core dynamically only when DEV=true; mark
|
||||
// external so Bun's static bundler doesn't try to resolve it at compile.
|
||||
"--external",
|
||||
"react-devtools-core",
|
||||
],
|
||||
cwd: workspaceRoot,
|
||||
stdout: "inherit",
|
||||
|
||||
@@ -68,10 +68,13 @@ describe("CLI bundle output", () => {
|
||||
expect(tsupConfig).toContain("cpSync(dashboardClientSrc, dashboardClientDest, { recursive: true });");
|
||||
});
|
||||
|
||||
it("preserves node: prefix in node:sqlite imports", () => {
|
||||
it("loads sqlite via runtime adapter (bun:sqlite under Bun, node:sqlite under Node)", () => {
|
||||
const content = readFileSync(bundlePath, "utf-8");
|
||||
// Should have node:sqlite, not bare "sqlite"
|
||||
expect(content).toContain('from "node:sqlite"');
|
||||
// The sqlite-adapter uses createRequire to pick the runtime backend at
|
||||
// construction time; both specifiers should appear as require() targets.
|
||||
expect(content).toMatch(/["']bun:sqlite["']/);
|
||||
expect(content).toMatch(/["']node:sqlite["']/);
|
||||
// No bare "sqlite" import (we never want to pull in an npm package named sqlite)
|
||||
expect(content).not.toMatch(/from\s+["']sqlite["'][^s]/);
|
||||
});
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ export default defineConfig({
|
||||
options.conditions = [...(options.conditions || []), "source"];
|
||||
},
|
||||
noExternal: [/^@fusion\//],
|
||||
// Native module: leave node-pty (aliased to @homebridge fork) out of the
|
||||
// bundle. esbuild can't statically resolve its conditional native require()s
|
||||
// (build/Release/pty.node, build/Debug/conpty.node, ...).
|
||||
external: ["node-pty", "@homebridge/node-pty-prebuilt-multiarch"],
|
||||
splitting: false,
|
||||
clean: true,
|
||||
removeNodeProtocol: false,
|
||||
|
||||
Reference in New Issue
Block a user