diff --git a/packages/cli/src/router/index.ts b/packages/cli/src/router/index.ts index dcf5e6af9d..d699869798 100644 --- a/packages/cli/src/router/index.ts +++ b/packages/cli/src/router/index.ts @@ -1,11 +1,13 @@ import - { - convertToMiddleware, each, introspect, isPromiseLike, Logger, map, MiddlewareAsync, MiddlewareCompositeAsync, - MiddlewareCompositeWithPriorityAsync, MiddlewareIndexedAsync, MiddlewarePromise - } from '@akala/core'; +{ + convertToMiddleware, each, introspect, isPromiseLike, Logger, map, MiddlewareAsync, MiddlewareCompositeAsync, + MiddlewareCompositeWithPriorityAsync, MiddlewareIndexedAsync, MiddlewarePromise +} from '@akala/core'; import normalize from '../helpers/normalize.js'; -export interface CliContext = Record, TState = unknown> +export type OptionType = string | boolean | string[] | number; + +export interface CliContext = Record, TState = unknown> { args: string[]; argv: string[]; @@ -39,7 +41,7 @@ export class ErrorMessage extends Error const defaultOptionParseOption: OptionParseOption = { flagStart: '-', fullOptionStart: '--', valueAssign: '=' }; -export interface OptionOptions +export interface OptionOptions { aliases?: string[], needsValue?: boolean, @@ -49,12 +51,13 @@ export interface OptionOptions optional?: boolean; positional?: boolean; position?: number; + default?: TValue; } -class OptionMiddleware implements MiddlewareAsync<[context: CliContext]> +class OptionMiddleware implements MiddlewareAsync<[context: CliContext]> { matchers: { isFull: boolean; pattern: RegExp; }[] = [] - constructor(private readonly name: string, private options?: OptionOptions, private parseOptions: OptionParseOption = defaultOptionParseOption) + constructor(private readonly name: string, private options?: OptionOptions, private parseOptions: OptionParseOption = defaultOptionParseOption) { const names = [name, ...options?.aliases || []]; names.forEach(n => @@ -74,6 +77,8 @@ class OptionMiddleware implements MiddlewareAsync<[context: CliContext]> handle(context: CliContext): MiddlewarePromise { + if (this.options.default) + context.options[this.name] = this.options.default; for (let index = 0; index < context.args.length; index++) { let element = context.args[index]; @@ -190,7 +195,7 @@ function formatUsage(obj: Record, indent?: number): string }).join('\n'); } -class OptionsMiddleware> implements MiddlewareAsync<[context: CliContext]> +class OptionsMiddleware> implements MiddlewareAsync<[context: CliContext]> { usage(context: CliContext): UsageObject['options'] { @@ -216,12 +221,12 @@ class OptionsMiddleware(); private positionalArgs = new MiddlewareCompositeWithPriorityAsync<[CliContext]>(); - public config: { [key in keyof TOptions]?: OptionOptions } = {}; + public config: { [key in keyof TOptions]?: OptionOptions } = {}; - option(name: TName, option?: OptionOptions): OptionsMiddleware + option(name: TName, option?: OptionOptions): OptionsMiddleware { - this.config[name] = option; + this.config[name] = option as any; if (option?.positional) { if (isNaN(Number(option.position))) @@ -240,10 +245,10 @@ class OptionsMiddleware(middleware: OptionMiddleware): OptionsMiddleware> + optionMiddleware(middleware: OptionMiddleware): OptionsMiddleware> { this.options.useMiddleware(middleware); - return this; + return this as any; } handle(context: CliContext): MiddlewarePromise @@ -270,7 +275,7 @@ export interface UsageObject export const usageParser = /^((?:@?[/$_#\w-]+)(?: ([@$_#\w-]+))*)((?: (?:<[-\w]+(?:\|[-\w]+)?>))*(?: (?:\[[-\w]+(?:\|[-\w]+)?\]))*(?: \[(?:\.{3})[-\w]+(?:\|[-\w]+)?\])?)/; -export class NamespaceMiddleware = Record, TState = unknown> extends MiddlewareIndexedAsync<[CliContext], NamespaceMiddleware> implements MiddlewareAsync<[context: CliContext]> +export class NamespaceMiddleware = Record, TState = unknown> extends MiddlewareIndexedAsync<[CliContext], NamespaceMiddleware> implements MiddlewareAsync<[context: CliContext]> { private readonly _preAction = new MiddlewareCompositeAsync<[CliContext]>(); private _action: MiddlewareAsync<[CliContext]>; @@ -319,7 +324,7 @@ export class NamespaceMiddleware = TOptions>(name: string, description?: string): NamespaceMiddleware + public command = TOptions>(name: string, description?: string): NamespaceMiddleware { let middleware: NamespaceMiddleware; if (name !== null) @@ -332,7 +337,7 @@ export class NamespaceMiddleware(cli[2] + cli[3], description); var args = cli[3]; - var parameters: ({ name: keyof TOptions2 | keyof TOptions, rest?: boolean } & OptionOptions)[] = []; + var parameters: ({ name: keyof TOptions2 | keyof TOptions, rest?: boolean } & OptionOptions)[] = []; var parameter: RegExpExecArray; const parameterParsing = / <([-\w]+)(?:\|[-\w]+)?>| \[([-\w]+)(?:\|[-\w]+)?\]| \[(?:\.{3})?([-\w]+)(?:\|[-\w]+)?\]/g; let position = 0; @@ -425,7 +430,7 @@ export class NamespaceMiddleware(options: { [key in Exclude]: OptionOptions }): NamespaceMiddleware + options(options: { [key in Exclude]: OptionOptions }): NamespaceMiddleware { each(options, (o, key) => { @@ -434,9 +439,18 @@ export class NamespaceMiddleware; } - option(name: TName, option?: OptionOptions) + option(): (name: TName, options?: OptionOptions) => NamespaceMiddleware + option(name: TName, option?: OptionOptions) : NamespaceMiddleware + option(name?: TName, option?: OptionOptions) + : NamespaceMiddleware | ((name: TName, options?: OptionOptions) => NamespaceMiddleware) { + if (typeof name == 'undefined') + return (name: TName, option?: OptionOptions) => + // : NamespaceMiddleware + { + return this.option(name, option); + } this._option.option(name, option); return this as unknown as NamespaceMiddleware; }