Skip to content
This repository was archived by the owner on Dec 27, 2025. It is now read-only.

Commit 062e287

Browse files
committed
feat: display @probitas package versions in --version output
Extend `probitas --version` to show all @probitas dependency versions alongside the CLI version. This helps users and maintainers understand which package versions are actually being used, including transitive dependencies. Implementation: - Add getVersionInfo() function that reads from deno.lock - Extract all @probitas/* package versions from lock file specifiers - Display packages in alphabetical order for consistent output - Preserve existing getVersion() for backward compatibility Example output: probitas 0.0.0 @probitas/builder 0.4.0 @probitas/client 0.4.1 @probitas/client-http 0.4.1 ...
1 parent fac275f commit 062e287

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

src/main.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { EXIT_CODE } from "./constants.ts";
1010
import { initCommand } from "./commands/init.ts";
1111
import { listCommand } from "./commands/list.ts";
1212
import { runCommand } from "./commands/run.ts";
13-
import { getVersion, readAsset } from "./utils.ts";
13+
import { getVersionInfo, readAsset } from "./utils.ts";
1414

1515
const logger = getLogger("probitas", "cli");
1616

@@ -39,8 +39,15 @@ export async function main(args: string[]): Promise<number> {
3939

4040
// Show version
4141
if (parsed.version) {
42-
const version = await getVersion() ?? "unknown";
43-
console.log(`probitas ${version}`);
42+
const info = await getVersionInfo();
43+
if (info) {
44+
console.log(`probitas ${info.version}`);
45+
for (const pkg of info.packages) {
46+
console.log(` ${pkg.name} ${pkg.version}`);
47+
}
48+
} else {
49+
console.log("probitas unknown");
50+
}
4451
return EXIT_CODE.SUCCESS;
4552
}
4653

src/utils.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,24 @@ const isDenoJson = is.ObjectOf({
2020
version: as.Optional(is.String),
2121
}) satisfies Predicate<DenoJson>;
2222

23+
type DenoLock = {
24+
specifiers?: Record<string, string>;
25+
};
26+
27+
const isDenoLock = is.ObjectOf({
28+
specifiers: as.Optional(is.RecordOf(is.String, is.String)),
29+
}) satisfies Predicate<DenoLock>;
30+
31+
/**
32+
* Version information including CLI and dependency versions
33+
*/
34+
export type VersionInfo = {
35+
/** CLI version */
36+
readonly version: string;
37+
/** @probitas package versions (sorted by name) */
38+
readonly packages: ReadonlyArray<{ name: string; version: string }>;
39+
};
40+
2341
const reporterMap: Record<string, (opts?: ReporterOptions) => Reporter> = {
2442
list: (opts) => new ListReporter(opts),
2543
json: (opts) => new JSONReporter(opts),
@@ -179,3 +197,61 @@ export async function getVersion(): Promise<string | undefined> {
179197
return undefined;
180198
}
181199
}
200+
201+
/**
202+
* Get version information including CLI and @probitas package versions
203+
*
204+
* Reads CLI version from deno.json and package versions from deno.lock.
205+
* Package versions are extracted from the specifiers section of deno.lock.
206+
*
207+
* @returns Version information including CLI and package versions
208+
*/
209+
export async function getVersionInfo(): Promise<VersionInfo | undefined> {
210+
try {
211+
// Get CLI version from deno.json
212+
const denoJsonUrl = new URL("../deno.json", import.meta.url);
213+
const denoJsonResp = await fetch(denoJsonUrl);
214+
const denoJsonContent = await denoJsonResp.text();
215+
const denoJson = ensure(JSON.parse(denoJsonContent), isDenoJson);
216+
217+
const version = denoJson.version ?? "unknown";
218+
219+
// Get package versions from deno.lock
220+
const denoLockUrl = new URL("../deno.lock", import.meta.url);
221+
const denoLockResp = await fetch(denoLockUrl);
222+
const denoLockContent = await denoLockResp.text();
223+
const denoLock = ensure(JSON.parse(denoLockContent), isDenoLock);
224+
225+
// Extract @probitas package versions from specifiers
226+
// Format: "jsr:@probitas/core@^0.2.0": "0.2.0"
227+
const packages: { name: string; version: string }[] = [];
228+
const seen = new Set<string>();
229+
230+
if (denoLock.specifiers) {
231+
for (
232+
const [specifier, resolvedVersion] of Object.entries(
233+
denoLock.specifiers,
234+
)
235+
) {
236+
// Match jsr:@probitas/package-name@version pattern
237+
const match = specifier.match(/^jsr:(@probitas\/[^@]+)@/);
238+
if (match) {
239+
const name = match[1];
240+
// Skip duplicates (same package with different version specifiers)
241+
if (!seen.has(name)) {
242+
seen.add(name);
243+
packages.push({ name, version: resolvedVersion });
244+
}
245+
}
246+
}
247+
}
248+
249+
// Sort packages by name for consistent output
250+
packages.sort((a, b) => a.name.localeCompare(b.name));
251+
252+
return { version, packages };
253+
} catch (err: unknown) {
254+
logger.debug("Failed to read version info", { err });
255+
return undefined;
256+
}
257+
}

0 commit comments

Comments
 (0)