Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/content/commands/npm-version.md83
-rw-r--r--lib/base-command.js20
-rw-r--r--lib/utils/config/definitions.js1
-rw-r--r--lib/version.js78
-rw-r--r--lib/workspaces/get-workspaces.js3
-rw-r--r--tap-snapshots/test/lib/dist-tag.js.test.cjs15
-rw-r--r--tap-snapshots/test/lib/utils/npm-usage.js.test.cjs47
-rw-r--r--test/lib/version.js172
8 files changed, 358 insertions, 61 deletions
diff --git a/docs/content/commands/npm-version.md b/docs/content/commands/npm-version.md
index 0eb814b98..cdf0f977f 100644
--- a/docs/content/commands/npm-version.md
+++ b/docs/content/commands/npm-version.md
@@ -14,6 +14,56 @@ npm version [<newversion> | major | minor | patch | premajor | preminor | prepat
'npm ls' to inspect current package/dependency versions
```
+### Configuration
+
+#### `allow-same-version`
+
+* Default: `false`
+* Type: Boolean
+
+Prevents throwing an error when `npm version` is used to set the new version
+to the same value as the current version.
+
+#### `git-tag-version`
+
+* Default: `true`
+* Type: Boolean
+
+Commit and tag the version change.
+
+#### `commit-hooks`
+
+* Default: `true`
+* Type: Boolean
+
+Run git commit hooks when committing the version change.
+
+#### `sign-git-tag`
+
+* Default: `false`
+* Type: Boolean
+
+Pass the `-s` flag to git to sign the tag.
+
+Note that you must have a default GPG key set up in your git config for this to work properly.
+
+#### workspaces
+
+* Default: `false`
+* Type: Boolean
+
+Enables workspaces context and includes workspaces in reported output
+when getting versions. When setting a new version *only the workspaces
+will be changed*.
+
+#### workspace
+
+* Default: []
+* Type: Array
+
+Enables workspaces context and limits results to only those specified by
+this config item.
+
### Description
Run this in a package directory to bump the version and write the new
@@ -87,39 +137,6 @@ This runs all your tests and proceeds only if they pass. Then runs your `build`
adds everything in the `dist` directory to the commit. After the commit, it pushes the new commit
and tag up to the server, and deletes the `build/temp` directory.
-### Configuration
-
-#### `allow-same-version`
-
-* Default: `false`
-* Type: Boolean
-
-Prevents throwing an error when `npm version` is used to set the new version
-to the same value as the current version.
-
-#### `git-tag-version`
-
-* Default: `true`
-* Type: Boolean
-
-Commit and tag the version change.
-
-#### `commit-hooks`
-
-* Default: `true`
-* Type: Boolean
-
-Run git commit hooks when committing the version change.
-
-#### `sign-git-tag`
-
-* Default: `false`
-* Type: Boolean
-
-Pass the `-s` flag to git to sign the tag.
-
-Note that you must have a default GPG key set up in your git config for this to work properly.
-
### See Also
* [npm init](/commands/npm-init)
diff --git a/lib/base-command.js b/lib/base-command.js
index 91c7c5357..322fd8963 100644
--- a/lib/base-command.js
+++ b/lib/base-command.js
@@ -4,6 +4,7 @@ const ConfigDefinitions = require('./utils/config/definitions.js')
class BaseCommand {
constructor (npm) {
+ this.wrapWidth = 80
this.npm = npm
}
@@ -27,8 +28,7 @@ class BaseCommand {
usage = `${usage}${this.constructor.usage.map(u => `npm ${this.constructor.name} ${u}`).join('\n')}`
if (this.constructor.params)
- // TODO word wrap this along params boundaries
- usage = `${usage}\n\nOptions:\n[${this.constructor.params.map(p => ConfigDefinitions[p].usage).join('] [')}]`
+ usage = `${usage}\n\nOptions:\n${this.wrappedParams}`
// Mostly this just appends aliases, this could be more clear
usage = usageUtil(this.constructor.name, usage)
@@ -36,6 +36,22 @@ class BaseCommand {
return usage
}
+ get wrappedParams () {
+ let results = ''
+ let line = ''
+
+ for (const param of this.constructor.params) {
+ const usage = `[${ConfigDefinitions[param].usage}]`
+ if (line.length && (line.length + usage.length) > this.wrapWidth) {
+ results = [results, line].filter(Boolean).join('\n')
+ line = ''
+ }
+ line = [line, usage].filter(Boolean).join(' ')
+ }
+ results = [results, line].filter(Boolean).join('\n')
+ return results
+ }
+
usageError (msg) {
if (!msg) {
return Object.assign(new Error(`\nUsage: ${this.usage}`), {
diff --git a/lib/utils/config/definitions.js b/lib/utils/config/definitions.js
index d87c43dda..db1f25e95 100644
--- a/lib/utils/config/definitions.js
+++ b/lib/utils/config/definitions.js
@@ -1389,6 +1389,7 @@ define('prefix', {
define('preid', {
default: '',
+ hint: 'prerelease-id',
type: String,
description: `
The "prerelease identifier" to use as a prefix for the "prerelease" part
diff --git a/lib/version.js b/lib/version.js
index 18b7d7d6c..3ef3801e7 100644
--- a/lib/version.js
+++ b/lib/version.js
@@ -1,6 +1,11 @@
-const libversion = require('libnpmversion')
+const libnpmversion = require('libnpmversion')
+const { resolve } = require('path')
+const { promisify } = require('util')
+const readFile = promisify(require('fs').readFile)
+const getWorkspaces = require('./workspaces/get-workspaces.js')
const BaseCommand = require('./base-command.js')
+
class Version extends BaseCommand {
static get description () {
return 'Bump a package version'
@@ -12,8 +17,22 @@ class Version extends BaseCommand {
}
/* istanbul ignore next - see test/lib/load-all-commands.js */
+ static get params () {
+ return [
+ 'allow-same-version',
+ 'commit-hooks',
+ 'git-tag-version',
+ 'json',
+ 'preid',
+ 'sign-git-tag',
+ 'workspace',
+ 'workspaces',
+ ]
+ }
+
+ /* istanbul ignore next - see test/lib/load-all-commands.js */
static get usage () {
- return ['[<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]']
+ return ['[<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]']
}
async completion (opts) {
@@ -37,6 +56,10 @@ class Version extends BaseCommand {
return this.version(args).then(() => cb()).catch(cb)
}
+ execWorkspaces (args, filters, cb) {
+ this.versionWorkspaces(args, filters).then(() => cb()).catch(cb)
+ }
+
async version (args) {
switch (args.length) {
case 0:
@@ -48,20 +71,42 @@ class Version extends BaseCommand {
}
}
+ async versionWorkspaces (args, filters) {
+ switch (args.length) {
+ case 0:
+ return this.listWorkspaces(filters)
+ case 1:
+ return this.changeWorkspaces(args, filters)
+ default:
+ throw this.usage
+ }
+ }
+
async change (args) {
const prefix = this.npm.config.get('tag-version-prefix')
- const version = await libversion(args[0], {
+ const version = await libnpmversion(args[0], {
...this.npm.flatOptions,
path: this.npm.prefix,
})
return this.npm.output(`${prefix}${version}`)
}
- async list () {
- const results = {}
- const { promisify } = require('util')
- const { resolve } = require('path')
- const readFile = promisify(require('fs').readFile)
+ async changeWorkspaces (args, filters) {
+ const prefix = this.npm.config.get('tag-version-prefix')
+ const workspaces =
+ await getWorkspaces(filters, { path: this.npm.localPrefix })
+ for (const [name, path] of workspaces) {
+ this.npm.output(name)
+ const version = await libnpmversion(args[0], {
+ ...this.npm.flatOptions,
+ 'git-tag-version': false,
+ path,
+ })
+ this.npm.output(`${prefix}${version}`)
+ }
+ }
+
+ async list (results = {}) {
const pj = resolve(this.npm.prefix, 'package.json')
const pkg = await readFile(pj, 'utf8')
@@ -80,5 +125,22 @@ class Version extends BaseCommand {
else
this.npm.output(results)
}
+
+ async listWorkspaces (filters) {
+ const results = {}
+ const workspaces =
+ await getWorkspaces(filters, { path: this.npm.localPrefix })
+ for (const [, path] of workspaces) {
+ const pj = resolve(path, 'package.json')
+ // getWorkspaces has already parsed this so we know it won't error
+ const pkg = await readFile(pj, 'utf8')
+ .then(data => JSON.parse(data))
+
+ if (pkg.name && pkg.version)
+ results[pkg.name] = pkg.version
+ }
+ return this.list(results)
+ }
}
+
module.exports = Version
diff --git a/lib/workspaces/get-workspaces.js b/lib/workspaces/get-workspaces.js
index 64812d540..91b007455 100644
--- a/lib/workspaces/get-workspaces.js
+++ b/lib/workspaces/get-workspaces.js
@@ -3,7 +3,10 @@ const mapWorkspaces = require('@npmcli/map-workspaces')
const minimatch = require('minimatch')
const rpj = require('read-package-json-fast')
+// Returns an Map of paths to workspaces indexed by workspace name
+// { foo => '/path/to/foo' }
const getWorkspaces = async (filters, { path }) => {
+ // TODO we need a better error to be bubbled up here if this rpj call fails
const pkg = await rpj(resolve(path, 'package.json'))
const workspaces = await mapWorkspaces({ cwd: path, pkg })
const res = filters.length ? new Map() : workspaces
diff --git a/tap-snapshots/test/lib/dist-tag.js.test.cjs b/tap-snapshots/test/lib/dist-tag.js.test.cjs
index ea25b568b..86a9c84eb 100644
--- a/tap-snapshots/test/lib/dist-tag.js.test.cjs
+++ b/tap-snapshots/test/lib/dist-tag.js.test.cjs
@@ -16,7 +16,8 @@ npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
-[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+[-ws|--workspaces]
alias: dist-tags
@@ -34,7 +35,8 @@ npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
-[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+[-ws|--workspaces]
alias: dist-tags
@@ -61,7 +63,8 @@ npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
-[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+[-ws|--workspaces]
alias: dist-tags
@@ -85,7 +88,8 @@ npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
-[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+[-ws|--workspaces]
alias: dist-tags
@@ -139,7 +143,8 @@ npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
Options:
-[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+[-ws|--workspaces]
alias: dist-tags
diff --git a/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs b/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
index 6bd38772e..e32d5e9f4 100644
--- a/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
+++ b/tap-snapshots/test/lib/utils/npm-usage.js.test.cjs
@@ -204,7 +204,8 @@ All commands:
npm audit [fix]
Options:
- [--audit-level <info|low|moderate|high|critical|none>] [--dry-run] [-f|--force] [--json] [--package-lock-only] [--production]
+ [--audit-level <info|low|moderate|high|critical|none>] [--dry-run] [-f|--force]
+ [--json] [--package-lock-only] [--production]
Run "npm help audit" for more info
@@ -324,7 +325,8 @@ All commands:
npm dist-tag ls [<pkg>]
Options:
- [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+ [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
alias: dist-tags
@@ -338,7 +340,9 @@ All commands:
npm docs [<pkgname> [<pkgname> ...]]
Options:
- [--browser|--browser <browser>] [--registry <registry>] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+ [--browser|--browser <browser>] [--registry <registry>]
+ [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
alias: home
@@ -373,7 +377,8 @@ All commands:
npm exec --package=foo -c '<cmd> [args...]'
Options:
- [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+ [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
alias: x
@@ -416,7 +421,8 @@ All commands:
npm fund [[<@scope>/]<pkg>]
Options:
- [--json] [--browser|--browser <browser>] [--unicode] [--which <fundingSourceNumber>]
+ [--json] [--browser|--browser <browser>] [--unicode]
+ [--which <fundingSourceNumber>]
Run "npm help fund" for more info
@@ -482,7 +488,8 @@ All commands:
npm install <github username>/<github project>
Options:
- [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact]
+ [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
+ [-E|--save-exact]
aliases: i, in, ins, inst, insta, instal, isnt, isnta, isntal, add
@@ -516,7 +523,8 @@ All commands:
npm install-test <github username>/<github project>
Options:
- [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact]
+ [-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
+ [-E|--save-exact]
alias: it
@@ -625,7 +633,9 @@ All commands:
npm pack [[<@scope>/]<pkg>...]
Options:
- [--dry-run] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+ [--dry-run]
+ [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
Run "npm help pack" for more info
@@ -705,7 +715,9 @@ All commands:
npm repo [<pkgname> [<pkgname> ...]]
Options:
- [--browser|--browser <browser>] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+ [--browser|--browser <browser>]
+ [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
Run "npm help repo" for more info
@@ -738,7 +750,8 @@ All commands:
npm run-script <command> [-- <args>]
Options:
- [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+ [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
aliases: run, rum, urn
@@ -775,7 +788,8 @@ All commands:
npm set-script [<script>] [<command>]
Options:
- [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+ [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
Run "npm help set-script" for more info
@@ -910,7 +924,13 @@ All commands:
Bump a package version
Usage:
- npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]
+ npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]
+
+ Options:
+ [--allow-same-version] [--commit-hooks] [--git-tag-version] [--json]
+ [--preid prerelease-id] [--sign-git-tag]
+ [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
alias: verison
@@ -924,7 +944,8 @@ All commands:
npm view [<@scope>/]<pkg>[@<version>] [<field>[.subfield]...]
Options:
- [--json] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]] [-ws|--workspaces]
+ [--json] [-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
+ [-ws|--workspaces]
aliases: v, info, show
diff --git a/test/lib/version.js b/test/lib/version.js
index 9cd5f47a0..6a83375b0 100644
--- a/test/lib/version.js
+++ b/test/lib/version.js
@@ -5,6 +5,7 @@ let result = []
const noop = () => null
const config = {
+ 'git-tag-version': true,
'tag-version-prefix': 'v',
json: false,
}
@@ -156,3 +157,174 @@ t.test('with one arg', t => {
t.end()
})
})
+
+t.test('workspaces', t => {
+ t.teardown(() => {
+ npm.localPrefix = ''
+ npm.prefix = ''
+ })
+
+ t.test('no args, all workspaces', t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'workspaces-test',
+ version: '1.0.0',
+ workspaces: ['workspace-a', 'workspace-b'],
+ }, null, 2),
+ 'workspace-a': {
+ 'package.json': JSON.stringify({
+ name: 'workspace-a',
+ version: '1.0.0',
+ }),
+ },
+ 'workspace-b': {
+ 'package.json': JSON.stringify({
+ name: 'workspace-b',
+ version: '1.0.0',
+ }),
+ },
+ })
+ npm.localPrefix = testDir
+ npm.prefix = testDir
+ const version = new Version(npm)
+ version.execWorkspaces([], [], err => {
+ if (err)
+ throw err
+ t.same(result, [{
+ 'workspaces-test': '1.0.0',
+ 'workspace-a': '1.0.0',
+ 'workspace-b': '1.0.0',
+ npm: '1.0.0',
+ }], 'outputs includes main package and workspace versions')
+ t.end()
+ })
+ })
+
+ t.test('no args, single workspaces', t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'workspaces-test',
+ version: '1.0.0',
+ workspaces: ['workspace-a', 'workspace-b'],
+ }, null, 2),
+ 'workspace-a': {
+ 'package.json': JSON.stringify({
+ name: 'workspace-a',
+ version: '1.0.0',
+ }),
+ },
+ 'workspace-b': {
+ 'package.json': JSON.stringify({
+ name: 'workspace-b',
+ version: '1.0.0',
+ }),
+ },
+ })
+ npm.localPrefix = testDir
+ npm.prefix = testDir
+ const version = new Version(npm)
+ version.execWorkspaces([], ['workspace-a'], err => {
+ if (err)
+ throw err
+ t.same(result, [{
+ 'workspaces-test': '1.0.0',
+ 'workspace-a': '1.0.0',
+ npm: '1.0.0',
+ }], 'outputs includes main package and requested workspace versions')
+ t.end()
+ })
+ })
+
+ t.test('no args, all workspaces, workspace with missing name or version', t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'workspaces-test',
+ version: '1.0.0',
+ workspaces: ['workspace-a', 'workspace-b', 'workspace-c'],
+ }, null, 2),
+ 'workspace-a': {
+ 'package.json': JSON.stringify({
+ name: 'workspace-a',
+ version: '1.0.0',
+ }),
+ },
+ 'workspace-b': {
+ 'package.json': JSON.stringify({
+ name: 'workspace-b',
+ }),
+ },
+ 'workspace-c': {
+ 'package.json': JSON.stringify({
+ version: '1.0.0',
+ }),
+ },
+ })
+ npm.localPrefix = testDir
+ npm.prefix = testDir
+ const version = new Version(npm)
+ version.execWorkspaces([], [], err => {
+ if (err)
+ throw err
+ t.same(result, [{
+ 'workspaces-test': '1.0.0',
+ 'workspace-a': '1.0.0',
+ npm: '1.0.0',
+ }], 'outputs includes main package and valid workspace versions')
+ t.end()
+ })
+ })
+
+ t.test('with one arg, all workspaces', t => {
+ const libNpmVersionArgs = []
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'workspaces-test',
+ version: '1.0.0',
+ workspaces: ['workspace-a', 'workspace-b'],
+ }, null, 2),
+ 'workspace-a': {
+ 'package.json': JSON.stringify({
+ name: 'workspace-a',
+ version: '1.0.0',
+ }),
+ },
+ 'workspace-b': {
+ 'package.json': JSON.stringify({
+ name: 'workspace-b',
+ version: '1.0.0',
+ }),
+ },
+ })
+ const Version = t.mock('../../lib/version.js', {
+ ...mocks,
+ libnpmversion: (arg, opts) => {
+ libNpmVersionArgs.push([arg, opts])
+ return '2.0.0'
+ },
+ })
+ npm.localPrefix = testDir
+ npm.prefix = testDir
+ const version = new Version(npm)
+
+ version.execWorkspaces(['major'], [], err => {
+ if (err)
+ throw err
+ t.same(result, ['workspace-a', 'v2.0.0', 'workspace-b', 'v2.0.0'], 'outputs the new version for only the workspaces prefixed by the tagVersionPrefix')
+ t.end()
+ })
+ })
+
+ t.test('too many args', t => {
+ version.execWorkspaces(['foo', 'bar'], [], err => {
+ t.match(
+ err,
+ 'npm version',
+ 'should throw usage instructions error'
+ )
+
+ t.end()
+ })
+ })
+
+ t.end()
+})