mrkeyoor.com_
Sat 31 Oct 22:56 UTC
npmInfraupdated 31 Oct 2026

semver review

A prerelease can be newer than your minimum version and still fail your range check. The npm semver package parses semantic version strings, compares versions and checks npm-style ranges. It gives a plugin loader or release script a consistent way to decide which version labels it accepts. It cannot establish whether the corresponding code works with your application. This guide uses semver 7.8.5 and concentrates on keeping that acceptance policy explicit, especially for prereleases and versions below 1.0.

Verdict

Use semver when you need npm-style version acceptance rules and can state your prerelease policy explicitly. Before wiring it into a loader or release job, turn the boundary cases below into checks against your own supported versions.

Answers from our run

semver or compare-versions: which should you use?

compare-versions: Consider compare-versions when the job is comparing version strings as greater, equal or lesser. Its registry description establishes that scope. This guide does not establish equivalence with semver's complete range grammar. Use semver when you need npm-style version acceptance rules and can state your prerelease policy explicitly.

When should you not use semver?

You need proof that an upgrade is compatible. A version label and a matching range cannot replace tests of the application that consumes it.

API stability4/5The version-pinned README documents separate contracts for valid, validRange, satisfies and maxSatisfying, including null results and prerelease options. That makes acceptance rules possible to specify before integration. The 7.8.5 changelog still records a tilde lower-bound fix with includePrerelease, so staying within major 7 is not evidence that every boundary behaves identically across patches. This is a contract-based judgment, not a reproduced compatibility matrix.
Docs4/5The 7.8.5 README explains comparator sets, prerelease opt-in, caret behavior below 1.0, coercion and build-aware comparison. Those details answer practical questions that function signatures alone leave open. Its API descriptions support the illustrations here, but this guide has not followed them through an executed integration. Under the stated rubric, useful coverage with that validation gap earns 4 rather than 5.
Maintenance4/5The pinned changelog lists fixes in 7.8.3 for caret prerelease lower bounds, in 7.8.4 for numeric segments after x-ranges, and in 7.8.5 for tilde prerelease lower bounds. Version 7.8.5's release notes describe a fix to tilde lower bounds when includePrerelease is enabled. These are specific corrections to range behavior, supporting a positive maintenance judgment. Release notes do not establish maintainer response times, a future support commitment or that our examples passed.
Ecosystem3/5The version-specific npm record describes semver as the semantic version parser used by npm, and the pinned README documents both module and command-line entry points. That is concrete integration context for an npm-oriented tool. It does not measure adoption in your stack or interoperability with another language's version rules. The alternative registry records establish narrower comparison and text-matching options, not migration compatibility. Those evaluation gaps keep this judgment at 3.

Use it if

  • Your plugin loader accepts a declared range and needs to check a plugin's version before loading it.
  • A release script must compare semantic versions numerically rather than sort their characters.
  • You already have a list of available versions and need the highest one that satisfies your policy.
  • You need npm-style caret, tilde or compound ranges and want their prerelease rules written into your checks.
Skip it if

Setup reality

Install the version covered here with npm install semver@7.8.5, then use const semver = require('semver') in a CommonJS file. The npm manifest declares Node >=10. That is an upstream engine constraint, not a recommendation to deploy an old Node release or a runtime matrix reproduced here. The examples below are documentation-based illustrations for semver 7.8.5. They were not executed for this guide. No install timing, security audit or runtime compatibility measurement is claimed.

Validate the version and the range separately before you make an acceptance decision. semver.valid returns a parsed version string or null. A partial range such as 1.2 is valid range syntax even though it is not a complete version. An empty range also means any non-prerelease version, so reject blank input yourself when a missing policy should be an error. Treat null as a result your application must handle. Don't silently turn a missing match into the latest release.

Prereleases need a deliberate rule. By default, a prerelease only passes a comparator set when a comparator with the same major, minor and patch also carries a prerelease. Setting includePrerelease changes this behavior. It does not make an out-of-range version pass. Caret ranges below 1.0 have another boundary: ^0.2.3 accepts patch updates below 0.3.0, while ^0.0.3 stops before 0.0.4. Write checks around the boundaries your plugin or release policy cares about.

Coercion is a separate import decision. The documented translation of 4.6.3.9.2-alpha2 is 4.6.3, which loses both the extra components and suffix. Keep the original input if you need to explain that transformation. Build metadata needs a policy too: compare ignores it for precedence, while compareBuild uses it to order otherwise equal versions. Neither rule tells you which artifact was tested.

The ratings are editorial judgments from documentation, package metadata and release notes, not benchmark results. On a 1-5 scale, 1 means little usable support in those sources, 3 means documented support with material evaluation gaps, and 5 requires direct validation of the relevant behavior. API stability assesses the documented contract and changes, docs quality assesses explanations of edge cases, maintenance assesses release evidence, and ecosystem assesses integration evidence. No dimension gets 5 from documentation alone.

