Internal Architecture and State
Relevant source files
The following files were used as context for generating this wiki page:
The node-semver library is designed as a modular system for parsing, validating, and comparing semantic versions according to the SemVer 2.0.0 specification. Its internal architecture relies on a centralized regular expression engine, a set of core classes (SemVer, Comparator, Range), and a suite of functional utilities that operate on these classes. The system maintains state primarily within class instances that encapsulate parsed version data, ensuring immutability during standard operations while providing methods for version transformation such as incrementing.
At a high level, the project is structured to export a comprehensive API via index.js, which aggregates functionality from specialized subdirectories. This includes internal constants for safety limits, centralized regex definitions to prevent Regular Expression Denial of Service (ReDoS), and shared logic for identifier comparison.
Sources: index.js:1-93, semver.js:20-22, internal/constants.js:5-7
Core Data Structures and Classes
The internal state of a semantic version is managed by the SemVer class. Each instance represents a single version and stores its components as distinct properties.
The SemVer Class
When a version string is parsed, the SemVer class decomposes it into major, minor, and patch numbers, alongside arrays for prerelease and build identifiers.
| Property | Type | Description |
|---|---|---|
major | Number | The major version number (e.g., 1 in 1.2.3). |
minor | Number | The minor version number (e.g., 2 in 1.2.3). |
patch | Number | The patch version number (e.g., 3 in 1.2.3). |
prerelease | Array | Components of the prerelease string (e.g., ['alpha', 1]). |
build | Array | Components of the build metadata (e.g., ['x86', '64']). |
raw | String | The original input string provided to the constructor. |
version | String | The formatted, canonical version string. |
options | Object | Configuration flags like loose or includePrerelease. |
Sources: classes/semver.js:11-85, semver.js:275-322
Instance Lifecycle
The following diagram illustrates the creation and initialization of a SemVer instance:
The constructor performs strict validation, including checks against MAX_SAFE_INTEGER to prevent overflow in version components.
Sources: classes/semver.js:12-70, semver.js:284-322
Regular Expression Engine and Safety
A critical component of the internal architecture is the internal/re.js module, which dynamically builds the regular expressions used for parsing. To mitigate security risks, the engine differentiates between "standard" and "safe" regexes.
ReDoS Prevention
The system implements a makeSafeRegex utility. This function replaces greedy tokens (* and +) with bounded repetitions based on global constants to prevent catastrophic backtracking.
Sources: internal/re.js:25-41, semver.js:46-61
| Constant | Value | Purpose |
|---|---|---|
MAX_LENGTH | 256 | Maximum length for any input string. |
MAX_SAFE_COMPONENT_LENGTH | 16 | Max length for numeric segments during coercion. |
MAX_SAFE_BUILD_LENGTH | 250 | Max length for build metadata segments. |
Sources: internal/constants.js:9-19, semver.js:24-31
Regex Tokenization
The engine uses a tiered approach to build complex expressions from primitive tokens:
- Primitives:
NUMERICIDENTIFIER,NONNUMERICIDENTIFIER. - Structures:
MAINVERSION,PRERELEASE,BUILD. - Aggregates:
FULL,LOOSE,XRANGE.
This modular approach ensures that logic for "loose" parsing (allowing 'v' prefixes or omitted hyphens) is consistent across the library.
Sources: internal/re.js:63-138, semver.js:67-160
Functional Logic and Operations
Version Comparison
Comparison logic is implemented by comparing identifiers sequentially: Major -> Minor -> Patch -> Prerelease. Prerelease comparison is unique because a version with no prerelease is considered "greater" than one with a prerelease.
Sources: classes/semver.js:104-162, semver.js:335-385
Version Incrementing (Transformation)
The inc method modifies the internal state of a SemVer instance. It handles various release types (major, minor, patch, prerelease) and can reset lower-order components (e.g., incrementing minor sets patch to 0).
Sources: classes/semver.js:189-311, semver.js:387-488
Coercion System
The coerce function attempts to extract a valid SemVer from messy strings. It supports both Left-to-Right (default) and Right-to-Left (RTL) searching.
- RTL Mode: Useful for strings like
1.2.3.4where the user wants to treat2.3.4as the version. - Implementation: It uses specialized
COERCERTLregexes and manually adjustslastIndexto find overlapping matches.
Sources: functions/coerce.js:7-60, internal/re.js:150-155
State Management Summary
The library maintains state through instance properties while relying on static internal utilities for heavy lifting:
| Component | Responsibility | State Type |
|---|---|---|
internal/re.js | Compilation of parsing rules. | Static Global |
SemVer Instance | Storage of version numeric/string data. | Instance Local |
Range Instance | Storage of parsed comparator sets (e.g., [[Comp, Comp], [Comp]]). | Instance Local |
internal/debug.js | Conditional logging based on NODE_DEBUG. | Environment Dependent |
Sources: index.js:46-65, semver.js:5-17, classes/semver.js:43-55