99 lines
3.4 KiB
JavaScript
99 lines
3.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/*
|
|
* Ensures the Electron binary exists after `pnpm install`.
|
|
*
|
|
* On some Windows/Node combos electron's own install script dies silently:
|
|
* its extract-zip dependency drops the event loop mid-extraction and the
|
|
* process exits 0 with a partial `dist/` and no `path.txt`, which later makes
|
|
* electron-vite fail with "Error: Electron uninstall". The download/cache
|
|
* layer (@electron/get) is unaffected, so when that happens we fetch the zip
|
|
* through it and extract with the OS-native unzipper instead.
|
|
*
|
|
* No-op when the binary is already in place (the normal case on macOS/Linux).
|
|
*/
|
|
const { createRequire } = require('node:module');
|
|
const { execFileSync } = require('node:child_process');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const electronPkgJson = require.resolve('electron/package.json');
|
|
const electronDir = path.dirname(electronPkgJson);
|
|
const electronRequire = createRequire(electronPkgJson);
|
|
|
|
const platformPath = {
|
|
win32: 'electron.exe',
|
|
darwin: 'Electron.app/Contents/MacOS/Electron',
|
|
mas: 'Electron.app/Contents/MacOS/Electron',
|
|
}[process.platform] || 'electron';
|
|
|
|
function isInstalled() {
|
|
try {
|
|
return (
|
|
fs.readFileSync(path.join(electronDir, 'path.txt'), 'utf8') === platformPath &&
|
|
fs.existsSync(path.join(electronDir, 'dist', platformPath))
|
|
);
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function extractNatively(zipPath, dist) {
|
|
if (process.platform === 'win32') {
|
|
execFileSync('powershell.exe', [
|
|
'-NoProfile', '-NonInteractive', '-Command',
|
|
`Expand-Archive -LiteralPath "${zipPath}" -DestinationPath "${dist}" -Force`,
|
|
], { stdio: 'inherit' });
|
|
} else if (process.platform === 'darwin') {
|
|
// ditto preserves the Electron.app symlinks and executable bits
|
|
execFileSync('ditto', ['-xk', zipPath, dist], { stdio: 'inherit' });
|
|
} else {
|
|
execFileSync('unzip', ['-oq', zipPath, '-d', dist], { stdio: 'inherit' });
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
if (isInstalled()) return;
|
|
|
|
// Normal route: electron's own installer (covers the case where pnpm
|
|
// skipped its build script).
|
|
try {
|
|
execFileSync(process.execPath, [path.join(electronDir, 'install.js')], { stdio: 'inherit' });
|
|
} catch {
|
|
// fall through to the manual route
|
|
}
|
|
if (isInstalled()) return;
|
|
|
|
console.log('[ensure-electron] electron install script left no binary; extracting manually...');
|
|
const { downloadArtifact } = electronRequire('@electron/get');
|
|
const { version } = electronRequire('./package.json');
|
|
const zipPath = await downloadArtifact({
|
|
version,
|
|
artifactName: 'electron',
|
|
cacheRoot: process.env.electron_config_cache,
|
|
checksums: electronRequire('./checksums.json'),
|
|
platform: process.platform,
|
|
arch: process.arch,
|
|
});
|
|
|
|
const dist = path.join(electronDir, 'dist');
|
|
fs.rmSync(dist, { recursive: true, force: true });
|
|
fs.mkdirSync(dist, { recursive: true });
|
|
extractNatively(zipPath, dist);
|
|
|
|
const typeDef = path.join(dist, 'electron.d.ts');
|
|
if (fs.existsSync(typeDef)) {
|
|
fs.renameSync(typeDef, path.join(electronDir, 'electron.d.ts'));
|
|
}
|
|
fs.writeFileSync(path.join(electronDir, 'path.txt'), platformPath);
|
|
|
|
if (!isInstalled()) {
|
|
throw new Error('Electron binary still missing after manual extraction');
|
|
}
|
|
console.log('[ensure-electron] Electron binary restored.');
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('[ensure-electron] failed:', err);
|
|
process.exit(1);
|
|
});
|