diff --git a/__tests__/version.test.ts b/__tests__/version.test.ts new file mode 100644 index 0000000..a1b94ef --- /dev/null +++ b/__tests__/version.test.ts @@ -0,0 +1,30 @@ +import { readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { afterEach, describe, expect, it, vi } from 'vitest'; + +class ExitCalled extends Error {} + +const realArgv = process.argv; + +afterEach(() => { + process.argv = realArgv; + vi.restoreAllMocks(); +}); + +describe('anyapi --version', () => { + it('prints the version in package.json, not a second copy', async () => { + const manifest = JSON.parse(readFileSync(join(process.cwd(), 'package.json'), 'utf8')); + let printed = ''; + vi.spyOn(process.stdout, 'write').mockImplementation((chunk) => { + printed += String(chunk); + return true; + }); + vi.spyOn(process, 'exit').mockImplementation(() => { + throw new ExitCalled(); + }); + process.argv = ['node', 'anyapi', '--version']; + + await expect(import('../src/index.js')).rejects.toBeInstanceOf(ExitCalled); + expect(printed).toBe(`${manifest.version}\n`); + }); +}); diff --git a/src/index.ts b/src/index.ts index 2cfb4c0..b966b56 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,6 +20,7 @@ import { feedbackCommand, reportBugCommand } from "./feedback.js"; import { CliError } from "./errors.js"; import { defaultContext } from "./io.js"; import { normalizeRunCLIOptions } from "./run.js"; +import { VERSION } from "./version.js"; const program = new Command(); const ctx = defaultContext(); @@ -31,7 +32,7 @@ program "--api-key ", "AnyAPI API key. Overrides ANYAPI_API_KEY and local config.", ) - .version("0.8.0"); + .version(VERSION); program .command("signup") diff --git a/src/version.ts b/src/version.ts new file mode 100644 index 0000000..661419d --- /dev/null +++ b/src/version.ts @@ -0,0 +1,12 @@ +import { createRequire } from 'node:module'; + +/** + * The package version, read from `package.json` rather than authored here. + * + * `../package.json` resolves from both `src/` and the published `dist/`, and npm + * always packs `package.json`, so `anyapi --version` reports the release that is + * actually installed. A hand-kept copy drifted from the published version. + */ +export const VERSION: string = ( + createRequire(import.meta.url)('../package.json') as { version: string } +).version;