@adonisjs/ace
repository·14.x·Indexed 19 days ago
https://github.com/adonisjs/aceA lightweight, test-oriented CLI framework for Node.js designed for building command-line applications. It provides a clean API for creating custom commands by extending BaseCommand, managing execution via a Kernel, and parsing input with a dedicated Parser. The framework includes built-in support for defining arguments and flags, a dedicated ExceptionHandler for error management, and UI helpers for interactive interfaces.
What's inside @adonisjs/ace
- Ace is a lightweight command-line framework for Node.js designed specifically for creating CLI commands. It features a clean API and is built with a strong emphasis on testability.
Access command arguments and flags as properties
14.xAfter a command is executed (via
exec()), thehydrate()method is called internally. This maps the parsed CLI arguments and flags to properties on the command instance using the names provided during definition. This allows you to access them directly viathis.propertyNameinside yourrun()method.// If you defined: Command.defineArgument('entity', { type: 'string' }) // And ran: ace my:command user async run() { console.log(this.entity) // 'user' }Understand the ParsedOutput structure
14.xWhen a command is executed, the CLI arguments are parsed into a
ParsedOutputobject. This object is passed to your command'svalidatemethod and is used to populate the command instance.Key fields in
ParsedOutput:nodeArgs: The original arguments passed to the Node.js process.args: An array of the parsed positional arguments._: Array<string | number>: Leftover arguments after parsing flags and args.unknownFlags: An array of flags that were not recognized by the parser.flags: A dictionary of parsed flags, where keys are flag names and values are the parsed values.
export type ParsedOutput = YargsOutput & { nodeArgs: string[] args: (any | any[])[] _: Array<string | number> unknownFlags: string[] flags: { [argName: string]: any } }Implement self-handling errors
14.xTheExceptionHandlerchecks if an error object has its ownrendermethod. If an error implements arender(error, kernel)function, theExceptionHandlerwill delegate the rendering responsibility to that error object instead of using its internal logic.Create a custom CLI command with BaseCommand
14.xTo create a new Ace command, extend the
BaseCommandclass and implement therun()method. You define the command's identity using static properties likecommandNameanddescription. Arguments and flags are registered using static methods, which allows them to be accessed as properties on the command instance after hydration.export class MyCommand extends BaseCommand { static commandName = 'my:command' static description = 'My custom command' async run() { this.logger.info('Hello from my command!') } }Configure ESLint using @adonisjs/eslint-config
14.xTo use the recommended ESLint configuration for AdonisJS projects, import
configPkgfrom@adonisjs/eslint-configand export the result of callingconfigPkg()in youreslint.config.jsfile. This provides a pre-configured ESLint setup tailored for the AdonisJS ecosystem.import { configPkg } from '@adonisjs/eslint-config' export default configPkg()Register command loaders in the Kernel
14.xThe Kernel uses loaders to discover and register commands. You must call
addLoaderbefore callingbootorhandle. You can provide a loader instance or a function that returns a promise of a loader (for lazy loading).If multiple loaders return the same command, the one from the most recent loader takes precedence.
// Using a direct instance kernel.addLoader(new FsLoader('./commands')) // Using a lazy-loading function kernel.addLoader(() => import('./lazy-loader').then(m => new m.LazyLoader()))Initialize and use the Ace Kernel
14.xThe
Kernelis the main entry point for an Ace console application. It manages command registration, loading, and execution. You can create a new instance usingKernel.create(), which sets up a default executor and a default command (usuallyListCommand).To run a CLI application using the kernel, pass the process arguments to
kernel.handle(argv).const kernel = Kernel.create() // Configure the kernel kernel.defineFlag('help', { type: 'boolean', alias: 'h', description: 'Display help' }) kernel.addLoader(new FsLoader('./commands')) kernel.info.set('App version', '1.1.1') // Execute the command line arguments await kernel.handle(process.argv.slice(2))Configure debug mode in ExceptionHandler
14.xThe
ExceptionHandlerhas adebugproperty (boolean, defaults totrue).- When
debugistrue: Uncaught errors are pretty-printed to the console usingYouchfor detailed stack traces. - When
debugisfalse: The error is logged as a fatal error via the kernel's logger, providing a more concise output suitable for production environments.
const handler = new ExceptionHandler() handler.debug = false- When
Configure command options
14.xThe
CommandOptionsobject allows you to control the behavior of the command during execution.allowUnknownFlags: Iffalse(default), the command will fail to run if the user provides any flags that are not explicitly defined. Set totrueto permit extra flags.staysAlive: Iftrue, the kernel will not trigger the termination process unless the command explicitly calls theterminatemethod. This is useful for long-running processes or watchers.
export type CommandOptions = { allowUnknownFlags?: boolean staysAlive?: boolean } & Record<string, any>Use ArgumentFormatter to format CLI argument displays
14.xThe
ArgumentFormatterclass is used to format command arguments for terminal output, following the docopt.org specification. It allows you to generate consistent visual representations for argument names, descriptions, and usage patterns (like required vs. optional or spread arguments) using provided color utilities.To use it, instantiate the class with an
Argumentconfiguration object and acolorsobject (of typeUIPrimitives['colors']).const formatter = new ArgumentFormatter(argument, colors) const formatted = formatter.formatOption() // e.g., '<entity>' const listOption = formatter.formatListOption() // e.g., ' entity 'Customize exception rendering with ExceptionHandler
14.xThe
ExceptionHandlerclass is the default handler for Ace exceptions. You can extend this class to override therendermethod and implement custom error handling logic for your CLI application.When implementing a custom handler, you can call
await super.render(error, kernel)to maintain the default behavior (such as handling command-not-found errors or usingYouchfor pretty-printing in debug mode) while adding your own logic.import { ExceptionHandler } from '@adonisjs/ace' export class MyExceptionHandler extends ExceptionHandler { async render(error: unknown, kernel: Kernel<any>) { // Custom error handling logic here // Fallback to default Ace error rendering await super.render(error, kernel) } }