Skip to content

Release/v8.3.2 #4301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
## v8.3.2 (2022-01-20)

### Bug Fixes

* [`cfd59b8c8`](https://github.com/npm/cli/commit/cfd59b8c81078f842328b13a23a234150842cd58)
[#4223](https://github.com/npm/cli/pull/4223)
fix: npm update --save
([@ruyadorno](https://github.com/ruyadorno))
* [`510f0ecbc`](https://github.com/npm/cli/commit/510f0ecbc9970ed8c8993107cc03cf27b7b996dc)
[#4218](https://github.com/npm/cli/pull/4218)
fix(arborist): ensure indentation is preserved
([@ljharb](https://github.com/ljharb))
* [`c99c2151a`](https://github.com/npm/cli/commit/c99c2151a868672c017f64ff0ecb12149a2fb095)
[#4230](https://github.com/npm/cli/pull/4230)
fix(arborist): prioritize valid workspace nodes
([@nlf](https://github.com/nlf))
* [`14a3d9500`](https://github.com/npm/cli/commit/14a3d95000f1cba937f3309d198a363ae65cf01f)
[#4265](https://github.com/npm/cli/pull/4265)
fix: resolve workspace paths from cwd when possible
([@nlf](https://github.com/nlf))

### Dependencies

* [`2ef9f9847`](https://github.com/npm/cli/commit/2ef9f9847c11fe8c0c0494558fe77c15ac4dbc80)
[#4254](https://github.com/npm/cli/pull/4254)
deps: `[email protected] [email protected]`

## v8.3.1 (2022-01-13)

### Bug Fixes
Expand Down
6 changes: 6 additions & 0 deletions docs/content/commands/npm-dedupe.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ result in new modules being installed.

Using `npm find-dupes` will run the command in `--dry-run` mode.

Note that by default `npm dedupe` will not update the semver values of direct
dependencies in your project `package.json`, if you want to also update
values in `package.json` you can run: `npm dedupe --save` (or add the
`save=true` option to a [configuration file](/configuring-npm/npmrc)
to make that the default behavior).

### Configuration

<!-- AUTOGENERATED CONFIG DESCRIPTIONS START -->
Expand Down
6 changes: 6 additions & 0 deletions docs/content/commands/npm-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ packages.
If no package name is specified, all packages in the specified location (global
or local) will be updated.

Note that by default `npm update` will not update the semver values of direct
dependencies in your project `package.json`, if you want to also update
values in `package.json` you can run: `npm update --save` (or add the
`save=true` option to a [configuration file](/configuring-npm/npmrc)
to make that the default behavior).

### Example

For the examples below, assume that the current package is `app` and it depends
Expand Down
9 changes: 6 additions & 3 deletions docs/content/using-npm/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -1326,13 +1326,16 @@ The base URL of the npm registry.

#### `save`

* Default: true
* Default: `true` unless when using `npm update` or `npm dedupe` where it
defaults to `false`
* Type: Boolean

Save installed packages to a package.json file as dependencies.
Save installed packages to a `package.json` file as dependencies.

When used with the `npm rm` command, removes the dependency from
package.json.
`package.json`.

Will also prevent writing to `package-lock.json` if set to `false`.

<!-- automatically generated, do not edit manually -->
<!-- see lib/utils/config/definitions.js -->
Expand Down
8 changes: 8 additions & 0 deletions lib/base-command.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// Base class for npm commands

const { relative } = require('path')

const usageUtil = require('./utils/usage.js')
const ConfigDefinitions = require('./utils/config/definitions.js')
const getWorkspaces = require('./workspaces/get-workspaces.js')
Expand Down Expand Up @@ -78,9 +81,14 @@ class BaseCommand {
this.includeWorkspaceRoot = false
}

const relativeFrom = relative(this.npm.localPrefix, process.cwd()).startsWith('..')
? this.npm.localPrefix
: process.cwd()

const ws = await getWorkspaces(filters, {
path: this.npm.localPrefix,
includeWorkspaceRoot: this.includeWorkspaceRoot,
relativeFrom,
})
this.workspaces = ws
this.workspaceNames = [...ws.keys()]
Expand Down
8 changes: 8 additions & 0 deletions lib/commands/dedupe.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Dedupe extends ArboristWorkspaceCmd {
'legacy-bundling',
'strict-peer-deps',
'package-lock',
'save',
'omit',
'ignore-scripts',
'audit',
Expand All @@ -29,13 +30,20 @@ class Dedupe extends ArboristWorkspaceCmd {
throw er
}

// In the context of `npm dedupe` the save
// config value should default to `false`
const save = this.npm.config.isDefault('save')
? false
: this.npm.config.get('save')

const dryRun = this.npm.config.get('dry-run')
const where = this.npm.prefix
const opts = {
...this.npm.flatOptions,
log,
path: where,
dryRun,
save,
workspaces: this.workspaceNames,
}
const arb = new Arborist(opts)
Expand Down
15 changes: 12 additions & 3 deletions lib/commands/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Update extends ArboristWorkspaceCmd {
'legacy-bundling',
'strict-peer-deps',
'package-lock',
'save',
'omit',
'ignore-scripts',
'audit',
Expand All @@ -40,19 +41,27 @@ class Update extends ArboristWorkspaceCmd {
? global
: this.npm.prefix

// In the context of `npm update` the save
// config value should default to `false`
const save = this.npm.config.isDefault('save')
? false
: this.npm.config.get('save')

if (this.npm.config.get('depth')) {
log.warn('update', 'The --depth option no longer has any effect. See RFC0019.\n' +
'https://github.com/npm/rfcs/blob/latest/implemented/0019-remove-update-depth-option.md')
}

const arb = new Arborist({
const opts = {
...this.npm.flatOptions,
log,
path: where,
save,
workspaces: this.workspaceNames,
})
}
const arb = new Arborist(opts)

await arb.reify({ update })
await arb.reify({ ...opts, update })
await reifyFinish(this.npm, arb)
}
}
Expand Down
8 changes: 6 additions & 2 deletions lib/utils/config/definitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1583,14 +1583,18 @@ define('registry', {

define('save', {
default: true,
defaultDescription: `\`true\` unless when using \`npm update\` or
\`npm dedupe\` where it defaults to \`false\``,
usage: '-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer',
type: Boolean,
short: 'S',
description: `
Save installed packages to a package.json file as dependencies.
Save installed packages to a \`package.json\` file as dependencies.

When used with the \`npm rm\` command, removes the dependency from
package.json.
\`package.json\`.

Will also prevent writing to \`package-lock.json\` if set to \`false\`.
`,
flatten,
})
Expand Down
6 changes: 3 additions & 3 deletions lib/workspaces/get-workspaces.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ 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, includeWorkspaceRoot }) => {
const getWorkspaces = async (filters, { path, includeWorkspaceRoot, relativeFrom }) => {
// 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 })
Expand All @@ -21,8 +21,8 @@ const getWorkspaces = async (filters, { path, includeWorkspaceRoot }) => {
for (const filterArg of filters) {
for (const [workspaceName, workspacePath] of workspaces.entries()) {
if (filterArg === workspaceName
|| resolve(path, filterArg) === workspacePath
|| minimatch(workspacePath, `${resolve(path, filterArg)}/*`)) {
|| resolve(relativeFrom || path, filterArg) === workspacePath
|| minimatch(workspacePath, `${resolve(relativeFrom || path, filterArg)}/*`)) {
res.set(workspaceName, workspacePath)
}
}
Expand Down
8 changes: 4 additions & 4 deletions node_modules/bin-links/lib/bin-target.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const isWindows = require('./is-windows.js')
const getPrefix = require('./get-prefix.js')
const getNodeModules = require('./get-node-modules.js')
const {dirname} = require('path')
const { dirname } = require('path')

module.exports = ({top, path}) =>
module.exports = ({ top, path }) =>
!top ? getNodeModules(path) + '/.bin'
: isWindows ? getPrefix(path)
: dirname(getPrefix(path)) + '/bin'
: isWindows ? getPrefix(path)
: dirname(getPrefix(path)) + '/bin'
47 changes: 26 additions & 21 deletions node_modules/bin-links/lib/check-bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,74 @@
// either rejects or resolves to nothing. return value not relevant.
const isWindows = require('./is-windows.js')
const binTarget = require('./bin-target.js')
const {resolve, dirname} = require('path')
const { resolve, dirname } = require('path')
const readCmdShim = require('read-cmd-shim')
const fs = require('fs')
const {promisify} = require('util')
const { promisify } = require('util')
const readlink = promisify(fs.readlink)

const checkBin = async ({bin, path, top, global, force}) => {
const checkBin = async ({ bin, path, top, global, force }) => {
// always ok to clobber when forced
// always ok to clobber local bins, or when forced
if (force || !global || !top)
if (force || !global || !top) {
return
}

// ok, need to make sure, then
const target = resolve(binTarget({path, top}), bin)
const target = resolve(binTarget({ path, top }), bin)
path = resolve(path)
return isWindows ? checkShim({target, path}) : checkLink({target, path})
return isWindows ? checkShim({ target, path }) : checkLink({ target, path })
}

// only enoent is allowed. anything else is a problem.
const handleReadLinkError = async ({er, target}) =>
const handleReadLinkError = async ({ er, target }) =>
er.code === 'ENOENT' ? null
: failEEXIST({target})
: failEEXIST({ target })

const checkLink = async ({target, path}) => {
const checkLink = async ({ target, path }) => {
const current = await readlink(target)
.catch(er => handleReadLinkError({er, target}))
.catch(er => handleReadLinkError({ er, target }))

if (!current)
if (!current) {
return
}

const resolved = resolve(dirname(target), current)

if (resolved.toLowerCase().indexOf(path.toLowerCase()) !== 0)
return failEEXIST({target})
if (resolved.toLowerCase().indexOf(path.toLowerCase()) !== 0) {
return failEEXIST({ target })
}
}

const handleReadCmdShimError = ({er, target}) =>
const handleReadCmdShimError = ({ er, target }) =>
er.code === 'ENOENT' ? null
: failEEXIST({target})
: failEEXIST({ target })

const failEEXIST = ({target}) =>
const failEEXIST = ({ target }) =>
Promise.reject(Object.assign(new Error('EEXIST: file already exists'), {
path: target,
code: 'EEXIST',
}))

const checkShim = async ({target, path}) => {
const checkShim = async ({ target, path }) => {
const shims = [
target,
target + '.cmd',
target + '.ps1',
]
await Promise.all(shims.map(async target => {
const current = await readCmdShim(target)
.catch(er => handleReadCmdShimError({er, target}))
.catch(er => handleReadCmdShimError({ er, target }))

if (!current)
if (!current) {
return
}

const resolved = resolve(dirname(target), current.replace(/\\/g, '/'))

if (resolved.toLowerCase().indexOf(path.toLowerCase()) !== 0)
return failEEXIST({target})
if (resolved.toLowerCase().indexOf(path.toLowerCase()) !== 0) {
return failEEXIST({ target })
}
}))
}

Expand Down
8 changes: 5 additions & 3 deletions node_modules/bin-links/lib/check-bins.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ const normalize = require('npm-normalize-package-bin')
const checkBins = async ({ pkg, path, top, global, force }) => {
// always ok to clobber when forced
// always ok to clobber local bins, or when forced
if (force || !global || !top)
if (force || !global || !top) {
return
}

pkg = normalize(pkg)
if (!pkg.bin)
if (!pkg.bin) {
return
}

await Promise.all(Object.keys(pkg.bin)
.map(bin => checkBin({bin, path, top, global, force})))
.map(bin => checkBin({ bin, path, top, global, force })))
}
module.exports = checkBins
5 changes: 3 additions & 2 deletions node_modules/bin-links/lib/get-node-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
// {prefix}/node_modules/{name}. Can't rely on pkg.name, because
// it might be installed as an alias.

const {dirname, basename} = require('path')
const { dirname, basename } = require('path')
// this gets called a lot and can't change, so memoize it
const memo = new Map()
module.exports = path => {
if (memo.has(path))
if (memo.has(path)) {
return memo.get(path)
}

const scopeOrNm = dirname(path)
const nm = basename(scopeOrNm) === 'node_modules' ? scopeOrNm
Expand Down
Loading