All files / src/old/toArgs convertCommands.js

100% Statements 45/45
85.71% Branches 36/42
100% Functions 23/23
100% Lines 39/39

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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 10475x   3x         49x 49x 49x   49x 141x 141x   141x 12x 12x   12x 11x   11x 11x 11x   11x 10x 10x 10x           49x         26x   90x   5x 5x     26x     5x 5x 5x         26x           26x 5x       10x                         177x       61x       238x       177x       125x       33x  
const convertCommands = (parsers, mode) => (mode === 'async' ? convertCommandsAsync : convertCommandsSync)(parsers)
 
module.exports = {
  convertCommands
}
 
function convertCommandsSync (parsers) {
  return ({errs = [], opts: OPTS = []} = {}) => {
    let args  = {_: []}
    let errs2 = []
  
    for (let i = 0; i < OPTS.length; i++) {
      const opt = OPTS[i]
      const {key, values} = opt
  
      if (Array.isArray(values) && isCommandOption(opt)) {
        const parentParser = parsers.__
        const childParser  = typeof parsers[key] === 'function' ? parsers[key] : parsers._
  
        if (typeof args[key] === 'undefined') {
          args[key] = {}
  
          const child = childParser(opt)(values, [])
          errs2       = errs2.concat(child.errs || [])
          args[key]   = child.args
  
          if (typeof parentParser === 'function') {
            const parent = parentParser({opts: filter(OPTS)})(child.args._, [])
            errs2        = errs2.concat(parent.errs || [])
            args         = {...parent.args, ...args, _: args._.concat(parent.args._)}
          }
        }
      }
    }
  
    return {errs: errs.concat(errs2), args}
  }
}
 
function convertCommandsAsync (parsers) {
  return ({errs = [], opts = []} = {}) => Promise.all(
    opts
    .filter(opt => Array.isArray(opt.values) && isCommandOption(opt))
    .map(cmd => {
      const childParser = typeof parsers[cmd.key] === 'function' ? parsers[cmd.key] : parsers._
      return childParser(cmd)(cmd.values, []).then(child => ({key: cmd.key, child}))
    })
  ).then(results =>
    Promise.all(
      results.map(
        ({key, child}) => {
          const parentParser = parsers.__
          return parentParser({opts: filter(opts)})(child.args._, []).then(
            parent => ({parent, key, child})
          )
        }
      )
    ).then(results =>
      results.map(({parent, key, child}) => ({
        errs: [...(child.errs || []), ...(parent.errs || [])],
        args: {...parent.args, [key]: child.args}
      }))
    )
  ).then(
    errsArgsList => errsArgsList.reduce(
      (acc, {errs, args}) => ({
        errs: [...acc.errs, ...errs],
        args: Object.keys(args).reduce(
          (acc2, key) => (
            key === '_'
              ? {...acc2, _: [...acc.args._, ...args._]}
              : typeof acc[key] === 'undefined' ? {...acc2, [key]: args[key]} : acc2
          ),
          acc.args
        )
      }),
      {errs, args: {_: []}}
    )
  )
}
 
function isCommandOption ({key, args, opts, types}) {
  return isOption({key, args}) && isVariadic({types}) && Array.isArray(opts)
}
 
function filter (opts) {
  return opts.filter(opt => isVariable(opt) && !isCommandOption(opt) && hasNoValues(opt))
}
 
function isVariable ({key}) {
  return typeof key !== 'undefined'
}
 
function isOption ({key, args}) {
  return isVariable({key}) && Array.isArray(args)
}
 
function isVariadic ({types}) {
  return typeof types === 'undefined'
}
 
function hasNoValues ({values}) {
  return typeof values === 'undefined'
}