diff --git a/package.json b/package.json index 9b23c28f..f6f90065 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "standalone:build": "node --max-old-space-size=8192 ./node_modules/electron-vite/bin/electron-vite.js build && node --max-old-space-size=8192 ./node_modules/vite/bin/vite.js build --config docker/vite.standalone.config.ts", "standalone:start": "node dist-standalone/index.cjs", "prepare": "husky", - "postinstall": "electron-rebuild -f -o node-pty,ssh2,cpu-features || echo 'native Electron rebuild failed (terminal/ssh features may be degraded)'" + "postinstall": "electron-rebuild -f -o node-pty,ssh2,cpu-features || echo 'native Electron rebuild failed (terminal/ssh features may be degraded)'; node ./scripts/ensure-electron-install.cjs" }, "lint-staged": { "src/**/*.{ts,tsx,js,jsx}": [ diff --git a/scripts/ensure-electron-install.cjs b/scripts/ensure-electron-install.cjs new file mode 100644 index 00000000..d91d7fbf --- /dev/null +++ b/scripts/ensure-electron-install.cjs @@ -0,0 +1,62 @@ +const childProcess = require('child_process'); +const fs = require('fs'); +const os = require('os'); +const path = require('path'); + +function getPlatformPath() { + const platform = process.env.npm_config_platform || os.platform(); + + switch (platform) { + case 'mas': + case 'darwin': + return 'Electron.app/Contents/MacOS/Electron'; + case 'freebsd': + case 'openbsd': + case 'linux': + return 'electron'; + case 'win32': + return 'electron.exe'; + default: + throw new Error(`Electron builds are not available on platform: ${platform}`); + } +} + +function ensurePathFile(electronDir, platformPath) { + const pathFile = path.join(electronDir, 'path.txt'); + const distPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(electronDir, 'dist'); + const executablePath = path.join(distPath, platformPath); + + if (!fs.existsSync(executablePath)) { + return false; + } + + const currentPath = fs.existsSync(pathFile) ? fs.readFileSync(pathFile, 'utf8') : ''; + if (currentPath !== platformPath) { + fs.writeFileSync(pathFile, platformPath); + } + return true; +} + +function runElectronInstaller(installPath) { + const result = childProcess.spawnSync(process.execPath, [installPath], { + stdio: 'inherit', + env: process.env, + }); + + if (result.status !== 0) { + throw new Error(`Electron installer failed with exit code ${result.status ?? 'unknown'}`); + } +} + +const electronPackagePath = require.resolve('electron/package.json'); +const electronDir = path.dirname(electronPackagePath); +const installPath = path.join(electronDir, 'install.js'); +const platformPath = getPlatformPath(); + +if (!ensurePathFile(electronDir, platformPath)) { + runElectronInstaller(installPath); +} + +if (!ensurePathFile(electronDir, platformPath)) { + throw new Error(`Electron binary is missing after install: ${platformPath}`); +}