Hone logo
Hone
Problems

Semantic Version Resolution in TypeScript

Version resolution is a critical aspect of dependency management in software projects. This challenge asks you to implement a TypeScript module that can parse, compare, and resolve semantic versions (SemVer) according to common resolution strategies. This is useful for ensuring compatibility between project dependencies and avoiding unexpected behavior due to version conflicts.

Problem Description

You need to create a TypeScript module that handles semantic version parsing, comparison, and resolution. The module should include the following functionalities:

  1. Version Parsing: A function to parse a SemVer string (e.g., "1.2.3", "2.0.1-alpha.1+build.123") into a structured object. The object should have the following properties:

    • major: Number (required)
    • minor: Number (required)
    • patch: Number (required)
    • prerelease: String[] (optional, can be empty) - An array of prerelease identifiers (e.g., ["alpha", "beta", "rc"]).
    • build: String (optional) - The build metadata.
  2. Version Comparison: A function to compare two parsed SemVer objects and return a number indicating the relationship:

    • -1: version1 < version2
    • 0: version1 == version2
    • 1: version1 > version2
  3. Version Resolution: A function that takes a range of allowed versions (e.g., "^1.2.3", "~1.2.3", "1.2.3") and a specific version string and returns the best matching version within the range, according to the following resolution strategies:

    • ^ (Caret): Allows updates that do not modify the left-most non-zero digit. For example, "^1.2.3" allows updates to "1.3.0" and "1.2.4", but not to "2.0.0".
    • ~ (Tilde): Allows patch updates. For example, "~1.2.3" allows updates to "1.2.4", but not to "1.3.0".
    • = (Exact): Requires an exact match.
    • No prefix: Allows any version greater than or equal to the specified version.

    The resolution function should return the parsed version object (not the string). If no matching version is found, return null.

Examples

Example 1:

Input: range = "^1.2.3", version = "1.2.4"
Output: { major: 1, minor: 2, patch: 4, prerelease: [], build: null }
Explanation: "1.2.4" is a valid update within the "^1.2.3" range (patch update).

Example 2:

Input: range = "~1.2.3", version = "1.3.0"
Output: null
Explanation: "1.3.0" is not a valid update within the "~1.2.3" range (minor update is not allowed).

Example 3:

Input: range = "1.2.3", version = "1.2.3"
Output: { major: 1, minor: 2, patch: 3, prerelease: [], build: null }
Explanation: "1.2.3" is an exact match for the "1.2.3" range.

Example 4:

Input: range = "^1.0.0", version = "2.0.0-alpha.1"
Output: null
Explanation:  The caret range "^1.0.0" does not allow major version updates.

Constraints

  • Version strings will conform to the standard SemVer format (major.minor.patch[-prerelease][+build]).
  • The major, minor, and patch components will always be non-negative integers.
  • The prerelease array will contain strings.
  • The build string will contain alphanumeric characters and periods.
  • The resolution function should handle invalid version strings gracefully (e.g., by returning null).
  • Performance is not a primary concern for this challenge, but avoid excessively inefficient algorithms.

Notes

  • Consider using regular expressions for parsing the version string.
  • The comparison logic should account for prerelease and build metadata. Prereleases have precedence over builds.
  • Think carefully about the logic for each resolution strategy (caret, tilde, exact).
  • Test your implementation thoroughly with various version strings and ranges, including edge cases.
  • You can assume that the input range will always be a valid SemVer string.
  • Focus on correctness and clarity of code.
Loading editor...
typescript