SemVer unstable
Immutable Semantic Versioning 2.0.0 values with strict parsing, canonical formatting, spec precedence ordering, and version bumps.
A SemVer has numeric major, minor, and patch components, optional
pre-release identifiers, and optional build metadata. Structural equality
and hashing include build metadata, while Order follows spec precedence
and ignores it. Version ranges live in SemVerRange.
Comparisons
difference
unstableClassifies the change between two versions by release type.
Details
Follows node-semver's diff, so the result names the bump that produces the
higher version from the lower one. Moving to a pre-release adds the pre
prefix, and finalizing a pre-release reports the level it was released at:
1.0.0-1 to 1.0.0 is "major", 1.1.0-1 to 1.1.0 is "minor", and
1.2.3-1 to 1.2.3 is "patch". The result does not depend on argument
order.
Gotchas
Returns None for versions with the same precedence, including versions
that differ only in build metadata.
See
- bump for applying a release type to a version
Signature
declare const difference: { (that: SemVer): (self: SemVer) => Option<ReleaseType>; (self: SemVer, that: SemVer): Option<ReleaseType>;}Example Classifying upgrades
import { Option, SemVer } from "effect"
SemVer.difference(SemVer.parseUnsafe("1.2.3"), SemVer.parseUnsafe("1.3.0")) // => Option.some("minor")SemVer.difference(SemVer.parseUnsafe("1.2.3"), SemVer.parseUnsafe("2.0.0-rc.1")) // => Option.some("premajor")SemVer.difference(SemVer.parseUnsafe("2.0.0-rc.1"), SemVer.parseUnsafe("2.0.0")) // => Option.some("major")SemVer.difference(SemVer.parseUnsafe("1.2.3+a"), SemVer.parseUnsafe("1.2.3+b")) // => Option.none()Constructors
Converts a version, version string, or version components into a SemVer.
Details
Versions are returned unchanged, strings are parsed like parse, and
components are validated like make. Invalid input fails with
SemVerError.
See
- fromInputUnsafe for throwing on invalid input
Signature
declare function fromInput(input: Input): Result<SemVer, SemVerError>Example Accepting flexible version input
import { Result, SemVer } from "effect"
Result.map(SemVer.fromInput("1.2.3-rc.1"), SemVer.format) // => Result.succeed("1.2.3-rc.1")Result.map(SemVer.fromInput({ major: 1, minor: 2, patch: 3 }), SemVer.format) // => Result.succeed("1.2.3")Result.isFailure(SemVer.fromInput({ major: -1, minor: 0, patch: 0 })) // => truefromInputUnsafe
unstableConverts a version, version string, or version components into a SemVer
and throws SemVerError for invalid input.
See
- fromInput for non-throwing conversion
Signature
declare function fromInputUnsafe(input: Input): SemVerCreates a version from its components and throws SemVerError for invalid
components.
Details
Components must be non-negative safe integers. Identifiers must be non-empty and contain only ASCII alphanumerics and hyphens. Digit-only pre-release strings are normalized to numbers and must not have leading zeros.
A SemVer spreads into exactly these components, so make({ ...version, patch: version.patch + 1 }) derives a validated version from an existing
one.
See
- parse for decoding version strings
Signature
declare function make(components: Components): SemVerExample Creating a pre-release version
import { SemVer } from "effect"
SemVer.format(SemVer.make({ major: 1, minor: 0, patch: 0, prerelease: ["beta", "2"] })) // => "1.0.0-beta.2"Parses a strict Semantic Versioning 2.0.0 string.
Details
The input must match the spec grammar exactly. Leading zeros in numeric
components or pre-release identifiers, empty identifiers, and numbers above
Number.MAX_SAFE_INTEGER are rejected.
Gotchas
A v prefix, surrounding whitespace, and partial versions such as 1.2 are
rejected because they are not semantic versions.
See
- parseUnsafe for throwing on invalid input
- format for the inverse operation
Signature
declare function parse(input: string): Result<SemVer, SemVerError>Example Parsing version strings
import { Result, SemVer } from "effect"
Result.isSuccess(SemVer.parse("1.2.3-alpha.1+001")) // => trueResult.isFailure(SemVer.parse("v1.2.3")) // => trueparseUnsafe
unstableParses a strict Semantic Versioning 2.0.0 string and throws SemVerError
for invalid input.
See
- parse for non-throwing parsing
Signature
declare function parseUnsafe(input: string): SemVerConverting
Errors
SemVerError
unstableError raised for invalid version strings, ranges, or components.
See
- isSemVerError for narrowing unknown values
Signature
declare class SemVerError extends YieldableError<this> & { readonly _tag: "SemVerError";} & Readonly<{ readonly input?: string; readonly message: string;}> { constructor(args: { readonly input?: string; readonly message: string; }); readonly "~effect/SemVer/SemVerError": "~effect/SemVer/SemVerError";}Guards
Checks whether a value is a SemVer.
Signature
declare function isSemVer(u: unknown): u is SemVerisSemVerError
unstableChecks whether a value is a SemVerError.
Signature
declare function isSemVerError(u: unknown): u is SemVerErrorInstances
Equivalence
unstableProvides structural equivalence for versions, including build metadata.
See
- Order for precedence that ignores build metadata
Signature
declare const Equivalence: Equ.Equivalence<SemVer>Orders versions by Semantic Versioning precedence.
Details
Major, minor, and patch are compared numerically. A pre-release has lower precedence than its release. Pre-release identifiers are compared left to right: numeric identifiers compare numerically and sort before alphanumeric identifiers, which compare in ASCII order. A longer list of otherwise equal identifiers has higher precedence.
Gotchas
Build metadata is ignored, so versions that differ only in build metadata
compare as 0 even though they are not Equal.
See
- Equivalence for structural equality including build metadata
Signature
declare const Order: order.Order<SemVer>Example Sorting by precedence
import { Array, SemVer } from "effect"
const versions = ["1.0.0", "1.0.0-rc.1", "1.0.0-beta.11", "1.0.0-beta.2", "1.0.0-alpha"].map(SemVer.parseUnsafe)
Array.sort(versions, SemVer.Order).map(SemVer.format) // => ["1.0.0-alpha", "1.0.0-beta.2", "1.0.0-beta.11", "1.0.0-rc.1", "1.0.0"]Models
The numeric components and identifiers of a version.
See
- make for validating components into a version
Signature
interface Components { readonly build?: readonly Array<string>; readonly major: number; readonly minor: number; readonly patch: number; readonly prerelease?: readonly Array<string | number>;}Values accepted by fromInput: a version, a version string literal, or
version components.
See
- fromInput for converting inputs
Signature
type Input = SemVer | VersionString | ComponentsNames of version changes, matching npm's release types.
See
- difference for classifying the change between two versions
Signature
type ReleaseType = "major" | "premajor" | "minor" | "preminor" | "patch" | "prepatch" | "prerelease"Represents a semantic version.
Details
Pre-release identifiers are numbers when they consist only of digits and strings otherwise. Build metadata identifiers are always strings because they may contain leading zeros. Both arrays are empty when absent.
See
Signature
interface SemVer extends Pipeable, Equal, Inspectable { readonly "~effect/SemVer": "~effect/SemVer"; readonly build: readonly Array<string>; readonly major: number; readonly minor: number; readonly patch: number; readonly prerelease: readonly Array<string | number>;}Example Reading version components
import { SemVer } from "effect"
const version = SemVer.parseUnsafe("1.2.3-rc.1+build.5")
version.minor // => 2version.prerelease // => ["rc", 1]version.build // => ["build", "5"]Version string literals accepted by fromInput.
Details
Requires three numeric components without signs or leading zeros, followed
by an optional - pre-release and + build suffix. Component magnitudes
(at most Number.MAX_SAFE_INTEGER) and identifiers are only validated at
runtime.
See
- parse for arbitrary strings
Signature
type VersionString = `${NumericComponent}.${NumericComponent}.${NumericComponent}${"" | `-${string}` | `+${string}`}`Ordering
Constrains a version's precedence to an inclusive range.
Signature
declare const clamp: { (options: { maximum: SemVer; minimum: SemVer; }): (self: SemVer) => SemVer; (self: SemVer, options: { maximum: SemVer; minimum: SemVer; }): SemVer;}Returns the version with higher precedence, preferring the first on ties.
Signature
declare const max: { (that: SemVer): (self: SemVer) => SemVer; (self: SemVer, that: SemVer): SemVer;}Returns the version with lower precedence, preferring the first on ties.
Signature
declare const min: { (that: SemVer): (self: SemVer) => SemVer; (self: SemVer, that: SemVer): SemVer;}Predicates
Checks whether a version's precedence is within an inclusive range.
Signature
declare const between: { (options: { maximum: SemVer; minimum: SemVer; }): (self: SemVer) => boolean; (self: SemVer, options: { maximum: SemVer; minimum: SemVer; }): boolean;}Checks whether two versions are structurally equal, including build metadata.
Signature
declare const equals: { (that: SemVer): (self: SemVer) => boolean; (self: SemVer, that: SemVer): boolean;}Checks whether a version has build metadata.
Details
Build metadata does not affect precedence, but it is part of structural equality.
Signature
declare function hasBuild(self: SemVer): booleanisGreaterThan
unstableChecks whether the first version has higher precedence than the second.
Signature
declare const isGreaterThan: { (that: SemVer): (self: SemVer) => boolean; (self: SemVer, that: SemVer): boolean;}isGreaterThanOrEqualTo
unstableChecks whether the first version has higher or equal precedence than the second.
Signature
declare const isGreaterThanOrEqualTo: { (that: SemVer): (self: SemVer) => boolean; (self: SemVer, that: SemVer): boolean;}isInitialDevelopment
unstableChecks whether a version is in initial development, meaning its major
version is 0.
Details
The SemVer spec treats 0.y.z as initial development where anything may
change at any time and the public API should not be considered stable.
Signature
declare function isInitialDevelopment(self: SemVer): booleanisLessThan
unstableChecks whether the first version has lower precedence than the second.
Signature
declare const isLessThan: { (that: SemVer): (self: SemVer) => boolean; (self: SemVer, that: SemVer): boolean;}isLessThanOrEqualTo
unstableChecks whether the first version has lower or equal precedence than the second.
Signature
declare const isLessThanOrEqualTo: { (that: SemVer): (self: SemVer) => boolean; (self: SemVer, that: SemVer): boolean;}isPrerelease
unstableChecks whether a version has pre-release identifiers.
Signature
declare function isPrerelease(self: SemVer): booleanTransforming
Bumps a version by release type.
When to use
Use when the release type is data, such as a CLI argument, configuration, or the result of difference.
Details
Dispatches to bumpMajor, bumpMinor, bumpPatch, bumpPremajor, bumpPreminor, bumpPrepatch, or bumpPrerelease, with the same semantics.
Gotchas
The pre-release identifier is ignored for "major", "minor", and
"patch".
Signature
declare const bump: { (releaseType: ReleaseType, identifier?: string): (self: SemVer) => SemVer; (self: SemVer, releaseType: ReleaseType, identifier?: string): SemVer;}Example Bumping by a release type from input
import { SemVer } from "effect"
const version = SemVer.parseUnsafe("1.2.3")
SemVer.format(SemVer.bump(version, "minor")) // => "1.3.0"SemVer.format(SemVer.bump(version, "premajor", "rc")) // => "2.0.0-rc.0"Example Defining custom bump rules
import { SemVer } from "effect"
// Always increment patch, even for pre-releases, and keep build metadataconst customBump = (version: SemVer.SemVer, releaseType: SemVer.ReleaseType): SemVer.SemVer => releaseType === "patch" ? SemVer.make({ ...version, patch: version.patch + 1, prerelease: [] }) : SemVer.withBuild(SemVer.bump(version, releaseType), version.build)
SemVer.format(customBump(SemVer.parseUnsafe("1.2.3-rc.1+b"), "patch")) // => "1.2.4+b"SemVer.format(customBump(SemVer.parseUnsafe("1.2.3-rc.1+b"), "minor")) // => "1.3.0+b"Returns the next major release.
Details
Returns the smallest major release with higher precedence, so a pre-release
of a major version, such as 2.0.0-rc.1, becomes 2.0.0. Pre-release
identifiers and build metadata are removed.
Signature
declare function bumpMajor(self: SemVer): SemVerExample Bumping major versions
import { SemVer } from "effect"
SemVer.format(SemVer.bumpMajor(SemVer.parseUnsafe("1.2.3"))) // => "2.0.0"SemVer.format(SemVer.bumpMajor(SemVer.parseUnsafe("2.0.0-rc.1"))) // => "2.0.0"SemVer.format(SemVer.bumpMajor(SemVer.parseUnsafe("2.1.0-rc.1"))) // => "3.0.0"Returns the next minor release.
Details
Returns the smallest minor release with higher precedence, so a pre-release
of a minor version, such as 1.3.0-rc.1, becomes 1.3.0. Pre-release
identifiers and build metadata are removed.
Signature
declare function bumpMinor(self: SemVer): SemVerReturns the next patch release.
Details
Returns the smallest patch release with higher precedence, so a pre-release
such as 1.2.3-rc.1 becomes 1.2.3. Pre-release identifiers and build
metadata are removed.
Signature
declare function bumpPatch(self: SemVer): SemVerbumpPremajor
unstableReturns the first pre-release of the next major version.
Details
Increments major, resets minor and patch, and starts the pre-release at
[identifier, 0], or [0] without an identifier. Build metadata is removed.
Signature
declare const bumpPremajor: { (identifier?: string): (self: SemVer) => SemVer; (self: SemVer, identifier?: string): SemVer;}bumpPreminor
unstableReturns the first pre-release of the next minor version.
Details
Increments minor, resets patch, and starts the pre-release at
[identifier, 0], or [0] without an identifier. Build metadata is removed.
Signature
declare const bumpPreminor: { (identifier?: string): (self: SemVer) => SemVer; (self: SemVer, identifier?: string): SemVer;}bumpPrepatch
unstableReturns the first pre-release of the next patch version.
Details
Increments patch and starts the pre-release at [identifier, 0], or [0]
without an identifier. Build metadata is removed.
Signature
declare const bumpPrepatch: { (identifier?: string): (self: SemVer) => SemVer; (self: SemVer, identifier?: string): SemVer;}bumpPrerelease
unstableReturns the next pre-release.
Details
- A release starts the pre-release of the next patch, like bumpPrepatch.
- An identifier that differs from the first pre-release identifier restarts
the pre-release at
[identifier, 0]. - Otherwise the right-most numeric identifier is incremented, or
0is appended when there is none.
Build metadata is removed.
Gotchas
Switching to an identifier that sorts lower, such as from beta to alpha,
returns a version with lower precedence.
Signature
declare const bumpPrerelease: { (identifier?: string): (self: SemVer) => SemVer; (self: SemVer, identifier?: string): SemVer;}Example Advancing pre-releases
import { SemVer } from "effect"
SemVer.format(SemVer.bumpPrerelease(SemVer.parseUnsafe("1.2.3"), "alpha")) // => "1.2.4-alpha.0"SemVer.format(SemVer.bumpPrerelease(SemVer.parseUnsafe("1.2.4-alpha.0"))) // => "1.2.4-alpha.1"SemVer.format(SemVer.bumpPrerelease(SemVer.parseUnsafe("1.2.4-alpha.1"), "beta")) // => "1.2.4-beta.0"Removes pre-release identifiers and build metadata from a version.
Signature
declare function release(self: SemVer): SemVerExample Finalizing a release candidate
import { SemVer } from "effect"
SemVer.format(SemVer.release(SemVer.parseUnsafe("2.0.0-rc.3+sha.5114f85"))) // => "2.0.0"Replaces the build metadata of a version and throws SemVerError for
invalid identifiers.
Details
An empty array removes the build metadata. Pre-release identifiers are preserved.
Signature
declare const withBuild: { (build: readonly Array<string>): (self: SemVer) => SemVer; (self: SemVer, build: readonly Array<string>): SemVer;}withPrerelease
unstableReplaces the pre-release identifiers of a version and throws SemVerError
for invalid identifiers.
Details
Digit-only strings are normalized to numbers. An empty array removes the pre-release. Build metadata is preserved.
Signature
declare const withPrerelease: { (prerelease: readonly Array<string | number>): (self: SemVer) => SemVer; (self: SemVer, prerelease: readonly Array<string | number>): SemVer;}