UNPKG

2.42 kBJavaScriptView Raw
1'use strict'
2
3// hoisted due to circular dependency on command.
4module.exports = argsert
5const command = require('./command')()
6const YError = require('./yerror')
7
8const positionName = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
9function argsert (expected, callerArguments, length) {
10 // TODO: should this eventually raise an exception.
11 try {
12 // preface the argument description with "cmd", so
13 // that we can run it through yargs' command parser.
14 let position = 0
15 let parsed = { demanded: [], optional: [] }
16 if (typeof expected === 'object') {
17 length = callerArguments
18 callerArguments = expected
19 } else {
20 parsed = command.parseCommand(`cmd ${expected}`)
21 }
22 const args = [].slice.call(callerArguments)
23
24 while (args.length && args[args.length - 1] === undefined) args.pop()
25 length = length || args.length
26
27 if (length < parsed.demanded.length) {
28 throw new YError(`Not enough arguments provided. Expected ${parsed.demanded.length} but received ${args.length}.`)
29 }
30
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}.`)
34 }
35
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)
41 position += 1
42 })
43
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)
50 position += 1
51 })
52 } catch (err) {
53 console.warn(err.stack)
54 }
55}
56
57function guessType (arg) {
58 if (Array.isArray(arg)) {
59 return 'array'
60 } else if (arg === null) {
61 return 'null'
62 }
63 return typeof arg
64}
65
66function argumentTypeError (observedType, allowedTypes, position, optional) {
67 throw new YError(`Invalid ${positionName[position] || 'manyith'} argument. Expected ${allowedTypes.join(' or ')} but received ${observedType}.`)
68}