yargs 15.3.1 → 15.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +2 -3
  3. package/README.md +5 -5
  4. package/build/lib/apply-extends.d.ts +2 -0
  5. package/build/lib/apply-extends.js +65 -0
  6. package/build/lib/argsert.d.ts +2 -0
  7. package/build/lib/argsert.js +65 -0
  8. package/build/lib/command.d.ts +64 -0
  9. package/build/lib/command.js +416 -0
  10. package/build/lib/common-types.d.ts +36 -0
  11. package/build/lib/common-types.js +25 -0
  12. package/build/lib/completion-templates.d.ts +2 -0
  13. package/{lib → build/lib}/completion-templates.js +6 -5
  14. package/build/lib/completion.d.ts +21 -0
  15. package/build/lib/completion.js +135 -0
  16. package/build/lib/is-promise.d.ts +1 -0
  17. package/build/lib/is-promise.js +9 -0
  18. package/build/lib/levenshtein.d.ts +1 -0
  19. package/{lib → build/lib}/levenshtein.js +33 -33
  20. package/build/lib/middleware.d.ts +10 -0
  21. package/build/lib/middleware.js +57 -0
  22. package/build/lib/obj-filter.d.ts +1 -0
  23. package/build/lib/obj-filter.js +14 -0
  24. package/build/lib/parse-command.d.ts +11 -0
  25. package/build/lib/parse-command.js +36 -0
  26. package/build/lib/process-argv.d.ts +2 -0
  27. package/build/lib/process-argv.js +31 -0
  28. package/build/lib/usage.d.ts +49 -0
  29. package/build/lib/usage.js +540 -0
  30. package/build/lib/validation.d.ts +34 -0
  31. package/build/lib/validation.js +330 -0
  32. package/build/lib/yargs.d.ts +274 -0
  33. package/build/lib/yargs.js +1190 -0
  34. package/build/lib/yerror.d.ts +4 -0
  35. package/build/lib/yerror.js +11 -0
  36. package/index.js +1 -1
  37. package/locales/ja.json +6 -4
  38. package/package.json +26 -13
  39. package/yargs.js +2 -1291
  40. package/lib/apply-extends.js +0 -67
  41. package/lib/argsert.js +0 -68
  42. package/lib/command.js +0 -462
  43. package/lib/completion.js +0 -132
  44. package/lib/is-promise.js +0 -3
  45. package/lib/middleware.js +0 -64
  46. package/lib/obj-filter.js +0 -11
  47. package/lib/process-argv.js +0 -34
  48. package/lib/usage.js +0 -571
  49. package/lib/validation.js +0 -394
  50. package/lib/yerror.js +0 -11
