Skip to content

Commit 1f3e88e

Browse files
nlfwraithgar
authored andcommitted
feat(workspaces): implement workspace support for dist-tag
PR-URL: #3032 Credit: @nlf Close: #3032 Reviewed-by: @wraithgar
1 parent ba4f7fe commit 1f3e88e

File tree

5 files changed

+345
-37
lines changed

5 files changed

+345
-37
lines changed

docs/content/commands/npm-dist-tag.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,18 @@ semver as `>=1.4.0 <1.5.0`. See <https://github.com/npm/npm/issues/6082>.
8888
The simplest way to avoid semver problems with tags is to use tags that do
8989
not begin with a number or the letter `v`.
9090

91+
### Configuration
92+
93+
#### workspaces
94+
95+
Only supported by `ls`. Enables listing dist-tags of all workspace
96+
contexts defined in the current `package.json`.
97+
98+
#### workspace
99+
100+
Only supported by `ls`. Enables listing dist-tags of workspace contexts
101+
limiting results to only those specified by this config item.
102+
91103
### See Also
92104

93105
* [npm publish](/commands/npm-publish)

lib/dist-tag.js

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@ const semver = require('semver')
55

66
const otplease = require('./utils/otplease.js')
77
const readLocalPkgName = require('./utils/read-local-package.js')
8+
const getWorkspaces = require('./workspaces/get-workspaces.js')
89
const BaseCommand = require('./base-command.js')
910

