import { LooseTest } from 'typanion';
import { BaseContext, MiniCli } from './Cli';
import { isOptionSymbol } from './options/utils';
/**
 * The usage of a Command.
 */
export declare type Usage = {
    /**
     * The category of the command.
     *
     * Included in the detailed usage.
     */
    category?: string;
    /**
     * The short description of the command, formatted as Markdown.
     *
     * Included in the detailed usage.
     */
    description?: string;
    /**
     * The extended details of the command, formatted as Markdown.
     *
     * Included in the detailed usage.
     */
    details?: string;
    /**
     * Examples of the command represented as an Array of tuples.
     *
     * The first element of the tuple represents the description of the example.
     *
     * The second element of the tuple represents the command of the example.
     * If present, the leading `$0` is replaced with `cli.binaryName`.
     */
    examples?: Array<[string, string]>;
};
/**
 * The definition of a Command.
 */
export declare type Definition = Usage & {
    /**
     * The path of the command, starting with `cli.binaryName`.
     */
    path: string;
    /**
     * The detailed usage of the command.
     */
    usage: string;
    /**
     * The various options registered on the command.
     */
    options: Array<{
        definition: string;
        description?: string;
        required: boolean;
    }>;
};
export declare type CommandClass<Context extends BaseContext = BaseContext> = {
    new (): Command<Context>;
    paths?: Array<Array<string>>;
    schema?: Array<LooseTest<{
        [key: string]: unknown;
    }>>;
    usage?: Usage;
};
/**
 * Base abstract class for CLI commands. The main thing to remember is to
 * declare an async `execute` member function that will be called when the
 * command is invoked from the CLI, and optionally a `paths` property to
 * declare the set of paths under which the command should be exposed.
 */
export declare abstract class Command<Context extends BaseContext = BaseContext> {
    /**
     * @deprecated Do not use this; prefer the static `paths` property instead.
     */
    paths?: undefined;
    /**
     * Defined to prevent a common typo.
     */
    static path: never;
    /**
     * Paths under which the command should be exposed.
     */
    static paths?: Array<Array<string>>;
    /**
     * Defines the usage information for the given command.
     */
    static Usage(usage: Usage): Usage;
    /**
     * Contains the usage information for the command. If undefined, the
     * command will be hidden from the general listing.
     */
    static usage?: Usage;
    /**
     * Defines a schema to apply before running the `execute` method. The
     * schema is expected to be generated by Typanion.
     *
     * @see https://github.com/arcanis/typanion
     */
    static schema?: Array<LooseTest<{
        [key: string]: unknown;
    }>>;
    /**
     * Standard function that'll get executed by `Cli#run` and `Cli#runExit`.
     *
     * Expected to return an exit code or nothing (which Clipanion will treat
     * as if 0 had been returned).
     */
    abstract execute(): Promise<number | void>;
    /**
     * Standard error handler which will simply rethrow the error. Can be used
     * to add custom logic to handle errors from the command or simply return
     * the parent class error handling.
     */
    catch(error: any): Promise<void>;
    /**
     * Predefined that will be set to true if `-h,--help` has been used, in
     * which case `Command#execute` won't be called.
     */
    help: boolean;
    /**
     * Predefined variable that will be populated with a miniature API that can
     * be used to query Clipanion and forward commands.
     */
    cli: MiniCli<Context>;
    /**
     * Predefined variable that will be populated with the context of the
     * application.
     */
    context: Context;
    /**
     * Predefined variable that will be populated with the path that got used
     * to access the command currently being executed.
     */
    path: Array<string>;
    validateAndExecute(): Promise<number>;
    /**
     * Used to detect option definitions.
     */
    static isOption: typeof isOptionSymbol;
    /**
     * Just an helper to use along with the `paths` fields, to make it
     * clearer that a command is the default one.
     *
     * @example
     * class MyCommand extends Command {
     *   static paths = [Command.Default];
     * }
     */
    static Default: never[];
}
