← Runnable Projects

阅读中文版本

Semantic Version Comparator CLI

A Node CLI that compares two semantic versions and reports whether the first is lower, equal, or higher, handling prerelease tags by semver precedence rules.

intermediatejavascriptunverified

Project

node-semver-compare

Entry point: semver.mjs

Install

node --version

Run

node semver.mjs 1.2.3-alpha 1.2.3

Test

node --test semver.test.mjs

Expected output

Prints which version is greater, or reports equality, following semver precedence.

Dependencies

  • node >=20

What it does

Compares two semantic versions with the precedence rules that matter: numeric fields compare numerically, and a prerelease sorts before its release.

function parse(v) {
  const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$/.exec(v.trim());
  if (!match) throw new Error('invalid version: ' + v);
  return { core: [Number(match[1]), Number(match[2]), Number(match[3])], pre: match[4] ?? null };
}

function comparePre(a, b) {
  if (a === b) return 0;
  if (a === null) return 1;
  if (b === null) return -1;
  const ap = a.split('.'); const bp = b.split('.');
  for (let i = 0; i < Math.max(ap.length, bp.length); i++) {
    const x = ap[i]; const y = bp[i];
    if (x === undefined) return -1;
    if (y === undefined) return 1;
    const nx = /^\d+$/.test(x); const ny = /^\d+$/.test(y);
    if (nx && ny) { if (+x !== +y) return +x < +y ? -1 : 1; }
    else if (x !== y) return x < y ? -1 : 1;
  }
  return 0;
}

function compare(a, b) {
  const pa = parse(a); const pb = parse(b);
  for (let i = 0; i < 3; i++) if (pa.core[i] !== pb.core[i]) return pa.core[i] < pb.core[i] ? -1 : 1;
  return comparePre(pa.pre, pb.pre);
}

const [a, b] = process.argv.slice(2);
console.log(a + ' ' + ['<', '=', '>'][compare(a, b) + 1] + ' ' + b);

Build metadata is ignored for precedence, which is exactly what the specification requires and a common source of disagreement.

Run and verify

node semver.mjs 1.2.3-alpha 1.2.3
node semver.mjs 2.0.0 1.9.9

Run the prerelease comparison first, then a major-version comparison to see numeric ordering.

Expected Output

The prerelease sorts before its release, and 2.0.0 outranks 1.9.9. The output is:

1.2.3-alpha < 1.2.3
2.0.0 > 1.9.9

A build-metadata suffix does not affect precedence, and an invalid version string fails with a parse error rather than a wrong comparison.

Limitations

It implements the precedence rules but not ranges or caret/tilde operators; range matching is a larger piece of work.