Skip to content

Commit

Permalink
feat(arborist): add named updates validation (#4307)
Browse files Browse the repository at this point in the history
* feat(arborist): add named updates validation

Arborist update does not support anything other than dependency names,
that is confusing to some users that are used to provide semver ranges
when using `npm install` and other commands.

This changeset adds validation to the values provided as arguments in
`npm update` and will throw a `EUPDATEARGS` error in case the user tries
to use semver ranges, e.g: `npm update [email protected]`

Relates to: #4240
  • Loading branch information
ruyadorno authored Jan 26, 2022
1 parent 1f853f8 commit fbe48a8
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
16 changes: 16 additions & 0 deletions workspaces/arborist/lib/arborist/build-ideal-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,22 @@ module.exports = cls => class IdealTreeBuilder extends cls {
this[_complete] = !!options.complete
this[_preferDedupe] = !!options.preferDedupe
this[_legacyBundling] = !!options.legacyBundling

// validates list of update names, they must
// be dep names only, no semver ranges are supported
for (const name of update.names) {
const spec = npa(name)
const validationError =
new TypeError(`Update arguments must not contain package version specifiers
Try using the package name instead, e.g:
npm update ${spec.name}`)
validationError.code = 'EUPDATEARGS'

if (spec.fetchSpec !== 'latest') {
throw validationError
}
}
this[_updateNames] = update.names

this[_updateAll] = update.all
Expand Down
16 changes: 16 additions & 0 deletions workspaces/arborist/test/arborist/build-ideal-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -2098,6 +2098,22 @@ t.test('update global', async t => {

t.matchSnapshot(await printIdeal(path, { global: true, update: ['wrappy'] }),
'updating sub-dep has no effect')

const invalidArgs = [
'[email protected]',
'once@next',
'once@^1.0.0',
'once@>=2.0.0',
'once@2',
]
for (const updateName of invalidArgs) {
t.rejects(
printIdeal(path, { global: true, update: [updateName] }),
{ code: 'EUPDATEARGS' },
'should throw an error when using semver ranges'
)
}

t.matchSnapshot(await printIdeal(path, { global: true, update: ['once'] }),
'update a single dep')
t.matchSnapshot(await printIdeal(path, { global: true, update: true }),
Expand Down

0 comments on commit fbe48a8

Please sign in to comment.