@hyperfrontend/versioning/semver

semver/

Semantic versioning utilities for parsing, comparing, formatting, and incrementing versions.

Overview

Complete implementation of the Semantic Versioning 2.0.0 specification. Parsing uses character-by-character state machines for predictable O(n) performance.

Usage Examples

Parsing Versions

import { parseVersion, parseVersionOrThrow, coerceVersion } from '@hyperfrontend/versioning'

// Safe parsing (returns null on invalid)
const v1 = parseVersion('1.2.3') // SemVer { major: 1, minor: 2, patch: 3 }
const v2 = parseVersion('invalid') // null

// Strict parsing (throws on invalid)
const v3 = parseVersionOrThrow('2.0.0-beta.1')

// Coerce with best effort
const v4 = coerceVersion('v1.2.3') // strips 'v' prefix
const v5 = coerceVersion('1.2') // normalizes to 1.2.0

Comparing Versions

import { compare, gt, lt, satisfies, parseVersion, parseRange } from '@hyperfrontend/versioning'

const a = parseVersion('1.0.0')!
const b = parseVersion('2.0.0')!

compare(a, b) // -1 (a < b)
gt(b, a) // true
lt(a, b) // true

// Range satisfaction
const range = parseRange('^1.0.0')!
satisfies(parseVersion('1.5.0')!, range) // true
satisfies(parseVersion('2.0.0')!, range) // false

Incrementing Versions

import { bump, parseVersion, format } from '@hyperfrontend/versioning'

const version = parseVersion('1.2.3')!

format(bump(version, 'major')) // '2.0.0'
format(bump(version, 'minor')) // '1.3.0'
format(bump(version, 'patch')) // '1.2.4'
format(bump(version, 'prerelease')) // '1.2.4-0'

Sorting Versions

import { sort, max, min, parseVersion, format } from '@hyperfrontend/versioning'

const versions = ['2.0.0', '1.0.0', '1.5.0'].map((raw) => parseVersion(raw)!)

sort(versions).map(format) // ['1.0.0', '1.5.0', '2.0.0']
format(max(versions)!) // '2.0.0'
format(min(versions)!) // '1.0.0'

Design Principles

  1. Immutable: All operations return new objects
  2. Pure Functions: No side effects, deterministic output
  3. No Regex: Character-by-character parsing eliminates ReDoS
  4. Null Safety: Parse functions return null on invalid input
  5. Factory Pattern: Use create* functions for object construction

See Also

API Reference§

ƒ Functions

§function

coerceVersion(input: string): SemVer

Attempts to coerce a string into a valid semver. More lenient than parseVersion - accepts partial versions.
Parameters
NameTypeDescription
§input
stringThe string to coerce
Returns
SemVer
The parsed SemVer or null if coercion failed
Example
Coerce partial versions to valid semver
coerceVersion('1') // { major: 1, minor: 0, patch: 0, ... }
coerceVersion('1.2') // { major: 1, minor: 2, patch: 0, ... }
coerceVersion('v2.0') // { major: 2, minor: 0, patch: 0, ... }
§function

compare(a: SemVer, b: SemVer): -1 | 0 | 1

Compares two semantic versions.
Parameters
NameTypeDescription
SemVerFirst version
SemVerSecond version
Returns
-1 | 0 | 1
-1 if a < b, 0 if a == b, 1 if a > b
Example
Compare two semantic versions
compare(parseVersion('1.0.0'), parseVersion('2.0.0')) // -1
compare(parseVersion('1.0.0'), parseVersion('1.0.0')) // 0
compare(parseVersion('2.0.0'), parseVersion('1.0.0')) // 1
§function

createAnyRange(): Range

Creates a range that matches any version.
Returns
Range
A Range matching any version (*)
Example

Create a range that matches any version

const anyRange = createAnyRange()
satisfies(parseVersionStrict('999.999.999'), anyRange) // => true
§function

createComparator(operator: RangeOperator, version: SemVer): Comparator

Creates a new Comparator.
Parameters
NameTypeDescription
§operator
RangeOperatorThe comparison operator
§version
SemVerThe version to compare against
Returns
Comparator
A new Comparator
Example

Create a comparator for version comparison

createComparator('>=', parseVersionStrict('1.0.0'))
// => { operator: '>=', version: { major: 1, minor: 0, patch: 0, ... } }
§function

createComparatorSet(comparators: unknown): ComparatorSet

Creates a new ComparatorSet.
Parameters
NameTypeDescription
§comparators
unknownArray of comparators (AND logic)
Returns
ComparatorSet
A new ComparatorSet
Example

Create a comparator set with AND logic