1011
class DistTag extends BaseCommand {
1112
static get description () {
1213
return 'Modify package distribution tags'
1314
}
1415

16+
/* istanbul ignore next - see test/lib/load-all-commands.js */
17+
static get params () {
18+
return ['workspace', 'workspaces']
19+
}
20+
1521
/* istanbul ignore next - see test/lib/load-all-commands.js */
1622
static get name () {
1723
return 'dist-tag'
@@ -43,15 +49,14 @@ class DistTag extends BaseCommand {
4349

4450
async distTag ([cmdName, pkg, tag]) {
4551
const opts = this.npm.flatOptions
46-
const has = (items) => new Set(items).has(cmdName)
4752

48-
if (has(['add', 'a', 'set', 's']))
53+
if (['add', 'a', 'set', 's'].includes(cmdName))
4954
return this.add(pkg, tag, opts)
5055

51-
if (has(['rm', 'r', 'del', 'd', 'remove']))
56+
if (['rm', 'r', 'del', 'd', 'remove'].includes(cmdName))
5257
return this.remove(pkg, tag, opts)
5358

54-
if (has(['ls', 'l', 'sl', 'list']))
59+
if (['ls', 'l', 'sl', 'list'].includes(cmdName))
5560
return this.list(pkg, opts)
5661

5762
if (!pkg) {
@@ -62,6 +67,33 @@ class DistTag extends BaseCommand {
6267
throw this.usage
6368
}
6469

70+
execWorkspaces (args, filters, cb) {
71+
this.distTagWorkspaces(args, filters).then(() => cb()).catch(cb)
72+
}
73+
74+
async distTagWorkspaces ([cmdName, pkg, tag], filters) {
75+
// cmdName is some form of list
76+
// pkg is one of:
77+
// - unset
78+
// - .
79+
// - .@version
80+
if (['ls', 'l', 'sl', 'list'].includes(cmdName) && (!pkg || pkg === '.' || /^\.@/.test(pkg)))
81+
return this.listWorkspaces(filters)
82+
83+
// pkg is unset
84+
// cmdName is one of:
85+
// - unset
86+
// - .
87+
// - .@version
88+
if (!pkg && (!cmdName || cmdName === '.' || /^\.@/.test(cmdName)))
89+
return this.listWorkspaces(filters)
90+
91+
// anything else is just a regular dist-tag command
92+
// so we fallback to the non-workspaces implementation
93+
log.warn('Ignoring workspaces for specified package')
94+
return this.distTag([cmdName, pkg, tag])
95+
}
96+
6597
async add (spec, tag, opts) {
6698
spec = npa(spec || '')
6799
const version = spec.rawSpec
@@ -145,6 +177,22 @@ class DistTag extends BaseCommand {
145177
}
146178
}
147179

180+
async listWorkspaces (filters) {
181+
const workspaces =
182+
await getWorkspaces(filters, { path: this.npm.localPrefix })
183+
184+
for (const [name] of workspaces) {
185+
try {
186+
this.npm.output(`${name}:`)
187+
await this.list(npa(name), this.npm.flatOptions)
188+
} catch (err) {
189+
// set the exitCode directly, but ignore the error
190+
// since it will have already been logged by this.list()
191+
process.exitCode = 1
192+
}
193+
}
194+
}
195+
148196
async fetchTags (spec, opts) {
149197
const data = await regFetch.json(
150198
`/-/package/${spec.escapedName}/dist-tags`,

tap-snapshots/test-lib-dist-tag.js-TAP.test.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
1515
npm dist-tag rm <pkg> <tag>
1616
npm dist-tag ls [<pkg>]
1717
18+
Options:
19+
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
20+
1821
alias: dist-tags
1922
2023
Run "npm help dist-tag" for more info
@@ -30,6 +33,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
3033
npm dist-tag rm <pkg> <tag>
3134
npm dist-tag ls [<pkg>]
3235
36+
Options:
37+
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
38+
3339
alias: dist-tags
3440
3541
Run "npm help dist-tag" for more info
@@ -54,6 +60,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
5460
npm dist-tag rm <pkg> <tag>
5561
npm dist-tag ls [<pkg>]
5662
63+
Options:
64+
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
65+
5766
alias: dist-tags
5867
5968
Run "npm help dist-tag" for more info
@@ -75,6 +84,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
7584
npm dist-tag rm <pkg> <tag>
7685
npm dist-tag ls [<pkg>]
7786
87+
Options:
88+
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
89+
7890
alias: dist-tags
7991
8092
Run "npm help dist-tag" for more info
@@ -126,6 +138,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
126138
npm dist-tag rm <pkg> <tag>
127139
npm dist-tag ls [<pkg>]
128140
141+
Options:
142+
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
143+
129144
alias: dist-tags
130145
131146
Run "npm help dist-tag" for more info
@@ -142,3 +157,100 @@ dist-tag add b to @scoped/[email protected]
142157
dist-tag add b is already set to version 0.6.0
143158
144159
`
160+
161+
exports[`test/lib/dist-tag.js TAP workspaces no args > printed the expected output 1`] = `
162+
workspace-a:
163+
latest-a: 1.0.0
164+
latest: 1.0.0
165+
workspace-b:
166+
latest-b: 2.0.0
167+
latest: 2.0.0
168+
workspace-c:
169+
latest-c: 3.0.0
170+
latest: 3.0.0
171+
`
172+
173+
exports[`test/lib/dist-tag.js TAP workspaces no args, one failing workspace sets exitCode to 1 > printed the expected output 1`] = `
174+
workspace-a:
175+
latest-a: 1.0.0
176+
latest: 1.0.0
177+
workspace-b:
178+
latest-b: 2.0.0
179+
latest: 2.0.0
180+
workspace-c:
181+
latest-c: 3.0.0
182+
latest: 3.0.0
183+
workspace-d:
184+
`
185+
186+
exports[`test/lib/dist-tag.js TAP workspaces no args, one workspace > printed the expected output 1`] = `
187+
workspace-a:
188+
latest-a: 1.0.0
189+
latest: 1.0.0
190+
`
191+
192+
exports[`test/lib/dist-tag.js TAP workspaces one arg -- . > printed the expected output 1`] = `
193+
workspace-a:
194+
latest-a: 1.0.0
195+
latest: 1.0.0
196+
workspace-b:
197+
latest-b: 2.0.0
198+
latest: 2.0.0
199+
workspace-c:
200+
latest-c: 3.0.0
201+
latest: 3.0.0
202+
`
203+
204+
exports[`test/lib/dist-tag.js TAP workspaces one arg -- .@1, ignores version spec > printed the expected output 1`] = `
205+
workspace-a:
206+
latest-a: 1.0.0
207+
latest: 1.0.0
208+
workspace-b:
209+
latest-b: 2.0.0
210+
latest: 2.0.0
211+
workspace-c:
212+
latest-c: 3.0.0
213+
latest: 3.0.0
214+
`
215+
216+
exports[`test/lib/dist-tag.js TAP workspaces one arg -- list > printed the expected output 1`] = `
217+
workspace-a:
218+
latest-a: 1.0.0
219+
latest: 1.0.0
220+
workspace-b:
221+
latest-b: 2.0.0
222+
latest: 2.0.0
223+
workspace-c:
224+
latest-c: 3.0.0
225+
latest: 3.0.0
226+
`
227+
228+
exports[`test/lib/dist-tag.js TAP workspaces two args -- list, . > printed the expected output 1`] = `
229+
workspace-a:
230+
latest-a: 1.0.0
231+
latest: 1.0.0
232+
workspace-b:
233+
latest-b: 2.0.0
234+
latest: 2.0.0
235+
workspace-c:
236+
latest-c: 3.0.0
237+
latest: 3.0.0
238+
`
239+
240+
exports[`test/lib/dist-tag.js TAP workspaces two args -- list, .@1, ignores version spec > printed the expected output 1`] = `
241+
workspace-a:
242+
latest-a: 1.0.0
243+
latest: 1.0.0
244+
workspace-b:
245+
latest-b: 2.0.0
246+
latest: 2.0.0
247+
workspace-c:
248+
latest-c: 3.0.0
249+
latest: 3.0.0
250+
`
251+
252+
exports[`test/lib/dist-tag.js TAP workspaces two args -- list, @scoped/pkg, logs a warning and ignores workspaces > printed the expected output 1`] = `
253+
a: 0.0.1
254+
b: 0.5.0
255+
latest: 1.0.0
256+
`

tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ All commands:
323323
npm dist-tag rm <pkg> <tag>
324324
npm dist-tag ls [<pkg>]
325325
326+
Options:
327+
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
328+
326329
alias: dist-tags
327330
328331
Run "npm help dist-tag" for more info

0 commit comments

Comments
 (0)