package/lib/usage.js DELETED
@@ -1,571 +0,0 @@
1
- 'use strict'
2
- // this file handles outputting usage instructions,
3
- // failures, etc. keeps logging in one place.
4
- const decamelize = require('decamelize')
5
- const stringWidth = require('string-width')
6
- const objFilter = require('./obj-filter')
7
- const path = require('path')
8
- const setBlocking = require('set-blocking')
9
- const YError = require('./yerror')
10
-
11
- module.exports = function usage (yargs, y18n) {
12
- const __ = y18n.__
13
- const self = {}
14
-
15
- // methods for ouputting/building failure message.
16
- const fails = []
17
- self.failFn = function failFn (f) {
18
- fails.push(f)
19
- }
20
-
21
- let failMessage = null
22
- let showHelpOnFail = true
23
- self.showHelpOnFail = function showHelpOnFailFn (enabled, message) {
24
- if (typeof enabled === 'string') {
25
- message = enabled
26
- enabled = true
27
- } else if (typeof enabled === 'undefined') {
28
- enabled = true
29
- }
30
- failMessage = message
31
- showHelpOnFail = enabled
32
- return self
33
- }
34
-
35
- let failureOutput = false
36
- self.fail = function fail (msg, err) {
37
- const logger = yargs._getLoggerInstance()
38
-
39
- if (fails.length) {
40
- for (let i = fails.length - 1; i >= 0; --i) {
41
- fails[i](msg, err, self)
42
- }
43
- } else {
44
- if (yargs.getExitProcess()) setBlocking(true)
45
-
46
- // don't output failure message more than once
47
- if (!failureOutput) {
48
- failureOutput = true
49
- if (showHelpOnFail) {
50
- yargs.showHelp('error')
51
- logger.error()
52
- }
53
- if (msg || err) logger.error(msg || err)
54
- if (failMessage) {
55
- if (msg || err) logger.error('')
56
- logger.error(failMessage)
57
- }
58
- }
59
-
60
- err = err || new YError(msg)
61
- if (yargs.getExitProcess()) {
62
- return yargs.exit(1)
63
- } else if (yargs._hasParseCallback()) {
64
- return yargs.exit(1, err)
65
- } else {
66
- throw err
67
- }
68
- }
69
- }
70
-
71
- // methods for ouputting/building help (usage) message.
72
- let usages = []
73
- let usageDisabled = false
74
- self.usage = (msg, description) => {
75
- if (msg === null) {
76
- usageDisabled = true
77
- usages = []
78
- return
79
- }
80
- usageDisabled = false
81
- usages.push([msg, description || ''])
82
- return self
83
- }
84
- self.getUsage = () => {
85
- return usages
86
- }
87
- self.getUsageDisabled = () => {
88
- return usageDisabled
89
- }
90
-
91
- self.getPositionalGroupName = () => {
92
- return __('Positionals:')
93
- }
94
-
95
- let examples = []
96
- self.example = (cmd, description) => {
97
- examples.push([cmd, description || ''])
98
- }
99
-
100
- let commands = []
101
- self.command = function command (cmd, description, isDefault, aliases) {
102
- // the last default wins, so cancel out any previously set default
103
- if (isDefault) {
104
- commands = commands.map((cmdArray) => {
105
- cmdArray[2] = false
106
- return cmdArray
107
- })
108
- }
109
- commands.push([cmd, description || '', isDefault, aliases])
110
- }
111
- self.getCommands = () => commands
112
-
113
- let descriptions = {}
114
- self.describe = function describe (key, desc) {
115
- if (typeof key === 'object') {
116
- Object.keys(key).forEach((k) => {
117
- self.describe(k, key[k])
118
- })
119
- } else {
120
- descriptions[key] = desc
121
- }
122
- }
123
- self.getDescriptions = () => descriptions
124
-
125
- let epilogs = []
126
- self.epilog = (msg) => {
127
- epilogs.push(msg)
128
- }
129
-
130
- let wrapSet = false
131
- let wrap
132
- self.wrap = (cols) => {
133
- wrapSet = true
134
- wrap = cols
135
- }
136
-
137
- function getWrap () {
138
- if (!wrapSet) {
139
- wrap = windowWidth()
140
- wrapSet = true
141
- }
142
-
143
- return wrap
144
- }
145
-
146
- const deferY18nLookupPrefix = '__yargsString__:'
147
- self.deferY18nLookup = str => deferY18nLookupPrefix + str
148
-
149
- const defaultGroup = __('Options:')
150
- self.help = function help () {
151
- if (cachedHelpMessage) return cachedHelpMessage
152
- normalizeAliases()
153
-
154
- // handle old demanded API
155
- const base$0 = yargs.customScriptName ? yargs.$0 : path.basename(yargs.$0)
156
- const demandedOptions = yargs.getDemandedOptions()
157
- const demandedCommands = yargs.getDemandedCommands()
158
- const deprecatedOptions = yargs.getDeprecatedOptions()
159
- const groups = yargs.getGroups()
160
- const options = yargs.getOptions()
161
-
162
- let keys = []
163
- keys = keys.concat(Object.keys(descriptions))
164
- keys = keys.concat(Object.keys(demandedOptions))
165
- keys = keys.concat(Object.keys(demandedCommands))
166
- keys = keys.concat(Object.keys(options.default))
167
- keys = keys.filter(filterHiddenOptions)
168
- keys = Object.keys(keys.reduce((acc, key) => {
169
- if (key !== '_') acc[key] = true
170
- return acc
171
- }, {}))
172
-
173
- const theWrap = getWrap()
174
- const ui = require('cliui')({
175
- width: theWrap,
176
- wrap: !!theWrap
177
- })
178
-
179
- // the usage string.
180
- if (!usageDisabled) {
181
- if (usages.length) {
182
- // user-defined usage.
183
- usages.forEach((usage) => {
184
- ui.div(`${usage[0].replace(/\$0/g, base$0)}`)
185
- if (usage[1]) {
186
- ui.div({ text: `${usage[1]}`, padding: [1, 0, 0, 0] })
187
- }
188
- })
189
- ui.div()
190
- } else if (commands.length) {
191
- let u = null
192
- // demonstrate how commands are used.
193
- if (demandedCommands._) {
194
- u = `${base$0} <${__('command')}>\n`
195
- } else {
196
- u = `${base$0} [${__('command')}]\n`
197
- }
198
- ui.div(`${u}`)
199
- }
200
- }
201
-
202
- // your application's commands, i.e., non-option
203
- // arguments populated in '_'.
204
- if (commands.length) {
205
- ui.div(__('Commands:'))
206
-
207
- const context = yargs.getContext()
208
- const parentCommands = context.commands.length ? `${context.commands.join(' ')} ` : ''
209
-
210
- if (yargs.getParserConfiguration()['sort-commands'] === true) {
211
- commands = commands.sort((a, b) => a[0].localeCompare(b[0]))
212
- }
213
-
214
- commands.forEach((command) => {
215
- const commandString = `${base$0} ${parentCommands}${command[0].replace(/^\$0 ?/, '')}` // drop $0 from default commands.
216
- ui.span(
217
- {
218
- text: commandString,
219
- padding: [0, 2, 0, 2],
220
- width: maxWidth(commands, theWrap, `${base$0}${parentCommands}`) + 4
221
- },
222
- { text: command[1] }
223
- )
224
- const hints = []
225
- if (command[2]) hints.push(`[${__('default')}]`)
226
- if (command[3] && command[3].length) {
227
- hints.push(`[${__('aliases:')} ${command[3].join(', ')}]`)
228
- }
229
- if (hints.length) {
230
- ui.div({ text: hints.join(' '), padding: [0, 0, 0, 2], align: 'right' })
231
- } else {
232
- ui.div()
233
- }
234
- })
235
-
236
- ui.div()
237
- }
238
-
239
- // perform some cleanup on the keys array, making it
240
- // only include top-level keys not their aliases.
241
- const aliasKeys = (Object.keys(options.alias) || [])
242
- .concat(Object.keys(yargs.parsed.newAliases) || [])
243
-
244
- keys = keys.filter(key => !yargs.parsed.newAliases[key] && aliasKeys.every(alias => (options.alias[alias] || []).indexOf(key) === -1))
245
-
246
- // populate 'Options:' group with any keys that have not
247
- // explicitly had a group set.
248
- if (!groups[defaultGroup]) groups[defaultGroup] = []
249
- addUngroupedKeys(keys, options.alias, groups)
250
-
251
- // display 'Options:' table along with any custom tables:
252
- Object.keys(groups).forEach((groupName) => {
253
- if (!groups[groupName].length) return
254
-
255
- // if we've grouped the key 'f', but 'f' aliases 'foobar',
256
- // normalizedKeys should contain only 'foobar'.
257
- const normalizedKeys = groups[groupName].filter(filterHiddenOptions).map((key) => {
258
- if (~aliasKeys.indexOf(key)) return key
259
- for (let i = 0, aliasKey; (aliasKey = aliasKeys[i]) !== undefined; i++) {
260
- if (~(options.alias[aliasKey] || []).indexOf(key)) return aliasKey
261
- }
262
- return key
263
- })
264
-
265
- if (normalizedKeys.length < 1) return
266
-
267
- ui.div(groupName)
268
-
269
- // actually generate the switches string --foo, -f, --bar.
270
- const switches = normalizedKeys.reduce((acc, key) => {
271
- acc[key] = [key].concat(options.alias[key] || [])
272
- .map(sw => {
273
- // for the special positional group don't
274
- // add '--' or '-' prefix.
275
- if (groupName === self.getPositionalGroupName()) return sw
276
- else {
277
- return (
278
- // matches yargs-parser logic in which single-digits
279
- // aliases declared with a boolean type are now valid
280
- /^[0-9]$/.test(sw)
281
- ? ~options.boolean.indexOf(key) ? '-' : '--'
282
- : sw.length > 1 ? '--' : '-'
283
- ) + sw
284
- }
285
- })
286
- .join(', ')
287
-
288
- return acc
289
- }, {})
290
-
291
- normalizedKeys.forEach((key) => {
292
- const kswitch = switches[key]
293
- let desc = descriptions[key] || ''
294
- let type = null
295
-
296
- if (~desc.lastIndexOf(deferY18nLookupPrefix)) desc = __(desc.substring(deferY18nLookupPrefix.length))
297
-
298
- if (~options.boolean.indexOf(key)) type = `[${__('boolean')}]`
299
- if (~options.count.indexOf(key)) type = `[${__('count')}]`
300
- if (~options.string.indexOf(key)) type = `[${__('string')}]`
301
- if (~options.normalize.indexOf(key)) type = `[${__('string')}]`
302
- if (~options.array.indexOf(key)) type = `[${__('array')}]`
303
- if (~options.number.indexOf(key)) type = `[${__('number')}]`
304
-
305
- const extra = [
306
- (key in deprecatedOptions) ? (
307
- typeof deprecatedOptions[key] === 'string'
308
- ? `[${__('deprecated: %s', deprecatedOptions[key])}]`
309
- : `[${__('deprecated')}]`
310
- ) : null,
311
- type,
312
- (key in demandedOptions) ? `[${__('required')}]` : null,
313
- options.choices && options.choices[key] ? `[${__('choices:')} ${
314
- self.stringifiedValues(options.choices[key])}]` : null,
315
- defaultString(options.default[key], options.defaultDescription[key])
316
- ].filter(Boolean).join(' ')
317
-
318
- ui.span(
319
- { text: kswitch, padding: [0, 2, 0, 2], width: maxWidth(switches, theWrap) + 4 },
320
- desc
321
- )
322
-
323
- if (extra) ui.div({ text: extra, padding: [0, 0, 0, 2], align: 'right' })
324
- else ui.div()
325
- })
326
-
327
- ui.div()
328
- })
329
-
330
- // describe some common use-cases for your application.
331
- if (examples.length) {
332
- ui.div(__('Examples:'))
333
-
334
- examples.forEach((example) => {
335
- example[0] = example[0].replace(/\$0/g, base$0)
336
- })
337
-
338
- examples.forEach((example) => {
339
- if (example[1] === '') {
340
- ui.div(
341
- {
342
- text: example[0],
343
- padding: [0, 2, 0, 2]
344
- }
345
- )
346
- } else {
347
- ui.div(
348
- {
349
- text: example[0],
350
- padding: [0, 2, 0, 2],
351
- width: maxWidth(examples, theWrap) + 4
352
- }, {
353
- text: example[1]
354
- }
355
- )
356
- }
357
- })
358
-
359
- ui.div()
360
- }
361
-
362
- // the usage string.
363
- if (epilogs.length > 0) {
364
- const e = epilogs.map(epilog => epilog.replace(/\$0/g, base$0)).join('\n')
365
- ui.div(`${e}\n`)
366
- }
367
-
368
- // Remove the trailing white spaces
369
- return ui.toString().replace(/\s*$/, '')
370
- }
371
-
372
- // return the maximum width of a string
373
- // in the left-hand column of a table.
374
- function maxWidth (table, theWrap, modifier) {
375
- let width = 0
376
-
377
- // table might be of the form [leftColumn],
378
- // or {key: leftColumn}
379
- if (!Array.isArray(table)) {
380
- table = Object.keys(table).map(key => [table[key]])
381
- }
382
-
383
- table.forEach((v) => {
384
- width = Math.max(
385
- stringWidth(modifier ? `${modifier} ${v[0]}` : v[0]),
386
- width
387
- )
388
- })
389
-
390
- // if we've enabled 'wrap' we should limit
391
- // the max-width of the left-column.
392
- if (theWrap) width = Math.min(width, parseInt(theWrap * 0.5, 10))
393
-
394
- return width
395
- }
396
-
397
- // make sure any options set for aliases,
398
- // are copied to the keys being aliased.
399
- function normalizeAliases () {
400
- // handle old demanded API
401
- const demandedOptions = yargs.getDemandedOptions()
402
- const options = yargs.getOptions()
403
-
404
- ;(Object.keys(options.alias) || []).forEach((key) => {
405
- options.alias[key].forEach((alias) => {
406
- // copy descriptions.
407
- if (descriptions[alias]) self.describe(key, descriptions[alias])
408
- // copy demanded.
409
- if (alias in demandedOptions) yargs.demandOption(key, demandedOptions[alias])
410
- // type messages.
411
- if (~options.boolean.indexOf(alias)) yargs.boolean(key)
412
- if (~options.count.indexOf(alias)) yargs.count(key)
413
- if (~options.string.indexOf(alias)) yargs.string(key)
414
- if (~options.normalize.indexOf(alias)) yargs.normalize(key)
415
- if (~options.array.indexOf(alias)) yargs.array(key)
416
- if (~options.number.indexOf(alias)) yargs.number(key)
417
- })
418
- })
419
- }
420
-
421
- // if yargs is executing an async handler, we take a snapshot of the
422
- // help message to display on failure:
423
- let cachedHelpMessage
424
- self.cacheHelpMessage = function () {
425
- cachedHelpMessage = this.help()
426
- }
427
-
428
- // however this snapshot must be cleared afterwards
429
- // not to be be used by next calls to parse
430
- self.clearCachedHelpMessage = function () {
431
- cachedHelpMessage = undefined
432
- }
433
-
434
- // given a set of keys, place any keys that are
435
- // ungrouped under the 'Options:' grouping.
436
- function addUngroupedKeys (keys, aliases, groups) {
437
- let groupedKeys = []
438
- let toCheck = null
439
- Object.keys(groups).forEach((group) => {
440
- groupedKeys = groupedKeys.concat(groups[group])
441
- })
442
-
443
- keys.forEach((key) => {
444
- toCheck = [key].concat(aliases[key])
445
- if (!toCheck.some(k => groupedKeys.indexOf(k) !== -1)) {
446
- groups[defaultGroup].push(key)
447
- }
448
- })
449
- return groupedKeys
450
- }
451
-
452
- function filterHiddenOptions (key) {
453
- return yargs.getOptions().hiddenOptions.indexOf(key) < 0 || yargs.parsed.argv[yargs.getOptions().showHiddenOpt]
454
- }
455
-
456
- self.showHelp = (level) => {
457
- const logger = yargs._getLoggerInstance()
458
- if (!level) level = 'error'
459
- const emit = typeof level === 'function' ? level : logger[level]
460
- emit(self.help())
461
- }
462
-
463
- self.functionDescription = (fn) => {
464
- const description = fn.name ? decamelize(fn.name, '-') : __('generated-value')
465
- return ['(', description, ')'].join('')
466
- }
467
-
468
- self.stringifiedValues = function stringifiedValues (values, separator) {
469
- let string = ''
470
- const sep = separator || ', '
471
- const array = [].concat(values)
472
-
473
- if (!values || !array.length) return string
474
-
475
- array.forEach((value) => {
476
- if (string.length) string += sep
477
- string += JSON.stringify(value)
478
- })
479
-
480
- return string
481
- }
482
-
483
- // format the default-value-string displayed in
484
- // the right-hand column.
485
- function defaultString (value, defaultDescription) {
486
- let string = `[${__('default:')} `
487
-
488
- if (value === undefined && !defaultDescription) return null
489
-
490
- if (defaultDescription) {
491
- string += defaultDescription
492
- } else {
493
- switch (typeof value) {
494
- case 'string':
495
- string += `"${value}"`
496
- break
497
- case 'object':
498
- string += JSON.stringify(value)
499
- break
500
- default:
501
- string += value
502
- }
503
- }
504
-
505
- return `${string}]`
506
- }
507
-
508
- // guess the width of the console window, max-width 80.
509
- function windowWidth () {
510
- const maxWidth = 80
511
- // CI is not a TTY
512
- /* c8 ignore next 2 */
513
- if (typeof process === 'object' && process.stdout && process.stdout.columns) {
514
- return Math.min(maxWidth, process.stdout.columns)
515
- } else {
516
- return maxWidth
517
- }
518
- }
519
-
520
- // logic for displaying application version.
521
- let version = null
522
- self.version = (ver) => {
523
- version = ver
524
- }
525
-
526
- self.showVersion = () => {
527
- const logger = yargs._getLoggerInstance()
528
- logger.log(version)
529
- }
530
-
531
- self.reset = function reset (localLookup) {
532
- // do not reset wrap here
533
- // do not reset fails here
534
- failMessage = null
535
- failureOutput = false
536
- usages = []
537
- usageDisabled = false
538
- epilogs = []
539
- examples = []
540
- commands = []
541
- descriptions = objFilter(descriptions, (k, v) => !localLookup[k])
542
- return self
543
- }
544
-
545
- const frozens = []
546
- self.freeze = function freeze () {
547
- const frozen = {}
548
- frozens.push(frozen)
549
- frozen.failMessage = failMessage
550
- frozen.failureOutput = failureOutput
551
- frozen.usages = usages
552
- frozen.usageDisabled = usageDisabled
553
- frozen.epilogs = epilogs
554
- frozen.examples = examples
555
- frozen.commands = commands
556
- frozen.descriptions = descriptions
557
- }
558
- self.unfreeze = function unfreeze () {
559
- const frozen = frozens.pop()
560
- failMessage = frozen.failMessage
561
- failureOutput = frozen.failureOutput
562
- usages = frozen.usages
563
- usageDisabled = frozen.usageDisabled
564
- epilogs = frozen.epilogs
565
- examples = frozen.examples
566
- commands = frozen.commands
567
- descriptions = frozen.descriptions
568
- }
569
-
570
- return self
571
- }