diff --git a/build.ts b/build.ts index 20cab98..437f6d6 100644 --- a/build.ts +++ b/build.ts @@ -3,13 +3,14 @@ import { readFileSync, writeFileSync } from 'fs'; const pkg = JSON.parse(readFileSync('package.json', 'utf-8')); const VERSION = process.env.VERSION ?? pkg.version; const OUT = 'dist/mmx.mjs'; +const DEV_BUILD = process.argv.includes('--dev'); await Bun.build({ entrypoints: ['src/main.ts'], outdir: 'dist', naming: 'mmx.mjs', target: 'node', - minify: true, + minify: !DEV_BUILD, define: { 'process.env.CLI_VERSION': JSON.stringify(VERSION) }, }); diff --git a/package.json b/package.json index ba9efc7..b51688b 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "scripts": { "dev": "bun run src/main.ts", "build": "bun run build.ts", - "build:dev": "bun build src/main.ts --outfile dist/mmx.mjs --target node --minify --define \"process.env.CLI_VERSION='1.0.4'\" && printf '#!/usr/bin/env node\\n' | cat - dist/mmx.mjs > dist/tmp && mv dist/tmp dist/mmx.mjs && chmod +x dist/mmx.mjs", + "build:dev": "bun run build.ts --dev", "prepublishOnly": "bun run build", "lint": "eslint src/ test/", "typecheck": "tsc --noEmit", diff --git a/src/client/http.ts b/src/client/http.ts index 8382b55..7e327d6 100644 --- a/src/client/http.ts +++ b/src/client/http.ts @@ -5,6 +5,7 @@ import { ExitCode } from '../errors/codes'; import { resolveCredential } from '../auth/resolver'; import { mapApiError } from '../errors/api'; import { maybeShowStatusBar } from '../output/status-bar'; +import { CLI_VERSION } from '../version'; export interface RequestOpts { url: string; @@ -20,9 +21,8 @@ export interface RequestOpts { export async function request(config: Config, opts: RequestOpts): Promise { const isFormData = typeof FormData !== 'undefined' && opts.body instanceof FormData; - const version = process.env.CLI_VERSION ?? '1.0.4'; const headers: Record = { - 'User-Agent': `mmx-cli/${version}`, + 'User-Agent': `mmx-cli/${CLI_VERSION}`, ...opts.headers, }; diff --git a/src/commands/update.ts b/src/commands/update.ts index ca43689..d4b3c9a 100644 --- a/src/commands/update.ts +++ b/src/commands/update.ts @@ -1,6 +1,5 @@ import { defineCommand } from '../command'; - -const CLI_VERSION = process.env.CLI_VERSION ?? '0.0.0'; +import { CLI_VERSION } from '../version'; export default defineCommand({ name: 'update', diff --git a/src/main.ts b/src/main.ts index cd7f630..67bd2c3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,8 +8,7 @@ import { REGIONS, type Region } from './config/schema'; import { checkForUpdate, getPendingUpdateNotification } from './update/checker'; import { loadCredentials } from './auth/credentials'; import { ensureApiKey } from './auth/setup'; - -const CLI_VERSION = process.env.CLI_VERSION ?? '1.0.4'; +import { CLI_VERSION } from './version'; // Handle Ctrl+C gracefully process.on('SIGINT', () => { diff --git a/src/version.ts b/src/version.ts new file mode 100644 index 0000000..d20aab9 --- /dev/null +++ b/src/version.ts @@ -0,0 +1,3 @@ +import pkg from '../package.json' with { type: 'json' }; + +export const CLI_VERSION = process.env.CLI_VERSION ?? pkg.version; diff --git a/test/client/http.test.ts b/test/client/http.test.ts index f59f882..07c0aeb 100644 --- a/test/client/http.test.ts +++ b/test/client/http.test.ts @@ -1,5 +1,6 @@ import { describe, it, expect, afterEach } from 'bun:test'; import { requestJson } from '../../src/client/http'; +import { CLI_VERSION } from '../../src/version'; import { createMockServer, jsonResponse, type MockServer } from '../helpers/mock-server'; import type { Config } from '../../src/config/schema'; @@ -28,9 +29,13 @@ describe('HTTP client', () => { }); it('makes authenticated GET request', async () => { + let userAgent: string | null = null; server = createMockServer({ routes: { - '/v1/test': () => jsonResponse({ result: 'ok' }), + '/v1/test': (req) => { + userAgent = req.headers.get('user-agent'); + return jsonResponse({ result: 'ok' }); + }, }, }); @@ -40,6 +45,7 @@ describe('HTTP client', () => { }); expect(result.result).toBe('ok'); + expect(userAgent ?? '').toBe(`mmx-cli/${CLI_VERSION}`); }); it('makes POST request with body', async () => { diff --git a/test/version.test.ts b/test/version.test.ts new file mode 100644 index 0000000..b3f18de --- /dev/null +++ b/test/version.test.ts @@ -0,0 +1,22 @@ +import { describe, it, expect } from 'bun:test'; +import { readFileSync } from 'fs'; +import { spawnSync } from 'child_process'; +import { CLI_VERSION } from '../src/version'; + +const packageVersion = (JSON.parse(readFileSync('package.json', 'utf-8')) as { version: string }).version; + +describe('CLI version', () => { + it('uses package.json as the source version when no build override is present', () => { + expect(CLI_VERSION).toBe(packageVersion); + }); + + it('prints the package version in dev mode', () => { + const result = spawnSync(process.execPath, ['src/main.ts', '--version'], { + cwd: process.cwd(), + encoding: 'utf-8', + }); + + expect(result.status).toBe(0); + expect(result.stdout.trim()).toBe(`mmx ${packageVersion}`); + }); +});