Skip to content

didrod205/verspec

verspec

Semantic Versioning done right — parse, compare, sort and range-match versions in ~2 KB, with zero dependencies.

npm version bundle size CI types license

Does 1.2.3-beta.11 come before or after 1.2.3-beta.2? Does 1.2.3-rc.1 satisfy ^1.0.0? These are spec questions with exact answers — and exactly the kind of fiddly rule that's easy to get wrong by hand. verspec implements SemVer 2.0.0 precisely, including prerelease precedence and the prerelease-in-range rule.

import { compare, satisfies, sort } from "verspec";

compare("1.2.3-beta.2", "1.2.3-beta.11"); // -1  (numeric identifiers compare numerically)
satisfies("1.2.3", "^1.0.0");             // true
satisfies("1.2.3-rc.1", "^1.0.0");        // false (prereleases don't leak into plain ranges)
sort(["1.10.0", "1.2.0", "1.0.0-rc.1"]);  // ["1.0.0-rc.1", "1.2.0", "1.10.0"]

Why verspec?

  • 📏 Spec-accurate. Passes the canonical semver.org precedence chain (alpha < alpha.1 < alpha.beta < beta < beta.2 < beta.11 < rc.1 < release) and the prerelease-in-range rule that trips up naive comparisons.
  • 🎯 Full range syntax. ^, ~, x-ranges, partials, hyphen ranges (1 - 2), comparator sets (>=1.2 <2), and || unions.
  • 🪶 ~2 KB gzipped, zero dependencies. A fraction of the size of the classic semver package.
  • 🧩 Complete toolkit. parse, valid, compare, eq/gt/lt/…, sort/rsort, satisfies, maxSatisfying/minSatisfying, inc.
  • 🌍 Runs everywhere. Node 18+, Deno, Bun, Workers and the browser.
  • 🛡️ Type-safe. Written in TypeScript, ships full declarations.

Install

npm install verspec
# or: pnpm add verspec  /  yarn add verspec  /  bun add verspec

Ships ESM and CommonJS:

import { satisfies } from "verspec";        // ESM / TypeScript
const { satisfies } = require("verspec");   // CommonJS

Usage

Parse & validate

parse("1.2.3-beta.1+build.5");
// { major: 1, minor: 2, patch: 3, prerelease: ["beta", 1], build: ["build", "5"] }

valid("v1.2.3");  // "1.2.3"
valid("1.2");     // null

Compare & sort

compare("2.0.0", "1.9.9");       // 1
gt("2.0.0", "1.0.0");            // true
lte("1.0.0-alpha", "1.0.0");     // true

sort(["1.10.0", "1.2.0", "1.1.0"]);  // ["1.1.0", "1.2.0", "1.10.0"]
rsort(versions);                     // descending

Ranges

satisfies("1.2.9", "~1.2.3");        // true
satisfies("0.3.0", "^0.2.3");        // false
satisfies("1.2.7", "1.2.x");         // true
satisfies("2.3.4", "1.2.3 - 2.3.4"); // true
satisfies("3.1.0", "^1 || ^3");      // true

maxSatisfying(["1.2.0", "1.2.5", "1.3.0"], "~1.2.0"); // "1.2.5"
validRange(">=1.0.0 <2.0.0 || 3.x");                  // true

Prerelease handling

By default, a prerelease only satisfies a range that explicitly targets the same major.minor.patch with a prerelease — matching npm's behavior. Opt in with includePrerelease:

satisfies("1.2.3-beta", "^1.0.0");                          // false
satisfies("1.2.3-beta", "^1.2.3-alpha");                    // true
satisfies("1.2.3-beta", "^1.0.0", { includePrerelease: true }); // true

Increment

inc("1.2.3", "minor");              // "1.3.0"
inc("1.2.3", "prerelease");         // "1.2.4-0"
inc("1.2.3-beta.1", "prerelease");  // "1.2.3-beta.2"
inc("1.2.3", "preminor", "beta");   // "1.3.0-beta.0"

API

Function Description
parse(v) / valid(v) / format(s) Parse, validate, render.
compare(a, b) -1 | 0 | 1 by SemVer precedence (build ignored).
eq neq gt gte lt lte Boolean comparisons.
sort(list) / rsort(list) Ascending / descending sort.
satisfies(v, range, opts?) Range test.
validRange(range) Is the range parseable?
maxSatisfying / minSatisfying(list, range, opts?) Best match.
inc(v, release, identifier?) Bump major/minor/patch/pre*.
Range The parsed-range class, if you want to reuse it.

Comparison

verspec hand-rolled compare the classic semver pkg
Prerelease precedence ⚠️
Full range syntax
Prerelease-in-range rule
Zero dependencies ⚠️
~2 KB gzipped

Contributing

Contributions are very welcome! Please read CONTRIBUTING.md and our Code of Conduct.

git clone https://github.com/didrod205/verspec.git
cd verspec
npm install
npm test

💖 Sponsor

verspec is free and MIT-licensed, built and maintained in spare time. If it saved you from a versioning headache, please consider supporting it — every bit helps keep the project healthy.

  • Star this repo — the simplest, free way to help others discover it.
  • 🍋 Sponsor via Lemon Squeezy — one-time or recurring support.

Sponsoring? Open an issue and we'll add your name/logo here. Thank you! 🙏

License

MIT © verspec contributors

About

Tiny zero-dependency SemVer toolkit — parse, compare, sort & range-match versions with correct prerelease precedence. ~2KB.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors