semver

Semantic Versioning 2.0.0: parse, compare, sort and match version ranges. Pure - no capabilities.

ecko get github.com/ecko-lang/semver
import semver

Pure computation: it declares no capabilities, so it cannot touch the network, the filesystem or the environment.

Version 0.10.1 - source - MIT.


fail(message)

The error every entry point raises for input that is not a version.

is_numeric(s)

Is s a run of one or more ASCII digits?

is_ident(s)

Identifier characters allowed in a pre-release or build part: alphanumerics and hyphen. Anything else - underscore, space, dot - ends the identifier.

numeric_field(s, what)

A numeric field of the version core. Rejects a leading zero, so "01.1.1" is invalid rather than quietly becoming 1.1.1.

identifiers(s, numeric_matters, what)

Split a pre-release or build string on dots, checking each identifier. Numeric pre-release identifiers become ints so they compare numerically; build identifiers stay text, since build metadata is never compared.

identifier(p, numeric_matters, what)

One identifier from a dot-separated list.

parse(text)

parse("1.2.3-rc.1+build.5") -> { major, minor, patch, prerelease, build }. Raises { kind: "semver" } for anything that is not a valid version.

valid(text)

Is text a valid version? The total form of parse.

string_of(p)

Render a parsed version back to text, build metadata included.

cmp_int(a, b)

-1, 0 or 1 for a < b, a == b, a > b.

cmp_identifier(a, b)

Compare two pre-release identifiers. Numeric always ranks below alphanumeric, and two numerics compare as numbers (spec §11.4.3).

cmp_prerelease(a, b)

Compare two pre-release lists. An empty list means "this is a release", which outranks any pre-release (§11.3); otherwise identifiers are compared left to right and a longer list wins the tie (§11.4.4).

compare(a, b)

compare(a, b) -> -1, 0 or 1. Accepts text or already-parsed versions. Build metadata is ignored, exactly as the spec requires (§10).

sort(versions)

Ascending order by precedence.

sort_with takes the comparator directly. sort_by could not express this: a pre-release list mixes numeric and alphanumeric identifiers whose ordering depends on their types, which is not a value any key function can return.

eq(a, b)

a == b by precedence, ignoring build metadata.

gt(a, b)

a > b by precedence.

lt(a, b)

a < b by precedence.

inc(text, part)

inc("1.2.3", "minor") -> "1.3.0". Bumping drops any pre-release and build metadata: they described the version being left behind, not the new one.

parse_range(text)

Expand a range string into alternatives, each a list of comparators. { op, version }, where op is one of >= > <= < =.

comparators(alt)

One alternative: whitespace-separated terms, each expanded to comparators.

expand_term(term)

A single term to the comparators it stands for. ^ and ~ and * are shorthand for a pair of bounds; the explicit operators pass through.

strip_op(term, n)

Drop an n-character operator prefix.

caret(text)

^1.2.3 allows changes that do not modify the leftmost non-zero number, so the upper bound moves depending on where that digit is: ^1.2.3 stops at 2.0.0, ^0.2.3 at 0.3.0, ^0.0.3 at 0.0.4.

tilde(text)

~1.2.3 allows patch-level changes: at least 1.2.3, below 1.3.0.

matches_comparator(version, c)

Does one comparator hold for version?

satisfies(version, range)

satisfies("1.5.0", "^1.2.3") -> true.

A pre-release only ever matches a range that mentions one at the same major.minor.patch. Without that rule ^1.0.0 would quietly accept 2.0.0-alpha, which is the behaviour every package ecosystem regrets.

alternative_holds(v, version, alt)

Every comparator in an alternative must hold, plus the pre-release rule.

mentions_same_prerelease(v, c)

Does this comparator name a pre-release on the same core version?

max_satisfying(versions, range)

The highest version in versions that satisfies range, or null.

min_satisfying(versions, range)

The lowest version in versions that satisfies range, or null.