UNPKG

@visulima/cerebro

Version:

A delightful toolkit for building cross-runtime CLIs for Node.js, Deno, and Bun.

204 lines (203 loc) 7.52 kB
import PluginManager from "./plugin-manager.d.ts"; import type { Cli as ICli, CliRunOptions, CommandSection as ICommandSection, RunCommandOptions } from "./types/cli.d.ts"; import type { Command as ICommand, OptionDefinition } from "./types/command.d.ts"; import type { Plugin } from "./types/plugin.d.ts"; export type CliOptions<T extends Console = Console> = { argv?: ReadonlyArray<string>; cwd?: string; logger?: T; packageName?: string; packageVersion?: string; }; export declare class Cli<T extends Console = Console> implements ICli<T> { #private; /** * Create a new CLI instance. * @param cliName * @param options The options for the CLI. * @param options.argv The command line arguments. * @param options.cwd The current working directory. * @param options.logger The logger to use. * @param options.packageName * @param options.packageVersion */ constructor(cliName: string, options?: CliOptions<T>); /** * Sets the command section configuration for help display. * * This affects how the CLI name and version are displayed in help output. * @param commandSection The command section configuration * @returns The CLI instance for method chaining * @example * ```typescript * cli.setCommandSection({ * header: 'My App v2.0.0', * footer: 'For more info, visit https://example.com' * }); * ``` */ setCommandSection(commandSection: ICommandSection): this; /** * Gets the current command section configuration. * @returns The command section configuration */ getCommandSection(): ICommandSection; /** * Sets the default command to run when no command is specified. * * By default, this is set to 'help'. The command must already be registered * with the CLI instance. * @param commandName The command name to use as the default * @returns The CLI instance for method chaining * @example * ```typescript * cli.setDefaultCommand('start'); * ``` */ setDefaultCommand(commandName: string): this; /** * Gets the current default command. * @returns The name of the default command */ get defaultCommand(): string; /** * Adds a command to the CLI. * * Commands define the available operations that users can execute. * Each command can have options, arguments, aliases, and custom execution logic. * @template OD - The option definition type for the command * @param command The command configuration object * @returns The CLI instance for method chaining * @throws {CerebroError} If the command name already exists or validation fails * @example * ```typescript * cli.addCommand({ * name: 'build', * description: 'Build the project', * options: [ * { * name: 'output', * alias: 'o', * type: String, * description: 'Output directory' * } * ], * execute: ({ options }) => { * console.log(`Building to ${options.output || 'dist'}`); * } * }); * ``` */ addCommand<OD extends OptionDefinition<unknown> = OptionDefinition<unknown>>(command: ICommand<OD, T>): this; /** * Adds a plugin to extend the CLI functionality. * * Plugins can hook into various lifecycle events and modify the toolbox * to provide additional functionality to commands. * @param plugin The plugin to register * @returns The CLI instance for method chaining * @example * ```typescript * cli.addPlugin({ * name: 'logger', * execute: (toolbox) => { * toolbox.logger = createCustomLogger(); * } * }); * ``` */ addPlugin(plugin: Plugin<T>): this; /** * Gets the plugin manager instance for advanced plugin management. * @returns The plugin manager instance */ getPluginManager(): PluginManager<T>; /** * Gets the CLI application name. */ getCliName(): string; /** * Gets the package version if configured. * @returns The package version or undefined */ getPackageVersion(): string | undefined; /** * Gets the package name if configured. * @returns The package name or undefined */ getPackageName(): string | undefined; /** * Gets all registered commands. * @returns A map of command names to command definitions */ getCommands(): Map<string, ICommand<OptionDefinition<unknown>, T>>; /** * Gets the current working directory. * @returns The current working directory path */ getCwd(): string; /** * Disposes the CLI instance and cleans up resources. * * This method removes event listeners and performs cleanup to prevent memory leaks. * Call this method when the CLI instance is no longer needed, especially in long-running * processes or when creating multiple CLI instances. * @example * ```typescript * const cli = new Cerebro('my-app'); * // ... use the cli * cli.dispose(); // Clean up when done * ``` */ dispose(): void; /** * Runs the CLI application. * * This method parses command line arguments, executes the appropriate command, * and handles the complete CLI lifecycle including plugin initialization, * error handling, process termination, and automatic cleanup. * @param extraOptions Additional options to pass to commands * @param extraOptions.shouldExitProcess Whether to exit the process after execution (default: true) * @param extraOptions.autoDispose Whether to automatically cleanup/dispose resources after execution (default: true) * @returns A promise that resolves when execution completes * @throws {CommandNotFoundError} If the specified command doesn't exist * @throws {Error} If command arguments are invalid or conflicting options are provided * @example * ```typescript * // Run with default behavior (exits process and auto-disposes) * await cli.run(); * * // Run without exiting (for testing) * await cli.run({ shouldExitProcess: false }); * * // Run without auto-disposing (for reuse) * await cli.run({ autoDispose: false }); * ``` */ run(extraOptions?: CliRunOptions): Promise<void>; /** * Runs a command programmatically from within another command. * * This method allows commands to call other commands during execution, * enabling composition of commands and reusable command logic. * @param commandName The name of the command to execute * @param options Optional options including argv and other command options * @returns A promise that resolves with the command's result * @throws {CommandNotFoundError} If the specified command doesn't exist * @throws {CerebroError} If command validation fails * @example * ```typescript * cli.addCommand({ * name: 'deploy', * execute: async ({ runtime, logger }) => { * logger.info('Building...'); * await runtime.runCommand('build', { argv: ['--production'] }); * * logger.info('Testing...'); * await runtime.runCommand('test', { argv: ['--coverage'] }); * } * }); * ``` */ runCommand(commandName: string, options?: RunCommandOptions): Promise<unknown>; }