Skip to content

Commit

Permalink
feat(workspaces): implement workspace support for dist-tag
Browse files Browse the repository at this point in the history
PR-URL: #3032
Credit: @nlf
Close: #3032
Reviewed-by: @wraithgar
  • Loading branch information
nlf authored and wraithgar committed Apr 8, 2021
1 parent ba4f7fe commit 1f3e88e
Show file tree
Hide file tree
Showing 5 changed files with 345 additions and 37 deletions.
12 changes: 12 additions & 0 deletions docs/content/commands/npm-dist-tag.md
Expand Up @@ -88,6 +88,18 @@ semver as `>=1.4.0 <1.5.0`. See <https://github.com/npm/npm/issues/6082>.
The simplest way to avoid semver problems with tags is to use tags that do
not begin with a number or the letter `v`.

### Configuration

#### workspaces

Only supported by `ls`. Enables listing dist-tags of all workspace
contexts defined in the current `package.json`.

#### workspace

Only supported by `ls`. Enables listing dist-tags of workspace contexts
limiting results to only those specified by this config item.

### See Also

* [npm publish](/commands/npm-publish)
Expand Down
56 changes: 52 additions & 4 deletions lib/dist-tag.js
Expand Up @@ -5,13 +5,19 @@ const semver = require('semver')

const otplease = require('./utils/otplease.js')
const readLocalPkgName = require('./utils/read-local-package.js')
const getWorkspaces = require('./workspaces/get-workspaces.js')
const BaseCommand = require('./base-command.js')

class DistTag extends BaseCommand {
static get description () {
return 'Modify package distribution tags'
}

/* istanbul ignore next - see test/lib/load-all-commands.js */
static get params () {
return ['workspace', 'workspaces']
}

/* istanbul ignore next - see test/lib/load-all-commands.js */
static get name () {
return 'dist-tag'
Expand Down Expand Up @@ -43,15 +49,14 @@ class DistTag extends BaseCommand {

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

if (has(['add', 'a', 'set', 's']))
if (['add', 'a', 'set', 's'].includes(cmdName))
return this.add(pkg, tag, opts)

if (has(['rm', 'r', 'del', 'd', 'remove']))
if (['rm', 'r', 'del', 'd', 'remove'].includes(cmdName))
return this.remove(pkg, tag, opts)

if (has(['ls', 'l', 'sl', 'list']))
if (['ls', 'l', 'sl', 'list'].includes(cmdName))
return this.list(pkg, opts)

if (!pkg) {
Expand All @@ -62,6 +67,33 @@ class DistTag extends BaseCommand {
throw this.usage
}

execWorkspaces (args, filters, cb) {
this.distTagWorkspaces(args, filters).then(() => cb()).catch(cb)
}

async distTagWorkspaces ([cmdName, pkg, tag], filters) {
// cmdName is some form of list
// pkg is one of:
// - unset
// - .
// - .@version
if (['ls', 'l', 'sl', 'list'].includes(cmdName) && (!pkg || pkg === '.' || /^\.@/.test(pkg)))
return this.listWorkspaces(filters)

// pkg is unset
// cmdName is one of:
// - unset
// - .
// - .@version
if (!pkg && (!cmdName || cmdName === '.' || /^\.@/.test(cmdName)))
return this.listWorkspaces(filters)

// anything else is just a regular dist-tag command
// so we fallback to the non-workspaces implementation
log.warn('Ignoring workspaces for specified package')
return this.distTag([cmdName, pkg, tag])
}

async add (spec, tag, opts) {
spec = npa(spec || '')
const version = spec.rawSpec
Expand Down Expand Up @@ -145,6 +177,22 @@ class DistTag extends BaseCommand {
}
}

async listWorkspaces (filters) {
const workspaces =
await getWorkspaces(filters, { path: this.npm.localPrefix })

for (const [name] of workspaces) {
try {
this.npm.output(`${name}:`)
await this.list(npa(name), this.npm.flatOptions)
} catch (err) {
// set the exitCode directly, but ignore the error
// since it will have already been logged by this.list()
process.exitCode = 1
}
}
}

async fetchTags (spec, opts) {
const data = await regFetch.json(
`/-/package/${spec.escapedName}/dist-tags`,
Expand Down
112 changes: 112 additions & 0 deletions tap-snapshots/test-lib-dist-tag.js-TAP.test.js
Expand Up @@ -15,6 +15,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
alias: dist-tags
Run "npm help dist-tag" for more info
Expand All @@ -30,6 +33,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
alias: dist-tags
Run "npm help dist-tag" for more info
Expand All @@ -54,6 +60,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
alias: dist-tags
Run "npm help dist-tag" for more info
Expand All @@ -75,6 +84,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
alias: dist-tags
Run "npm help dist-tag" for more info
Expand Down Expand Up @@ -126,6 +138,9 @@ npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
alias: dist-tags
Run "npm help dist-tag" for more info
Expand All @@ -142,3 +157,100 @@ dist-tag add b to @scoped/another@0.6.0
dist-tag add b is already set to version 0.6.0
`

exports[`test/lib/dist-tag.js TAP workspaces no args > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces no args, one failing workspace sets exitCode to 1 > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
workspace-d:
`

exports[`test/lib/dist-tag.js TAP workspaces no args, one workspace > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces one arg -- . > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces one arg -- .@1, ignores version spec > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces one arg -- list > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces two args -- list, . > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces two args -- list, .@1, ignores version spec > printed the expected output 1`] = `
workspace-a:
latest-a: 1.0.0
latest: 1.0.0
workspace-b:
latest-b: 2.0.0
latest: 2.0.0
workspace-c:
latest-c: 3.0.0
latest: 3.0.0
`

exports[`test/lib/dist-tag.js TAP workspaces two args -- list, @scoped/pkg, logs a warning and ignores workspaces > printed the expected output 1`] = `
a: 0.0.1
b: 0.5.0
latest: 1.0.0
`
3 changes: 3 additions & 0 deletions tap-snapshots/test-lib-utils-npm-usage.js-TAP.test.js
Expand Up @@ -323,6 +323,9 @@ All commands:
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
alias: dist-tags
Run "npm help dist-tag" for more info
Expand Down

0 comments on commit 1f3e88e

Please sign in to comment.