@black-flag/extensions
Version:
A collection of set-theoretic declarative-first APIs for yargs and Black Flag
563 lines • 26.6 kB
TypeScript
import { $executionContext } from '@black-flag/core';
import { BfeErrorMessage } from "./error.js";
import { $artificiallyInvoked } from "./symbols.js";
import type { SafeDeepCloneOptions } from '@-xun/js';
import type { Arguments, Configuration, ImportedConfigurationModule } from '@black-flag/core';
import type { ExecutionContext, FrameworkArguments } from '@black-flag/core/util';
import type { LiteralUnion, Merge, OmitIndexSignature, Promisable } from 'type-fest';
export { $artificiallyInvoked, BfeErrorMessage };
/**
* The function type of the `builder` export accepted by Black Flag.
*/
export type BfBuilderFunction<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = Extract<Configuration<CustomCliArguments, CustomExecutionContext>['builder'], Function>;
/**
* The object type of the `builder` export accepted by Black Flag.
*/
export type BfBuilderObject<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = Exclude<Configuration<CustomCliArguments, CustomExecutionContext>['builder'], Function>;
/**
* The object value type of a {@link BfBuilderObject}.
*
* Equivalent to `yargs.Options` as of yargs\@17.7.2.
*/
export type BfBuilderObjectValue<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = BfBuilderObject<CustomCliArguments, CustomExecutionContext>[string];
/**
* The generic object value type of a {@link BfBuilderObject}.
*/
export type BfGenericBuilderObjectValue = BfBuilderObjectValue<Record<string, unknown>, ExecutionContext>;
/**
* A version of the object type of the `builder` export accepted by Black Flag
* that supports BFE's additional functionality.
*/
export type BfeBuilderObject<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = {
[key: string]: BfeBuilderObjectValue<CustomCliArguments, CustomExecutionContext>;
};
/**
* The object value type of a {@link BfeBuilderObject}.
*/
export type BfeBuilderObjectValue<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = BfeBuilderObjectValueWithoutExtensions & BfeBuilderObjectValueExtensions<CustomCliArguments, CustomExecutionContext>;
/**
* An object containing only those properties recognized by
* BFE.
*
* This type + {@link BfeBuilderObjectValueWithoutExtensions} =
* {@link BfeBuilderObjectValue}.
*/
export type BfeBuilderObjectValueExtensions<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = {
/**
* `requires` enables checks to ensure the specified arguments, or
* argument-value pairs, are given conditioned on the existence of another
* argument. For example:
*
* ```jsonc
* {
* "x": { "requires": "y" }, // ◄ Disallows x without y
* "y": {}
* }
* ```
*
* Note: if an argument-value pair is specified and said argument is
* configured as an array (`{ array: true }`), it will be searched for the
* specified value. Otherwise, a strict deep equality check is performed.
*/
requires?: BfeBuilderObjectValueExtensionValue;
/**
* `conflicts` enables checks to ensure the specified arguments, or
* argument-value pairs, are _never_ given conditioned on the existence of
* another argument. For example:
*
* ```jsonc
* {
* "x": { "conflicts": "y" }, // ◄ Disallows y if x is given
* "y": {}
* }
* ```
*
* Note: if an argument-value pair is specified and said argument is
* configured as an array (`{ array: true }`), it will be searched for the
* specified value. Otherwise, a strict deep equality check is performed.
*/
conflicts?: BfeBuilderObjectValueExtensionValue;
/**
* `demandThisOptionIf` enables checks to ensure an argument is given when at
* least one of the specified groups of arguments, or argument-value pairs, is
* also given. For example:
*
* ```jsonc
* {
* "x": {},
* "y": { "demandThisOptionIf": "x" }, // ◄ Demands y if x is given
* "z": { "demandThisOptionIf": "x" } // ◄ Demands z if x is given
* }
* ```
*
* Note: if an argument-value pair is specified and said argument is
* configured as an array (`{ array: true }`), it will be searched for the
* specified value. Otherwise, a strict deep equality check is performed.
*/
demandThisOptionIf?: BfeBuilderObjectValueExtensionValue;
/**
* `demandThisOption` enables checks to ensure an argument is always given.
* This is equivalent to `demandOption` from vanilla yargs. For example:
*
* ```jsonc
* {
* "x": { "demandThisOption": true }, // ◄ Disallows ∅, y
* "y": { "demandThisOption": false }
* }
* ```
*/
demandThisOption?: BfGenericBuilderObjectValue['demandOption'];
/**
* `demandThisOptionOr` enables non-optional inclusive disjunction checks per
* group. Put another way, `demandThisOptionOr` enforces a "logical or"
* relation within groups of required options. For example:
*
* ```jsonc
* {
* "x": { "demandThisOptionOr": ["y", "z"] }, // ◄ Demands x or y or z
* "y": { "demandThisOptionOr": ["x", "z"] },
* "z": { "demandThisOptionOr": ["x", "y"] }
* }
* ```
*
* Note: if an argument-value pair is specified and said argument is
* configured as an array (`{ array: true }`), it will be searched for the
* specified value. Otherwise, a strict deep equality check is performed.
*/
demandThisOptionOr?: BfeBuilderObjectValueExtensionValue;
/**
* `demandThisOptionXor` enables non-optional exclusive disjunction checks per
* exclusivity group. Put another way, `demandThisOptionXor` enforces mutual
* exclusivity within groups of required options. For example:
*
* ```jsonc
* {
* // ▼ Disallows ∅, z, w, xy, xyw, xyz, xyzw
* "x": { "demandThisOptionXor": ["y"] },
* "y": { "demandThisOptionXor": ["x"] },
* // ▼ Disallows ∅, x, y, zw, xzw, yzw, xyzw
* "z": { "demandThisOptionXor": ["w"] },
* "w": { "demandThisOptionXor": ["z"] }
* }
* ```
*
* Note: if an argument-value pair is specified and said argument is
* configured as an array (`{ array: true }`), it will be searched for the
* specified value. Otherwise, a strict deep equality check is performed.
*/
demandThisOptionXor?: BfeBuilderObjectValueExtensionValue;
/**
* `implies` will set default values for the specified arguments conditioned
* on the existence of another argument. These implied defaults will override
* any `default` configurations of the specified arguments.
*
* If any of the specified arguments are explicitly given on the command line,
* their values must match the specified argument-value pairs respectively
* (which is the behavior of `requires`/`conflicts`). Use `looseImplications`
* to modify this behavior.
*
* Hence, `implies` only accepts one or more argument-value pairs and not raw
* strings. For example:
*
* ```jsonc
* {
* "x": { "implies": { "y": true } }, // ◄ x is now synonymous with xy
* "y": {}
* }
* ```
*
* @see {@link BfeBuilderObjectValueExtensions.looseImplications}
* @see {@link BfeBuilderObjectValueExtensions.vacuousImplications}
*/
implies?: Exclude<BfeBuilderObjectValueExtensionValue, string | unknown[]> | Exclude<BfeBuilderObjectValueExtensionValue, string | unknown[]>[];
/**
* When `looseImplications` is set to `true`, any implied arguments, when
* explicitly given on the command line, will _override_ their configured
* implications instead of causing an error.
*
* @default false
* @see {@link BfeBuilderObjectValueExtensions.implies}
*/
looseImplications?: boolean;
/**
* When `vacuousImplications` is set to `true` and the option is also
* configured as a "boolean" type, the implications configured via `implies`
* will still be applied to `argv` even if said option has a `false` value in
* `argv`. In the same scenario except with `vacuousImplications` set to
* `false`, the implications configured via `implies` are instead ignored.
*
* @default false
* @see {@link BfeBuilderObjectValueExtensions.implies}
*/
vacuousImplications?: boolean;
/**
* `check` is the declarative option-specific version of vanilla yargs's
* `yargs::check()`. It also supports async and promise-returning functions.
*
* This function receives the `currentArgumentValue`, which you are free to
* type as you please, and the fully parsed `argv`. If this function throws,
* the exception will bubble. If this function returns an instance of `Error`,
* a string, or any non-truthy value (including `undefined` or not returning
* anything), Black Flag will throw a `CliError` on your behalf.
*
* You may also pass an array of check functions, each being executed after
* the other. Note that providing an array of one or more async check
* functions will result in them being awaited concurrently.
*
* Note that `check` runs _at the very end of Black Flag's second parsing
* pass_, meaning it runs _after_ things like `coerce` and `subOptionOf`, and
* therefore receives the _final_ version of `argv` (the one passed to a
* command's `handler`).
*
* See [the
* documentation](https://github.com/Xunnamius/black-flag/tree/main/packages/extensions/README.md#check)
* for details.
*/
check?: BfeCheckFunction<CustomCliArguments, CustomExecutionContext> | BfeCheckFunction<CustomCliArguments, CustomExecutionContext>[];
/**
* `subOptionOf` is declarative sugar around Black Flag's support for double
* argument parsing, allowing you to describe the relationship between options
* and the suboptions whose configurations they determine.
*
* See [the
* documentation](https://github.com/Xunnamius/black-flag/tree/main/packages/extensions/README.md#suboptionof)
* for details.
*
* For describing simpler implicative relations, see `implies`.
*/
subOptionOf?: Record<string, BfeSubOptionOfExtensionValue<CustomCliArguments, CustomExecutionContext> | BfeSubOptionOfExtensionValue<CustomCliArguments, CustomExecutionContext>[]>;
/**
* `default` will set a default value for an argument. This is equivalent to
* `default` from vanilla yargs.
*
* However, unlike vanilla yargs and Black Flag, this default value is applied
* towards the end of BFE's execution, enabling its use alongside keys like
* `conflicts`. See [the
* documentation](https://github.com/Xunnamius/black-flag/tree/main/packages/extensions/README.md#support-for-default-with-conflictsrequiresetc)
* for details.
*
* Note also that a defaulted argument will not be coerced by the `coerce`
* setting. Only arguments given via `argv` trigger `coerce`. This is vanilla
* yargs behavior.
*/
default?: unknown;
/**
* `coerce` transforms an original `argv` value into another one. This is
* equivalent to `coerce` from vanilla yargs.
*
* However, unlike vanilla yargs and Black Flag, the `coerce` function will
* _always_ receive an array if the option was configured with `{ array: true
* }`.
*
* Note that **a defaulted argument will not result in this function being
* called.** Only arguments given via `argv` trigger `coerce`. This is vanilla
* yargs behavior.
*/
coerce?: BfGenericBuilderObjectValue['coerce'];
};
/**
* The string/object/array type of a {@link BfeBuilderObjectValueExtensions}.
*
* This type is a superset of {@link BfeBuilderObjectValueExtensionObject}.
*/
export type BfeBuilderObjectValueExtensionValue = string | BfeBuilderObjectValueExtensionObject | (string | BfeBuilderObjectValueExtensionObject)[];
/**
* The object type of a {@link BfeBuilderObjectValueExtensions}.
*
* This type is a subset of {@link BfeBuilderObjectValueExtensionValue}.
*/
export type BfeBuilderObjectValueExtensionObject = Record<string, unknown>;
/**
* An object containing a subset of only those properties recognized by
* Black Flag (and, consequentially, vanilla yargs). Also excludes
* properties that conflict with {@link BfeBuilderObjectValueExtensions} and/or
* are deprecated by vanilla yargs.
*
* This type + {@link BfeBuilderObjectValueExtensions} =
* {@link BfeBuilderObjectValue}.
*
* This type is a subset of {@link BfBuilderObjectValue}.
*/
export type BfeBuilderObjectValueWithoutExtensions = Omit<BfGenericBuilderObjectValue, 'conflicts' | 'implies' | 'demandOption' | 'demand' | 'require' | 'required' | 'default' | 'coerce'>;
/**
* A {@link BfeBuilderObjectValue} instance with the `subOptionOf` BFE key
* omitted.
*/
export type BfeBuilderObjectValueWithoutSubOptionOfExtension<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = Omit<BfeBuilderObjectValue<CustomCliArguments, CustomExecutionContext>, 'subOptionOf'>;
/**
* The array element type of
* {@link BfeBuilderObjectValueExtensions.subOptionOf}.
*/
export type BfeSubOptionOfExtensionValue<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = {
/**
* This function receives the `superOptionValue` of the so-called "super
* option" (i.e. `key` in `{ subOptionOf: { key: { when: ... }}}`), which you
* are free to type as you please, and the fully parsed `argv` (not including
* any default values). This function must return a boolean indicating whether
* the `update` function should run or not.
*
* Note that this function is only invoked if the super option is given on the
* command line. If it is not, neither this function nor `update` will ever
* run. Therefore, if your updater should run whenever the super option is
* given, regardless of its value, it is acceptable to use `{ when: () => true
* }`
*/
when: (superOptionValue: any, argv: Arguments<CustomCliArguments, CustomExecutionContext>) => boolean;
/**
* This function receives the current configuration for this option
* (`oldOptionConfig`) and the fully parsed `argv` (not including any default
* values), and must return the new configuration for this option.
*
* This configuration will completely overwrite the old configuration. To
* extend the old configuration instead, spread it. For example:
*
* ```javascript
* return {
* ...oldOptionConfig,
* description: 'New description'
* }
* ```
*/
update: ((oldOptionConfig: BfeBuilderObjectValueWithoutSubOptionOfExtension<CustomCliArguments, CustomExecutionContext>, argv: Arguments<CustomCliArguments, CustomExecutionContext>) => BfeBuilderObjectValueWithoutSubOptionOfExtension<CustomCliArguments, CustomExecutionContext>) | BfeBuilderObjectValueWithoutSubOptionOfExtension<CustomCliArguments, CustomExecutionContext>;
};
/**
* This function is used to validate an argument passed to Black Flag.
*
* @see {@link BfeBuilderObjectValueExtensions.check}
*/
export type BfeCheckFunction<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = (currentArgumentValue: any, argv: Arguments<CustomCliArguments, CustomExecutionContext>) => Promisable<unknown>;
/**
* This function implements several additional optionals-related units of
* functionality. This function is meant to take the place of a command's
* `builder` export.
*
* This type cannot be instantiated by direct means. Instead, it is created and
* returned by {@link withBuilderExtensions}.
*
* @see {@link withBuilderExtensions}
*/
export type BfeBuilderFunction<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = (...args: Parameters<BfBuilderFunction<CustomCliArguments, CustomExecutionContext>>) => BfBuilderObject<CustomCliArguments, CustomExecutionContext>;
/**
* A stricter version of Black Flag's
* [Arguments](https://github.com/Xunnamius/black-flag/blob/main/docs/api/src/exports/type-aliases/Arguments.md)
* type that explicitly omits the fallback indexers for unrecognized arguments.
* Even though it is the runtime equivalent of `Arguments`, using this type
* allows intellisense to report bad/misspelled/missing arguments from `argv` in
* various places where it otherwise couldn't.
*
* **This type is intended for intellisense purposes only.**
*/
export type BfeStrictArguments<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = OmitIndexSignature<Arguments<CustomCliArguments, CustomExecutionContext>> & FrameworkArguments<CustomExecutionContext> & {
[$artificiallyInvoked]?: boolean;
};
/**
* A stricter version of Black Flag's
* [ExecutionContext](https://github.com/Xunnamius/black-flag/blob/main/docs/api/src/exports/util/type-aliases/ExecutionContext.md)
* type that explicitly omits the fallback indexers for unrecognized properties.
* Even though it is the runtime equivalent of `ExecutionContext`, using this
* type allows intellisense to report bad/misspelled/missing arguments from
* `context` in various places where it otherwise couldn't.
*
* **This type is intended for intellisense purposes only.**
*/
export type AsStrictExecutionContext<CustomExecutionContext extends ExecutionContext> = OmitIndexSignature<Exclude<CustomExecutionContext, 'state'>> & OmitIndexSignature<CustomExecutionContext['state']>;
/**
* A version of Black Flag's `builder` function parameters that exclude yargs
* methods that are not supported by BFE.
*
* @see {@link withBuilderExtensions}
*/
export type BfeCustomBuilderFunctionParameters<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext, P = Parameters<BfBuilderFunction<CustomCliArguments, CustomExecutionContext>>> = P extends [infer R, ...infer S] ? S extends [infer T, ...infer _U] ? [blackFlag: R & {
options: never;
option: never;
}, T, (BfeStrictArguments<Partial<CustomCliArguments>, CustomExecutionContext> | undefined)] : [blackFlag: R & {
options: never;
option: never;
}, ...S] : never;
/**
* This function implements several additional optionals-related units of
* functionality. The return value of this function is meant to take the place
* of a command's `handler` export.
*
* This type cannot be instantiated by direct means. Instead, it is created and
* returned by {@link withBuilderExtensions}.
*
* Note that `customHandler` provides a stricter constraint than Black Flag's
* `handler` command export in that `customHandler`'s `argv` parameter type
* explicitly omits the fallback indexer for unrecognized arguments. This
* means all possible arguments must be included in {@link CustomCliArguments}.
*
* @see {@link withBuilderExtensions}
*/
export type WithHandlerExtensions<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = (customHandler?: (argv: BfeStrictArguments<CustomCliArguments, CustomExecutionContext>) => Promisable<void>) => Configuration<CustomCliArguments, CustomExecutionContext>['handler'];
/**
* The array of extended exports and high-order functions returned by
* {@link withBuilderExtensions}.
*/
export type WithBuilderExtensionsReturnType<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext> = [builder: BfeBuilderFunction<CustomCliArguments, CustomExecutionContext>, withHandlerExtensions: WithHandlerExtensions<CustomCliArguments, CustomExecutionContext>];
/**
* A configuration object that further configures the behavior of
* {@link withBuilderExtensions}.
*/
export type WithBuilderExtensionsConfig<CustomCliArguments extends Record<string, unknown>> = {
/**
* Set to `true` to disable BFE's support for automatic grouping of related
* options.
*
* See [the
* documentation](https://github.com/Xunnamius/black-flag/blob/main/packages/extensions/README.md#automatic-grouping-of-related-options)
* for details.
*
* @default false
*/
disableAutomaticGrouping?: boolean;
/**
* Set to `true` to enable BFE's support for automatic sorting of options.
*
* See [the
* documentation](https://github.com/Xunnamius/black-flag/blob/main/packages/extensions/README.md#automatic-sorting-of-options)
* for details.
*
* @default false
*/
enableAutomaticSorting?: boolean;
/**
* An array of zero or more string keys of `CustomCliArguments`, with the
* optional addition of `'help'` and `'version'`, that should be grouped under
* _"Common Options"_ when [automatic grouping of related
* options](https://github.com/Xunnamius/black-flag/blob/main/packages/extensions/README.md#automatic-sorting-of-options)
* is enabled.
*
* This setting is ignored if `disableAutomaticGrouping === true`.
*
* @default ['help']
*/
commonOptions?: readonly LiteralUnion<keyof CustomCliArguments | 'help' | 'version', string>[];
};
/**
* A configuration object that further configures the behavior of
* {@link withUsageExtensions}.
*/
export type WithUsageExtensionsConfig = {
/**
* The result of calling this function defaults to: `Usage:
* $000\n\n${altDescription}`.
*
* @default "$1."
*/
altDescription?: string;
/**
* Whether `altDescription` will be `trim()`'d or not.
*
* @default true
*/
trim?: boolean;
/**
* Whether a period will be appended to the resultant string or not. A
* period is only appended if one is not already appended.
*
* @default true
*/
appendPeriod?: boolean;
/**
* Whether newlines will be prepended to `altDescription` or not.
*
* @default true
*/
prependNewlines?: boolean;
/**
* Whether the string `' [...options]'` will be appended to the first line
* of usage text (after `includeSubCommand`).
*
* @default options.prependNewlines
*/
includeOptions?: boolean;
/**
* Whether some variation of the string `' [subcommand]'` will be appended
* to the first line of usage text (before `includeOptions`). Set to `true`
* or `required` when generating usage for a command with subcommands.
*
* @default false
*/
includeSubCommand?: boolean | 'required';
};
/**
* This function enables several additional options-related units of
* functionality via analysis of the returned options configuration object and
* the parsed command line arguments (argv).
*
* @see {@link WithBuilderExtensionsReturnType}
*/
export declare function withBuilderExtensions<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext>(customBuilder?: BfeBuilderObject<CustomCliArguments, CustomExecutionContext> | ((...args: BfeCustomBuilderFunctionParameters<CustomCliArguments, CustomExecutionContext>) => BfeBuilderObject<CustomCliArguments, CustomExecutionContext> | void), {
commonOptions,
disableAutomaticGrouping,
enableAutomaticSorting
}?: WithBuilderExtensionsConfig<CustomCliArguments>): WithBuilderExtensionsReturnType<CustomCliArguments, CustomExecutionContext>;
/**
* Generate command usage text consistently yet flexibly.
*
* Defaults to: `Usage: $000\n\n${altDescription}` where `altDescription` is
* `"$1."`.
*/
export declare function withUsageExtensions(altDescription?: string): string;
export declare function withUsageExtensions(altDescription?: string, config?: Omit<WithUsageExtensionsConfig, 'altDescription'>): string;
export declare function withUsageExtensions(config?: WithUsageExtensionsConfig): string;
export declare function withUsageExtensions(config?: WithUsageExtensionsConfig | string, moreConfig?: Omit<WithUsageExtensionsConfig, 'altDescription'>): string;
/**
* This function returns a version of `maybeCommand`'s handler function that is
* ready to invoke immediately. It can be used with both BFE and normal Black
* Flag command exports.
*
* It returns a handler that expects to be passed a "reified argv," i.e. the
* object normally given to the command handler after all checks have passed and
* all updates to argv have been applied (including `subOptionOf` and BFE's
* `implies`).
*
* For this reason, invoking the returned handler will not run any BF or BFE
* builder configurations on the given argv object. **Whatever you pass the
* returned handler function will be (safely) deep cloned and then re-gifted to
* the command's handler _without_ any correctness checks.**
*
* Use `CustomCliArguments` (and `CustomExecutionContext`) to assert the
* expected shape of the "reified argv".
*
* Note that, like the `argv` passed to the returned handler function, the
* `context` argument passed to this function will be (safely) deep cloned,
* meaning any context changes effected by the handler will not persist outside
* of that handler's scope.
*
* Also note that the `$executionContext` key, if included in `argv`, will be
* ignored.
*
* See [the
* documentation](https://github.com/Xunnamius/black-flag/blob/main/packages/extensions/README.md#getinvocableextendedhandler)
* for more details.
*/
export declare function getInvocableExtendedHandler<CustomCliArguments extends Record<string, unknown>, CustomExecutionContext extends ExecutionContext & {
state: {
extensions?: SafeDeepCloneOptions;
};
}>(maybeCommand: Promisable<ImportedConfigurationModule<CustomCliArguments, CustomExecutionContext> | ImportedConfigurationModule<CustomCliArguments, AsStrictExecutionContext<CustomExecutionContext>>>, context: CustomExecutionContext): Promise<(argv: Merge<BfeStrictArguments<CustomCliArguments, CustomExecutionContext>, {
/**
* Do not manually provide this key. It will be included in `argv`
* automatically.
*/
[$executionContext]?: unknown;
/**
* The script name or node command that, when omitted from the `argv`
* passed to a handler returned by `getInvocableExtendedHandler`,
* defaults to the `name` value exported from the command's module file
* (or `"???"` if no name was exported).
*
* **Note that this default value IS LIKELY DIFFERENT THAN the _full
* name_ to which Black Flag sets `$0`!** If this is an issue, manually
* provide a value for `$0` in `argv`.
*/
$0?: string;
/**
* Non-option arguments that, when omitted from the `argv` passed to a
* handler returned by `getInvocableExtendedHandler`, defaults to an
* empty array (`[]`).
*/
_?: BfeStrictArguments<CustomCliArguments, CustomExecutionContext>["_"];
}>) => Promise<void>>;