Skip to content

Commit a22a683

Browse files
committed
feat(cli): add plebbit-js version and commit to --version output
Display plebbit-js version and git commit hash on a second line when running bitsocial --version. This helps users identify which version of the plebbit-js library is bundled with their CLI installation. Output format: bitsocial-cli/0.18.0 linux-x64 node-v22.18.0 plebbit-js/0.0.8 (a21d896)
1 parent 23c2189 commit a22a683

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

src/cli/hooks/init/version-hook.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Hook } from "@oclif/core";
2+
import { createRequire } from "module";
3+
import { readFileSync } from "fs";
4+
import { dirname, join } from "path";
5+
6+
// Get plebbit-js version from its package.json
7+
const getPlebbitJsVersion = (): string => {
8+
const require = createRequire(import.meta.url);
9+
// Get path to plebbit-js module
10+
const plebbitJsPath = require.resolve("@plebbit/plebbit-js");
11+
// Navigate to package root (plebbit-js main export is dist/node/index.js)
12+
const plebbitJsRoot = dirname(dirname(dirname(plebbitJsPath)));
13+
const plebbitPkgPath = join(plebbitJsRoot, "package.json");
14+
const plebbitPkg = JSON.parse(readFileSync(plebbitPkgPath, "utf-8"));
15+
return plebbitPkg.version;
16+
};
17+
18+
// Get commit hash from CLI's package.json dependency URL
19+
const getPlebbitJsCommit = (cliRoot: string): string | undefined => {
20+
try {
21+
const cliPkgPath = join(cliRoot, "package.json");
22+
const cliPkg = JSON.parse(readFileSync(cliPkgPath, "utf-8"));
23+
const plebbitJsDep = cliPkg.dependencies["@plebbit/plebbit-js"];
24+
// Extract commit hash from URL like "https://github.com/plebbit/plebbit-js#a21d896bd55c76070758dae65dc0693d1c3726db"
25+
const match = plebbitJsDep?.match(/#([a-f0-9]+)$/);
26+
return match ? match[1].substring(0, 7) : undefined;
27+
} catch {
28+
return undefined;
29+
}
30+
};
31+
32+
const hook: Hook<"init"> = async function (opts) {
33+
// Check process.argv because oclif normalizes argv and --version becomes the id, not part of argv
34+
if (process.argv.includes("--version")) {
35+
const { config } = opts;
36+
const plebbitJsVersion = getPlebbitJsVersion();
37+
const commit = getPlebbitJsCommit(config.root);
38+
const commitStr = commit ? ` (${commit})` : "";
39+
40+
// Output CLI version on first line, plebbit-js version + commit on second line
41+
this.log(`${config.name}/${config.version} ${config.platform}-${config.arch} node-${process.version}`);
42+
this.log(`plebbit-js/${plebbitJsVersion}${commitStr}`);
43+
// Use process.exit to actually stop - this.exit(0) throws an error that gets caught by oclif
44+
process.exit(0);
45+
}
46+
};
47+
48+
export default hook;

test/cli/version.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { spawn } from "child_process";
2+
import { describe, it, expect } from "vitest";
3+
import { join } from "path";
4+
import { readFileSync } from "fs";
5+
6+
const CLI_PATH = join(process.cwd(), "bin", "run");
7+
const PACKAGE_JSON_PATH = join(process.cwd(), "package.json");
8+
9+
// Get expected values from package.json
10+
const getExpectedValues = () => {
11+
const cliPkg = JSON.parse(readFileSync(PACKAGE_JSON_PATH, "utf-8"));
12+
const cliVersion = cliPkg.version;
13+
const plebbitJsDep = cliPkg.dependencies["@plebbit/plebbit-js"];
14+
// Extract commit hash from URL like "https://github.com/plebbit/plebbit-js#a21d896bd55c76070758dae65dc0693d1c3726db"
15+
const commitMatch = plebbitJsDep?.match(/#([a-f0-9]+)$/);
16+
const commit = commitMatch ? commitMatch[1].substring(0, 7) : undefined;
17+
return { cliVersion, commit };
18+
};
19+
20+
describe("bitsocial --version", () => {
21+
it("should print CLI version and plebbit-js version with commit hash", async () => {
22+
const { cliVersion, commit } = getExpectedValues();
23+
24+
const result = await new Promise<{ stdout: string; stderr: string; exitCode: number | null }>((resolve) => {
25+
const proc = spawn("node", [CLI_PATH, "--version"], {
26+
cwd: process.cwd(),
27+
env: { ...process.env }
28+
});
29+
30+
let stdout = "";
31+
let stderr = "";
32+
33+
proc.stdout.on("data", (data) => {
34+
stdout += data.toString();
35+
});
36+
37+
proc.stderr.on("data", (data) => {
38+
stderr += data.toString();
39+
});
40+
41+
proc.on("close", (exitCode) => {
42+
resolve({ stdout, stderr, exitCode });
43+
});
44+
});
45+
46+
expect(result.exitCode).toBe(0);
47+
48+
const lines = result.stdout.trim().split("\n");
49+
expect(lines.length).toBe(2);
50+
51+
// First line should contain CLI name and version
52+
expect(lines[0]).toContain("bitsocial-cli");
53+
expect(lines[0]).toContain(cliVersion);
54+
expect(lines[0]).toMatch(/linux-x64|darwin-x64|darwin-arm64|win32-x64/);
55+
expect(lines[0]).toMatch(/node-v\d+\.\d+\.\d+/);
56+
57+
// Second line should contain plebbit-js version and commit
58+
expect(lines[1]).toContain("plebbit-js/");
59+
if (commit) {
60+
expect(lines[1]).toContain(`(${commit})`);
61+
}
62+
});
63+
});

0 commit comments

Comments
 (0)