Basic Usage
import { semver } from "bun";
// Parse version
const version = semver.parse("1.2.3");
console.log(version); // { major: 1, minor: 2, patch: 3 }
// Compare versions
console.log(semver.satisfies("1.2.3", "^1.0.0")); // true
console.log(semver.satisfies("2.0.0", "^1.0.0")); // false
Version Parsing
Basic Versions
import { semver } from "bun";
// Major.minor.patch
const v1 = semver.parse("1.2.3");
console.log(v1.major, v1.minor, v1.patch); // 1 2 3
// With v prefix
const v2 = semver.parse("v2.0.0");
console.log(v2.major); // 2
Prerelease Versions
// Alpha, beta, rc
const alpha = semver.parse("1.0.0-alpha");
const beta = semver.parse("1.0.0-beta.1");
const rc = semver.parse("2.0.0-rc.1");
console.log(alpha.prerelease); // "alpha"
console.log(beta.prerelease); // "beta.1"
Build Metadata
const version = semver.parse("1.0.0+20230615");
console.log(version.build); // "20230615"
// Both prerelease and build
const full = semver.parse("1.0.0-beta.1+exp.sha.5114f85");
console.log(full.prerelease); // "beta.1"
console.log(full.build); // "exp.sha.5114f85"
Version Comparison
Order Comparison
import { semver } from "bun";
// Greater than
console.log(semver.order("2.0.0", "1.0.0")); // 1
// Less than
console.log(semver.order("1.0.0", "2.0.0")); // -1
// Equal
console.log(semver.order("1.0.0", "1.0.0")); // 0
Comparison Functions
import { semver } from "bun";
console.log(semver.gt("2.0.0", "1.0.0")); // true (greater than)
console.log(semver.gte("2.0.0", "2.0.0")); // true (greater than or equal)
console.log(semver.lt("1.0.0", "2.0.0")); // true (less than)
console.log(semver.lte("1.0.0", "1.0.0")); // true (less than or equal)
console.log(semver.eq("1.0.0", "1.0.0")); // true (equal)
console.log(semver.neq("1.0.0", "2.0.0")); // true (not equal)
Version Ranges
Caret Ranges (^)
Allows changes that don’t modify the left-most non-zero digit:import { semver } from "bun";
// ^1.2.3 := >=1.2.3 <2.0.0
console.log(semver.satisfies("1.2.3", "^1.2.3")); // true
console.log(semver.satisfies("1.3.0", "^1.2.3")); // true
console.log(semver.satisfies("2.0.0", "^1.2.3")); // false
// ^0.2.3 := >=0.2.3 <0.3.0
console.log(semver.satisfies("0.2.3", "^0.2.3")); // true
console.log(semver.satisfies("0.2.4", "^0.2.3")); // true
console.log(semver.satisfies("0.3.0", "^0.2.3")); // false
// ^0.0.3 := >=0.0.3 <0.0.4
console.log(semver.satisfies("0.0.3", "^0.0.3")); // true
console.log(semver.satisfies("0.0.4", "^0.0.3")); // false
Tilde Ranges (~)
Allows patch-level changes:import { semver } from "bun";
// ~1.2.3 := >=1.2.3 <1.3.0
console.log(semver.satisfies("1.2.3", "~1.2.3")); // true
console.log(semver.satisfies("1.2.4", "~1.2.3")); // true
console.log(semver.satisfies("1.3.0", "~1.2.3")); // false
// ~1.2 := >=1.2.0 <1.3.0
console.log(semver.satisfies("1.2.0", "~1.2")); // true
console.log(semver.satisfies("1.2.9", "~1.2")); // true
// ~1 := >=1.0.0 <2.0.0
console.log(semver.satisfies("1.0.0", "~1")); // true
console.log(semver.satisfies("1.9.9", "~1")); // true
Wildcard Ranges (x, X, *)
import { semver } from "bun";
// * := >=0.0.0 (any version)
console.log(semver.satisfies("1.2.3", "*")); // true
// 1.x := >=1.0.0 <2.0.0
console.log(semver.satisfies("1.2.3", "1.x")); // true
console.log(semver.satisfies("2.0.0", "1.x")); // false
// 1.2.x := >=1.2.0 <1.3.0
console.log(semver.satisfies("1.2.3", "1.2.x")); // true
console.log(semver.satisfies("1.3.0", "1.2.x")); // false
Comparison Operators
import { semver } from "bun";
// Greater than
console.log(semver.satisfies("2.0.0", ">1.0.0")); // true
// Greater than or equal
console.log(semver.satisfies("1.0.0", ">=1.0.0")); // true
// Less than
console.log(semver.satisfies("1.0.0", "<2.0.0")); // true
// Less than or equal
console.log(semver.satisfies("1.0.0", "<=1.0.0")); // true
// Equal
console.log(semver.satisfies("1.0.0", "=1.0.0")); // true
Range Combinations
import { semver } from "bun";
// AND (space or &&)
console.log(semver.satisfies("1.2.3", ">=1.0.0 <2.0.0")); // true
console.log(semver.satisfies("1.2.3", ">=1.0.0 && <2.0.0")); // true
// OR (||)
console.log(semver.satisfies("1.0.0", "1.x || 2.x")); // true
console.log(semver.satisfies("2.0.0", "1.x || 2.x")); // true
console.log(semver.satisfies("3.0.0", "1.x || 2.x")); // false
Hyphen Ranges
import { semver } from "bun";
// 1.2.3 - 2.3.4 := >=1.2.3 <=2.3.4
console.log(semver.satisfies("1.2.3", "1.2.3 - 2.3.4")); // true
console.log(semver.satisfies("2.0.0", "1.2.3 - 2.3.4")); // true
console.log(semver.satisfies("2.3.4", "1.2.3 - 2.3.4")); // true
console.log(semver.satisfies("2.3.5", "1.2.3 - 2.3.4")); // false
Prerelease Versions
Prerelease Precedence
import { semver } from "bun";
// Prerelease versions are lower than release versions
console.log(semver.lt("1.0.0-alpha", "1.0.0")); // true
// Prerelease identifiers are compared lexically
console.log(semver.lt("1.0.0-alpha", "1.0.0-beta")); // true
console.log(semver.lt("1.0.0-beta", "1.0.0-rc")); // true
// Numeric identifiers are compared numerically
console.log(semver.lt("1.0.0-alpha.1", "1.0.0-alpha.2")); // true
console.log(semver.lt("1.0.0-alpha.9", "1.0.0-alpha.10")); // true
Prerelease Ranges
import { semver } from "bun";
// Prerelease versions only match if explicitly included
console.log(semver.satisfies("1.0.0-alpha", "1.0.0")); // false
console.log(semver.satisfies("1.0.0-alpha", ">=1.0.0-alpha")); // true
// Range must include prerelease
console.log(semver.satisfies("1.0.0-beta", "^1.0.0-alpha")); // true
console.log(semver.satisfies("1.0.0-beta", "^1.0.0")); // false
Common Use Cases
Package Version Checking
import { semver } from "bun";
function checkDependency(installed: string, required: string): boolean {
return semver.satisfies(installed, required);
}
console.log(checkDependency("2.1.0", "^2.0.0")); // true
console.log(checkDependency("1.9.0", "^2.0.0")); // false
Finding Latest Version
import { semver } from "bun";
function findLatest(versions: string[]): string {
return versions.sort((a, b) => semver.order(b, a))[0];
}
const versions = ["1.0.0", "2.1.0", "1.5.0", "2.0.0"];
console.log(findLatest(versions)); // "2.1.0"
Version Compatibility
import { semver } from "bun";
function isCompatible(
version: string,
minVersion: string,
maxVersion: string,
): boolean {
return (
semver.gte(version, minVersion) &&
semver.lte(version, maxVersion)
);
}
console.log(isCompatible("1.5.0", "1.0.0", "2.0.0")); // true
console.log(isCompatible("2.1.0", "1.0.0", "2.0.0")); // false
Breaking Change Detection
import { semver } from "bun";
function hasBreakingChange(from: string, to: string): boolean {
const v1 = semver.parse(from);
const v2 = semver.parse(to);
return v2.major > v1.major;
}
console.log(hasBreakingChange("1.5.0", "2.0.0")); // true
console.log(hasBreakingChange("1.5.0", "1.6.0")); // false
Increment Version
import { semver } from "bun";
function increment(
version: string,
type: "major" | "minor" | "patch",
): string {
const v = semver.parse(version);
switch (type) {
case "major":
return `${v.major + 1}.0.0`;
case "minor":
return `${v.major}.${v.minor + 1}.0`;
case "patch":
return `${v.major}.${v.minor}.${v.patch + 1}`;
}
}
console.log(increment("1.2.3", "major")); // "2.0.0"
console.log(increment("1.2.3", "minor")); // "1.3.0"
console.log(increment("1.2.3", "patch")); // "1.2.4"
Performance
Bun’s semver is highly optimized:import { semver } from "bun";
const start = performance.now();
for (let i = 0; i < 100_000; i++) {
semver.satisfies("1.2.3", "^1.0.0");
}
console.log(`${performance.now() - start}ms`);
// Typically <50ms for 100k checks
- Bun semver: ~2M ops/sec
- node-semver: ~500k ops/sec
Best Practices
-
Use caret for libraries
// Allow compatible updates semver.satisfies(version, "^1.2.3"); -
Use exact versions for apps
// Lock to specific version semver.satisfies(version, "1.2.3"); -
Be careful with prereleases
// Explicitly handle prereleases if (version.includes("-")) { console.warn("Prerelease version"); } -
Validate versions
try { semver.parse(version); } catch { console.error("Invalid version"); }
API Reference
semver.parse()
Parse a version string:semver.parse(version: string): {
major: number;
minor: number;
patch: number;
prerelease?: string;
build?: string;
}
semver.satisfies()
Check if version satisfies range:semver.satisfies(version: string, range: string): boolean
semver.order()
Compare two versions:semver.order(a: string, b: string): -1 | 0 | 1
Comparison Functions
semver.gt(a: string, b: string): boolean // greater than
semver.gte(a: string, b: string): boolean // greater than or equal
semver.lt(a: string, b: string): boolean // less than
semver.lte(a: string, b: string): boolean // less than or equal
semver.eq(a: string, b: string): boolean // equal
semver.neq(a: string, b: string): boolean // not equal