Skip to content

Commit

Permalink
feat(subcommand): support alias for subcommand (unjs#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
fu050409 committed Jul 5, 2024
1 parent 53cd585 commit 2eed9af
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 9 deletions.
21 changes: 20 additions & 1 deletion src/_utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Resolvable } from "./types";
import type { CommandDef, Resolvable, SubCommandsDef } from "./types";

export function toArray(val: any) {
if (Array.isArray(val)) {
Expand Down Expand Up @@ -30,6 +30,25 @@ export function resolveValue<T>(input: Resolvable<T>): T | Promise<T> {
return typeof input === "function" ? (input as any)() : input;
}

export async function getSubCommand(
subCommands: SubCommandsDef,
command: string,
): Promise<CommandDef<any>> {
if (Object.keys(subCommands).includes(command)) {
return resolveValue(subCommands[command]);
}

for (const subCommand of Object.values(subCommands)) {
const resolvedSubCommand = await resolveValue(subCommand);
for (const alias of toArray(resolvedSubCommand.alias)) {
if (alias === command) {
return resolvedSubCommand;
}
}
}
throw new CLIError(`Unknown command \`${command}\``, "E_UNKNOWN_COMMAND");
}

export class CLIError extends Error {
constructor(
message: string,
Expand Down
10 changes: 2 additions & 8 deletions src/command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { CommandContext, CommandDef, ArgsDef } from "./types";
import { CLIError, resolveValue } from "./_utils";
import { CLIError, getSubCommand, resolveValue } from "./_utils";
import { parseArgs } from "./args";

export function defineCommand<T extends ArgsDef = ArgsDef>(
Expand Down Expand Up @@ -43,13 +43,7 @@ export async function runCommand<T extends ArgsDef = ArgsDef>(
);
const subCommandName = opts.rawArgs[subCommandArgIndex];
if (subCommandName) {
if (!subCommands[subCommandName]) {
throw new CLIError(
`Unknown command \`${subCommandName}\``,
"E_UNKNOWN_COMMAND",
);
}
const subCommand = await resolveValue(subCommands[subCommandName]);
const subCommand = await getSubCommand(subCommands, subCommandName);
if (subCommand) {
await runCommand(subCommand, {
rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1),
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export type SubCommandsDef = Record<string, Resolvable<CommandDef<any>>>;
export type CommandDef<T extends ArgsDef = ArgsDef> = {
meta?: Resolvable<CommandMeta>;
args?: Resolvable<T>;
alias?: Resolvable<string | string[]>;
subCommands?: Resolvable<SubCommandsDef>;
setup?: (context: CommandContext<T>) => any | Promise<any>;
cleanup?: (context: CommandContext<T>) => any | Promise<any>;
Expand Down

0 comments on commit 2eed9af

Please sign in to comment.