diff --git a/package.json b/package.json index f2027ea..cdac9c1 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "build:app": "vite build", "dev": "node scripts/dev-server.mjs", "start": "node dist/cli.js serve", - "test": "tsx src/config.test.ts && tsx src/roots.test.ts && tsx src/skills.test.ts && tsx src/workspaces.test.ts && tsx src/review-checkpoints.test.ts && tsx src/oauth-store.test.ts", + "test": "tsx src/config.test.ts && tsx src/roots.test.ts && tsx src/skills.test.ts && tsx src/workspaces.test.ts && tsx src/review-checkpoints.test.ts && tsx src/oauth-store.test.ts && tsx src/cli.test.ts", "typecheck": "tsc -p tsconfig.json --noEmit" }, "keywords": [], diff --git a/src/cli.test.ts b/src/cli.test.ts new file mode 100644 index 0000000..96dfd55 --- /dev/null +++ b/src/cli.test.ts @@ -0,0 +1,16 @@ +import assert from "node:assert/strict"; +import { execFileSync } from "node:child_process"; +import { readFileSync } from "node:fs"; + +const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")) as { + version: string; +}; + +for (const flag of ["-v", "--version"]) { + const output = execFileSync("node", ["--import", "tsx", "src/cli.ts", flag], { + encoding: "utf8", + env: { ...process.env, DEVSPACE_CONFIG_DIR: "/tmp/devspace-cli-version-test" }, + }).trim(); + + assert.equal(output, packageJson.version); +} diff --git a/src/cli.ts b/src/cli.ts index fb0272d..87ba662 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -15,7 +15,7 @@ import { } from "./user-config.js"; import { expandHomePath } from "./roots.js"; -type Command = "serve" | "init" | "doctor" | "config" | "help"; +type Command = "serve" | "init" | "doctor" | "config" | "help" | "version"; const require = createRequire(import.meta.url); const SUPPORTED_NODE_RANGE = ">=20.12 <27"; @@ -42,6 +42,9 @@ async function main(argv: string[]): Promise { case "help": printHelp(); return; + case "version": + printVersion(); + return; } } @@ -49,6 +52,7 @@ function normalizeCommand(command: string | undefined): Command { if (!command || command === "serve" || command === "start") return "serve"; if (command === "init" || command === "doctor" || command === "config") return command; if (command === "help" || command === "--help" || command === "-h") return "help"; + if (command === "version" || command === "--version" || command === "-v") return "version"; throw new Error(`Unknown command: ${command}`); } @@ -264,6 +268,7 @@ function printHelp(): void { " devspace doctor Show config, runtime, and native dependency status", " devspace config get Print persisted config", " devspace config set publicBaseUrl ", + " devspace -v, --version Print the installed version", "", "For temporary tunnels:", " DEVSPACE_PUBLIC_BASE_URL=https://example.trycloudflare.com devspace serve", @@ -271,6 +276,15 @@ function printHelp(): void { ); } +function printVersion(): void { + const packageJson = require("../package.json") as { version?: unknown }; + if (typeof packageJson.version !== "string") { + throw new Error("Unable to read DevSpace package version."); + } + + console.log(packageJson.version); +} + function normalizeOptionalPublicBaseUrl(value: string): string | null { const trimmed = value.trim(); if (!trimmed || trimmed === "null" || trimmed === "none") return null;