fix(cli): report binary startup failures with actionable diagnostics (#220)

This commit is contained in:
Mark L
2026-02-27 09:01:24 +08:00
committed by GitHub
parent acfc777d08
commit 1f958f44fa
2 changed files with 147 additions and 27 deletions
+83 -27
View File
@@ -5,44 +5,100 @@ const path = require('path');
const platform = process.platform;
const arch = process.arch;
const pkgName = `@twsxtd/hapi-${platform}-${arch}`;
function getBinaryPath() {
function getBinaryPath(platformName = platform, archName = arch) {
const pkgName = `@twsxtd/hapi-${platformName}-${archName}`;
try {
// Try to find the platform-specific package
const pkgPath = require.resolve(`${pkgName}/package.json`);
const binName = platform === 'win32' ? 'hapi.exe' : 'hapi';
const binName = platformName === 'win32' ? 'hapi.exe' : 'hapi';
return path.join(path.dirname(pkgPath), 'bin', binName);
} catch (e) {
return null;
}
}
const binPath = getBinaryPath();
if (!binPath) {
console.error(`Unsupported platform: ${platform}-${arch}`);
console.error('');
console.error('Supported platforms:');
console.error(' - darwin-arm64 (macOS Apple Silicon)');
console.error(' - darwin-x64 (macOS Intel)');
console.error(' - linux-arm64');
console.error(' - linux-x64');
console.error(' - win32-x64');
console.error('');
console.error('You can download the binary manually from:');
console.error(' https://github.com/tiann/hapi/releases');
process.exit(1);
function formatCommand(binPath, args) {
return [binPath, ...args].map((arg) => JSON.stringify(String(arg))).join(' ');
}
try {
execFileSync(binPath, process.argv.slice(2), { stdio: 'inherit' });
} catch (e) {
// If the binary execution fails, exit with the same code
if (e.status !== undefined) {
process.exit(e.status);
function normalizeExecError(error) {
return {
status: typeof error?.status === 'number' ? error.status : null,
signal: typeof error?.signal === 'string' ? error.signal : null,
message: error?.message ? String(error.message) : null,
};
}
function reportExecutionFailure(error, binPath, args, log = console.error) {
const { status, signal, message } = normalizeExecError(error);
log(`Failed to execute: ${formatCommand(binPath, args)}`);
if (signal) {
log(`Binary terminated by signal ${signal}.`);
}
// For other errors (e.g., binary not found), print and exit
console.error(`Failed to execute ${binPath}:`, e.message);
process.exit(1);
if (status !== null) {
log(`Binary exited with status ${status}.`);
}
if (message) {
log(message);
}
return { status, signal };
}
function main() {
const binPath = getBinaryPath();
if (!binPath) {
console.error(`Unsupported platform: ${platform}-${arch}`);
console.error('');
console.error('Supported platforms:');
console.error(' - darwin-arm64 (macOS Apple Silicon)');
console.error(' - darwin-x64 (macOS Intel)');
console.error(' - linux-arm64');
console.error(' - linux-x64');
console.error(' - win32-x64');
console.error('');
console.error('You can download the binary manually from:');
console.error(' https://github.com/tiann/hapi/releases');
process.exit(1);
}
const args = process.argv.slice(2);
try {
execFileSync(binPath, args, { stdio: 'inherit' });
} catch (error) {
const { status, signal } = reportExecutionFailure(error, binPath, args);
if (status !== null) {
process.exit(status);
}
if (signal) {
try {
process.kill(process.pid, signal);
} catch {
// ignore unsupported/invalid signal names on this platform
}
}
process.exit(1);
}
}
if (require.main === module) {
main();
}
module.exports = {
formatCommand,
getBinaryPath,
normalizeExecError,
reportExecutionFailure,
};