Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / node_modules / yargs / lib / validation.js
1 // validation-type-stuff, missing params,
2 // bad implications, custom checks.
3 module.exports = function (yargs, usage, y18n) {
4   var __ = y18n.__
5   var __n = y18n.__n
6   var self = {}
7
8   // validate appropriate # of non-option
9   // arguments were provided, i.e., '_'.
10   self.nonOptionCount = function (argv) {
11     var demanded = yargs.getDemanded()
12     var _s = argv._.length
13
14     if (demanded._ && (_s < demanded._.count || _s > demanded._.max)) {
15       if (demanded._.msg !== undefined) {
16         usage.fail(demanded._.msg)
17       } else if (_s < demanded._.count) {
18         usage.fail(
19           __('Not enough non-option arguments: got %s, need at least %s', argv._.length, demanded._.count)
20         )
21       } else {
22         usage.fail(
23           __('Too many non-option arguments: got %s, maximum of %s', argv._.length, demanded._.max)
24         )
25       }
26     }
27   }
28
29   // make sure that any args that require an
30   // value (--foo=bar), have a value.
31   self.missingArgumentValue = function (argv) {
32     var defaultValues = [true, false, '']
33     var options = yargs.getOptions()
34
35     if (options.requiresArg.length > 0) {
36       var missingRequiredArgs = []
37
38       options.requiresArg.forEach(function (key) {
39         var value = argv[key]
40
41         // if a value is explicitly requested,
42         // flag argument as missing if it does not
43         // look like foo=bar was entered.
44         if (~defaultValues.indexOf(value) ||
45           (Array.isArray(value) && !value.length)) {
46           missingRequiredArgs.push(key)
47         }
48       })
49
50       if (missingRequiredArgs.length > 0) {
51         usage.fail(__n(
52           'Missing argument value: %s',
53           'Missing argument values: %s',
54           missingRequiredArgs.length,
55           missingRequiredArgs.join(', ')
56         ))
57       }
58     }
59   }
60
61   // make sure all the required arguments are present.
62   self.requiredArguments = function (argv) {
63     var demanded = yargs.getDemanded()
64     var missing = null
65
66     Object.keys(demanded).forEach(function (key) {
67       if (!argv.hasOwnProperty(key)) {
68         missing = missing || {}
69         missing[key] = demanded[key]
70       }
71     })
72
73     if (missing) {
74       var customMsgs = []
75       Object.keys(missing).forEach(function (key) {
76         var msg = missing[key].msg
77         if (msg && customMsgs.indexOf(msg) < 0) {
78           customMsgs.push(msg)
79         }
80       })
81
82       var customMsg = customMsgs.length ? '\n' + customMsgs.join('\n') : ''
83
84       usage.fail(__n(
85         'Missing required argument: %s',
86         'Missing required arguments: %s',
87         Object.keys(missing).length,
88         Object.keys(missing).join(', ') + customMsg
89       ))
90     }
91   }
92
93   // check for unknown arguments (strict-mode).
94   self.unknownArguments = function (argv, aliases) {
95     var aliasLookup = {}
96     var descriptions = usage.getDescriptions()
97     var demanded = yargs.getDemanded()
98     var unknown = []
99
100     Object.keys(aliases).forEach(function (key) {
101       aliases[key].forEach(function (alias) {
102         aliasLookup[alias] = key
103       })
104     })
105
106     Object.keys(argv).forEach(function (key) {
107       if (key !== '$0' && key !== '_' &&
108         !descriptions.hasOwnProperty(key) &&
109         !demanded.hasOwnProperty(key) &&
110         !aliasLookup.hasOwnProperty(key)) {
111         unknown.push(key)
112       }
113     })
114
115     if (unknown.length > 0) {
116       usage.fail(__n(
117         'Unknown argument: %s',
118         'Unknown arguments: %s',
119         unknown.length,
120         unknown.join(', ')
121       ))
122     }
123   }
124
125   // validate arguments limited to enumerated choices
126   self.limitedChoices = function (argv) {
127     var options = yargs.getOptions()
128     var invalid = {}
129
130     if (!Object.keys(options.choices).length) return
131
132     Object.keys(argv).forEach(function (key) {
133       if (key !== '$0' && key !== '_' &&
134         options.choices.hasOwnProperty(key)) {
135         [].concat(argv[key]).forEach(function (value) {
136           // TODO case-insensitive configurability
137           if (options.choices[key].indexOf(value) === -1) {
138             invalid[key] = (invalid[key] || []).concat(value)
139           }
140         })
141       }
142     })
143
144     var invalidKeys = Object.keys(invalid)
145
146     if (!invalidKeys.length) return
147
148     var msg = __('Invalid values:')
149     invalidKeys.forEach(function (key) {
150       msg += '\n  ' + __(
151         'Argument: %s, Given: %s, Choices: %s',
152         key,
153         usage.stringifiedValues(invalid[key]),
154         usage.stringifiedValues(options.choices[key])
155       )
156     })
157     usage.fail(msg)
158   }
159
160   // custom checks, added using the `check` option on yargs.
161   var checks = []
162   self.check = function (f) {
163     checks.push(f)
164   }
165
166   self.customChecks = function (argv, aliases) {
167     checks.forEach(function (f) {
168       try {
169         var result = f(argv, aliases)
170         if (!result) {
171           usage.fail(__('Argument check failed: %s', f.toString()))
172         } else if (typeof result === 'string') {
173           usage.fail(result)
174         }
175       } catch (err) {
176         usage.fail(err.message ? err.message : err)
177       }
178     })
179   }
180
181   // check implications, argument foo implies => argument bar.
182   var implied = {}
183   self.implies = function (key, value) {
184     if (typeof key === 'object') {
185       Object.keys(key).forEach(function (k) {
186         self.implies(k, key[k])
187       })
188     } else {
189       implied[key] = value
190     }
191   }
192   self.getImplied = function () {
193     return implied
194   }
195
196   self.implications = function (argv) {
197     var implyFail = []
198
199     Object.keys(implied).forEach(function (key) {
200       var num
201       var origKey = key
202       var value = implied[key]
203
204       // convert string '1' to number 1
205       num = Number(key)
206       key = isNaN(num) ? key : num
207
208       if (typeof key === 'number') {
209         // check length of argv._
210         key = argv._.length >= key
211       } else if (key.match(/^--no-.+/)) {
212         // check if key doesn't exist
213         key = key.match(/^--no-(.+)/)[1]
214         key = !argv[key]
215       } else {
216         // check if key exists
217         key = argv[key]
218       }
219
220       num = Number(value)
221       value = isNaN(num) ? value : num
222
223       if (typeof value === 'number') {
224         value = argv._.length >= value
225       } else if (value.match(/^--no-.+/)) {
226         value = value.match(/^--no-(.+)/)[1]
227         value = !argv[value]
228       } else {
229         value = argv[value]
230       }
231
232       if (key && !value) {
233         implyFail.push(origKey)
234       }
235     })
236
237     if (implyFail.length) {
238       var msg = __('Implications failed:') + '\n'
239
240       implyFail.forEach(function (key) {
241         msg += ('  ' + key + ' -> ' + implied[key])
242       })
243
244       usage.fail(msg)
245     }
246   }
247
248   return self
249 }