diff --git a/playground/commands/build.ts b/playground/commands/build.ts index af062e6..e552a34 100644 --- a/playground/commands/build.ts +++ b/playground/commands/build.ts @@ -4,6 +4,7 @@ import { defineCommand } from "../../src"; export default defineCommand({ meta: { name: "build", + aliases: ["b"], description: "Build the project from current directory", }, args: { diff --git a/src/command.ts b/src/command.ts index 1abfe44..d458209 100644 --- a/src/command.ts +++ b/src/command.ts @@ -1,4 +1,9 @@ -import type { CommandContext, CommandDef, ArgsDef } from "./types"; +import type { + CommandContext, + CommandDef, + ArgsDef, + SubCommandsDef, +} from "./types"; import { CLIError, resolveValue } from "./_utils"; import { parseArgs } from "./args"; @@ -14,6 +19,27 @@ export interface RunCommandOptions { showUsage?: boolean; } +async function getSubCommand( + subCommandsList: SubCommandsDef, + subCommandName: string, +): Promise | undefined> { + const subCommand = await resolveValue(subCommandsList[subCommandName]); + + if (subCommand) { + return subCommand; + } + + for (const _subCmd of Object.values(subCommandsList)) { + const subCmd = await resolveValue(_subCmd); + const subCmdMeta = await resolveValue(subCmd.meta); + if ((subCmdMeta?.aliases || []).includes(subCommandName)) { + return subCmd; + } + } + + return undefined; +} + export async function runCommand( cmd: CommandDef, opts: RunCommandOptions, @@ -43,13 +69,14 @@ export async function runCommand( ); const subCommandName = opts.rawArgs[subCommandArgIndex]; if (subCommandName) { - if (!subCommands[subCommandName]) { + const subCommand = await getSubCommand(subCommands, subCommandName); + + if (!subCommand) { throw new CLIError( `Unknown command \`${subCommandName}\``, "E_UNKNOWN_COMMAND", ); } - const subCommand = await resolveValue(subCommands[subCommandName]); if (subCommand) { await runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1), @@ -81,7 +108,8 @@ export async function resolveSubCommand( if (subCommands && Object.keys(subCommands).length > 0) { const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-")); const subCommandName = rawArgs[subCommandArgIndex]; - const subCommand = await resolveValue(subCommands[subCommandName]); + const subCommand = await getSubCommand(subCommands, subCommandName); + if (subCommand) { return resolveSubCommand( subCommand, diff --git a/src/types.ts b/src/types.ts index a622922..cf6118b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -78,6 +78,7 @@ export type ParsedArgs = { _: string[] } & Record< export interface CommandMeta { name?: string; + aliases?: string[]; version?: string; description?: string; hidden?: boolean; diff --git a/src/usage.ts b/src/usage.ts index cb4a794..f1a8b61 100644 --- a/src/usage.ts +++ b/src/usage.ts @@ -86,7 +86,10 @@ export async function renderUsage( if (meta?.hidden) { continue; } - commandsLines.push([`\`${name}\``, meta?.description || ""]); + commandsLines.push([ + `\`${[name, ...(meta?.aliases || [])].join(", ")}\``, + meta?.description || "", + ]); commandNames.push(name); } usageLine.push(commandNames.join("|"));