/flags/semver/semver-p-include-prerelease
semver -p (--include-prerelease): let ^1.2.0 match 1.3.0-beta.1
- tool
- SemVer
- command
- semver
- flag
- -p, --include-prerelease
- default
- off (a range matches a prerelease only when a comparator in the range has a prerelease on the same major.minor.patch)
semver -p -r '^1.2.0' 1.3.0-beta.1 makes the range match prerelease versions as well. By default node-semver excludes prereleases from ranges: ^1.2.0 matches 1.3.0 but not 1.3.0-beta.1 or 1.2.5-rc.1, even though they fall between the bounds numerically. The rule protects users from installing unstable versions by accident; -p (--include-prerelease, the includePrerelease option in the library) turns it off.
Matching with and without -p
node-semver's CLI is installed in a temporary folder (npx semver behaves the same). -r prints the versions that satisfy the range, and exits with 1 if none does:
npm init -y >/dev/null && npm install --silent --no-audit --no-fund semver@7.8.5 >/dev/null 2>&1
export PATH="$PWD/node_modules/.bin:$PATH"
echo "--- ^1.2.0 without -p:"
semver -r '^1.2.0' 1.2.5-rc.1 1.3.0-beta.1 1.3.0
echo "--- ^1.2.0 with -p:"
semver -p -r '^1.2.0' 1.2.5-rc.1 1.3.0-beta.1 1.3.0
echo "--- a range that names a prerelease:"
semver -r '^1.2.5-rc.0' 1.2.5-rc.1 1.3.0-beta.1
echo "--- only prereleases, no -p:"
semver -r '^1.2.0' 1.3.0-beta.1; echo "exit $?"
echo "--- sorting is unchanged:"
semver 1.3.0 1.3.0-beta.1 1.3.0-rc.1Output
--- ^1.2.0 without -p: 1.3.0 --- ^1.2.0 with -p: 1.2.5-rc.1 1.3.0-beta.1 1.3.0 --- a range that names a prerelease: 1.2.5-rc.1 --- only prereleases, no -p: exit 1 --- sorting is unchanged: 1.3.0-beta.1 1.3.0-rc.1 1.3.0
Without -p only 1.3.0 matches. With it, both prereleases match too. A range that itself contains a prerelease (^1.2.5-rc.0) admits prereleases of that version tuple only: 1.2.5-rc.1 matches, 1.3.0-beta.1 does not. When nothing matches, semver prints nothing and exits with 1.
The default rule in detail
| Range | Version | Default | With -p |
|---|---|---|---|
| ^1.2.0 | 1.3.0 | match | match |
| ^1.2.0 | 1.3.0-beta.1 | no match | match |
| >=1.2.0-rc.0 | 1.2.0-rc.5 | match (same tuple 1.2.0) | match |
| >=1.2.0-rc.0 | 1.3.0-beta.1 | no match (different tuple) | match |
| * | 2.0.0-alpha.1 | no match | match |
| 2.0.0-alpha.1 | 2.0.0-alpha.1 | match (exact) | match |
The "same tuple" exception exists so that a project that already opted into 1.2.0-rc.0 receives newer release candidates of 1.2.0, but not the prereleases of every later version.
Where the option exists
- CLI:
semver -por--include-prerelease. - Library:
semver.satisfies(v, range, { includePrerelease: true }), and the same option formaxSatisfying,minSatisfyingandRange. - npm installs follow the default rule: a prerelease is installed only when you ask for it by version, by a range that names it, or by a dist-tag such as
beta.
Pitfalls
- Wildcards.
*andxranges also exclude prereleases by default, sosemver -r '*' 2.0.0-alpha.1prints nothing. - Invalid ranges. A malformed range makes the library throw TypeError: Invalid comparator; the CLI prints nothing and exits with 1.
- Publishing betas. Publish prereleases with
npm publish --tag betasolatestkeeps pointing at the stable release; bump them with semver -i prerelease --preid.
The full range grammar is on SemVer range syntax and the concept on pre-release versions.
FAQ
Why does npm not install my beta although it is newer?
A range such as ^1.2.0 only matches prereleases when the range itself names a prerelease of the same major.minor.patch. Install the beta explicitly (npm install pkg@beta or pkg@1.3.0-beta.1) or use a range like ^1.3.0-beta.0.
Does -p change how versions are sorted?
No. Prereleases always sort before their release (1.3.0-beta.1 < 1.3.0). -p only changes which versions a range is allowed to match.
How do I get the newest version including prereleases in code?
Pass the option to the library: semver.maxSatisfying(versions, '^1.2.0', { includePrerelease: true }). Without it, maxSatisfying ignores prereleases just like the CLI without -p.