@mesh-tech/mesh-cli
Version:
CLI for Mesh platform development utilities
180 lines (179 loc) • 6.68 kB
JavaScript
import os from "node:os";
function currentMachinePaths() {
return { homeDir: os.homedir(), tmpDir: os.tmpdir() };
}
export function normalizeMachinePaths(value, paths) {
const candidates = [
{ prefix: paths.tmpDir, symbol: "$TMPDIR" },
{ prefix: paths.homeDir, symbol: "~" },
];
const substitutions = candidates
.filter((candidate) => candidate.prefix && candidate.prefix !== "/")
.sort((a, b) => b.prefix.length - a.prefix.length);
for (const { prefix, symbol } of substitutions) {
if (value === prefix)
return symbol;
if (value.startsWith(`${prefix}/`))
return symbol + value.slice(prefix.length);
}
return value;
}
export function formatDefault(value, paths = currentMachinePaths()) {
if (value === undefined || value === null)
return undefined;
if (typeof value === "string")
return normalizeMachinePaths(value, paths);
if (typeof value === "boolean" || typeof value === "number")
return String(value);
return normalizeMachinePaths(JSON.stringify(value), paths);
}
export function slugifyCommandPath(path) {
return path
.trim()
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
function extractOptions(command) {
const options = command.options ?? [];
return options
.map((option) => option)
.filter((option) => !option.hidden)
.map((option) => {
const ref = {
flags: option.flags ?? "",
description: option.description ?? "",
required: Boolean(option.mandatory ?? option.required ?? false),
};
const rendered = formatDefault(option.defaultValue);
if (rendered !== undefined)
ref.defaultValue = rendered;
if (option.argChoices?.length)
ref.choices = [...option.argChoices];
return ref;
});
}
function extractArgs(command) {
const internals = command;
const declared = internals.registeredArguments ?? internals._args ?? [];
if (!Array.isArray(declared) || declared.length === 0)
return "";
return declared
.map((argument) => {
const arg = argument;
const name = typeof arg.name === "function" ? arg.name() : "arg";
const spread = arg.variadic ? "..." : "";
return arg.required ? `<${name}${spread}>` : `[${name}${spread}]`;
})
.join(" ");
}
function isUndocumented(command) {
const internals = command;
return internals._name === "help" || internals._hidden === true;
}
function extractCommand(command, parentPath, depth) {
const internals = command;
const name = internals._name ?? "";
const path = parentPath ? `${parentPath} ${name}` : name;
return {
path,
name,
aliases: [...(internals._aliases ?? [])],
description: internals._description ?? "",
args: extractArgs(command),
options: extractOptions(command),
slug: slugifyCommandPath(path),
depth,
subcommands: (internals.commands ?? [])
.filter((child) => !isUndocumented(child))
.map((child) => extractCommand(child, path, depth + 1)),
};
}
export function extractCliReference(program) {
const internals = program;
const rootName = internals._name ?? "mesh";
return {
name: rootName,
description: internals._description ?? "",
options: extractOptions(program).filter((option) => !/(^|\s)(-V|--version)(\s|,|$)/.test(option.flags)),
commands: (internals.commands ?? [])
.filter((child) => !isUndocumented(child))
.map((child) => extractCommand(child, rootName, 1)),
};
}
export function flattenCommands(reference) {
const flat = [];
const visit = (command) => {
flat.push(command);
command.subcommands.forEach(visit);
};
reference.commands.forEach(visit);
return flat;
}
function cell(text) {
return text
.replace(/\\/g, "\\\\")
.replace(/\|/g, "\\|")
.replace(/\r?\n/g, " ")
.trim();
}
function renderOptionsTable(options) {
if (options.length === 0)
return [];
const lines = ["| Option | Description | Default |", "| --- | --- | --- |"];
for (const option of options) {
const notes = [];
if (option.required)
notes.push("**required**");
if (option.choices?.length)
notes.push(`one of: ${option.choices.join(", ")}`);
const description = [cell(option.description), ...notes].filter(Boolean).join(" — ");
const defaultValue = option.defaultValue === undefined ? "" : `\`${cell(option.defaultValue)}\``;
lines.push(`| \`${cell(option.flags)}\` | ${description} | ${defaultValue} |`);
}
lines.push("");
return lines;
}
function renderCommand(command) {
const heading = "#".repeat(Math.min(command.depth + 1, 4));
const usage = [command.path, command.options.length > 0 ? "[options]" : "", command.args]
.filter(Boolean)
.join(" ");
const lines = [`${heading} \`${command.path}\``, ""];
if (command.description)
lines.push(command.description, "");
if (command.aliases.length > 0) {
lines.push(`Alias: ${command.aliases.map((alias) => `\`${alias}\``).join(", ")}`, "");
}
lines.push("```bash", usage, "```", "");
lines.push(...renderOptionsTable(command.options));
command.subcommands.forEach((child) => lines.push(...renderCommand(child)));
return lines;
}
export function renderCliReferenceMarkdown(reference) {
const lines = [
"<!--",
" GENERATED FILE — do not edit by hand.",
" Source: the commander tree in libs/mesh-cli/src/program.ts",
" Rebuild: pnpm exec mesh docs cli-reference",
"-->",
"",
"# `mesh` CLI reference",
"",
reference.description,
"",
"Every command below is generated from the CLI's own command tree, so this",
"page cannot drift from the binary you have installed. Run any command with",
"`--help` for the same information at the terminal.",
"",
];
lines.push(...renderOptionsTable(reference.options));
lines.push("## Commands", "");
for (const command of reference.commands) {
const summary = cell(command.description) || "—";
lines.push(`- [\`${command.path}\`](#${command.slug}) — ${summary}`);
}
lines.push("");
reference.commands.forEach((command) => lines.push(...renderCommand(command)));
return `${lines.join("\n").replace(/\n{3,}/g, "\n\n").trimEnd()}\n`;
}