3 // hoisted due to circular dependency on command.
4 module.exports = argsert
5 const command = require('./command')()
6 const YError = require('./yerror')
8 const positionName = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
9 function argsert (expected, callerArguments, length) {
10 // TODO: should this eventually raise an exception.
12 // preface the argument description with "cmd", so
13 // that we can run it through yargs' command parser.
15 let parsed = { demanded: [], optional: [] }
16 if (typeof expected === 'object') {
17 length = callerArguments
18 callerArguments = expected
20 parsed = command.parseCommand(`cmd ${expected}`)
22 const args = [].slice.call(callerArguments)
24 while (args.length && args[args.length - 1] === undefined) args.pop()
25 length = length || args.length
27 if (length < parsed.demanded.length) {
28 throw new YError(`Not enough arguments provided. Expected ${parsed.demanded.length} but received ${args.length}.`)
31 const totalCommands = parsed.demanded.length + parsed.optional.length
32 if (length > totalCommands) {
33 throw new YError(`Too many arguments provided. Expected max ${totalCommands} but received ${length}.`)
36 parsed.demanded.forEach((demanded) => {
37 const arg = args.shift()
38 const observedType = guessType(arg)
39 const matchingTypes = demanded.cmd.filter(type => type === observedType || type === '*')
40 if (matchingTypes.length === 0) argumentTypeError(observedType, demanded.cmd, position, false)
44 parsed.optional.forEach((optional) => {
45 if (args.length === 0) return
46 const arg = args.shift()
47 const observedType = guessType(arg)
48 const matchingTypes = optional.cmd.filter(type => type === observedType || type === '*')
49 if (matchingTypes.length === 0) argumentTypeError(observedType, optional.cmd, position, true)
53 console.warn(err.stack)
57 function guessType (arg) {
58 if (Array.isArray(arg)) {
60 } else if (arg === null) {
66 function argumentTypeError (observedType, allowedTypes, position, optional) {
67 throw new YError(`Invalid ${positionName[position] || 'manyith'} argument. Expected ${allowedTypes.join(' or ')} but received ${observedType}.`)