Files
MTranServer/scripts/electron-dev.ts
2026-01-01 17:21:06 +08:00

117 lines
2.5 KiB
TypeScript

import { spawn } from 'child_process'
import fs from 'fs'
import path from 'path'
const root = process.cwd()
const electronBin = path.join(root, 'node_modules', '.bin', process.platform === 'win32' ? 'electron.cmd' : 'electron')
const bunBin = process.execPath
function run(command: string, args: string[]) {
return spawn(command, args, { stdio: 'inherit', env: process.env })
}
function runOnce(command: string, args: string[]) {
return new Promise<void>((resolve, reject) => {
const proc = run(command, args)
proc.on('exit', (code) => {
if (code === 0) resolve()
else reject(new Error(`exit ${code}`))
})
})
}
async function runBuildOnce() {
await runOnce(bunBin, ['run', 'build:lib'])
}
function startBuildWatch() {
const args = [
'build',
'src/index.ts',
'src/main.ts',
'src/desktop.ts',
'--outdir',
'dist',
'--target',
'node',
'--format',
'esm',
'--sourcemap',
'--external',
'zstd-wasm-decoder',
'--external',
'express',
'--watch'
]
return run(bunBin, args)
}
let electronProcess: ReturnType<typeof run> | null = null
let restartTimer: NodeJS.Timeout | null = null
let restarting = false
function startElectron() {
if (electronProcess) return
electronProcess = run(electronBin, ['./scripts/electron-main.js'])
electronProcess.on('exit', () => {
electronProcess = null
})
}
async function stopElectron() {
if (!electronProcess) return
const proc = electronProcess
await new Promise<void>((resolve) => {
proc.once('exit', () => resolve())
proc.kill('SIGTERM')
setTimeout(() => {
if (!proc.killed) {
proc.kill('SIGKILL')
}
}, 3000)
})
}
function scheduleRestart() {
if (restartTimer) clearTimeout(restartTimer)
restartTimer = setTimeout(async () => {
if (restarting) return
restarting = true
await stopElectron()
startElectron()
restarting = false
}, 250)
}
function watchPath(target: string) {
try {
fs.watch(target, () => scheduleRestart())
} catch {
return
}
}
function setupWatchers() {
watchPath(path.join(root, 'dist'))
watchPath(path.join(root, 'desktop'))
watchPath(path.join(root, 'scripts/electron-main.js'))
}
async function main() {
await runBuildOnce()
const buildWatcher = startBuildWatch()
startElectron()
setupWatchers()
const cleanup = async () => {
await stopElectron()
buildWatcher.kill('SIGTERM')
process.exit(0)
}
process.on('SIGINT', cleanup)
process.on('SIGTERM', cleanup)
}
main().catch(() => process.exit(1))