createComparatorSet([gte100, lt200]) // AND: >=1.0.0 AND <2.0.0
§function

createExactRange(version: SemVer): Range

Creates a range that matches exactly one version.
Parameters
NameTypeDescription
§version
SemVerThe exact version to match
Returns
Range
A Range matching exactly the specified version
Example

Create a range that matches exactly one version

const exact = createExactRange(parseVersionStrict('1.2.3'))
satisfies(parseVersionStrict('1.2.3'), exact) // => true
satisfies(parseVersionStrict('1.2.4'), exact) // => false
§function

createFirstRelease(): SemVer

Creates a SemVer representing version 1.0.0.
Returns
SemVer
A SemVer at version 1.0.0
Example

Create first 1.0.0 release version

const first = createFirstRelease()
format(first) // => '1.0.0'
§function

createInitialVersion(): SemVer

Creates a SemVer representing version 0.0.0.
Returns
SemVer
A SemVer at version 0.0.0
Example

Create initial 0.0.0 version

const initial = createInitialVersion()
format(initial) // => '0.0.0'
§function

createRange(sets: unknown, raw?: string): Range

Creates a new Range.
Parameters
NameTypeDescription
§sets
unknownArray of comparator sets (OR logic)
§raw?
stringOriginal raw string
Returns
Range
A new Range
Example

Create a range with OR logic between sets

createRange([set1, set2], '>=1.0.0 || >=2.0.0 <3.0.0')
§function

createSemVer(options: Partial<SemVer> & RequiredVersionComponents): SemVer

Creates a new SemVer object.
Parameters
NameTypeDescription
§options
Partial<SemVer> & RequiredVersionComponentsVersion components
Returns
SemVer
A new SemVer object
Example

Create a SemVer object from components

createSemVer({ major: 1, minor: 2, patch: 3 })
// => { major: 1, minor: 2, patch: 3, prerelease: [], build: [] }
createSemVer({ major: 1, minor: 0, patch: 0, prerelease: ['beta', '1'] })
// => 1.0.0-beta.1
§function

diff(older: SemVer, newer: SemVer): BumpType

Calculates the difference type between two versions.
Parameters
NameTypeDescription
§older
SemVerThe older version
§newer
SemVerThe newer version
Returns
BumpType
The type of difference, or null if versions are equal
Example
Calculate the difference type between two versions
diff(parseVersion('1.0.0'), parseVersion('2.0.0')) // 'major'
diff(parseVersion('1.0.0'), parseVersion('1.1.0')) // 'minor'
diff(parseVersion('1.0.0'), parseVersion('1.0.1')) // 'patch'
§function

eq(a: SemVer, b: SemVer): boolean

Checks if two versions are equal (ignoring build metadata).
Parameters
NameTypeDescription
SemVerFirst version
SemVerSecond version
Returns
boolean
True if versions are equal
Example

Check if two versions are equal

eq(parseVersionStrict('1.0.0'), parseVersionStrict('1.0.0')) // => true
eq(parseVersionStrict('1.0.0'), parseVersionStrict('1.0.1')) // => false
§function

format(version: SemVer): string

Converts a SemVer to its canonical string representation.
Parameters
NameTypeDescription
§version
SemVerThe version to format
Returns
string
The version string (e.g., "1.2.3-alpha.1+build.123")
Example

Format a version to its canonical string

format(parseVersionStrict('1.2.3')) // => '1.2.3'
format(createSemVer({ major: 1, minor: 0, patch: 0, prerelease: ['beta', '1'] }))
// => '1.0.0-beta.1'
§function

formatComparator(comparator: Comparator): string

Converts a Comparator to its string representation.
Parameters
NameTypeDescription
§comparator
ComparatorThe comparator to format
Returns
string
The comparator string (e.g., ">=1.0.0")
Example

Format a comparator to its string representation

formatComparator(createComparator('>=', parseVersionStrict('1.0.0')))
// => '>=1.0.0'
§function

formatRange(range: Range): string

Converts a Range to its string representation.
Parameters
NameTypeDescription
§range
RangeThe range to format
Returns
string
The range string
Example

Format a range to its string representation

formatRange(parseRangeStrict('^1.0.0')) // => '^1.0.0'
formatRange(createAnyRange()) // => '*'
§function

formatSimple(version: SemVer): string

Converts a SemVer to a string without prerelease/build.
Parameters
NameTypeDescription
§version
SemVerThe version to format
Returns
string
The version string (e.g., "1.2.3")
Example

Format version without prerelease/build metadata

formatSimple(parseVersionStrict('1.2.3-beta.1+build')) // => '1.2.3'
§function

gt(a: SemVer, b: SemVer): boolean

