diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 33b3ce1b..e234402c 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,6 +1,7 @@ # Mops CLI Changelog ## Next +- Add `mops info ` command to show detailed package metadata from the registry ## 2.8.1 diff --git a/cli/cli.ts b/cli/cli.ts index 7a9285da..bf67bb53 100755 --- a/cli/cli.ts +++ b/cli/cli.ts @@ -8,7 +8,7 @@ import { getNetwork } from "./api/network.js"; import { cacheSize, cleanCache, show } from "./cache.js"; import { add } from "./commands/add.js"; import { bench } from "./commands/bench.js"; -import { build, DEFAULT_BUILD_OUTPUT_DIR } from "./commands/build.js"; +import { build } from "./commands/build.js"; import { bump } from "./commands/bump.js"; import { check } from "./commands/check.js"; import { checkCandid } from "./commands/check-candid.js"; @@ -16,6 +16,7 @@ import { checkStable } from "./commands/check-stable.js"; import { docsCoverage } from "./commands/docs-coverage.js"; import { docs } from "./commands/docs.js"; import { format } from "./commands/format.js"; +import { info } from "./commands/info.js"; import { init } from "./commands/init.js"; import { lint } from "./commands/lint.js"; import { installAll } from "./commands/install/install-all.js"; @@ -279,6 +280,15 @@ program await search(text); }); +// info +program + .command("info ") + .description("Show detailed information about a package from the registry") + .option("--versions", "List all published versions, one per line") + .action(async (pkg: string, options) => { + await info(pkg, options); + }); + // cache program .command("cache") diff --git a/cli/commands/info.ts b/cli/commands/info.ts new file mode 100644 index 00000000..bb43f697 --- /dev/null +++ b/cli/commands/info.ts @@ -0,0 +1,103 @@ +import process from "node:process"; +import chalk from "chalk"; +import { mainActor } from "../api/actors.js"; +import { resolveVersion } from "../api/resolveVersion.js"; +import type { PackageDetails } from "../declarations/main/main.did.js"; + +function label(text: string): string { + return chalk.bold(text.padEnd(16)); +} + +export interface InfoOptions { + versions?: boolean; +} + +export async function info(pkgArg: string, options: InfoOptions = {}) { + let [name, versionArg] = pkgArg.split("@") as [string, string | undefined]; + let actor = await mainActor(); + + let version: string; + try { + version = await resolveVersion(name, versionArg ?? ""); + } catch (err) { + let message = err instanceof Error ? err.message : String(err); + console.error(chalk.red("Error: ") + message); + process.exit(1); + } + + let res = await actor.getPackageDetails(name, version); + if ("err" in res) { + console.error(chalk.red("Error: ") + res.err); + process.exit(1); + } + + let d: PackageDetails = res.ok; + let c = d.config; + + // d.versions is in ascending order (oldest first) + if (options.versions) { + for (let ver of d.versions) { + console.log(ver); + } + return; + } + + console.log(""); + console.log( + `${chalk.green.bold(c.name)}${chalk.gray("@")}${chalk.yellow(c.version)}`, + ); + + if (c.description) { + console.log(chalk.dim(c.description)); + } + + if (c.version !== d.highestVersion) { + console.log(chalk.yellow(`latest: ${d.highestVersion}`)); + } + + console.log(""); + + if (c.license) { + console.log(`${label("license")}${c.license}`); + } + if (c.repository) { + console.log(`${label("repository")}${chalk.cyan(c.repository)}`); + } + if (c.homepage) { + console.log(`${label("homepage")}${chalk.cyan(c.homepage)}`); + } + if (c.documentation) { + console.log(`${label("documentation")}${chalk.cyan(c.documentation)}`); + } + + if (c.dependencies.length > 0) { + console.log(""); + console.log( + `${label("dependencies")}${c.dependencies.map((dep) => `${dep.name}${chalk.gray("@")}${dep.version || dep.repo}`).join(", ")}`, + ); + } + if (c.devDependencies.length > 0) { + console.log( + `${label("dev-deps")}${c.devDependencies.map((dep) => `${dep.name}${chalk.gray("@")}${dep.version || dep.repo}`).join(", ")}`, + ); + } + + if (c.keywords.length > 0) { + console.log(""); + console.log( + `${label("keywords")}${c.keywords.map((k) => chalk.yellow(k)).join(", ")}`, + ); + } + + if (d.versions.length > 0) { + let versionsDisplay = d.versions.slice(-10).reverse().join(", "); + let extra = + d.versions.length > 10 + ? ` ${chalk.gray(`(+${d.versions.length - 10} more)`)}` + : ""; + console.log(""); + console.log(`${label("versions")}${versionsDisplay}${extra}`); + } + + console.log(""); +} diff --git a/docs/docs/cli/7-misc/01-mops-info.md b/docs/docs/cli/7-misc/01-mops-info.md new file mode 100644 index 00000000..ddc62206 --- /dev/null +++ b/docs/docs/cli/7-misc/01-mops-info.md @@ -0,0 +1,43 @@ +--- +slug: /cli/mops-info +sidebar_label: mops info +--- + +# `mops info` + +Show detailed information about a package from the mops registry. +``` +mops info +``` + +### Examples + +Show info for the latest version of the `base` package +``` +mops info base +``` + +Show info for a specific version +``` +mops info base@0.10.0 +``` + +## Options + +### `--versions` + +Print all published versions, one per line (oldest to newest). Useful for scripting. +``` +mops info base --versions +``` + +## Output + +Displays package metadata including: +- Version and description +- Latest version indicator (shown when querying a non-latest version) +- License +- Repository, homepage, and documentation links +- Dependencies and dev-dependencies +- Keywords +- Version history