90 lines
3.6 KiB
JavaScript
90 lines
3.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Memory-aware development entrypoint for Fusion.
|
|
*
|
|
* This script increases the Node.js heap size to prevent memory pressure
|
|
* during the initial build/start sequence, while preserving argument
|
|
* pass-through for documented invocations like `pnpm dev dashboard`.
|
|
*
|
|
* Cross-platform: Works on Windows, macOS, and Linux.
|
|
*/
|
|
import { buildDevNodeArgs } from "./dev-with-memory-lib.mjs";
|
|
|
|
// Set increased heap size (8GB) to prevent OOM during initial build/start
|
|
const MEMORY_MB = process.env.FUSION_DEV_MEMORY_MB || "8192";
|
|
|
|
// Spawn the actual dev command with all arguments passed through
|
|
const { spawn } = await import("child_process");
|
|
const rawArgs = process.argv.slice(2);
|
|
|
|
// --inspect / --inspect-brk / --inspect=PORT enables the Node inspector.
|
|
// Strip these from forwarded args so they don't reach the dashboard CLI
|
|
// parser. We pass them as CLI flags directly to node (NOT via NODE_OPTIONS),
|
|
// because NODE_OPTIONS is inherited by every grandchild process — every
|
|
// vitest / agent / claude subprocess would then try to bind 9229 and fail.
|
|
const inspectFlags = [];
|
|
const args = [];
|
|
for (const a of rawArgs) {
|
|
if (a === "--inspect" || a === "--inspect-brk" || a.startsWith("--inspect=") || a.startsWith("--inspect-brk=")) {
|
|
inspectFlags.push(a);
|
|
} else {
|
|
args.push(a);
|
|
}
|
|
}
|
|
|
|
// NODE_OPTIONS is shared with every spawned node process (build + run +
|
|
// agents). Heap size belongs here. Inspector flags do NOT — see comment above.
|
|
const nodeOptions = `--max-old-space-size=${MEMORY_MB} ${process.env.NODE_OPTIONS || ""}`.trim();
|
|
process.env.NODE_OPTIONS = nodeOptions;
|
|
|
|
// In dev we bind the dashboard to 0.0.0.0 so the server is reachable from
|
|
// mobile devices and other machines on the LAN for testing. Production
|
|
// builds default to 127.0.0.1; this override only applies when starting
|
|
// the dashboard via `pnpm dev dashboard` and only if no --host was passed.
|
|
const needsDevHostInjection =
|
|
args[0] === "dashboard" && !args.includes("--host");
|
|
const forwardedArgs = needsDevHostInjection
|
|
? [...args, "--host", "0.0.0.0"]
|
|
: args;
|
|
|
|
// Resolve absolute paths to tsx loader so they survive shell quoting.
|
|
// Use Node's resolver instead of hardcoding the pnpm version-specific path.
|
|
const { createRequire } = await import("node:module");
|
|
const path = await import("node:path");
|
|
const require = createRequire(import.meta.url);
|
|
const tsxPkgJson = require.resolve("tsx/package.json");
|
|
const tsxDir = path.dirname(tsxPkgJson);
|
|
const PRELOAD = path.join(tsxDir, "dist", "preflight.cjs");
|
|
const LOADER = path.join(tsxDir, "dist", "loader.mjs");
|
|
const ENTRY = path.resolve(process.cwd(), "packages/cli/src/bin.ts");
|
|
|
|
// Spawn node directly (no shell) so the inspector attaches to the real app
|
|
// process and there's no parent/child wrapper consuming --inspect.
|
|
// Inspector flags are CLI args here so they apply only to this process and
|
|
// don't propagate to grandchildren via NODE_OPTIONS.
|
|
function runApp(extraArgs) {
|
|
const tsx = spawn(process.execPath, buildDevNodeArgs({
|
|
inspectFlags,
|
|
preload: PRELOAD,
|
|
loader: LOADER,
|
|
entry: ENTRY,
|
|
args: extraArgs,
|
|
}), { stdio: "inherit" });
|
|
tsx.on("close", (c) => process.exit(c ?? 1));
|
|
}
|
|
|
|
// If no args, run default: build + CLI
|
|
if (forwardedArgs.length === 0) {
|
|
const pnpm = spawn("pnpm", ["build"], { stdio: "inherit", shell: true });
|
|
pnpm.on("close", (code) => {
|
|
if (code !== 0) process.exit(code ?? 1);
|
|
runApp([]);
|
|
});
|
|
} else {
|
|
const build = spawn("pnpm", ["build"], { stdio: "inherit", shell: true });
|
|
build.on("close", (code) => {
|
|
if (code !== 0) process.exit(code ?? 1);
|
|
runApp(forwardedArgs);
|
|
});
|
|
}
|