Skip to content

Commit b876442

Browse files
committed
fix(usage): tie usage to config
This starts us down the path of tying the params our commands accept to their config items. For now it is optional, and not every current config item would cleanly render if we added them today. The ones that are added here DO render nicely, and we can iterate from here. We can also at a later date do the same kind of appraoch with our positional args. PR-URL: #2908 Credit: @wraithgar Close: #2908 Reviewed-by: @nlf, @isaacs
1 parent 629aaf3 commit b876442

27 files changed

+297
-45
lines changed

docs/content/using-npm/config.md

+30
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ The following shorthands are parsed on the command-line:
9696
* `-H`: `--usage`
9797
* `--help`: `--usage`
9898
* `-v`: `--version`
99+
* `-w`: `--workspace`
100+
* `--ws`: `--workspaces`
99101
* `-y`: `--yes`
100102

101103
<!-- AUTOGENERATED CONFIG SHORTHANDS END -->
@@ -1311,6 +1313,34 @@ The program to use to view help content.
13111313

13121314
Set to `"browser"` to view html help content in the default web browser.
13131315

1316+
#### `which`
1317+
1318+
* Default: null
1319+
* Type: null or Number
1320+
1321+
If there are multiple funding sources, which 1-indexed source URL to open.
1322+
1323+
#### `workspace`
1324+
1325+
* Default:
1326+
* Type: String (can be set multiple times)
1327+
1328+
Enable running a command in the context of the configured workspaces of the
1329+
current project while filtering by running only the workspaces defined by
1330+
this configuration option.
1331+
1332+
Valid values for the `workspace` config are either: - Workspace names - Path
1333+
to a workspace directory - Path to a parent workspace directory (will result
1334+
to selecting all of the nested workspaces)
1335+
1336+
#### `workspaces`
1337+
1338+
* Default: false
1339+
* Type: Boolean
1340+
1341+
Enable running a command in the context of **all** the configured
1342+
workspaces.
1343+
13141344
#### `yes`
13151345

13161346
* Default: false

lib/adduser.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ class AddUser extends BaseCommand {
1717
return 'adduser'
1818
}
1919

