Range Bounds and Outside Checks
Relevant source files
The following files were used as context for generating this wiki page:
Range Bounds and Outside Checks refer to the logic within the node-semver library used to determine if a specific version falls entirely above or below a defined version range. While common satisfaction checks determine if a version is within a range, outside checks provide directional context, identifying if a version is too high (Greater Than Range) or too low (Less Than Range) relative to the range's constraints.
The system relies on the outside function, which serves as the underlying engine for directional comparisons. This logic is critical for versioning systems that need to handle non-contiguous ranges, where a version might not satisfy a range but is also not strictly "greater" than every possible version in that range.
Sources: ranges/outside.js, README.md:380-391
Core Functions and API
The library provides three primary functions for performing outside checks. These functions compare a single version against a range string or Range object.
| Function | Description | hilo parameter |
|---|---|---|
outside(version, range, hilo, options) | Base function to check if a version is outside a range in a specific direction. | '>' or '<' |
gtr(version, range, options) | Return true if version is greater than all versions possible in the range. | N/A (calls outside with '>') |
ltr(version, range, options) | Return true if version is less than all versions possible in the range. | N/A (calls outside with '<') |
Sources: ranges/outside.js:12, semver.js:1255-1264, README.md:353-362
The outside Logic Engine
The outside function operates by evaluating the input version against the internal comparator sets of a Range. A Range in node-semver is represented as a 2D array (range.set), where the outer array elements are joined by OR (||) logic, and the inner array elements (Comparators) are joined by AND logic.
Comparison Logic Flow
- Normalization: The version is parsed into a
SemVerobject and the range into aRangeobject. - Satisfaction Check: If the version satisfies the range (using the
satisfiesfunction), it is by definition not "outside" the range. - Set Iteration: The function iterates through each inner comparator set.
- Extrema Identification: For each set, it identifies the "high" and "low" boundary comparators.
- Directional Validation: It applies logic based on the
hilovalue to see if the version violates the bounds of every set.
The diagram shows the logical flow of the outside function, highlighting how it delegates to specific directional checks after verifying the version does not satisfy the range.
Sources: ranges/outside.js:13-39, classes/range.js:37-52
Boundary Determination Logic
When checking if a version is greater than a range (hilo: '>'), the engine determines the "high" bound of each set. If any high bound in any set has an operator that would include the version (like >= or >), the version is not considered outside that specific set's upper limit.
Conversely, for less than checks (hilo: '<'), the engine identifies the "low" bound. The logic is inverted: if a version is greater than the low bound of a set, it cannot be "less than" that range.
Sources: ranges/outside.js:41-80
Implementation Details
Handling Non-Contiguous Ranges
A unique characteristic of SemVer ranges is that they can be non-contiguous. For example, the range 1.2.0 <1.2.9 || >2.0.0 has a "hole" between 1.2.9 and 2.0.0.
- A version like
1.2.10does not satisfy the range. - It is not greater than the range (because
2.0.1is in the range and is higher). - It is not less than the range (because
1.2.5is in the range and is lower).
In this scenario, both gtr() and ltr() would return false.
Sources: README.md:380-391
Comparator Set Processing
Within ranges/outside.js, the code uses function aliasing to handle both directions using the same loop structure:
switch (hilo) {
case '>':
gtfn = gt
ltefn = lte
ltfn = lt
comp = '>'
ecomp = '>='
break
case '<':
gtfn = lt
ltefn = gte
ltfn = gt
comp = '<'
ecomp = '<='
break
default:
throw new TypeError('Must provide a hilo val of "<" or ">"')
}
Sources: ranges/outside.js:16-34
Summary of Bound Components
The following table describes the internal components used during the evaluation of range bounds.
| Component | File | Role |
|---|---|---|
SemVer class | classes/semver.js | Represents and compares individual versions. |
Range class | classes/range.js | Parses range strings into sets of comparators. |
Comparator class | semver.js | Represents a single operator/version pair (e.g., >=1.0.0). |
ANY constant | semver.js | A special marker for the * or empty range, representing any version. |
Sources: ranges/outside.js:3-7, semver.js:1140-1160
Range Bounds and Outside Checks provide the necessary logic for applications to react differently when a version fails to meet requirements—allowing systems to distinguish between an outdated version (less than range) and a version that is too new or "experimental" (greater than range). This directional awareness is essential for automated dependency resolution and upgrade paths.