const nodeSemver = require('semver'); const { Semver, SemverRange } = require('./sver'); module.exports = function nodeRangeToSemverRange (range) { let parsed = nodeSemver.validRange(range); // tag version if (!parsed) return new SemverRange(range); if (parsed === '*') return new SemverRange(parsed); try { let semverRange = new SemverRange(range); if (!semverRange.version.tag) return semverRange; } catch (e) { if (e.code !== 'ENOTSEMVER') throw e; } let outRange; for (let union of parsed.split('||')) { // compute the intersection into a lowest upper bound and a highest lower bound let upperBound, lowerBound, upperEq, lowerEq; for (let intersection of union.split(' ')) { let lt = intersection[0] === '<'; let gt = intersection[0] === '>'; if (!lt && !gt) { upperBound = intersection; upperEq = true; break; } let eq = intersection[1] === '='; if (!gt) { let version = new Semver(intersection.substr(1 + eq)); if (!upperBound || upperBound.gt(version)) { upperBound = version; upperEq = eq; } } else if (!lt) { let eq = intersection[1] === '='; let version = new Semver(intersection.substr(1 + eq)); if (!lowerBound || lowerBound.lt(version)) { lowerBound = version; lowerEq = eq; } } } // no upper bound -> wildcard if (!upperBound) { outRange = new SemverRange('*'); continue; } // if the lower bound is greater than the upper bound then just return the lower bound exactly if (lowerBound && upperBound && lowerBound.gt(upperBound)) { let curRange = new SemverRange(lowerBound.toString()); // the largest or highest union range wins if (!outRange || !outRange.contains(curRange) && (curRange.gt(outRange) || curRange.contains(outRange))) outRange = curRange; continue; } // determine the largest semver range satisfying the upper bound let upperRange; if (upperBound) { // if the upper bound has an equality then we return it directly if (upperEq) { let curRange = new SemverRange(upperBound.toString()); // the largest or highest union range wins if (!outRange || !outRange.contains(curRange) && (curRange.gt(outRange) || curRange.contains(outRange))) outRange = curRange; continue; } let major = 0, minor = 0, patch = 0, rangeType = ''; // if an exact prerelease range, match the lower bound as a range if (upperBound.pre && lowerBound.major === upperBound.major && lowerBound.minor === upperBound.minor && lowerBound.patch === upperBound.patch) { outRange = new SemverRange('~' + lowerBound.toString()); continue; } // <2.0.0 -> ^1.0.0 else if (upperBound.patch === 0) { if (upperBound.minor === 0) { if (upperBound.major > 0) { major = upperBound.major - 1; rangeType = '^'; } } // <1.2.0 -> ~1.1.0 else { major = upperBound.major; minor = upperBound.minor - 1; rangeType = '~'; } } // <1.2.3 -> ~1.2.0 else { major = upperBound.major; minor = upperBound.minor; patch = 0; rangeType = '~'; } if (major === 0 && rangeType === '^') upperRange = new SemverRange('0'); else upperRange = new SemverRange(rangeType + major + '.' + minor + '.' + patch); } if (!lowerBound) { outRange = upperRange; continue; } // determine the lower range semver range let lowerRange; if (!lowerEq) { if (lowerBound.pre) lowerRange = new SemverRange('^^' + lowerBound.major + '.' + lowerBound.minor + '.' + lowerBound.patch + '-' + [...lowerBound.pre, 1].join('.')); else lowerRange = new SemverRange('^^' + lowerBound.major + '.' + lowerBound.minor + '.' + (lowerBound.patch + 1)); } else { lowerRange = new SemverRange('^^' + lowerBound.toString()); } // we then intersect the upper semver range with the lower semver range // if the intersection is empty, we return the upper range only let curRange = upperRange ? lowerRange.intersect(upperRange) || upperRange : lowerRange; // the largest or highest union range wins if (!outRange || !outRange.contains(curRange) && (curRange.gt(outRange) || curRange.contains(outRange))) outRange = curRange; } return outRange; }