version-range
Version:
Check version ranges like `>=N` and `X || Y || Z` with support for Node.js, Web Browsers, Deno, and TypeScript.
259 lines (258 loc) • 12.8 kB
JavaScript
;
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = withinVersionRange;
var orRegex = /\s*\|\|\s*/g;
var andRegex = /\s*&&\s*/g;
var rangeRegex = /^\s*([<>=~^]*)\s*([\d.x]+)(-[^\s]+)?\s*/;
var xRegex = /[.]x/g;
/**
* Check if the version is within the range
* @param subject The version to check against the range
* @param range The range to check the version against
*/
function withinVersionRange(subject, range) {
var e_1, _a, e_2, _b;
// prepare and verify subject
subject = String(subject);
var _c = __read(subject.split('.'), 3), _d = _c[0], subjectMajor = _d === void 0 ? null : _d, _e = _c[1], subjectMinor = _e === void 0 ? null : _e, _f = _c[2], subjectPatch = _f === void 0 ? null : _f;
if (subjectMajor === null)
throw new Error("subject was invalid: ".concat(JSON.stringify(subject)));
var subjectMajorNumber = Number(subjectMajor || 0);
var subjectMinorNumber = Number(subjectMinor || 0);
var subjectPatchNumber = Number(subjectPatch || 0);
// cycle through the conditions
var orRanges = Array.isArray(range)
? range.slice()
: String(range).split(orRegex);
try {
for (var orRanges_1 = __values(orRanges), orRanges_1_1 = orRanges_1.next(); !orRanges_1_1.done; orRanges_1_1 = orRanges_1.next()) {
var orRange = orRanges_1_1.value;
var orResult = false;
var andRanges = String(orRange).split(andRegex);
try {
for (var andRanges_1 = (e_2 = void 0, __values(andRanges)), andRanges_1_1 = andRanges_1.next(); !andRanges_1_1.done; andRanges_1_1 = andRanges_1.next()) {
var andRange = andRanges_1_1.value;
var andResult = false;
// process range
var _g = __read(String(andRange).match(rangeRegex) || [], 4), match = _g[0], comparator = _g[1], targetRaw = _g[2], prerelease = _g[3];
var target = (targetRaw || '').replace(xRegex, '');
// // log
// console.log({
// orRange,
// andRange,
// match,
// comparator,
// target,
// prerelease,
// })
// prepare and verify target
var _h = __read(target.split('.'), 3), _j = _h[0], targetMajor = _j === void 0 ? null : _j, _k = _h[1], targetMinor = _k === void 0 ? null : _k, _l = _h[2], targetPatch = _l === void 0 ? null : _l;
if (!match || !target || targetMajor == null || prerelease)
throw new Error("range condition was invalid: ".concat(JSON.stringify(andRange)));
var targetMajorNumber = Number(targetMajor || 0);
var targetMinorNumber = Number(targetMinor || 0);
var targetPatchNumber = Number(targetPatch || 0);
// is there more range matches? add it to and condition
var remainder = String(andRange).slice(match.length);
if (remainder)
andRanges.push(remainder);
// handle comparator
switch (comparator) {
case '^':
if (subjectMajorNumber === targetMajorNumber) {
if (subjectMinorNumber === targetMinorNumber) {
if (subjectPatchNumber >= targetPatchNumber) {
andResult = true;
}
}
else if (subjectMinorNumber >= targetMinorNumber) {
andResult = true;
}
}
break;
case '~':
if (subjectMajorNumber === targetMajorNumber) {
if (subjectMinor !== null &&
subjectMinorNumber === targetMinorNumber) {
if (subjectPatchNumber >= targetPatchNumber) {
andResult = true;
}
}
}
break;
case '>=':
if (subjectMajorNumber === targetMajorNumber) {
if (subjectMinorNumber === targetMinorNumber) {
if (subjectPatchNumber >= targetPatchNumber) {
andResult = true;
}
}
else if (subjectMinorNumber >= targetMinorNumber) {
andResult = true;
}
}
else if (subjectMajorNumber >= targetMajorNumber) {
andResult = true;
}
break;
case '>':
if (subjectMajorNumber === targetMajorNumber) {
if (targetMinor === null) {
// x > x = false
// x.y > x = false
}
else if (subjectMinorNumber === targetMinorNumber) {
if (targetPatch === null) {
// x.y > x.y = false
// x.y.z > x.y = false
}
else if (subjectPatchNumber > targetPatchNumber) {
andResult = true;
}
}
else if (subjectMinorNumber > targetMinorNumber) {
andResult = true;
}
}
else if (subjectMajorNumber > targetMajorNumber) {
andResult = true;
}
break;
case '<':
if (subjectMajorNumber === targetMajorNumber) {
if (subjectMinor === null) {
// x < x = false
// x < x.y = false
}
else if (subjectMinorNumber === targetMinorNumber) {
if (subjectPatch === null) {
// x.y < x.y = false
// x.y < x.y.z = false
}
else if (subjectPatchNumber < targetPatchNumber) {
andResult = true;
}
}
else if (subjectMinorNumber < targetMinorNumber) {
andResult = true;
}
}
else if (subjectMajorNumber < targetMajorNumber) {
andResult = true;
}
break;
case '<=':
if (subjectMajorNumber === targetMajorNumber) {
if (subjectMinor === null) {
if (targetMinor === null) {
// x <= x = true
andResult = true;
}
// x <= x.y = false
}
else if (targetMinor === null) {
// x.y <= x = true
andResult = true;
}
else if (subjectMinorNumber === targetMinorNumber) {
if (subjectPatch === null) {
if (targetPatch === null) {
// x.y <= x.y = true
andResult = true;
}
// x.y <= x.y.z = false
}
else if (targetPatch === null) {
// x.y.z <= x.y = true
andResult = true;
}
else if (subjectPatchNumber <= targetPatchNumber) {
// x.y.z <= x.y.z = true
andResult = true;
}
}
else if (subjectMinorNumber <= targetMinorNumber) {
andResult = true;
}
}
else if (subjectMajorNumber <= targetMajorNumber) {
andResult = true;
}
break;
case '=':
case '':
if (subjectMajor === targetMajor) {
if (targetMinor === null) {
andResult = true;
}
else if (subjectMinor === targetMinor) {
if (targetPatch === null || subjectPatch === targetPatch) {
andResult = true;
}
}
}
break;
default:
throw new Error("range comparator was invalid: ".concat(JSON.stringify(andRange)));
}
// if one of the and conditions failed, don't continue and checks, and note failure to the or condition
if (!andResult) {
orResult = false;
break;
}
else {
// otherwise note success to the or condition
orResult = true;
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (andRanges_1_1 && !andRanges_1_1.done && (_b = andRanges_1.return)) _b.call(andRanges_1);
}
finally { if (e_2) throw e_2.error; }
}
// if the entire and conditions passed, then we can break out of the or conditions
if (orResult) {
return true;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (orRanges_1_1 && !orRanges_1_1.done && (_a = orRanges_1.return)) _a.call(orRanges_1);
}
finally { if (e_1) throw e_1.error; }
}
// nothing passed
return false;
}