All files / sportident-testbench-shell/src/commands BaseCommand.ts

53.84% Statements 21/39
50% Branches 7/14
62.5% Functions 5/8
56.75% Lines 21/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78                    1x                                     1x 1x 1x 2x 2x 2x 1x 1x   2x                                         1x       1x 1x 2x   1x 1x 1x 2x 2x 2x 2x        
import {ShellCommandContext} from '../Shell';
 
export interface ArgType {
    name: string;
    description?: string;
    choices?: string[];
    regex?: RegExp;
    isOptional?: boolean;
}
 
export abstract class BaseCommand {
    abstract getArgTypes(): ArgType[];
 
    autocomplete(args: string[]): string[] {
        const argTypes = this.getArgTypes();
        const lastArgType = argTypes[args.length - 1];
        Iif (!lastArgType) {
            return [args.join(' ')];
        }
        const lastArg = args[args.length - 1];
        Iif (lastArgType.choices) {
            return lastArgType.choices.filter((s) => s.startsWith(lastArg));
        }
        return [];
    }
 
    abstract run(context: ShellCommandContext): Promise<void>;
 
    validateArgs(context: ShellCommandContext): boolean {
        let isValid = true;
        const argTypes = this.getArgTypes();
        argTypes.forEach((argType: ArgType, argIndex: number) => {
            const arg = context.args[argIndex + 1];
            if (!arg) {
                if (!argType.isOptional) {
                    context.putString(`${argType.name} is not optional\n`);
                    isValid = false;
                }
                return;
            }
            Iif (argType.regex) {
                Iif (!argType.regex.exec(arg)) {
                    context.putString(
                        `For ${argType.name}, "${arg}" is not valid\n` +
                        `Must match: ${argType.regex}\n`,
                    );
                    isValid = false;
                }
            }
            Iif (argType.choices) {
                Iif (!argType.choices.some((choice) => choice === arg)) {
                    context.putString(
                        `For ${argType.name}, "${arg}" is not a valid choice\n` +
                        `Valid choices: ${argType.choices.join(', ')}\n`,
                    );
                    isValid = false;
                }
            }
        });
        return isValid;
    }
 
    printUsage(context: ShellCommandContext): void {
        const argTypes = this.getArgTypes();
        const argUsage = argTypes
            .map((argType: ArgType) => `[${argType.name}]${argType.isOptional ? '?' : ''}`)
            .join(' ');
        const usageTitle = `Usage: ${context.args[0]} ${argUsage}`;
        context.putString(`${usageTitle}\n`);
        argTypes.forEach((argType: ArgType) => {
            const choicesString = argType.choices ? argType.choices.join(', ') : '';
            const descriptionString = argType.description || '';
            const argUsageDescription = `${descriptionString}${choicesString}`;
            context.putString(`${argType.name}: ${argUsageDescription}\n`);
        });
    }
}