2026-04-22 04:33:38 +02:00
|
|
|
import { execFileSync, spawn } from 'child_process'
|
2026-05-06 16:15:42 +08:00
|
|
|
import { join } from 'path'
|
2026-04-22 04:33:38 +02:00
|
|
|
|
|
|
|
|
function getNpmBin() {
|
2026-05-06 16:15:42 +08:00
|
|
|
return process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
2026-04-22 04:33:38 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-06 16:15:42 +08:00
|
|
|
function getGlobalPrefix() {
|
|
|
|
|
return execFileSync(getNpmBin(), ['prefix', '-g'], {
|
|
|
|
|
encoding: 'utf-8',
|
|
|
|
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
|
|
|
}).trim()
|
2026-04-22 04:33:38 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-06 16:15:42 +08:00
|
|
|
function getGlobalCliBin() {
|
|
|
|
|
const prefix = getGlobalPrefix()
|
2026-04-22 04:33:38 +02:00
|
|
|
|
|
|
|
|
if (process.platform === 'win32') {
|
2026-05-06 16:15:42 +08:00
|
|
|
return join(prefix, 'hermes-web-ui.cmd')
|
2026-04-22 04:33:38 +02:00
|
|
|
}
|
|
|
|
|
|
2026-05-06 16:15:42 +08:00
|
|
|
return join(prefix, 'bin', 'hermes-web-ui')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function runUpdateInstall() {
|
2026-04-22 04:33:38 +02:00
|
|
|
return execFileSync(getNpmBin(), ['install', '-g', 'hermes-web-ui@latest'], {
|
|
|
|
|
encoding: 'utf-8',
|
2026-05-06 16:15:42 +08:00
|
|
|
timeout: 10 * 60 * 1000,
|
2026-04-22 04:33:38 +02:00
|
|
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function spawnRestart(port: string) {
|
2026-05-06 16:15:42 +08:00
|
|
|
const cli = getGlobalCliBin()
|
2026-04-22 04:33:38 +02:00
|
|
|
|
2026-05-06 16:15:42 +08:00
|
|
|
return spawn(cli, ['restart', '--port', port], {
|
2026-04-22 04:33:38 +02:00
|
|
|
detached: true,
|
|
|
|
|
stdio: 'ignore',
|
|
|
|
|
windowsHide: true,
|
|
|
|
|
})
|
|
|
|
|
}
|
2026-04-21 12:35:48 +08:00
|
|
|
|
|
|
|
|
export async function handleUpdate(ctx: any) {
|
|
|
|
|
try {
|
2026-04-22 04:33:38 +02:00
|
|
|
const output = runUpdateInstall()
|
2026-05-06 16:15:42 +08:00
|
|
|
|
|
|
|
|
ctx.body = {
|
|
|
|
|
success: true,
|
|
|
|
|
message: output.trim() || 'hermes-web-ui updated successfully',
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-21 12:35:48 +08:00
|
|
|
setTimeout(() => {
|
2026-05-06 16:15:42 +08:00
|
|
|
try {
|
|
|
|
|
spawnRestart(process.env.PORT || '8648').unref()
|
|
|
|
|
} finally {
|
|
|
|
|
process.exit(0)
|
|
|
|
|
}
|
|
|
|
|
}, 3000)
|
2026-04-21 12:35:48 +08:00
|
|
|
} catch (err: any) {
|
2026-04-22 04:33:38 +02:00
|
|
|
ctx.status = 500
|
2026-05-06 16:15:42 +08:00
|
|
|
ctx.body = {
|
|
|
|
|
success: false,
|
|
|
|
|
message: err.stderr?.toString() || err.message || String(err),
|
|
|
|
|
}
|
2026-04-21 12:35:48 +08:00
|
|
|
}
|
|
|
|
|
}
|