[eric] build: bundle npm with node so packaged apps can install custom deps (fixes imported backend apps not starting)

This commit is contained in:
ciregenz
2026-06-26 05:14:04 -07:00
parent e57bc06c9f
commit a2b8a2c335
3 changed files with 22 additions and 14 deletions
@@ -23,18 +23,17 @@ def p_resolve_npm() -> list[str] | None:
node_path = os.environ.get("OPENSWARM_NODE_PATH")
if node_path and os.path.exists(node_path):
node_dir = os.path.dirname(node_path)
# Prefer invoking npm-cli.js through our bundled node so this doesn't depend on a system node for the shim's shebang. Second entry is the canonical Mac-dist layout (lib/node_modules/npm); first is the Windows layout (node_modules/npm beside node.exe).
for cli in (
os.path.join(node_dir, "node_modules", "npm", "bin", "npm-cli.js"),
os.path.join(os.path.dirname(node_dir), "lib", "node_modules", "npm", "bin", "npm-cli.js"),
):
if os.path.exists(cli):
return [node_path, cli]
for shim in ("npm.cmd", "npm"):
cand = os.path.join(node_dir, shim)
if os.path.exists(cand):
return [cand]
# node.exe with no sibling npm: invoke npm-cli.js directly via node.
for rel in (
os.path.join("node_modules", "npm", "bin", "npm-cli.js"),
os.path.join(node_dir, "node_modules", "npm", "bin", "npm-cli.js"),
):
cli = rel if os.path.isabs(rel) else os.path.join(node_dir, rel)
if os.path.exists(cli):
return [node_path, cli]
for name in ("npm.cmd", "npm") if sys.platform == "win32" else ("npm",):
found = shutil.which(name)
if found:
+5 -3
View File
@@ -322,11 +322,13 @@ try {
Write-Host "[3b] Downloading $NodeUrl..."
Invoke-WebRequest -Uri $NodeUrl -OutFile $NodeZip -UseBasicParsing
Expand-Archive -Path $NodeZip -DestinationPath $NodeExtract -Force
# Ship just node.exe — npm/npx are unused at runtime (router + MCP
# bundles are pre-built). Saves ~70 MB from the installer.
$SrcNode = Join-Path $NodeExtract "node-$NodeVersion-win-x64\node.exe"
$SrcRoot = Join-Path $NodeExtract "node-$NodeVersion-win-x64"
$SrcNode = Join-Path $SrcRoot 'node.exe'
if (-not (Test-Path $SrcNode)) { throw "node.exe not found at $SrcNode after extract" }
Copy-Item -Force $SrcNode (Join-Path $NodeStageDir 'node.exe')
# Bundle npm too so packaged apps with custom deps can `npm install` them. npm.cmd + node_modules\npm sit next to node.exe in the win dist; p_resolve_npm finds node_dir\npm.cmd.
Copy-Item -Force (Join-Path $SrcRoot 'npm.cmd') (Join-Path $NodeStageDir 'npm.cmd')
Copy-Item -Recurse -Force (Join-Path $SrcRoot 'node_modules') (Join-Path $NodeStageDir 'node_modules')
$Size = (Get-Item (Join-Path $NodeStageDir 'node.exe')).Length / 1MB
Write-Host ("[3b] Node {0} (x64) staged ({1:N1} MB)" -f $NodeVersion, $Size)
} finally {
+10 -3
View File
@@ -330,11 +330,18 @@ download_node_for_arch() {
local tmp; tmp=$(mktemp -d)
curl -fsSL --progress-bar -o "$tmp/node.tar.gz" "$url"
tar xzf "$tmp/node.tar.gz" -C "$tmp"
# Ship just the `node` binary. We don't need npm/npx/corepack at runtime —
# all router + MCP code is pre-bundled. ~50 MB per arch -> ~25 MB after
# gzip/dmg compression.
cp "$tmp/node-${NODE_VERSION}-darwin-${arch}/bin/node" "$out_dir/bin/node"
chmod +x "$out_dir/bin/node"
# Bundle npm too so packaged apps with custom deps can `npm install` them (the bare node can't).
mkdir -p "$out_dir/lib/node_modules"
cp -R "$tmp/node-${NODE_VERSION}-darwin-${arch}/lib/node_modules/npm" "$out_dir/lib/node_modules/npm"
# An explicit wrapper, not the dist's bin/npm symlink (packaging may not preserve symlinks): always runs our bundled node + npm-cli.js, no PATH/system-node reliance. run.sh picks it up as $NODE_DIR/npm.
cat > "$out_dir/bin/npm" <<'NPMSH'
#!/bin/sh
here="$(cd "$(dirname "$0")" && pwd)"
exec "$here/node" "$here/../lib/node_modules/npm/bin/npm-cli.js" "$@"
NPMSH
chmod +x "$out_dir/bin/npm"
rm -rf "$tmp"
echo "[3b] Node $NODE_VERSION ($arch) staged ($(du -h "$out_dir/bin/node" | cut -f1))"
}