yargs 13.3.2 → 14.0.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [14.0.0](https://github.com/yargs/yargs/compare/v13.3.0...v14.0.0) (2019-07-30)
6
+
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ * we now only officially support yargs.$0 parameter and discourage direct access to yargs.parsed
11
+ * previously to this fix methods like `yargs.getOptions()` contained the state of the last command to execute.
12
+ * do not allow additional positionals in strict mode
13
+
14
+ ### Bug Fixes
15
+
16
+ * calling parse multiple times now appropriately maintains state ([#1137](https://github.com/yargs/yargs/issues/1137)) ([#1369](https://github.com/yargs/yargs/issues/1369)) ([026b151](https://github.com/yargs/yargs/commit/026b151))
17
+ * prefer user supplied script name in usage ([#1383](https://github.com/yargs/yargs/issues/1383)) ([28c74b9](https://github.com/yargs/yargs/commit/28c74b9))
18
+ * **deps:** use decamelize from npm instead of vendored copy ([#1377](https://github.com/yargs/yargs/issues/1377)) ([015eeb9](https://github.com/yargs/yargs/commit/015eeb9))
19
+ * **examples:** fix usage-options.js to reflect current API ([#1375](https://github.com/yargs/yargs/issues/1375)) ([6e5b76b](https://github.com/yargs/yargs/commit/6e5b76b))
20
+ * do not allow additional positionals in strict mode ([35d777c](https://github.com/yargs/yargs/commit/35d777c))
21
+ * properties accessed on singleton now reflect current state of instance ([#1366](https://github.com/yargs/yargs/issues/1366)) ([409d35b](https://github.com/yargs/yargs/commit/409d35b))
22
+ * tolerate null prototype for config objects with `extends` ([#1376](https://github.com/yargs/yargs/issues/1376)) ([3d26d11](https://github.com/yargs/yargs/commit/3d26d11)), closes [#1372](https://github.com/yargs/yargs/issues/1372)
23
+ * yargs.parsed now populated before returning, when yargs.parse() called with no args (#1382) ([e3981fd](https://github.com/yargs/yargs/commit/e3981fd)), closes [#1382](https://github.com/yargs/yargs/issues/1382)
24
+
25
+ ### Features
26
+
27
+ * adds support for multiple epilog messages ([#1384](https://github.com/yargs/yargs/issues/1384)) ([07a5554](https://github.com/yargs/yargs/commit/07a5554))
28
+ * allow completionCommand to be set via showCompletionScript ([#1385](https://github.com/yargs/yargs/issues/1385)) ([5562853](https://github.com/yargs/yargs/commit/5562853))
29
+
5
30
  ## [13.3.0](https://www.github.com/yargs/yargs/compare/v13.2.4...v13.3.0) (2019-06-10)
6
31
 
7
32
 
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  <p align="center">
6
6
  <b >Yargs be a node.js library fer hearties tryin' ter parse optstrings</b>
7
7
  </p>
8
+
8
9
  <br>
9
10
 
10
11
  [![Build Status][travis-image]][travis-url]
@@ -15,7 +16,7 @@
15
16
  [![Slack][slack-image]][slack-url]
16
17
 
17
18
  ## Description :
18
- Yargs helps you build interactive command line tools, by parsing arguments and generating an elegant user interface.
19
+ Yargs helps you build interactive command line tools, by parsing arguments and generating an elegant user interface.
19
20
 
20
21
  It gives you:
21
22
 
@@ -86,6 +87,16 @@ require('yargs') // eslint-disable-line
86
87
 
87
88
  Run the example above with `--help` to see the help for the application.
88
89
 
90
+ ## TypeScript
91
+
92
+ yargs has type definitions at [@types/yargs][type-definitions].
93
+
94
+ ```
95
+ npm i @types/yargs --save-dev
96
+ ```
97
+
98
+ See usage examples in [docs](/docs/typescript.md)
99
+
89
100
  ## Community :
90
101
 
91
102
  Having problems? want to contribute? join our [community slack](http://devtoolscommunity.herokuapp.com).
@@ -102,6 +113,7 @@ Having problems? want to contribute? join our [community slack](http://devtoolsc
102
113
  * [Numbers](/docs/tricks.md#numbers)
103
114
  * [Arrays](/docs/tricks.md#arrays)
104
115
  * [Objects](/docs/tricks.md#objects)
116
+ * [Quotes](/docs/tricks.md#quotes)
105
117
  * [Advanced Topics](/docs/advanced.md)
106
118
  * [Composing Your App Using Commands](/docs/advanced.md#commands)
107
119
  * [Building Configurable CLI Apps](/docs/advanced.md#configuration)
@@ -120,3 +132,4 @@ Having problems? want to contribute? join our [community slack](http://devtoolsc
120
132
  [conventional-commits-url]: https://conventionalcommits.org/
121
133
  [slack-image]: http://devtoolscommunity.herokuapp.com/badge.svg
122
134
  [slack-url]: http://devtoolscommunity.herokuapp.com
135
+ [type-definitions]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/yargs
package/index.js CHANGED
@@ -25,8 +25,16 @@ function singletonify (inst) {
25
25
  Object.keys(inst).forEach((key) => {
26
26
  if (key === 'argv') {
27
27
  Argv.__defineGetter__(key, inst.__lookupGetter__(key))
28
+ } else if (typeof inst[key] === 'function') {
29
+ Argv[key] = inst[key].bind(inst)
28
30
  } else {
29
- Argv[key] = typeof inst[key] === 'function' ? inst[key].bind(inst) : inst[key]
31
+ Argv.__defineGetter__('$0', () => {
32
+ return inst.$0
33
+ })
34
+ Argv.__defineGetter__('parsed', () => {
35
+ console.warn('In future major releases of yargs, "parsed" will be a private field. Use the return value of ".parse()" or ".argv" instead')
36
+ return inst.parsed
37
+ })
30
38
  }
31
39
  })
32
40
  }
@@ -19,7 +19,7 @@ function getPathToDefaultConfig (cwd, pathToExtend) {
19
19
  function applyExtends (config, cwd) {
20
20
  let defaultConfig = {}
21
21
 
22
- if (config.hasOwnProperty('extends')) {
22
+ if (Object.prototype.hasOwnProperty.call(config, 'extends')) {
23
23
  if (typeof config.extends !== 'string') return defaultConfig
24
24
  const isPath = /\.json|\..*rc$/.test(config.extends)
25
25
  let pathToDefault = null
package/lib/command.js CHANGED
@@ -186,24 +186,17 @@ module.exports = function command (yargs, usage, validation, globalMiddleware) {
186
186
  // a function can be provided, which builds
187
187
  // up a yargs chain and possibly returns it.
188
188
  innerYargs = commandHandler.builder(yargs.reset(parsed.aliases))
189
- // if the builder function did not yet parse argv with reset yargs
190
- // and did not explicitly set a usage() string, then apply the
191
- // original command string as usage() for consistent behavior with
192
- // options object below.
193
- if (yargs.parsed === false) {
194
- if (shouldUpdateUsage(yargs)) {
195
- yargs.getUsageInstance().usage(
196
- usageFromParentCommandsCommandHandler(parentCommands, commandHandler),
197
- commandHandler.description
198
- )
199
- }
200
- innerArgv = innerYargs ? innerYargs._parseArgs(null, null, true, commandIndex) : yargs._parseArgs(null, null, true, commandIndex)
201
- } else {
202
- innerArgv = yargs.parsed.argv
189
+ if (!innerYargs || (typeof innerYargs._parseArgs !== 'function')) {
190
+ innerYargs = yargs
203
191
  }
204
-
205
- if (innerYargs && yargs.parsed === false) aliases = innerYargs.parsed.aliases
206
- else aliases = yargs.parsed.aliases
192
+ if (shouldUpdateUsage(innerYargs)) {
193
+ innerYargs.getUsageInstance().usage(
194
+ usageFromParentCommandsCommandHandler(parentCommands, commandHandler),
195
+ commandHandler.description
196
+ )
197
+ }
198
+ innerArgv = innerYargs._parseArgs(null, null, true, commandIndex)
199
+ aliases = innerYargs.parsed.aliases
207
200
  } else if (typeof commandHandler.builder === 'object') {
208
201
  // as a short hand, an object can instead be provided, specifying
209
202
  // the options that a command takes.
@@ -419,18 +412,19 @@ module.exports = function command (yargs, usage, validation, globalMiddleware) {
419
412
  // the state of commands such that
420
413
  // we can apply .parse() multiple times
421
414
  // with the same yargs instance.
422
- let frozen
415
+ let frozens = []
423
416
  self.freeze = () => {
424
- frozen = {}
417
+ let frozen = {}
418
+ frozens.push(frozen)
425
419
  frozen.handlers = handlers
426
420
  frozen.aliasMap = aliasMap
427
421
  frozen.defaultCommand = defaultCommand
428
422
  }
429
423
  self.unfreeze = () => {
424
+ let frozen = frozens.pop()
430
425
  handlers = frozen.handlers
431
426
  aliasMap = frozen.aliasMap
432
427
  defaultCommand = frozen.defaultCommand
433
- frozen = undefined
434
428
  }
435
429
 
436
430
  return self
package/lib/usage.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
  // this file handles outputting usage instructions,
3
3
  // failures, etc. keeps logging in one place.
4
- const decamelize = require('./decamelize')
4
+ const decamelize = require('decamelize')
5
5
  const stringWidth = require('string-width')
6
6
  const objFilter = require('./obj-filter')
7
7
  const path = require('path')
@@ -122,9 +122,9 @@ module.exports = function usage (yargs, y18n) {
122
122
  }
123
123
  self.getDescriptions = () => descriptions
124
124
 
125
- let epilog
125
+ let epilogs = []
126
126
  self.epilog = (msg) => {
127
- epilog = msg
127
+ epilogs.push(msg)
128
128
  }
129
129
 
130
130
  let wrapSet = false
@@ -151,7 +151,7 @@ module.exports = function usage (yargs, y18n) {
151
151
  normalizeAliases()
152
152
 
153
153
  // handle old demanded API
154
- const base$0 = path.basename(yargs.$0)
154
+ const base$0 = yargs.customScriptName ? yargs.$0 : path.basename(yargs.$0)
155
155
  const demandedOptions = yargs.getDemandedOptions()
156
156
  const demandedCommands = yargs.getDemandedCommands()
157
157
  const groups = yargs.getGroups()
@@ -345,8 +345,8 @@ module.exports = function usage (yargs, y18n) {
345
345
  }
346
346
 
347
347
  // the usage string.
348
- if (epilog) {
349
- const e = epilog.replace(/\$0/g, base$0)
348
+ if (epilogs.length > 0) {
349
+ const e = epilogs.map(epilog => epilog.replace(/\$0/g, base$0)).join('\n')
350
350
  ui.div(`${e}\n`)
351
351
  }
352
352
 
@@ -505,35 +505,36 @@ module.exports = function usage (yargs, y18n) {
505
505
  failureOutput = false
506
506
  usages = []
507
507
  usageDisabled = false
508
- epilog = undefined
508
+ epilogs = []
509
509
  examples = []
510
510
  commands = []
511
511
  descriptions = objFilter(descriptions, (k, v) => !localLookup[k])
512
512
  return self
513
513
  }
514
514
 
515
- let frozen
515
+ let frozens = []
516
516
  self.freeze = function freeze () {
517
- frozen = {}
517
+ let frozen = {}
518
+ frozens.push(frozen)
518
519
  frozen.failMessage = failMessage
519
520
  frozen.failureOutput = failureOutput
520
521
  frozen.usages = usages
521
522
  frozen.usageDisabled = usageDisabled
522
- frozen.epilog = epilog
523
+ frozen.epilogs = epilogs
523
524
  frozen.examples = examples
524
525
  frozen.commands = commands
525
526
  frozen.descriptions = descriptions
526
527
  }
527
528
  self.unfreeze = function unfreeze () {
529
+ let frozen = frozens.pop()
528
530
  failMessage = frozen.failMessage
529
531
  failureOutput = frozen.failureOutput
530
532
  usages = frozen.usages
531
533
  usageDisabled = frozen.usageDisabled
532
- epilog = frozen.epilog
534
+ epilogs = frozen.epilogs
533
535
  examples = frozen.examples
534
536
  commands = frozen.commands
535
537
  descriptions = frozen.descriptions
536
- frozen = undefined
537
538
  }
538
539
 
539
540
  return self
package/lib/validation.js CHANGED
@@ -102,7 +102,7 @@ module.exports = function validation (yargs, usage, y18n) {
102
102
  }
103
103
  })
104
104
 
105
- if (commandKeys.length > 0) {
105
+ if ((currentContext.commands.length > 0) || (commandKeys.length > 0)) {
106
106
  argv._.slice(currentContext.commands.length).forEach((key) => {
107
107
  if (commandKeys.indexOf(key) === -1) {
108
108
  unknown.push(key)
@@ -323,18 +323,19 @@ module.exports = function validation (yargs, usage, y18n) {
323
323
  return self
324
324
  }
325
325
 
326
- let frozen
326
+ let frozens = []
327
327
  self.freeze = function freeze () {
328
- frozen = {}
328
+ let frozen = {}
329
+ frozens.push(frozen)
329
330
  frozen.implied = implied
330
331
  frozen.checks = checks
331
332
  frozen.conflicting = conflicting
332
333
  }
333
334
  self.unfreeze = function unfreeze () {
335
+ let frozen = frozens.pop()
334
336
  implied = frozen.implied
335
337
  checks = frozen.checks
336
338
  conflicting = frozen.conflicting
337
- frozen = undefined
338
339
  }
339
340
 
340
341
  return self
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yargs",
3
- "version": "13.3.2",
3
+ "version": "14.0.0",
4
4
  "description": "yargs the modern, pirate-themed, successor to optimist.",
5
5
  "main": "./index.js",
6
6
  "contributors": [
@@ -20,6 +20,7 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "cliui": "^5.0.0",
23
+ "decamelize": "^1.2.0",
23
24
  "find-up": "^3.0.0",
24
25
  "get-caller-file": "^2.0.1",
25
26
  "require-directory": "^2.1.1",
@@ -28,7 +29,7 @@
28
29
  "string-width": "^3.0.0",
29
30
  "which-module": "^2.0.0",
30
31
  "y18n": "^4.0.0",
31
- "yargs-parser": "^13.1.2"
32
+ "yargs-parser": "^13.1.1"
32
33
  },
33
34
  "devDependencies": {
34
35
  "chai": "^4.2.0",
@@ -42,7 +43,7 @@
42
43
  "nyc": "^14.1.0",
43
44
  "rimraf": "^2.6.3",
44
45
  "standard": "^12.0.1",
45
- "standard-version": "^6.0.1",
46
+ "standard-version": "^7.0.0",
46
47
  "which": "^1.3.1",
47
48
  "yargs-test-extends": "^1.0.1"
48
49
  },
package/yargs.js CHANGED
@@ -37,7 +37,8 @@ function Yargs (processArgs, cwd, parentRequire) {
37
37
 
38
38
  if (!cwd) cwd = process.cwd()
39
39
 
40
- self.scriptName = function scriptName (scriptName) {
40
+ self.scriptName = function (scriptName) {
41
+ self.customScriptName = true
41
42
  self.$0 = scriptName
42
43
  return self
43
44
  }
@@ -144,9 +145,10 @@ function Yargs (processArgs, cwd, parentRequire) {
144
145
  self.resetOptions()
145
146
 
146
147
  // temporary hack: allow "freezing" of reset-able state for parse(msg, cb)
147
- let frozen
148
+ let frozens = []
148
149
  function freeze () {
149
- frozen = {}
150
+ let frozen = {}
151
+ frozens.push(frozen)
150
152
  frozen.options = options
151
153
  frozen.configObjects = options.configObjects.slice(0)
152
154
  frozen.exitProcess = exitProcess
@@ -160,8 +162,11 @@ function Yargs (processArgs, cwd, parentRequire) {
160
162
  frozen.exitError = exitError
161
163
  frozen.hasOutput = hasOutput
162
164
  frozen.parsed = self.parsed
165
+ frozen.parseFn = parseFn
166
+ frozen.parseContext = parseContext
163
167
  }
164
168
  function unfreeze () {
169
+ let frozen = frozens.pop()
165
170
  options = frozen.options
166
171
  options.configObjects = frozen.configObjects
167
172
  exitProcess = frozen.exitProcess
@@ -175,9 +180,8 @@ function Yargs (processArgs, cwd, parentRequire) {
175
180
  command.unfreeze()
176
181
  strict = frozen.strict
177
182
  completionCommand = frozen.completionCommand
178
- parseFn = null
179
- parseContext = null
180
- frozen = undefined
183
+ parseFn = frozen.parseFn
184
+ parseContext = frozen.parseContext
181
185
  }
182
186
 
183
187
  self.boolean = function (keys) {
@@ -231,7 +235,6 @@ function Yargs (processArgs, cwd, parentRequire) {
231
235
  function populateParserHintArray (type, keys, value) {
232
236
  keys = [].concat(keys)
233
237
  keys.forEach((key) => {
234
- key = sanitizeKey(key)
235
238
  options[type].push(key)
236
239
  })
237
240
  }
@@ -287,8 +290,8 @@ function Yargs (processArgs, cwd, parentRequire) {
287
290
 
288
291
  function populateParserHintObject (builder, isArray, type, key, value) {
289
292
  if (Array.isArray(key)) {
290
- const temp = Object.create(null)
291
293
  // an array of keys with one value ['x', 'y', 'z'], function parse () {}
294
+ const temp = {}
292
295
  key.forEach((k) => {
293
296
  temp[k] = value
294
297
  })
@@ -299,7 +302,6 @@ function Yargs (processArgs, cwd, parentRequire) {
299
302
  builder(k, key[k])
300
303
  })
301
304
  } else {
302
- key = sanitizeKey(key)
303
305
  // a single key value pair 'x', parse() {}
304
306
  if (isArray) {
305
307
  options[type][key] = (options[type][key] || []).concat(value)
@@ -309,13 +311,6 @@ function Yargs (processArgs, cwd, parentRequire) {
309
311
  }
310
312
  }
311
313
 
312
- // TODO(bcoe): in future major versions move more objects towards
313
- // Object.create(null):
314
- function sanitizeKey (key) {
315
- if (key === '__proto__') return '___proto___'
316
- return key
317
- }
318
-
319
314
  function deleteFromParserHintObject (optionKey) {
320
315
  // delete from all parsing hints:
321
316
  // boolean, array, key, alias, etc.
@@ -547,8 +542,12 @@ function Yargs (processArgs, cwd, parentRequire) {
547
542
  let parseContext = null
548
543
  self.parse = function parse (args, shortCircuit, _parseFn) {
549
544
  argsert('[string|array] [function|boolean|object] [function]', [args, shortCircuit, _parseFn], arguments.length)
545
+ freeze()
550
546
  if (typeof args === 'undefined') {
551
- return self._parseArgs(processArgs)
547
+ const parsed = self._parseArgs(processArgs)
548
+ unfreeze()
549
+ // TODO: remove this compatibility hack when we release yargs@15.x:
550
+ return (this.parsed = parsed)
552
551
  }
553
552
 
554
553
  // a context object can optionally be provided, this allows
@@ -569,7 +568,6 @@ function Yargs (processArgs, cwd, parentRequire) {
569
568
  // skipping validation, etc.
570
569
  if (!shortCircuit) processArgs = args
571
570
 
572
- freeze()
573
571
  if (parseFn) exitProcess = false
574
572
 
575
573
  const parsed = self._parseArgs(args, shortCircuit)
@@ -910,7 +908,7 @@ function Yargs (processArgs, cwd, parentRequire) {
910
908
  }
911
909
 
912
910
  // register the completion command.
913
- completionCommand = cmd || 'completion'
911
+ completionCommand = cmd || completionCommand || 'completion'
914
912
  if (!desc && desc !== false) {
915
913
  desc = 'generate completion script'
916
914
  }
@@ -922,9 +920,10 @@ function Yargs (processArgs, cwd, parentRequire) {
922
920
  return self
923
921
  }
924
922
 
925
- self.showCompletionScript = function ($0) {
926
- argsert('[string]', [$0], arguments.length)
923
+ self.showCompletionScript = function ($0, cmd) {
924
+ argsert('[string] [string]', [$0, cmd], arguments.length)
927
925
  $0 = $0 || self.$0
926
+ completionCommand = cmd || completionCommand || 'completion'
928
927
  _logger.log(completion.generateCompletionScript($0, completionCommand))
929
928
  return self
930
929
  }
@@ -1032,7 +1031,7 @@ function Yargs (processArgs, cwd, parentRequire) {
1032
1031
  // Deprecated
1033
1032
  let pkgConfig = pkgUp()['yargs']
1034
1033
  if (pkgConfig) {
1035
- console.warn('Configuring yargs through package.json is deprecated and will be removed in the next major release, please use the JS API instead.')
1034
+ console.warn('Configuring yargs through package.json is deprecated and will be removed in a future major release, please use the JS API instead.')
1036
1035
  options.configuration = Object.assign({}, pkgConfig, options.configuration)
1037
1036
  }
1038
1037
 
package/lib/decamelize.js DELETED
@@ -1,32 +0,0 @@
1
- /*
2
- MIT License
3
-
4
- Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy of
7
- this software and associated documentation files (the "Software"), to deal in
8
- the Software without restriction, including without limitation the rights to
9
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10
- the Software, and to permit persons to whom the Software is furnished to do so,
11
- subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in all
14
- copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- */
23
- 'use strict'
24
-
25
- module.exports = (text, separator) => {
26
- separator = typeof separator === 'undefined' ? '_' : separator
27
-
28
- return text
29
- .replace(/([a-z\d])([A-Z])/g, `$1${separator}$2`)
30
- .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, `$1${separator}$2`)
31
- .toLowerCase()
32
- }