Skip to content

Commit 1afe5ba

Browse files
wraithgarlukekarrys
authored andcommitted
fix: account for new npm-package-arg behavior
`npm`, `npm@`, and `npm@*` are all now the same spec
1 parent de2d33f commit 1afe5ba

File tree

19 files changed

+91
-91
lines changed

19 files changed

+91
-91
lines changed

lib/commands/deprecate.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ class Deprecate extends BaseCommand {
3939

4040
// fetch the data and make sure it exists.
4141
const p = npa(pkg)
42-
// npa makes the default spec "latest", but for deprecation
43-
// "*" is the appropriate default.
44-
const spec = p.rawSpec === '' ? '*' : p.fetchSpec
42+
const spec = p.rawSpec === '*' ? '*' : p.fetchSpec
4543

4644
if (semver.validRange(spec, true) === null) {
4745
throw new Error(`invalid version range: ${spec}`)

lib/commands/diff.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class Diff extends BaseCommand {
185185
// work from the top of the arborist tree to find the original semver
186186
// range declared in the package that depends on the package.
187187
let bSpec
188-
if (spec.rawSpec) {
188+
if (spec.rawSpec !== '*') {
189189
bSpec = spec.rawSpec
190190
} else {
191191
const bTargetVersion =
@@ -269,7 +269,7 @@ class Diff extends BaseCommand {
269269

270270
return specs.map(i => {
271271
const spec = npa(i)
272-
if (spec.rawSpec) {
272+
if (spec.rawSpec !== '*') {
273273
return i
274274
}
275275

lib/commands/init.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,7 @@ class Init extends BaseCommand {
9898
packageName = initerName
9999
.replace(user + '/' + project, user + '/create-' + project)
100100
} else if (req.registry) {
101-
packageName = req.name.replace(/^(@[^/]+\/)?/, '$1create-')
102-
if (req.rawSpec) {
103-
packageName += '@' + req.rawSpec
104-
}
101+
packageName = `${req.name.replace(/^(@[^/]+\/)?/, '$1create-')}@${req.rawSpec}`
105102
} else {
106103
throw Object.assign(new Error(
107104
'Unrecognized initializer: ' + initerName +

lib/commands/rebuild.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class Rebuild extends ArboristWorkspaceCmd {
3939
const tree = await arb.loadActual()
4040
const specs = args.map(arg => {
4141
const spec = npa(arg)
42-
if (spec.type === 'tag' && spec.rawSpec === '') {
42+
if (spec.rawSpec === '*') {
4343
return spec
4444
}
4545

lib/commands/view.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -196,15 +196,16 @@ class View extends BaseCommand {
196196
// get the data about this package
197197
let version = this.npm.config.get('tag')
198198
// rawSpec is the git url if this is from git
199-
if (spec.type !== 'git' && spec.type !== 'directory' && spec.rawSpec) {
199+
if (spec.type !== 'git' && spec.type !== 'directory' && spec.rawSpec !== '*') {
200200
version = spec.rawSpec
201201
}
202202

203203
const pckmnt = await packument(spec, opts)
204204

205-
if (pckmnt['dist-tags'] && pckmnt['dist-tags'][version]) {
205+
if (pckmnt['dist-tags']?.[version]) {
206206
version = pckmnt['dist-tags'][version]
207207
}
208+
208209
if (pckmnt.time && pckmnt.time.unpublished) {
209210
const u = pckmnt.time.unpublished
210211
const er = new Error(`Unpublished on ${u.time}`)

tap-snapshots/test/lib/commands/dist-tag.js.test.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ latest: 1.0.0
2121
`
2222

2323
exports[`test/lib/commands/dist-tag.js TAP ls on missing package > should log no dist-tag found msg 1`] = `
24-
dist-tag ls Couldn't get dist-tag data for foo@latest
24+
dist-tag ls Couldn't get dist-tag data for foo@*
2525
2626
`
2727

test/lib/commands/diff.js

+14-14
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ t.test('single arg', t => {
216216
})
217217

218218
libnpmdiff = async ([a, b], opts) => {
219-
t.equal(a, 'simple-output@latest', 'should forward single spec')
219+
t.equal(a, 'simple-output@*', 'should forward single spec')
220220
t.equal(b, `file:${path}`, 'should compare to cwd')
221221
t.match(opts, npm.flatOptions, 'should forward flat options')
222222
}
@@ -460,7 +460,7 @@ t.test('single arg', t => {
460460
}
461461
},
462462
libnpmdiff: async ([a, b], opts) => {
463-
t.equal(a, 'lorem@latest', 'should target latest version of pkg name')
463+
t.equal(a, 'lorem@*', 'should target any version of pkg name')
464464
t.equal(b, `file:${path}`, 'should target current cwd')
465465
},
466466
})
@@ -479,7 +479,7 @@ t.test('single arg', t => {
479479
'package.json': JSON.stringify({ version: '1.0.0' }),
480480
})
481481
libnpmdiff = async ([a, b], opts) => {
482-
t.equal(a, 'bar@latest', 'should target latest tag of name')
482+
t.equal(a, 'bar@*', 'should target any version of pkg name')
483483
t.equal(b, `file:${path}`, 'should compare to cwd')
484484
}
485485

@@ -493,7 +493,7 @@ t.test('single arg', t => {
493493
t.plan(2)
494494

495495
libnpmdiff = async ([a, b], opts) => {
496-
t.equal(a, 'foo@latest', 'should target latest tag of name')
496+
t.equal(a, 'foo@*', 'should target any version of pkg name')
497497
t.equal(b, `file:${fooPath}`, 'should compare to cwd')
498498
}
499499

@@ -592,7 +592,7 @@ t.test('first arg is a qualified spec', t => {
592592

593593
libnpmdiff = async ([a, b], opts) => {
594594
t.equal(a, '[email protected]', 'should set expected first spec')
595-
t.equal(b, 'bar-fork@latest', 'should target latest tag if not a dep')
595+
t.equal(b, 'bar-fork@*', 'should target any version if not a dep')
596596
}
597597

598598
config.diff = ['[email protected]', 'bar-fork']
@@ -753,7 +753,7 @@ t.test('first arg is a known dependency name', async t => {
753753
`bar@file:${resolve(path, 'node_modules/bar')}`,
754754
'should target local node_modules pkg'
755755
)
756-
t.equal(b, 'bar-fork@latest', 'should set expected second spec')
756+
t.equal(b, 'bar-fork@*', 'should set expected second spec')
757757
}
758758

759759
npm.prefix = path
@@ -840,7 +840,7 @@ t.test('first arg is a valid semver range', t => {
840840

841841
libnpmdiff = async ([a, b], opts) => {
842842
t.equal(a, '[email protected]', 'should use name from second arg')
843-
t.equal(b, 'bar@latest', 'should compare against latest tag')
843+
t.equal(b, 'bar@*', 'should compare against any version')
844844
}
845845

846846
config.diff = ['1.0.0', 'bar']
@@ -884,7 +884,7 @@ t.test('first arg is an unknown dependency name', t => {
884884
t.plan(4)
885885

886886
libnpmdiff = async ([a, b], opts) => {
887-
t.equal(a, 'bar@latest', 'should set expected first spec')
887+
t.equal(a, 'bar@*', 'should set expected first spec')
888888
t.equal(b, '[email protected]', 'should set expected second spec')
889889
t.match(opts, npm.flatOptions, 'should forward flat options')
890890
t.match(opts, { where: fooPath }, 'should forward pacote options')
@@ -919,7 +919,7 @@ t.test('first arg is an unknown dependency name', t => {
919919
})
920920

921921
libnpmdiff = async ([a, b], opts) => {
922-
t.equal(a, 'bar-fork@latest', 'should use latest tag')
922+
t.equal(a, 'bar-fork@*', 'should use any version')
923923
t.equal(
924924
b,
925925
`bar@file:${resolve(path, 'node_modules/bar')}`,
@@ -940,7 +940,7 @@ t.test('first arg is an unknown dependency name', t => {
940940
t.plan(2)
941941

942942
libnpmdiff = async ([a, b], opts) => {
943-
t.equal(a, 'bar@latest', 'should use latest tag')
943+
t.equal(a, 'bar@*', 'should use any version')
944944
t.equal(b, 'bar@^1.0.0', 'should use name from first arg')
945945
}
946946

@@ -956,8 +956,8 @@ t.test('first arg is an unknown dependency name', t => {
956956
t.plan(2)
957957

958958
libnpmdiff = async ([a, b], opts) => {
959-
t.equal(a, 'bar@latest', 'should use latest tag')
960-
t.equal(b, 'bar-fork@latest', 'should use latest tag')
959+
t.equal(a, 'bar@*', 'should use any version')
960+
t.equal(b, 'bar-fork@*', 'should use any version')
961961
}
962962

963963
config.diff = ['bar', 'bar-fork']
@@ -973,8 +973,8 @@ t.test('first arg is an unknown dependency name', t => {
973973

974974
const path = t.testdir({})
975975
libnpmdiff = async ([a, b], opts) => {
976-
t.equal(a, 'bar@latest', 'should use latest tag')
977-
t.equal(b, 'bar-fork@latest', 'should use latest tag')
976+
t.equal(a, 'bar@*', 'should use any version')
977+
t.equal(b, 'bar-fork@*', 'should use any version')
978978
}
979979

980980
config.diff = ['bar', 'bar-fork']

test/lib/commands/dist-tag.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ t.test('workspaces', t => {
277277
await distTag.execWorkspaces([], [])
278278
t.equal(process.exitCode, 1, 'set the error status')
279279
process.exitCode = 0
280-
t.match(log, 'dist-tag ls Couldn\'t get dist-tag data for workspace-d@latest', 'logs the error')
280+
t.match(log, 'dist-tag ls Couldn\'t get dist-tag data for workspace-d@*', 'logs the error')
281281
t.matchSnapshot(result, 'printed the expected output')
282282
})
283283

test/lib/commands/init.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ t.test('npm init <arg>', async t => {
8585
libnpmexec: ({ args, cache, npxCache }) => {
8686
t.same(
8787
args,
88-
['create-react-app'],
88+
['create-react-app@*'],
8989
'should npx with listed packages'
9090
)
9191
t.same(cache, flatOptions.cache)
@@ -106,7 +106,7 @@ t.test('npm init <arg> -- other-args', async t => {
106106
libnpmexec: ({ args }) => {
107107
t.same(
108108
args,
109-
['create-react-app', 'my-path', '--some-option', 'some-value'],
109+
['create-react-app@*', 'my-path', '--some-option', 'some-value'],
110110
'should npm exec with expected args'
111111
)
112112
},
@@ -125,7 +125,7 @@ t.test('npm init @scope/name', async t => {
125125
libnpmexec: ({ args }) => {
126126
t.same(
127127
args,
128-
['@npmcli/create-something'],
128+
['@npmcli/create-something@*'],
129129
'should npx with scoped packages'
130130
)
131131
},
@@ -268,7 +268,7 @@ t.test('should not rewrite flatOptions', async t => {
268268
libnpmexec: async ({ args }) => {
269269
t.same(
270270
args,
271-
['create-react-app', 'my-app'],
271+
['create-react-app@*', 'my-app'],
272272
'should npx with extra args'
273273
)
274274
},
@@ -500,7 +500,7 @@ t.test('workspaces', t => {
500500
libnpmexec: ({ args, path }) => {
501501
t.same(
502502
args,
503-
['create-react-app'],
503+
['create-react-app@*'],
504504
'should npx with listed packages'
505505
)
506506
t.same(

workspaces/arborist/lib/add-rm-pkg-deps.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ const add = ({ pkg, add, saveBundle, saveType }) => {
3535
const depType = saveTypeMap.get(addSaveType)
3636

3737
pkg[depType] = pkg[depType] || {}
38-
if (rawSpec !== '' || pkg[depType][name] === undefined) {
39-
pkg[depType][name] = rawSpec || '*'
38+
if (rawSpec !== '*' || pkg[depType][name] === undefined) {
39+
pkg[depType][name] = rawSpec
4040
}
4141
if (addSaveType === 'optional') {
4242
// Affordance for previous npm versions that require this behaviour

workspaces/arborist/lib/arborist/build-ideal-tree.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,12 @@ module.exports = cls => class IdealTreeBuilder extends cls {
254254
for (const name of update.names) {
255255
const spec = npa(name)
256256
const validationError =
257-
new TypeError(`Update arguments must not contain package version specifiers
258-
259-
Try using the package name instead, e.g:
257+
new TypeError(`Update arguments must only contain package names, eg:
260258
npm update ${spec.name}`)
261259
validationError.code = 'EUPDATEARGS'
262260

263-
if (spec.fetchSpec !== 'latest') {
261+
// If they gave us anything other than a bare package name
262+
if (spec.raw !== spec.name) {
264263
throw validationError
265264
}
266265
}

workspaces/arborist/lib/consistent-resolve.js

+17-11
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,23 @@ const consistentResolve = (resolved, fromPath, toPath, relPaths = false) => {
1919
rawSpec,
2020
raw,
2121
} = npa(resolved, fromPath)
22-
const isPath = type === 'file' || type === 'directory'
23-
return isPath && !relPaths ? `file:${fetchSpec.replace(/#/g, '%23')}`
24-
: isPath ? 'file:' + (toPath ? relpath(toPath, fetchSpec.replace(/#/g, '%23')) : fetchSpec.replace(/#/g, '%23'))
25-
: hosted ? `git+${
26-
hosted.auth ? hosted.https(hostedOpt) : hosted.sshurl(hostedOpt)
27-
}`
28-
: type === 'git' ? saveSpec
29-
// always return something. 'foo' is interpreted as 'foo@' otherwise.
30-
: rawSpec === '' && raw.slice(-1) !== '@' ? raw
31-
// just strip off the name, but otherwise return as-is
32-
: rawSpec
22+
if (type === 'file' || type === 'directory') {
23+
const cleanFetchSpec = fetchSpec.replace(/#/g, '%23')
24+
if (relPaths && toPath) {
25+
return `file:${relpath(toPath, cleanFetchSpec)}`
26+
}
27+
return `file:${cleanFetchSpec}`
28+
}
29+
if (hosted) {
30+
return `git+${hosted.auth ? hosted.https(hostedOpt) : hosted.sshurl(hostedOpt)}`
31+
}
32+
if (type === 'git') {
33+
return saveSpec
34+
}
35+
if (rawSpec === '*') {
36+
return raw
37+
}
38+
return rawSpec
3339
} catch (_) {
3440
// whatever we passed in was not acceptable to npa.
3541
// leave it 100% untouched.

workspaces/arborist/lib/edge.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ class Edge {
166166
}
167167

168168
get spec () {
169-
if (this.overrides && this.overrides.value && this.overrides.name === this.name) {
169+
if (this.overrides?.value && this.overrides.value !== '*' && this.overrides.name === this.name) {
170170
if (this.overrides.value.startsWith('$')) {
171171
const ref = this.overrides.value.slice(1)
172172
// we may be a virtual root, if we are we want to resolve reference overrides

workspaces/arborist/lib/override-set.js

+4-7
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class OverrideSet {
2525
this.name = spec.name
2626
spec.name = ''
2727
this.key = key
28-
this.keySpec = spec.rawSpec === '' ? '' : spec.toString()
28+
this.keySpec = spec.toString()
2929
this.value = overrides['.'] || this.keySpec
3030
}
3131

@@ -50,8 +50,7 @@ class OverrideSet {
5050
continue
5151
}
5252

53-
if (rule.keySpec === '' ||
54-
semver.intersects(edge.spec, rule.keySpec)) {
53+
if (semver.intersects(edge.spec, rule.keySpec)) {
5554
return rule
5655
}
5756
}
@@ -65,8 +64,7 @@ class OverrideSet {
6564
continue
6665
}
6766

68-
if (rule.keySpec === '' ||
69-
semver.satisfies(node.version, rule.keySpec) ||
67+
if (semver.satisfies(node.version, rule.keySpec) ||
7068
semver.satisfies(node.version, rule.value)) {
7169
return rule
7270
}
@@ -81,8 +79,7 @@ class OverrideSet {
8179
continue
8280
}
8381

84-
if (rule.keySpec === '' ||
85-
semver.satisfies(node.version, rule.keySpec) ||
82+
if (semver.satisfies(node.version, rule.keySpec) ||
8683
semver.satisfies(node.version, rule.value)) {
8784
return rule
8885
}

workspaces/arborist/lib/query-selector-all.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,13 @@ class Results {
120120
this.#pendingCombinator = combinators[String(this.currentAstNode)]
121121
}
122122

123-
// name selectors (i.e. #foo, #[email protected])
123+
// name selectors (i.e. #foo)
124124
// css calls this id, we interpret it as name
125125
idType () {
126-
const spec = npa(this.currentAstNode.value)
126+
const name = this.currentAstNode.value
127127
const nextResults = this.initialItems.filter(node =>
128-
(node.name === spec.name || node.package.name === spec.name) &&
129-
(semver.satisfies(node.version, spec.fetchSpec) || !spec.rawSpec))
128+
(name === node.name) || (name === node.package.name)
129+
)
130130
this.processPendingCombinator(nextResults)
131131
}
132132

workspaces/arborist/tap-snapshots/test/node.js.test.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ exports[`test/node.js TAP basic instantiation > just a lone root node 1`] = `
3232
"foo" => OverrideSet {
3333
"children": Map {},
3434
"key": "foo",
35-
"keySpec": "",
35+
"keySpec": "*",
3636
"name": "foo",
3737
"parent": <*ref_2>,
3838
"value": "1",

0 commit comments

Comments
 (0)