Patterns

Reject an incomplete version validate-version

const semver = require('semver')

const input = '1.2'
const version = semver.valid(input)
if (version === null) {
  throw new Error('A complete semantic version is required')
}

Documentation-based, unexecuted illustration. valid('1.2') returns null. Version syntax and range syntax accept different inputs. valid is a parser check, not a character-for-character canonical-format check.

Reject a blank policy before parsing validate-range

const semver = require('semver')

const input = '^1.2.3'
if (input.trim() === '') throw new Error('A range is required')
const range = semver.validRange(input)
if (range === null) throw new Error('Invalid range')
const accepted = semver.satisfies('1.4.0', range) // true

Documentation-based, unexecuted illustration. An empty range is valid and means any non-prerelease version by default. The explicit blank check is application policy.

Make the zero-major boundary visible caret-below-one

const semver = require('semver')

const patchAccepted = semver.satisfies('0.2.9', '^0.2.3') // true
const minorRejected = semver.satisfies('0.3.0', '^0.2.3') // false
const nextPatchRejected = semver.satisfies('0.0.4', '^0.0.3') // false

Documentation-based, unexecuted illustration. A caret preserves the leftmost non-zero component. These results express permitted labels, not tested compatibility between the releases.

Keep preview acceptance on one version tuple prerelease-default

const semver = require('semver')

const sameTuple = semver.satisfies(
  '1.2.3-beta.4', '>=1.2.3-beta.2 <2.0.0'
) // true
const nextTuple = semver.satisfies(
  '1.2.4-beta.1', '>=1.2.3-beta.2 <2.0.0'
) // false

Documentation-based, unexecuted illustration. Default prerelease matching requires a prerelease comparator with the same major, minor and patch. A later preview does not inherit that opt-in.

Accept previews within explicit bounds prerelease-opt-in

const semver = require('semver')

const version = '1.3.0-beta.1'
const range = '>=1.2.3 <2.0.0'
const stablePolicy = semver.satisfies(version, range) // false
const previewPolicy = semver.satisfies(version, range, {
  includePrerelease: true
}) // true

Documentation-based, unexecuted illustration. includePrerelease removes the extra prerelease exclusion. The ordinary comparator bounds still apply.

Select from a supplied release list select-available-version

const semver = require('semver')

const available = ['1.2.3', '1.9.0', '2.0.0']
const selected = semver.maxSatisfying(available, '^1.2.3')
if (selected === null) throw new Error('No acceptable release')
console.log(selected) // '1.9.0'

Documentation-based, unexecuted illustration. maxSatisfying only chooses from your list and returns null if nothing matches. It does not query npm or download the selected package.

Sort numeric components in order sort-by-precedence

const semver = require('semver')

const versions = ['1.10.0', '1.2.0', '1.3.0-beta.1']
const ordered = [...versions].sort(semver.compare)
console.log(ordered)
// ['1.2.0', '1.3.0-beta.1', '1.10.0']

Documentation-based, unexecuted illustration. compare sorts by semantic-version precedence. A preview can appear in this ordering even when your default range policy would exclude it.

Distinguish precedence from artifact labels separate-build-metadata

const semver = require('semver')

const a = '1.2.3+build.1'
const b = '1.2.3+build.2'
const samePrecedence = semver.compare(a, b) === 0 // true
const buildOrder = semver.compareBuild(a, b) // -1

Documentation-based, unexecuted illustration. compare ignores build metadata for precedence. compareBuild considers it when versions are otherwise equal. Build ordering does not establish artifact equivalence.

Keep the original before coercion coerce-imported-text

const semver = require('semver')

const original = '4.6.3.9.2-alpha2'
const parsed = semver.coerce(original)
if (parsed === null) throw new Error('No version found')
const normalized = parsed.version // '4.6.3'
console.log({ original, normalized })

Documentation-based, unexecuted illustration. coerce intentionally ignores surrounding text and truncates extra components. Use valid when your input contract requires an already formed version.

Generate the next preview label increment-preview

const semver = require('semver')

const next = semver.inc('1.2.3', 'prerelease', 'beta')
if (next === null) throw new Error('Could not increment version')
console.log(next) // '1.2.4-beta.0'

Documentation-based, unexecuted illustration. The documented identifier overload supplies the beta prefix. This computes a version string. Your script must still write metadata, test the release and publish it separately.

Alternatives

PackageRegistryPick it when
compare-versionsnpmConsider compare-versions when the job is comparing version strings as greater, equal or lesser. Its registry description establishes that scope. This guide does not establish equivalence with semver's complete range grammar.
semver-regexnpmConsider semver-regex when the job is matching semantic-version text. Its registry description promises a regular expression for that task. Choose a range evaluator instead when the decision is whether a version satisfies a policy.

More infra guides

boto3 · opentelemetry-api · @opentelemetry/api · psutil · distro · @aws-sdk/client-s3 · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.