Skip to content

Commit

Permalink
feat(command,flags): make options generic
Browse files Browse the repository at this point in the history
  • Loading branch information
c4spar committed May 20, 2020
1 parent c64282e commit 09a3d00
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 46 deletions.
50 changes: 24 additions & 26 deletions packages/command/lib/base-command.ts
Expand Up @@ -23,7 +23,7 @@ export type ITypeMap = IGenericObject<Type<any> | ITypeHandler<any>>
/**
* Base command implementation without pre configured command's and option's.
*/
export class BaseCommand {
export class BaseCommand<O = any> {

protected types: ITypeMap = {
string: new StringType(),
Expand All @@ -35,10 +35,10 @@ export class BaseCommand {
// protected name: string = location.pathname.split( '/' ).pop() as string;
protected _name: string = 'COMMAND';
protected _parent?: BaseCommand;
protected ver: string = '';
protected ver: string = '0.0.0';
protected desc: string = 'No description ...';
protected fn: IAction | undefined;
protected options: IOption[] = [];
protected fn: IAction<O> | undefined;
protected options: IOption<O>[] = [];
protected commands: Map<string, CommandMap> = new Map();
protected examples: IExample[] = [];
protected envVars: IEnvVariable[] = [];
Expand Down Expand Up @@ -210,7 +210,7 @@ export class BaseCommand {
*
* @param fn Callback method.
*/
public action( fn: IAction ): this {
public action( fn: IAction<O> ): this {
this.cmd.fn = fn;
this.reset();
return this;
Expand Down Expand Up @@ -320,8 +320,8 @@ export class BaseCommand {
* @param desc Flag description.
* @param opts Flag options.
*/
public option( flags: string, desc: string, opts?: ICommandOption ): this;
public option( flags: string, desc: string, opts?: ICommandOption | IFlagValueHandler ): this {
public option( flags: string, desc: string, opts?: ICommandOption<O> ): this;
public option( flags: string, desc: string, opts?: ICommandOption<O> | IFlagValueHandler ): this {

if ( typeof opts === 'function' ) {
return this.option( flags, desc, { value: opts } );
Expand All @@ -335,7 +335,7 @@ export class BaseCommand {

const args: IArgumentDetails[] = result.typeDefinition ? this.parseArgsDefinition( result.typeDefinition ) : [];

const option: IOption = {
const option: IOption<O> = {
name: '',
description: desc,
args,
Expand Down Expand Up @@ -442,7 +442,7 @@ export class BaseCommand {
* @param args Command line args to parse. Ex: `cmd.parse( Deno.args )`
* @param dry Execute command after parsed.
*/
public async parse( args: string[], dry?: boolean ): Promise<IFlagsParseResult> {
public async parse( args: string[], dry?: boolean ): Promise<IFlagsParseResult<O>> {

// if ( !this.name ) {
// throw new Error( 'Missing command name' );
Expand All @@ -464,15 +464,15 @@ export class BaseCommand {
await this.executeExecutable( this.rawArgs );
}

return { options: {}, args: this.rawArgs, cmd: this };
return { options: {} as O, args: this.rawArgs, cmd: this };

} else if ( this._useRawArgs ) {

if ( dry ) {
return { options: {}, args: this.rawArgs, cmd: this };
return { options: {} as O, args: this.rawArgs, cmd: this };
}

return await this.execute( {}, ...this.rawArgs );
return await this.execute( {} as O, ...this.rawArgs );

} else {

Expand All @@ -496,7 +496,7 @@ export class BaseCommand {
* @param options A map of options.
* @param args Command arguments.
*/
protected async execute( options: IFlags = {}, ...args: IFlagValue[] ): Promise<IFlagsParseResult> {
protected async execute( options: O, ...args: IFlagValue[] ): Promise<IFlagsParseResult<O>> {

const actionOption = this.findActionFlag( options, args );

Expand Down Expand Up @@ -575,10 +575,10 @@ export class BaseCommand {
* @param stopEarly Stop early.
* @param knownFlaks Known command line args.
*/
protected parseFlags( args: string[], stopEarly?: boolean, knownFlaks?: IFlags ): IFlagsResult {
protected parseFlags( args: string[], stopEarly?: boolean, knownFlaks?: IFlags ): IFlagsResult<O> {

try {
return parseFlags( args, {
return parseFlags<O>( args, {
stopEarly,
knownFlaks,
allowEmpty: this._allowEmpty,
Expand Down Expand Up @@ -654,10 +654,8 @@ export class BaseCommand {

/**
* Match commands and arguments from command line arguments.
*
* @param args
*/
protected parseArguments( args: string[], flags: IFlags ): IFlagValue[] {
protected parseArguments( args: string[], flags: O ): IFlagValue[] {

const params: IFlagValue[] = [];

Expand Down Expand Up @@ -787,7 +785,7 @@ export class BaseCommand {
* @param flags Command options.
* @param args Command arguments.
*/
protected findActionFlag( flags: IFlags, args: IFlagValue[] ): IOption | undefined {
protected findActionFlag( flags: O, args: IFlagValue[] ): IOption<O> | undefined {

const flagNames = Object.keys( flags );

Expand Down Expand Up @@ -888,7 +886,7 @@ export class BaseCommand {
return this.options.length > 0;
}

public getOptions(): IOption[] {
public getOptions(): IOption<O>[] {

return this.options;
}
Expand All @@ -906,7 +904,7 @@ export class BaseCommand {
*
* @param name Name of the option. Must be in param-case.
*/
public getOption( name: string ): IOption | undefined {
public getOption( name: string ): IOption<O> | undefined {

return this.options.find( option => option.name === name );
}
Expand All @@ -916,7 +914,7 @@ export class BaseCommand {
*
* @param name Name of the option. Must be in param-case.
*/
public removeOption( name: string ): IOption | undefined {
public removeOption( name: string ): IOption<O> | undefined {

const index = this.options.findIndex( option => option.name === name );

Expand Down Expand Up @@ -966,7 +964,7 @@ export class BaseCommand {
*
* @param name Name of the sub-command.
*/
public getCommand( name: string ): BaseCommand {
public getCommand<O = any>( name: string ): BaseCommand<O> {

return this.getCommandMap( name ).cmd;
}
Expand All @@ -976,9 +974,9 @@ export class BaseCommand {
*
* @param name Name of the sub-command.
*/
public getCommandMap( name: string ): CommandMap {
public getCommandMap<O = any>( name: string ): CommandMap<O> {

const cmd: CommandMap | undefined = this.commands.get( name );
const cmd: CommandMap<O> | undefined = this.commands.get( name );
// || this.commands.get( '*' );

if ( !cmd ) {
Expand All @@ -993,7 +991,7 @@ export class BaseCommand {
*
* @param name Name of the command.
*/
public removeCommand( name: string ): BaseCommand {
public removeCommand<O = any>( name: string ): BaseCommand<O> {

const command = this.getCommand( name );
this.commands.delete( name );
Expand Down
2 changes: 1 addition & 1 deletion packages/command/lib/command.ts
Expand Up @@ -12,7 +12,7 @@ import { DefaultCommand } from './default-command.ts';
* -h, --help Output's autogenerated help.
* -V, --version Output's version number
*/
export class Command extends DefaultCommand {
export class Command<O = any> extends DefaultCommand<O> {

public constructor() {

Expand Down
2 changes: 1 addition & 1 deletion packages/command/lib/default-command.ts
Expand Up @@ -10,7 +10,7 @@ import { BaseCommand } from './base-command.ts';
* -h, --help Output's autogenerated help.
* -V, --version Output's version number
*/
export class DefaultCommand extends BaseCommand {
export class DefaultCommand<O = any> extends BaseCommand<O> {

public constructor() {

Expand Down
25 changes: 12 additions & 13 deletions packages/command/lib/types.ts
@@ -1,15 +1,15 @@
import { BaseCommand } from '../../command/lib/base-command.ts';
import { IFlagArgument, IFlagOptions, IFlags, IFlagValue, IGenericObject, OptionType } from '../../flags/lib/types.ts';
import { IFlagArgument, IFlagOptions, IFlagValue, IGenericObject, OptionType } from '../../flags/lib/types.ts';

/** Command map. */
export interface CommandMap {
export interface CommandMap<O = any> {
name: string;
aliases: string[];
cmd: BaseCommand;
cmd: BaseCommand<O>;
}

/** Action handler. */
export type IAction = ( options: any, ...args: any[] ) => void | Promise<void>;
export type IAction<O> = ( options: O, ...args: any[] ) => void | Promise<void>;

/** Omit key from object. */
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
Expand All @@ -25,7 +25,7 @@ export interface IArgumentDetails extends IFlagArgument {
}

/** Command settings. */
export interface ICommandOption extends Omit<Omit<Omit<Omit<Omit<Omit<Omit<IFlagOptions,
export interface ICommandOption<O> extends Omit<Omit<Omit<Omit<Omit<Omit<Omit<IFlagOptions,
'name'>,
'args'>,
'type'>,
Expand All @@ -34,11 +34,11 @@ export interface ICommandOption extends Omit<Omit<Omit<Omit<Omit<Omit<Omit<IFlag
'variadic'>,
'list'> {
override?: boolean;
action?: IAction;
action?: IAction<O>;
}

/** Command option setting's. */
export interface IOption extends ICommandOption, IFlagOptions {
export interface IOption<O = any> extends ICommandOption<O>, IFlagOptions {
description: string,
flags: string;
typeDefinition?: string;
Expand All @@ -60,10 +60,10 @@ export interface IExample {
}

/** Result of `cmd.parse()`. */
export interface IFlagsParseResult {
options: IFlags,
export interface IFlagsParseResult<O> {
options: O,
args: IFlagValue[]
cmd: BaseCommand;
cmd: BaseCommand<O>;
}

/** Type parser method. */
Expand All @@ -72,12 +72,11 @@ export type ICompleteHandler = () => string[] | Promise<string[]>;
/** Map of type handlers. */
export type ICompleteHandlerMap = IGenericObject<ICompleteHandler>

export interface IHelpCommand extends BaseCommand {

export interface IHelpCommand<O = any> extends BaseCommand<O> {
show( name?: string ): void;
}

export function isHelpCommand( cmd: BaseCommand ): cmd is IHelpCommand {
export function isHelpCommand<O = any>( cmd: BaseCommand<O> ): cmd is IHelpCommand<O> {

return typeof ( cmd as any ).show === 'function';
}
2 changes: 1 addition & 1 deletion packages/command/types/command-list.ts
Expand Up @@ -8,6 +8,6 @@ export class CommandListType extends StringType {
}

public complete(): string[] {
return this.cmd.getCommands().map( cmd => cmd.getName() );
return this.cmd.getCommands().map( ( cmd: BaseCommand ) => cmd.getName() );
}
}
4 changes: 2 additions & 2 deletions packages/flags/lib/flags.ts
Expand Up @@ -18,7 +18,7 @@ const Types: IGenericObject<IType<any>> = {
* @param args Command line arguments e.g: `Deno.args`
* @param opts Parse options.
*/
export function parseFlags( args: string[], opts: IParseOptions = {} ): IFlagsResult {
export function parseFlags<O = any>( args: string[], opts: IParseOptions = {} ): IFlagsResult<O> {

!opts.flags && ( opts.flags = [] );

Expand Down Expand Up @@ -244,7 +244,7 @@ export function parseFlags( args: string[], opts: IParseOptions = {} ): IFlagsRe
validateFlags( opts.flags, flags, defaultValues, opts.knownFlaks, opts.allowEmpty );
}

return { flags, unknown, literal };
return { flags: flags as any as O, unknown, literal };
}

export function parseFlagValue( option: IFlagOptions, arg: IFlagArgument, nextValue: string ): any {
Expand Down
4 changes: 2 additions & 2 deletions packages/flags/lib/types.ts
Expand Up @@ -28,8 +28,8 @@ export type IFlags = IGenericObject<undefined | IFlagValue | IFlagValue[]>;
/**
* Parse result.
*/
export interface IFlagsResult {
flags: IFlags;
export interface IFlagsResult<O = any> {
flags: O;
unknown: string[];
literal: string[];
}
Expand Down

0 comments on commit 09a3d00

Please sign in to comment.