From f4aaf1701d7952fab8076b3a7e7e89840d1127f3 Mon Sep 17 00:00:00 2001 From: cyq <15000851237@163.com> Date: Tue, 2 Jun 2026 09:36:14 +0800 Subject: [PATCH] fix(npm): prefer binary version output --- npm/codewhale/scripts/run.js | 48 +++++++++++++++++++------------ npm/codewhale/test/run.test.js | 52 +++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/npm/codewhale/scripts/run.js b/npm/codewhale/scripts/run.js index 94e3b7e68..e9478374f 100644 --- a/npm/codewhale/scripts/run.js +++ b/npm/codewhale/scripts/run.js @@ -7,31 +7,43 @@ function isVersionFlag(args = process.argv.slice(2)) { return args.includes("--version") || args.includes("-V"); } -function handleVersionFallback(binaryName) { - if (isVersionFlag()) { - const binVersion = - pkg.codewhaleBinaryVersion || pkg.deepseekBinaryVersion || pkg.version; - console.log(`${binaryName} (npm wrapper) v${pkg.version}`); - console.log(`binary version: v${binVersion}`); - console.log(`repo: ${pkg.repository?.url || "N/A"}`); - process.exit(0); - } +function printVersionFallback(binaryName) { + const binVersion = + pkg.codewhaleBinaryVersion || pkg.deepseekBinaryVersion || pkg.version; + console.log(`${binaryName} (npm wrapper) v${pkg.version}`); + console.log(`binary version: v${binVersion}`); + console.log(`repo: ${pkg.repository?.url || "N/A"}`); } -async function run(binaryName) { - // Intercept --version before attempting binary download/launch - handleVersionFallback(binaryName); +async function run(binaryName, options = {}) { + const args = options.args || process.argv.slice(2); + const resolveBinaryPath = options.getBinaryPath || getBinaryPath; + const spawn = options.spawnSync || spawnSync; + const exit = options.exit || process.exit; + const versionFlag = isVersionFlag(args); + + let binaryPath; + try { + binaryPath = await resolveBinaryPath(binaryName); + } catch (error) { + if (versionFlag) { + printVersionFallback(binaryName); + return exit(0); + } + throw error; + } - const binaryPath = await getBinaryPath(binaryName); - const result = spawnSync(binaryPath, process.argv.slice(2), { + const result = spawn(binaryPath, args, { stdio: "inherit", }); if (result.error) { - // If binary fails and user asked for --version, show npm version instead - handleVersionFallback(binaryName); + if (versionFlag) { + printVersionFallback(binaryName); + return exit(0); + } throw result.error; } - process.exit(result.status ?? 1); + return exit(result.status ?? 1); } async function runCodeWhale() { @@ -46,7 +58,7 @@ module.exports = { run, runCodeWhale, runCodeWhaleTui, - _internal: { isVersionFlag }, + _internal: { isVersionFlag, printVersionFallback }, }; if (require.main === module) { diff --git a/npm/codewhale/test/run.test.js b/npm/codewhale/test/run.test.js index 3b471f1e6..5bc03a79c 100644 --- a/npm/codewhale/test/run.test.js +++ b/npm/codewhale/test/run.test.js @@ -1,7 +1,7 @@ const assert = require("node:assert/strict"); const test = require("node:test"); -const { _internal } = require("../scripts/run"); +const { run, _internal } = require("../scripts/run"); test("version fallback handles only version flags", () => { assert.equal(_internal.isVersionFlag(["--version"]), true); @@ -9,3 +9,53 @@ test("version fallback handles only version flags", () => { assert.equal(_internal.isVersionFlag(["-v"]), false); assert.equal(_internal.isVersionFlag(["--verbose"]), false); }); + +test("version flags prefer the installed binary over package metadata", async () => { + let spawned = false; + const exits = []; + + await run("codewhale", { + args: ["--version"], + getBinaryPath: async () => "/tmp/codewhale-test-binary", + spawnSync: (binary, args, options) => { + spawned = true; + assert.equal(binary, "/tmp/codewhale-test-binary"); + assert.deepEqual(args, ["--version"]); + assert.deepEqual(options, { stdio: "inherit" }); + return { status: 0 }; + }, + exit: (status) => { + exits.push(status); + }, + }); + + assert.equal(spawned, true); + assert.deepEqual(exits, [0]); +}); + +test("version flags fall back to package metadata when the binary is unavailable", async () => { + const originalLog = console.log; + const lines = []; + const exits = []; + console.log = (line) => lines.push(line); + try { + await run("codewhale", { + args: ["--version"], + getBinaryPath: async () => { + throw new Error("download unavailable"); + }, + spawnSync: () => { + throw new Error("spawn should not run without a binary"); + }, + exit: (status) => { + exits.push(status); + }, + }); + } finally { + console.log = originalLog; + } + + assert.deepEqual(exits, [0]); + assert.match(lines.join("\n"), /codewhale \(npm wrapper\) v/); + assert.match(lines.join("\n"), /binary version: v/); +});