Checks if a > b.
Parameters
NameTypeDescription
SemVerFirst version to compare
SemVerSecond version to compare
Returns
boolean
True if a is greater than b
Example

Check if version a is greater than b

gt(parseVersionStrict('2.0.0'), parseVersionStrict('1.0.0')) // => true
gt(parseVersionStrict('1.0.0'), parseVersionStrict('2.0.0')) // => false
§function

gte(a: SemVer, b: SemVer): boolean

Checks if a >= b.
Parameters
NameTypeDescription
SemVerFirst version to compare
SemVerSecond version to compare
Returns
boolean
True if a is greater than or equal to b
Example

Check if version a is greater than or equal to b

gte(parseVersionStrict('2.0.0'), parseVersionStrict('1.0.0')) // => true
gte(parseVersionStrict('1.0.0'), parseVersionStrict('1.0.0')) // => true
§function

increment(version: SemVer, type: BumpType, prereleaseId?: string): SemVer

Increments a version based on the bump type.
Parameters
NameTypeDescription
§version
SemVerThe version to increment
§type
BumpTypeThe type of bump (major, minor, patch, etc.)
§prereleaseId?
stringOptional prerelease identifier for prerelease bumps
Returns
SemVer
A new incremented SemVer
Example
Increment version by bump type
increment(parseVersion('1.2.3'), 'minor') // 1.3.0
increment(parseVersion('1.2.3'), 'major') // 2.0.0
increment(parseVersion('1.2.3'), 'prerelease', 'alpha') // 1.2.4-alpha.0
§function

incrementPrerelease(version: SemVer, id?: string): SemVer

Increments the prerelease portion of a version.
Parameters
NameTypeDescription
§version
SemVerThe version to increment
§id?
stringOptional prerelease identifier
Returns
SemVer
A new version with incremented prerelease
Example

Increment the prerelease portion of a version

incrementPrerelease(parseVersionStrict('1.0.0')) // => 1.0.1-alpha.0
incrementPrerelease(parseVersionStrict('1.0.0-alpha.0')) // => 1.0.0-alpha.1
incrementPrerelease(parseVersionStrict('1.0.0'), 'beta') // => 1.0.1-beta.0
§function

isPrerelease(version: SemVer): boolean

Checks if the version has prerelease identifiers.
Parameters
NameTypeDescription
§version
SemVerThe version to check
Returns
boolean
True if version has prerelease identifiers
Example

Check if version has prerelease identifiers

isPrerelease(parseVersionStrict('1.0.0-beta.1')) // => true
isPrerelease(parseVersionStrict('1.0.0')) // => false
§function

isStable(version: SemVer): boolean

Checks if the version is a stable release (>= 1.0.0 with no prerelease).
Parameters
NameTypeDescription
§version
SemVerThe version to check
Returns
boolean
True if version is stable
Example

Check if version is a stable release

isStable(parseVersionStrict('1.0.0')) // => true
isStable(parseVersionStrict('0.9.0')) // => false (< 1.0.0)
isStable(parseVersionStrict('1.0.0-beta')) // => false (prerelease)
§function

isWildcard(range: Range): boolean

Checks if a range represents a wildcard/any match.
Parameters
NameTypeDescription
§range
RangeThe range to check
Returns
boolean
True if the range matches any version
Example

Check if a range represents a wildcard

isWildcard(parseRangeStrict('*')) // => true
isWildcard(parseRangeStrict('^1.0.0')) // => false
§function

lt(a: SemVer, b: SemVer): boolean

Checks if a < b.
Parameters
NameTypeDescription
SemVerFirst version to compare
SemVerSecond version to compare
Returns
boolean
True if a is less than b
Example

Check if version a is less than b

lt(parseVersionStrict('1.0.0'), parseVersionStrict('2.0.0')) // => true
lt(parseVersionStrict('2.0.0'), parseVersionStrict('1.0.0')) // => false
§function

lte(a: SemVer, b: SemVer): boolean

Checks if a <= b.
Parameters
NameTypeDescription
SemVerFirst version to compare
SemVerSecond version to compare
Returns
boolean
True if a is less than or equal to b
Example

Check if version a is less than or equal to b

lte(parseVersionStrict('1.0.0'), parseVersionStrict('1.0.0')) // => true
lte(parseVersionStrict('1.0.0'), parseVersionStrict('2.0.0')) // => true
§function

max(versions: unknown): SemVer

Returns the maximum version from an array.
Parameters
NameTypeDescription
§versions
unknownArray of versions
Returns
SemVer
The maximum version, or null if array is empty
Example

Get the maximum version from an array

