VERS version ranges
2 minutes read
Ebb parses, normalises, formats, and evaluates VERS (vers:) version ranges offline via @velella/ebb/vers. Every built-in versioning scheme lives in one lookup table in src/vers/schemes.ts.
import {
SUPPORTED_SCHEMES,
formatVers,
normalizeVers,
parseVers,
versContains,
} from "@velella/ebb/vers";
const canonical = normalizeVers("VERS:NPM/ >= 2.0.0 | = 1.0.0 ");
const parsed = parseVers(canonical);
console.log(
JSON.stringify(
{
schemeCount: Object.keys(SUPPORTED_SCHEMES).length,
canonical,
formatted: formatVers(parsed),
matchesV1: versContains(parsed, "1.0.0"),
matchesV15: versContains(parsed, "1.5.0"),
},
null,
2,
),
);
Output:
{
"schemeCount": 10,
"canonical": "vers:npm/1.0.0|>=2.0.0",
"formatted": "vers:npm/1.0.0|>=2.0.0",
"matchesV1": true,
"matchesV15": false
}
Supported schemes
All built-in schemes are defined in SUPPORTED_SCHEMES:
| Scheme | Comparator | Versioning rules |
|---|---|---|
intdot |
intdotScheme |
Dot-separated integers; suffixes after the first non-digit/non-dot character are ignored. |
semver |
semverScheme |
Semantic Versioning 2.0 (build metadata ignored; short v1 / 1.2 prefixes accepted). |
npm |
semverScheme |
Semantic Versioning 2.0. |
cargo |
semverScheme |
Semantic Versioning 2.0. |
golang |
semverScheme |
Semantic Versioning 2.0 with short v1 / 1.2 prefixes. |
composer |
semverScheme |
Semantic Versioning 2.0 with short v1 / 1.2 prefixes. |
pypi |
pep440Scheme |
Python PEP 440 ordering (epochs, pre/post/dev releases, local segments). |
maven |
mavenScheme |
Apache Maven ComparableVersion qualifier and segment rules. |
nuget |
nugetScheme |
NuGet four-part numeric versions and SemVer 2.0 case-insensitive pre-release labels. |
gem |
gemScheme |
RubyGems Gem::Version ordering (pre-release segments sort before releases). |
Parsing or evaluating any scheme not registered in SUPPORTED_SCHEMES throws VersError (an EbbError with code: "invalid-version"), unless added at runtime with registerVersionScheme.
What is not supported
- Unsupported schemes in the upstream suite:
apk,alpm,conan,datetime,gentoo,lexicographic,openssl, andnginxare not built in. The suite skips920non-from_nativevectors for those schemes (716apk,42alpm,47conan,11datetime,48gentoo,12lexicographic,44openssl;nginxappears infrom_nativevectors only). - Native range conversion (
from_native): Ebb does not translate ecosystem-native range expressions (^1.2,~> 2.0, etc.) intovers:strings. The737from_nativevectors in the vendored suite are skipped.
Conformance suite and pass rate
The vendored fixtures in tests/vers/fixtures/ come unchanged from package-url/vers-spec@v1.2.1 (2,721 total vectors).
| Metric | Value | Notes |
|---|---|---|
| Supported schemes pass rate | 1064/1064 (100%) |
Reported on every CI run by tests/vers/spec.test.ts. |
| Documented upstream inconsistencies | 7 |
Verified via conforming alternatives in tests/vers/upstream-inconsistencies.json (4 NuGet pre-release casing differences, 3 PyPI Clause 5.4 contradictions). |
| Canonical round-trips | 30 unique strings |
Verified in tests/vers/roundtrip.test.ts via parseVers(normalizeVers(v)) → formatVers → parseVers. |
| Unsupported-scheme vectors skipped | 920 |
Schemes without a registered comparator (apk, alpm, conan, datetime, gentoo, lexicographic, openssl). |
from_native vectors skipped |
737 |
Native-syntax conversion tests outside Ebb's vers: parser scope. |
Running the suite
Run the full project checks (formatting, TypeScript build, unit tests, and conformance suites):
npm ci
npm run check
To build and run only the VERS suite and related tests:
npm run build --silent
node --test dist/tests/vers/spec.test.js dist/tests/vers/roundtrip.test.js dist/tests/vers/schemes.test.js dist/tests/vers/errors.test.js