Skip to content

Commit 75bccac

Browse files
committed
add bundled node
1 parent 4f3796a commit 75bccac

File tree

5 files changed

+80
-9
lines changed

5 files changed

+80
-9
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,7 @@ artifacts
127127
.cursor/
128128
.claude/
129129
CLAUDE.md
130+
131+
# Bundled Node binary (downloaded during build)
132+
bin/node
133+
bin/node.exe

forge.config.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,10 @@ const config: ForgeConfig = {
114114
],
115115
plugins: [ new AutoUnpackNativesPlugin( {} ) ],
116116
hooks: {
117-
prePackage: async () => {
118-
console.log( "Ensuring latest WordPress zip isn't included in production build ..." );
117+
prePackage: async ( _forgeConfig, platform, arch ) => {
118+
const execAsync = promisify( exec );
119119

120+
console.log( "Ensuring latest WordPress zip isn't included in production build ..." );
120121
const zipPath = path.join( __dirname, 'wp-files', 'latest.zip' );
121122
try {
122123
fs.unlinkSync( zipPath );
@@ -125,8 +126,10 @@ const config: ForgeConfig = {
125126
}
126127

127128
console.log( 'Building CLI ...' );
128-
const execAsync = promisify( exec );
129129
await execAsync( 'npm run cli:build' );
130+
131+
console.log( `Downloading Node.js binary for ${ platform }-${ arch }...` );
132+
await execAsync( `./scripts/download-node-binary.sh ${ platform } ${ arch }` );
130133
},
131134
},
132135
};

scripts/download-node-binary.sh

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Download Node.js binary for bundling with Studio
5+
# Usage: ./scripts/download-node-binary.sh <platform> <arch>
6+
# Example: ./scripts/download-node-binary.sh darwin arm64
7+
8+
NODE_VERSION="v22.12.0" # LTS version
9+
PLATFORM="${1:-darwin}"
10+
ARCH="${2:-arm64}"
11+
12+
# Map architecture names
13+
case "$ARCH" in
14+
arm64) NODE_ARCH="arm64" ;;
15+
x64) NODE_ARCH="x64" ;;
16+
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
17+
esac
18+
19+
# Map platform names
20+
case "$PLATFORM" in
21+
darwin) NODE_PLATFORM="darwin" ;;
22+
win32) NODE_PLATFORM="win" ;;
23+
linux) NODE_PLATFORM="linux" ;;
24+
*) echo "Unsupported platform: $PLATFORM"; exit 1 ;;
25+
esac
26+
27+
BIN_DIR="$(dirname "$0")/../bin"
28+
mkdir -p "$BIN_DIR"
29+
30+
if [ "$NODE_PLATFORM" = "win" ]; then
31+
FILENAME="node-${NODE_VERSION}-${NODE_PLATFORM}-${NODE_ARCH}.zip"
32+
URL="https://nodejs.org/dist/${NODE_VERSION}/${FILENAME}"
33+
34+
echo "Downloading Node.js ${NODE_VERSION} for ${NODE_PLATFORM}-${NODE_ARCH}..."
35+
curl -L "$URL" -o "/tmp/${FILENAME}"
36+
37+
echo "Extracting node.exe..."
38+
unzip -j "/tmp/${FILENAME}" "node-${NODE_VERSION}-${NODE_PLATFORM}-${NODE_ARCH}/node.exe" -d "$BIN_DIR"
39+
rm "/tmp/${FILENAME}"
40+
else
41+
FILENAME="node-${NODE_VERSION}-${NODE_PLATFORM}-${NODE_ARCH}.tar.gz"
42+
URL="https://nodejs.org/dist/${NODE_VERSION}/${FILENAME}"
43+
44+
echo "Downloading Node.js ${NODE_VERSION} for ${NODE_PLATFORM}-${NODE_ARCH}..."
45+
curl -L "$URL" -o "/tmp/${FILENAME}"
46+
47+
echo "Extracting node binary..."
48+
tar -xzf "/tmp/${FILENAME}" -C /tmp
49+
cp "/tmp/node-${NODE_VERSION}-${NODE_PLATFORM}-${NODE_ARCH}/bin/node" "$BIN_DIR/node"
50+
chmod +x "$BIN_DIR/node"
51+
rm -rf "/tmp/${FILENAME}" "/tmp/node-${NODE_VERSION}-${NODE_PLATFORM}-${NODE_ARCH}"
52+
fi
53+
54+
echo "Node.js binary installed to $BIN_DIR"
55+
ls -la "$BIN_DIR"

src/modules/cli/lib/execute-command.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { fork, ChildProcess, StdioOptions } from 'node:child_process';
22
import EventEmitter from 'node:events';
33
import * as Sentry from '@sentry/electron/main';
4-
import { getCliPath } from 'src/storage/paths';
4+
import { getBundledNodeBinaryPath, getCliPath } from 'src/storage/paths';
55

66
export interface CliCommandResult {
77
stdout: string;
@@ -55,13 +55,10 @@ export function executeCliCommand(
5555
stdio = [ 'ignore', 'ignore', 'ignore', 'ipc' ];
5656
}
5757

58-
// Using Electron's utilityProcess.fork API gave us issues with the child process never exiting
5958
const child = fork( cliPath, [ ...args, '--avoid-telemetry' ], {
6059
stdio,
61-
env: {
62-
...process.env,
63-
ELECTRON_RUN_AS_NODE: '1',
64-
},
60+
execPath: getBundledNodeBinaryPath(),
61+
env: process.env,
6562
} );
6663
const eventEmitter = new CliCommandEventEmitter();
6764

src/storage/paths.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ export function getCliPath(): string {
6666
: path.join( getResourcesPath(), 'cli', 'main.js' );
6767
}
6868

69+
export function getBundledNodeBinaryPath(): string {
70+
const nodeBinaryName = process.platform === 'win32' ? 'node.exe' : 'node';
71+
72+
if ( process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' ) {
73+
// In development, use system Node
74+
const { execSync } = require( 'child_process' );
75+
return execSync( 'which node', { encoding: 'utf-8' } ).trim();
76+
}
77+
78+
return path.join( getResourcesPath(), 'bin', nodeBinaryName );
79+
}
80+
6981
function getAppDataPath(): string {
7082
if ( inChildProcess() ) {
7183
if ( ! process.env.STUDIO_APP_DATA_PATH ) {

0 commit comments

Comments
 (0)