20-
static get usage () {
21-
return ['[--registry=url] [--scope=@orgname] [--always-auth]']
20+
static get params () {
21+
return [
22+
'registry',
23+
'scope',
24+
'always-auth',
25+
]
2226
}
2327

2428
exec (args, cb) {

lib/audit.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,21 @@ class Audit extends BaseCommand {
1616
}
1717

1818
/* istanbul ignore next - see test/lib/load-all-commands.js */
19-
static get usage () {
19+
static get params () {
2020
return [
21-
'[--json] [--production]',
22-
'fix [--force|--package-lock-only|--dry-run|--production|--only=(dev|prod)]',
21+
'dry-run',
22+
'force',
23+
'json',
24+
'package-lock-only',
25+
'production',
2326
]
2427
}
2528

29+
/* istanbul ignore next - see test/lib/load-all-commands.js */
30+
static get usage () {
31+
return ['[fix]']
32+
}
33+
2634
async completion (opts) {
2735
const argv = opts.conf.argv.remain
2836

lib/base-command.js

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Base class for npm.commands[cmd]
22
const usageUtil = require('./utils/usage.js')
3+
const ConfigDefinitions = require('./utils/config/definitions.js')
34

45
class BaseCommand {
56
constructor (npm) {
@@ -25,6 +26,9 @@ class BaseCommand {
2526
else
2627
usage = `${usage}${this.constructor.usage.map(u => `npm ${this.constructor.name} ${u}`).join('\n')}`
2728

29+
if (this.constructor.params)
30+
usage = `${usage}\n\nOptions:\n[${this.constructor.params.map(p => ConfigDefinitions[p].usage).join('] [')}]`
31+
2832
// Mostly this just appends aliases, this could be more clear
2933
usage = usageUtil(this.constructor.name, usage)
3034
usage = `${usage}\n\nRun "npm help ${this.constructor.name}" for more info`

lib/bin.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ class Bin extends BaseCommand {
1010
return 'bin'
1111
}
1212

13-
static get usage () {
14-
return ['[-g]']
13+
static get params () {
14+
return ['global']
1515
}
1616

1717
exec (args, cb) {

lib/fund.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,19 @@ class Fund extends BaseCommand {
3232
return 'fund'
3333
}
3434

35+
/* istanbul ignore next - see test/lib/load-all-commands.js */
36+
static get params () {
37+
return [
38+
'json',
39+
'browser',
40+
'unicode',
41+
'which',
42+
]
43+
}
44+
3545
/* istanbul ignore next - see test/lib/load-all-commands.js */
3646
static get usage () {
37-
return ['[--json] [--browser] [--unicode] [[<@scope>/]<pkg> [--which=<fundingSourceNumber>]']
47+
return ['[[<@scope>/]<pkg>]']
3848
}
3949

4050
/* istanbul ignore next - see test/lib/load-all-commands.js */

lib/install.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ class Install extends BaseCommand {
2121
return 'install'
2222
}
2323

24+
/* istanbul ignore next - see test/lib/load-all-commands.js */
25+
static get params () {
26+
return [
27+
'save',
28+
'save-exact',
29+
]
30+
}
31+
2432
/* istanbul ignore next - see test/lib/load-all-commands.js */
2533
static get usage () {
2634
return [
@@ -33,7 +41,7 @@ class Install extends BaseCommand {
3341
'<tarball file>',
3442
'<tarball url>',
3543
'<git:// url>',
36-
'<github username>/<github project> [--save-prod|--save-dev|--save-optional|--save-peer] [--save-exact] [--no-save]',
44+
'<github username>/<github project>',
3745
]
3846
}
3947

lib/logout.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ class Logout extends BaseCommand {
1515
}
1616

1717
/* istanbul ignore next - see test/lib/load-all-commands.js */
18-
static get usage () {
19-
return ['[--registry=<url>] [--scope=<@scope>]']
18+
static get params () {
19+
return [
20+
'registry',
21+
'scope',
22+
]
2023
}
2124

2225
exec (args, cb) {

lib/pack.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ class Pack extends BaseCommand {
2121
return 'pack'
2222
}
2323

24+
/* istanbul ignore next - see test/lib/load-all-commands.js */
25+
static get params () {
26+
return ['dry-run']
27+
}
28+
2429
/* istanbul ignore next - see test/lib/load-all-commands.js */
2530
static get usage () {
26-
return ['[[<@scope>/]<pkg>...] [--dry-run]']
31+
return ['[[<@scope>/]<pkg>...]']
2732
}
2833

2934
exec (args, cb) {

lib/ping.js

+5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ class Ping extends BaseCommand {
88
return 'Ping npm registry'
99
}
1010

11+
/* istanbul ignore next - see test/lib/load-all-commands.js */
12+
static get params () {
13+
return ['registry']
14+
}
15+
1116
/* istanbul ignore next - see test/lib/load-all-commands.js */
1217
static get name () {
1318
return 'ping'

lib/prune.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ class Prune extends BaseCommand {
1414
return 'prune'
1515
}
1616

17+
/* istanbul ignore next - see test/lib/load-all-commands.js */
18+
static get params () {
19+
return ['production']
20+
}
21+
1722
/* istanbul ignore next - see test/lib/load-all-commands.js */
1823
static get usage () {
19-
return ['[[<@scope>/]<pkg>...] [--production]']
24+
return ['[[<@scope>/]<pkg>...]']
2025
}
2126

2227
exec (args, cb) {

lib/publish.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,15 @@ class Publish extends BaseCommand {
2828
return 'publish'
2929
}
3030

31+
/* istanbul ignore next - see test/lib/load-all-commands.js */
32+
static get params () {
33+
return ['tag', 'access', 'dry-run']
34+
}
35+
3136
/* istanbul ignore next - see test/lib/load-all-commands.js */
3237
static get usage () {
3338
return [
34-
'[<folder>] [--tag <tag>] [--access <public|restricted>] [--dry-run]',
39+
'[<folder>]',
3540
]
3641
}
3742

lib/root.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class Root extends BaseCommand {
1111
}
1212

1313
/* istanbul ignore next - see test/lib/load-all-commands.js */
14-
static get usage () {
15-
return ['[-g]']
14+
static get params () {
15+
return ['global']
1616
}
1717

1818
exec (args, cb) {

lib/search.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,19 @@ class Search extends BaseCommand {
3636
return 'search'
3737
}
3838

39+
/* istanbul ignore next - see test/lib/load-all-commands.js */
40+
static get params () {
41+
return [
42+
'long',
43+
'json',
44+
'parseable',
45+
'description',
46+
]
47+
}
48+
3949
/* istanbul ignore next - see test/lib/load-all-commands.js */
4050
static get usage () {
41-
return ['[-l|--long] [--json] [--parseable] [--no-description] [search terms ...]']
51+
return ['[search terms ...]']
4252
}
4353

4454
exec (args, cb) {

lib/uninstall.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ class Uninstall extends BaseCommand {
1616
return 'uninstall'
1717
}
1818

19+
/* istanbul ignore next - see test/lib/load-all-commands.js */
20+
static get params () {
21+
return ['save']
22+
}
23+
1924
/* istanbul ignore next - see test/lib/load-all-commands.js */
2025
static get usage () {
21-
return ['[<@scope>/]<pkg>[@<version>]... [-S|--save|--no-save]']
26+
return ['[<@scope>/]<pkg>...']
2227
}
2328

2429
/* istanbul ignore next - see test/lib/load-all-commands.js */

lib/update.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@ class Update extends BaseCommand {
1818
return 'update'
1919
}
2020

21+
/* istanbul ignore next - see test/lib/load-all-commands.js */
22+
static get params () {
23+
return ['global']
24+
}
25+
2126
/* istanbul ignore next - see test/lib/load-all-commands.js */
2227
static get usage () {
23-
return ['[-g] [<pkg>...]']
28+
return ['[<pkg>...]']
2429
}
2530

2631
/* istanbul ignore next - see test/lib/load-all-commands.js */

lib/utils/config/definition.js

+32-4
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ const required = [
1515

1616
const allowed = [
1717
'default',
18-
'type',
18+
'defaultDescription',
19+
'deprecated',
1920
'description',
2021
'flatten',
22+
'hint',
23+
'key',
2124
'short',
25+
'type',
2226
'typeDescription',
23-
'defaultDescription',
24-
'deprecated',
25-
'key',
27+
'usage',
2628
]
2729

2830
const {
@@ -43,6 +45,10 @@ class Definition {
4345
this.defaultDescription = describeValue(this.default)
4446
if (!this.typeDescription)
4547
this.typeDescription = describeType(this.type)
48+
if (!this.hint)
49+
this.hint = `<${this.key}>`
50+
if (!this.usage)
51+
this.usage = describeUsage(this)
4652
}
4753

4854
validate () {
@@ -73,6 +79,28 @@ ${description}
7379
}
7480
}
7581

82+
// Usage for a single param, abstracted because we have arrays of types in
83+
// config definition
84+
const paramUsage = (type, def) => {
85+
let key = `--${def.key}`
86+
if (def.short && typeof def.short === 'string')
87+
key = `-${def.short}|${key}`
88+
if (type === Boolean)
89+
return `${key}`
90+
else
91+
return `${key} ${def.hint}`
92+
}
93+
94+
const describeUsage = (def) => {
95+
if (Array.isArray(def.type)) {
96+
if (!def.type.some(d => d !== null && typeof d !== 'string'))
97+
return `--${def.key} <${def.type.filter(d => d).join('|')}>`
98+
else
99+
return def.type.filter(d => d).map((t) => paramUsage(t, def)).join('|')
100+
}
101+
return paramUsage(def.type, def)
102+
}
103+
76104
const describeType = type => {
77105
if (Array.isArray(type)) {
78106
const descriptions = type

0 commit comments

Comments
 (0)