const versions = [parseVersionStrict('1.0.0'), parseVersionStrict('2.0.0')]
max(versions) // => { major: 2, minor: 0, patch: 0, ... }
max([]) // => null
§function

maxSatisfying(versions: unknown, range: Range): SemVer

Finds the maximum version that satisfies a range.
Parameters
NameTypeDescription
§versions
unknownArray of versions to check
§range
RangeRange to test against
Returns
SemVer
The maximum satisfying version, or null if none satisfy
Example

Find the maximum version satisfying a range

const versions = ['1.0.0', '1.5.0', '2.0.0'].map(parseVersionStrict)
maxSatisfying(versions, parseRangeStrict('^1.0.0'))
// => { major: 1, minor: 5, patch: 0, ... }
§function

min(versions: unknown): SemVer

Returns the minimum version from an array.
Parameters
NameTypeDescription
§versions
unknownArray of versions
Returns
SemVer
The minimum version, or null if array is empty
Example

Get the minimum version from an array

const versions = [parseVersionStrict('1.0.0'), parseVersionStrict('2.0.0')]
min(versions) // => { major: 1, minor: 0, patch: 0, ... }
min([]) // => null
§function

minSatisfying(versions: unknown, range: Range): SemVer

Finds the minimum version that satisfies a range.
Parameters
NameTypeDescription
§versions
unknownArray of versions to check
§range
RangeRange to test against
Returns
SemVer
The minimum satisfying version, or null if none satisfy
Example

Find the minimum version satisfying a range

const versions = ['1.0.0', '1.5.0', '2.0.0'].map(parseVersionStrict)
minSatisfying(versions, parseRangeStrict('^1.0.0'))
// => { major: 1, minor: 0, patch: 0, ... }
§function

neq(a: SemVer, b: SemVer): boolean

Checks if a != b.
Parameters
NameTypeDescription
SemVerFirst version to compare
SemVerSecond version to compare
Returns
boolean
True if versions are not equal
Example

Check if two versions are not equal

neq(parseVersionStrict('1.0.0'), parseVersionStrict('2.0.0')) // => true
neq(parseVersionStrict('1.0.0'), parseVersionStrict('1.0.0')) // => false
§function

parseRange(input: string): ParseRangeResult

Parses a semver range string.
Supports:
  • Exact: 1.2.3, =1.2.3
  • Comparators: >1.0.0, >=1.0.0, <2.0.0, <=2.0.0
  • Caret: ^1.2.3 (compatible with version)
  • Tilde: ~1.2.3 (approximately equivalent)
  • X-ranges: 1.x, 1.2.x, *
  • Hyphen ranges: 1.0.0 - 2.0.0
  • OR: 1.0.0 || 2.0.0
  • AND: >=1.0.0 <2.0.0
Parameters
NameTypeDescription
§input
stringThe range string to parse
Returns
ParseRangeResult
A ParseRangeResult with the parsed range or error
Example

Parse semver range strings

parseRange('^1.0.0') // => { success: true, range: ... }
parseRange('>=1.0.0 <2.0.0') // => { success: true, range: ... }
parseRange('1.0.0 || 2.0.0') // => { success: true, range: ... }
§function

parseRangeStrict(input: string): Range

Parses a range string, throwing on invalid input.
Parameters
NameTypeDescription
§input
stringThe range string to parse
Returns
Range
The parsed Range
Example

Parse range with strict validation

const range = parseRangeStrict('^1.0.0')
parseRangeStrict('invalid range!!!') // throws Error
§function

parseVersion(input: string): ParseVersionResult

Parses a semantic version string.
Accepts versions in the format: MAJOR.MINOR.PATCH[-prerelease][+build] Optional leading 'v' or '=' prefixes are stripped.
Parameters
NameTypeDescription
§input
stringThe version string to parse
Returns
ParseVersionResult
A ParseVersionResult with the parsed version or error
Example
Parse a semantic version string
parseVersion('1.2.3') // { success: true, version: { major: 1, minor: 2, patch: 3, ... } }
parseVersion('v1.0.0-alpha.1+build.123') // { success: true, ... }
parseVersion('invalid') // { success: false, error: '...' }
§function

parseVersionStrict(input: string): SemVer

Parses a version string, throwing on invalid input.
Parameters
NameTypeDescription
§input
stringThe version string to parse
Returns
SemVer
The parsed SemVer
Example

Parse version with strict validation

const v = parseVersionStrict('1.2.3')
// => { major: 1, minor: 2, patch: 3, prerelease: [], build: [] }
parseVersionStrict('invalid') // throws Error
§function

satisfies(version: SemVer, range: Range): boolean

