blob: 6b7f2c4229e0cce16ecf39f725b3466cc15b10d8 [file]
#!/usr/bin/env node
import { spawn } from 'node:child_process';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import {
clearDevelopmentSession,
createDevelopmentSession,
quitMacosDevelopmentApp,
recoverStaleDevelopmentSession,
resolveMacosDevelopmentLaunch,
waitForMacosDevelopmentApp,
writeDevelopmentSession,
} from './dev-app-runtime.mjs';
const desktopDir = resolve(fileURLToPath(new URL('..', import.meta.url)));
const repoRoot = resolve(desktopDir, '..', '..');
const cliArgs = process.argv.slice(2);
const forwardedArgs = [desktopDir, ...cliArgs];
const macosLaunch = await resolveMacosDevelopmentLaunch();
if (macosLaunch) {
await recoverStaleDevelopmentSession();
const userDataArg = cliArgs.find((arg) => arg.startsWith('--user-data-dir='));
writeDevelopmentSession(createDevelopmentSession({
supervisorPid: process.pid,
env: process.env,
userDataDir: userDataArg?.slice('--user-data-dir='.length),
electronArgs: cliArgs.filter((arg) => !arg.startsWith('--user-data-dir=')),
}));
}
const electronBin =
process.platform === 'win32'
? join(repoRoot, 'node_modules', 'electron', 'dist', 'electron.exe')
: join(repoRoot, 'node_modules', '.bin', 'electron');
const command = macosLaunch?.command ?? electronBin;
const args = macosLaunch?.args ?? ['.', ...process.argv.slice(2)];
const child = spawn(command, args, {
cwd: desktopDir,
stdio: 'inherit',
env: process.env,
});
const keepAlive = macosLaunch ? setInterval(() => undefined, 60_000) : null;
let stopping = false;
async function stop() {
if (stopping) return;
stopping = true;
if (macosLaunch) {
await quitMacosDevelopmentApp();
clearDevelopmentSession();
} else child.kill('SIGTERM');
if (keepAlive) clearInterval(keepAlive);
process.exitCode = 0;
}
child.on('error', (error) => {
console.error(`[dev-app] failed to start: ${error.message}`);
void stop().then(() => {
process.exitCode = 1;
});
});
child.on('exit', (code, signal) => {
if (!macosLaunch && !stopping) {
process.exitCode = signal ? 1 : (code ?? 0);
} else if (macosLaunch && code && code !== 0) {
void stop().then(() => {
process.exitCode = code;
});
}
});
process.on('SIGINT', () => void stop());
process.on('SIGTERM', () => void stop());
if (macosLaunch) {
void waitForMacosDevelopmentApp().then(
() => console.log('[dev-app] Maka Dev startup handshake complete'),
(error) => {
console.error(`[dev-app] ${error.message}`);
void stop().then(() => {
process.exitCode = 1;
});
},
);
}
// `open` exits immediately after handing the launch to LaunchServices. The
// timer above keeps the supervisor alive so app restarts can recover its session.