1.x matches >=1.0.0 <2.0.0: any 1.y.z release. The x stands in for a number left open, and X and * do the same, so 1.x, 1.X, 1.*, 1.x.x and a plain 1 are all one range. ^1 and ~1 compile to it too.
Against real versions
0.9.9 no
1.0.0 yes
1.4.2 yes
1.9.9 yes the highest match
1.5.0-rc.1 no a prerelease
2.0.0 no
2.0.0-beta.1 no
More x-ranges
1.2.x >=1.2.0 <1.3.0 same as 1.2 and ~1.2
1.x || 2.x >=1.0.0 <2.0.0 || >=2.0.0 <3.0.0
* any release x and an empty string mean the same
An x-range keeps every number you wrote and frees the rest. That’s why 1.2.x is narrower than ^1.2.0: it holds the minor version too.
Gotchas
- There’s no floor.
1.xaccepts 1.0.0. If your code needs something added in 1.4, write^1.4.0: a fresh install would pick a high 1.x anyway, but an older lockfile or another package’s range can leave you on 1.0.x. *isn’tlatest.*accepts every release, so npm normally installs the one thelatesttag points to. The wordlatestinpackage.jsonis a dist-tag, not a range: npm resolves it at install time, and node-semver (and this tool) rejects it withInvalid comparator: latest.- Prereleases need to be named. Neither
1.xnor*admits1.5.0-rc.1. A range only takes a prerelease when it names one on the same version, such as^1.5.0-rc.1. - A lockfile overrides the looseness.
package-lock.jsonkeeps the exact version installed, andnpm ciinstalls only that;npm updatemoves it to the newest 1.x.
Elsewhere
- Cargo:
1.*is>=1.0.0, <2.0.0, and so is a plain"1", which Cargo reads as a caret requirement. - Python (PEP 440):
==1.*matches any 1.x release.