UNPKG

@lodestar/utils

Version:

Utilities required across multiple lodestar packages

75 lines (68 loc) 2.6 kB
import type {Argv, Options} from "yargs"; export interface CliExample { command: string; title?: string; description?: string; } // biome-ignore lint/suspicious/noExplicitAny: We need to use `any` type here export interface CliOptionDefinition<T = any> extends Options { example?: Omit<CliExample, "title">; // Ensure `type` property matches type of `T` type: T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : T extends Array<unknown> ? "array" : never; } export type CliCommandOptions<OwnArgs> = Required<{ [K in keyof OwnArgs]: undefined extends OwnArgs[K] ? CliOptionDefinition<OwnArgs[K]> : // If arg cannot be undefined it must specify a default value or be provided by the user CliOptionDefinition<OwnArgs[K]> & (Required<Pick<Options, "default">> | {demandOption: true}); }>; // biome-ignore lint/suspicious/noExplicitAny: We need to use `any` type here export interface CliCommand<OwnArgs = Record<never, never>, ParentArgs = Record<never, never>, R = any> { command: string; describe: string; /** * The folder in docs/pages that the cli.md should be placed in. If not provided no * cli flags page will be generated for the command */ docsFolder?: string; examples?: CliExample[]; options?: CliCommandOptions<OwnArgs>; // 1st arg: any = free own sub command options // 2nd arg: subcommand parent options is = to this command options + parent options // biome-ignore lint/suspicious/noExplicitAny: We need to use `any` type here subcommands?: CliCommand<any, OwnArgs & ParentArgs>[]; handler?: (args: OwnArgs & ParentArgs) => Promise<R>; } /** * Register a CliCommand type to yargs. Recursively registers subcommands too. * @param yargs * @param cliCommand */ // biome-ignore lint/suspicious/noExplicitAny: We need to use `any` type here export function registerCommandToYargs(yargs: Argv, cliCommand: CliCommand<any, any>): void { yargs.command({ command: cliCommand.command, describe: cliCommand.describe, builder: (yargsBuilder) => { yargsBuilder.options(cliCommand.options ?? {}); for (const subcommand of cliCommand.subcommands ?? []) { registerCommandToYargs(yargsBuilder, subcommand); } if (cliCommand.examples) { for (const example of cliCommand.examples) { yargsBuilder.example(`$0 ${example.command}`, example.description ?? ""); } } return yargs; }, handler: cliCommand.handler ?? function emptyHandler(): void {}, }); }