All files / lib/command find.ts

100% Statements 21/21
100% Branches 8/8
100% Functions 2/2
100% Lines 21/21

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 602x 2x                                                 2x 21x 21x 21x 1x   20x 20x 20x   20x 31x 9x   22x 1x   21x 21x 21x     20x 1x     19x              
import _forEach from "lodash/forEach";
import _trim from "lodash/trim";
 
import { Def, Defs } from "../types";
 
/**
 * returns the deepest possible command for the cmdLine string
 * It may be a command with subcommands that it returns
 *
 * @param {Object} arg0 -
 * @param {Object} arg0.cmdLine -
 * @param {Object} arg0.commands - app commands definition
 * @returns {Object} { appCmd, cmdPath, cmdArgs }
 */
type Args = {
  cmdLine: string;
  commands: Defs;
};
 
export type CommandMeta = {
  appCmd: Def;
  cmdPath: string[];
  cmdArgs: string;
  cmdArgsList: string[];
};
 
export async function findCommand(arg0: Args): Promise<CommandMeta | void> {
  const { cmdLine, commands } = arg0;
  const cleanCmdLine = _trim(cmdLine);
  if (!cleanCmdLine) {
    return;
  }
  const words: string[] = cleanCmdLine.split(/\s+/);
  let appCmd: Partial<Def> = { commands };
  const cmdPath: string[] = [];
 
  _forEach([...words], word => {
    if (!appCmd.commands) {
      return false; // there are no sub-commands
    }
    if (!appCmd.commands[word]) {
      return false; // partial command or arg
    }
    cmdPath.push(word);
    words.shift();
    appCmd = appCmd.commands[word];
  });
 
  if (appCmd.commands === commands) {
    return;
  }
 
  return {
    appCmd,
    cmdPath,
    cmdArgs: words.join(" "),
    cmdArgsList: words
  };
}