Checks if a version satisfies a range.
Parameters
NameTypeDescription
§version
SemVerVersion to check
§range
RangeRange to test against
Returns
boolean
True if version satisfies the range
Example
Check if version satisfies a range
satisfies(parseVersion('1.2.3'), parseRange('^1.0.0')) // true
satisfies(parseVersion('2.0.0'), parseRange('^1.0.0')) // false
§function

satisfiesComparator(version: SemVer, comparator: Comparator): boolean

Checks if a version satisfies a comparator.
Parameters
NameTypeDescription
§version
SemVerVersion to check
§comparator
ComparatorComparator to test against
Returns
boolean
True if version satisfies the comparator
Example

Check if version satisfies a comparator

const gte100 = createComparator('>=', parseVersionStrict('1.0.0'))
satisfiesComparator(parseVersionStrict('2.0.0'), gte100) // => true
satisfiesComparator(parseVersionStrict('0.9.0'), gte100) // => false
§function

sort(versions: unknown): SemVer[]

Sorts an array of versions in ascending order.
Parameters
NameTypeDescription
§versions
unknownArray of versions to sort
Returns
SemVer[]
A new sorted array
Example
Sort versions in ascending order
sort([v2, v1, v3]) // [v1, v2, v3]
§function

sortDescending(versions: unknown): SemVer[]

Sorts an array of versions in descending order.
Parameters
NameTypeDescription
§versions
unknownArray of versions to sort
Returns
SemVer[]
A new sorted array
Example
Sort versions in descending order
sortDescending([v1, v3, v2]) // [v3, v2, v1]
§function

stripBuild(version: SemVer): SemVer

Returns a new version with build metadata stripped.
Parameters
NameTypeDescription
§version
SemVerThe version to strip
Returns
SemVer
A new SemVer without build metadata
Example

Strip build metadata from version

const v = parseVersionStrict('1.0.0+build.123')
format(stripBuild(v)) // => '1.0.0'
§function

stripPrerelease(version: SemVer): SemVer

Returns a new version with prerelease identifiers stripped.
Parameters
NameTypeDescription
§version
SemVerThe version to strip
Returns
SemVer
A new SemVer without prerelease identifiers
Example

Strip prerelease identifiers from version

const v = parseVersionStrict('1.0.0-beta.1')
format(stripPrerelease(v)) // => '1.0.0'

◈ Interfaces

§interface

Comparator

A single comparator in a range set.
Examples:
  • >=1.2.3 -> { operator: '>=', version: { major: 1, minor: 2, patch: 3 } }
  • ^1.2.0 -> { operator: '^', version: { major: 1, minor: 2, patch: 0 } }
Properties
§readonly operator:RangeOperatorThe comparison operator
§readonly version:SemVerThe version to compare against
§interface

ComparatorSet

A set of comparators that must all be satisfied. Represents the space-separated part of a range (AND logic).
Example: ">=1.0.0 <2.0.0" -> two comparators in one set
Properties
§readonly comparators:unknownArray of comparators that must all be satisfied (AND logic).
§interface

ParseRangeResult

Result of parsing a range string.
Properties
§readonly success:booleanWhether parsing succeeded
§readonly range?:RangeThe parsed range (if successful)
§readonly error?:stringError message (if failed)
§interface

ParseVersionResult

Result of parsing a version string.
Properties
§readonly success:booleanWhether parsing succeeded
§readonly version?:SemVerThe parsed version (if successful)
§readonly error?:stringError message (if failed)
§interface

Range

A version range that can contain multiple comparator sets. Represents the || separated parts (OR logic).
Example: "^1.0.0 || ^2.0.0" -> two comparator sets
Properties
§readonly sets:unknownComparator sets (OR logic between sets, AND logic within)
§readonly raw?:stringOriginal raw string if parsed
§interface

SemVer

Semantic Version
A version number in the format MAJOR.MINOR.PATCH with optional prerelease and build metadata.
Properties
§readonly major:numberMajor version - incremented for breaking changes
§readonly minor:numberMinor version - incremented for new features
§readonly patch:numberPatch version - incremented for bug fixes
§readonly prerelease:unknownPrerelease identifiers (e.g., ["alpha", "1"])
§readonly build:unknownBuild metadata identifiers (e.g., ["build", "123"])
§readonly raw?:stringOriginal raw string if parsed

◆ Types

§type

BumpType

Bump type for version increments.
type BumpType = "major" | "minor" | "patch" | "premajor" | "preminor" | "prepatch" | "prerelease" | "none"
§type

RangeOperator

Comparison operator for version ranges.
type RangeOperator = "=" | ">" | ">=" | "<" | "<=" | "^" | "~"