gitlink-cli/npm/bin/cli.js

121 lines
3.3 KiB
JavaScript
Executable File

#!/usr/bin/env node
"use strict";
const fs = require("fs");
const path = require("path");
const https = require("https");
const http = require("http");
const { execFileSync } = require("child_process");
const BINARY_NAME = "gitlink-cli";
const PACKAGE = require("../package.json");
const CURRENT_VERSION = PACKAGE.version;
function getBinaryName(platform = process.platform) {
return platform === "win32" ? `${BINARY_NAME}.exe` : BINARY_NAME;
}
function getBinaryPath(platform = process.platform, baseDir = __dirname) {
return path.join(baseDir, getBinaryName(platform));
}
function formatMissingBinaryError(
binaryPath,
platform = process.platform,
arch = process.arch
) {
return [
`Error: ${BINARY_NAME} binary not found at ${binaryPath}`,
`Platform: ${platform}/${arch}`,
"",
"The npm package was installed, but the native binary is missing.",
"This usually means the release asset for your platform is unavailable or postinstall failed.",
"",
"Try reinstalling:",
" npm install -g @gitlink-ai/cli",
"",
"If the problem persists, check the GitLink CLI release assets:",
" https://www.gitlink.org.cn/Gitlink/gitlink-cli/releases",
].join("\n");
}
function checkForUpdate() {
if (process.env.GITLINK_CLI_NO_UPDATE_CHECK) return;
const registryUrl = "https://registry.npmjs.org/@gitlink-ai/cli/latest";
const mod = registryUrl.startsWith("https") ? https : http;
try {
mod.get(registryUrl, { timeout: 3000 }, (res) => {
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => {
try {
const pkg = JSON.parse(body);
const latest = pkg.version;
if (latest && latest !== CURRENT_VERSION) {
process.stderr.write(
`\nA new version of ${BINARY_NAME} is available: ${latest} (current: ${CURRENT_VERSION})\n` +
`Update with: npm update -g @gitlink-ai/cli\n\n`
);
}
} catch {
// Silently ignore parse errors
}
});
}).on("error", () => {
// Silently ignore network errors
});
} catch {
// Silently ignore any errors
}
}
function run(args = process.argv.slice(2), options = {}) {
const platform = options.platform || process.platform;
const arch = options.arch || process.arch;
const binaryPath = options.binaryPath || getBinaryPath(platform);
const execFile = options.execFileSync || execFileSync;
const stderr = options.stderr || process.stderr;
const exit = options.exit || process.exit;
function failMissingBinary() {
stderr.write(`${formatMissingBinaryError(binaryPath, platform, arch)}\n`);
return exit(1);
}
// Binary existence check before any other logic
if (!fs.existsSync(binaryPath)) {
return failMissingBinary();
}
// Run optional update check in background (fire-and-forget)
if (require.main === module) {
checkForUpdate();
}
try {
execFile(binaryPath, args, { stdio: "inherit" });
} catch (err) {
if (err.code === "ENOENT") {
return failMissingBinary();
}
if (err.status !== undefined) {
return exit(err.status);
}
stderr.write(`Failed to run ${BINARY_NAME}: ${err.message}\n`);
return exit(1);
}
}
if (require.main === module) {
run();
}
module.exports = {
getBinaryName,
getBinaryPath,
formatMissingBinaryError,
run,
checkForUpdate,
};