UNPKG

@storybook/semver

Version:

The semantic version parser used by npm for browser.

600 lines (478 loc) 20.6 kB
"use strict"; require("core-js/modules/es.symbol"); require("core-js/modules/es.symbol.description"); require("core-js/modules/es.symbol.iterator"); require("core-js/modules/es.array.concat"); require("core-js/modules/es.array.every"); require("core-js/modules/es.array.filter"); require("core-js/modules/es.array.from"); require("core-js/modules/es.array.is-array"); require("core-js/modules/es.array.iterator"); require("core-js/modules/es.array.join"); require("core-js/modules/es.array.map"); require("core-js/modules/es.array.slice"); require("core-js/modules/es.array.some"); require("core-js/modules/es.date.to-string"); require("core-js/modules/es.function.name"); require("core-js/modules/es.map"); require("core-js/modules/es.object.define-property"); require("core-js/modules/es.object.to-string"); require("core-js/modules/es.regexp.exec"); require("core-js/modules/es.regexp.to-string"); require("core-js/modules/es.string.iterator"); require("core-js/modules/es.string.match"); require("core-js/modules/es.string.replace"); require("core-js/modules/es.string.split"); require("core-js/modules/es.string.trim"); require("core-js/modules/web.dom-collections.iterator"); function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _createForOfIteratorHelper(o) { if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) { var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var it, normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } // hoisted class for cyclic dependency var Range = /*#__PURE__*/function () { function Range(range, options) { var _this = this; _classCallCheck(this, Range); if (!options || _typeof(options) !== 'object') { options = { loose: !!options, includePrerelease: false }; } if (range instanceof Range) { if (range.loose === !!options.loose && range.includePrerelease === !!options.includePrerelease) { return range; } else { return new Range(range.raw, options); } } if (range instanceof Comparator) { // just put it in the set and return this.raw = range.value; this.set = [[range]]; this.format(); return this; } this.options = options; this.loose = !!options.loose; this.includePrerelease = !!options.includePrerelease; // First, split based on boolean or || this.raw = range; this.set = range.split(/\s*\|\|\s*/) // map the range to a 2d array of comparators .map(function (range) { return _this.parseRange(range.trim()); }) // throw out any comparator lists that are empty // this generally means that it was not a valid range, which is allowed // in loose mode, but will still throw if the WHOLE range is invalid. .filter(function (c) { return c.length; }); if (!this.set.length) { throw new TypeError("Invalid SemVer Range: ".concat(range)); } // if we have any that are not the null set, throw out null sets. if (this.set.length > 1) { // keep the first one, in case they're all null sets var first = this.set[0]; this.set = this.set.filter(function (c) { return !isNullSet(c[0]); }); if (this.set.length === 0) this.set = [first];else if (this.set.length > 1) { // if we have any that are *, then the range is just * var _iterator = _createForOfIteratorHelper(this.set), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var c = _step.value; if (c.length === 1 && isAny(c[0])) { this.set = [c]; break; } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } } this.format(); } _createClass(Range, [{ key: "format", value: function format() { this.range = this.set.map(function (comps) { return comps.join(' ').trim(); }).join('||').trim(); return this.range; } }, { key: "toString", value: function toString() { return this.range; } }, { key: "parseRange", value: function parseRange(range) { var _this2 = this; var loose = this.options.loose; range = range.trim(); // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` var hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); debug('hyphen replace', range); // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); debug('comparator trim', range, re[t.COMPARATORTRIM]); // `~ 1.2.3` => `~1.2.3` range = range.replace(re[t.TILDETRIM], tildeTrimReplace); // `^ 1.2.3` => `^1.2.3` range = range.replace(re[t.CARETTRIM], caretTrimReplace); // normalize spaces range = range.split(/\s+/).join(' '); // At this point, the range is completely trimmed and // ready to be split into comparators. var compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; var rangeList = range.split(' ').map(function (comp) { return parseComparator(comp, _this2.options); }).join(' ').split(/\s+/) // >=0.0.0 is equivalent to * .map(function (comp) { return replaceGTE0(comp, _this2.options); }) // in loose mode, throw out any that are not valid comparators .filter(this.options.loose ? function (comp) { return !!comp.match(compRe); } : function () { return true; }).map(function (comp) { return new Comparator(comp, _this2.options); }); // if any comparators are the null set, then replace with JUST null set // if more than one comparator, remove any * comparators // also, don't include the same comparator more than once var l = rangeList.length; var rangeMap = new Map(); var _iterator2 = _createForOfIteratorHelper(rangeList), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var comp = _step2.value; if (isNullSet(comp)) return [comp]; rangeMap.set(comp.value, comp); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } if (rangeMap.size > 1 && rangeMap.has('')) rangeMap["delete"](''); return _toConsumableArray(rangeMap.values()); } }, { key: "intersects", value: function intersects(range, options) { if (!(range instanceof Range)) { throw new TypeError('a Range is required'); } return this.set.some(function (thisComparators) { return isSatisfiable(thisComparators, options) && range.set.some(function (rangeComparators) { return isSatisfiable(rangeComparators, options) && thisComparators.every(function (thisComparator) { return rangeComparators.every(function (rangeComparator) { return thisComparator.intersects(rangeComparator, options); }); }); }); }); } // if ANY of the sets match ALL of its comparators, then pass }, { key: "test", value: function test(version) { if (!version) { return false; } if (typeof version === 'string') { try { version = new SemVer(version, this.options); } catch (er) { return false; } } for (var i = 0; i < this.set.length; i++) { if (testSet(this.set[i], version, this.options)) { return true; } } return false; } }]); return Range; }(); module.exports = Range; var Comparator = require('./comparator'); var debug = require('../internal/debug'); var SemVer = require('./semver'); var _require = require('../internal/re'), re = _require.re, t = _require.t, comparatorTrimReplace = _require.comparatorTrimReplace, tildeTrimReplace = _require.tildeTrimReplace, caretTrimReplace = _require.caretTrimReplace; var isNullSet = function isNullSet(c) { return c.value === '<0.0.0-0'; }; var isAny = function isAny(c) { return c.value === ''; }; // take a set of comparators and determine whether there // exists a version which can satisfy it var isSatisfiable = function isSatisfiable(comparators, options) { var result = true; var remainingComparators = comparators.slice(); var testComparator = remainingComparators.pop(); while (result && remainingComparators.length) { result = remainingComparators.every(function (otherComparator) { return testComparator.intersects(otherComparator, options); }); testComparator = remainingComparators.pop(); } return result; }; // comprised of xranges, tildes, stars, and gtlt's at this point. // already replaced the hyphen ranges // turn into a set of JUST comparators. var parseComparator = function parseComparator(comp, options) { debug('comp', comp, options); comp = replaceCarets(comp, options); debug('caret', comp); comp = replaceTildes(comp, options); debug('tildes', comp); comp = replaceXRanges(comp, options); debug('xrange', comp); comp = replaceStars(comp, options); debug('stars', comp); return comp; }; var isX = function isX(id) { return !id || id.toLowerCase() === 'x' || id === '*'; }; // ~, ~> --> * (any, kinda silly) // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0 // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0 // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0 // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0 // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0 var replaceTildes = function replaceTildes(comp, options) { return comp.trim().split(/\s+/).map(function (comp) { return replaceTilde(comp, options); }).join(' '); }; var replaceTilde = function replaceTilde(comp, options) { var r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; return comp.replace(r, function (_, M, m, p, pr) { debug('tilde', comp, _, M, m, p, pr); var ret; if (isX(M)) { ret = ''; } else if (isX(m)) { ret = ">=".concat(M, ".0.0 <").concat(+M + 1, ".0.0-0"); } else if (isX(p)) { // ~1.2 == >=1.2.0 <1.3.0-0 ret = ">=".concat(M, ".").concat(m, ".0 <").concat(M, ".").concat(+m + 1, ".0-0"); } else if (pr) { debug('replaceTilde pr', pr); ret = ">=".concat(M, ".").concat(m, ".").concat(p, "-").concat(pr, " <").concat(M, ".").concat(+m + 1, ".0-0"); } else { // ~1.2.3 == >=1.2.3 <1.3.0-0 ret = ">=".concat(M, ".").concat(m, ".").concat(p, " <").concat(M, ".").concat(+m + 1, ".0-0"); } debug('tilde return', ret); return ret; }); }; // ^ --> * (any, kinda silly) // ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0 // ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0 // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0 // ^1.2.3 --> >=1.2.3 <2.0.0-0 // ^1.2.0 --> >=1.2.0 <2.0.0-0 var replaceCarets = function replaceCarets(comp, options) { return comp.trim().split(/\s+/).map(function (comp) { return replaceCaret(comp, options); }).join(' '); }; var replaceCaret = function replaceCaret(comp, options) { debug('caret', comp, options); var r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; var z = options.includePrerelease ? '-0' : ''; return comp.replace(r, function (_, M, m, p, pr) { debug('caret', comp, _, M, m, p, pr); var ret; if (isX(M)) { ret = ''; } else if (isX(m)) { ret = ">=".concat(M, ".0.0").concat(z, " <").concat(+M + 1, ".0.0-0"); } else if (isX(p)) { if (M === '0') { ret = ">=".concat(M, ".").concat(m, ".0").concat(z, " <").concat(M, ".").concat(+m + 1, ".0-0"); } else { ret = ">=".concat(M, ".").concat(m, ".0").concat(z, " <").concat(+M + 1, ".0.0-0"); } } else if (pr) { debug('replaceCaret pr', pr); if (M === '0') { if (m === '0') { ret = ">=".concat(M, ".").concat(m, ".").concat(p, "-").concat(pr, " <").concat(M, ".").concat(m, ".").concat(+p + 1, "-0"); } else { ret = ">=".concat(M, ".").concat(m, ".").concat(p, "-").concat(pr, " <").concat(M, ".").concat(+m + 1, ".0-0"); } } else { ret = ">=".concat(M, ".").concat(m, ".").concat(p, "-").concat(pr, " <").concat(+M + 1, ".0.0-0"); } } else { debug('no pr'); if (M === '0') { if (m === '0') { ret = ">=".concat(M, ".").concat(m, ".").concat(p).concat(z, " <").concat(M, ".").concat(m, ".").concat(+p + 1, "-0"); } else { ret = ">=".concat(M, ".").concat(m, ".").concat(p).concat(z, " <").concat(M, ".").concat(+m + 1, ".0-0"); } } else { ret = ">=".concat(M, ".").concat(m, ".").concat(p, " <").concat(+M + 1, ".0.0-0"); } } debug('caret return', ret); return ret; }); }; var replaceXRanges = function replaceXRanges(comp, options) { debug('replaceXRanges', comp, options); return comp.split(/\s+/).map(function (comp) { return replaceXRange(comp, options); }).join(' '); }; var replaceXRange = function replaceXRange(comp, options) { comp = comp.trim(); var r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; return comp.replace(r, function (ret, gtlt, M, m, p, pr) { debug('xRange', comp, ret, gtlt, M, m, p, pr); var xM = isX(M); var xm = xM || isX(m); var xp = xm || isX(p); var anyX = xp; if (gtlt === '=' && anyX) { gtlt = ''; } // if we're including prereleases in the match, then we need // to fix this to -0, the lowest possible prerelease value pr = options.includePrerelease ? '-0' : ''; if (xM) { if (gtlt === '>' || gtlt === '<') { // nothing is allowed ret = '<0.0.0-0'; } else { // nothing is forbidden ret = '*'; } } else if (gtlt && anyX) { // we know patch is an x, because we have any x at all. // replace X with 0 if (xm) { m = 0; } p = 0; if (gtlt === '>') { // >1 => >=2.0.0 // >1.2 => >=1.3.0 gtlt = '>='; if (xm) { M = +M + 1; m = 0; p = 0; } else { m = +m + 1; p = 0; } } else if (gtlt === '<=') { // <=0.7.x is actually <0.8.0, since any 0.7.x should // pass. Similarly, <=7.x is actually <8.0.0, etc. gtlt = '<'; if (xm) { M = +M + 1; } else { m = +m + 1; } } if (gtlt === '<') pr = '-0'; ret = "".concat(gtlt + M, ".").concat(m, ".").concat(p).concat(pr); } else if (xm) { ret = ">=".concat(M, ".0.0").concat(pr, " <").concat(+M + 1, ".0.0-0"); } else if (xp) { ret = ">=".concat(M, ".").concat(m, ".0").concat(pr, " <").concat(M, ".").concat(+m + 1, ".0-0"); } debug('xRange return', ret); return ret; }); }; // Because * is AND-ed with everything else in the comparator, // and '' means "any version", just remove the *s entirely. var replaceStars = function replaceStars(comp, options) { debug('replaceStars', comp, options); // Looseness is ignored here. star is always as loose as it gets! return comp.trim().replace(re[t.STAR], ''); }; var replaceGTE0 = function replaceGTE0(comp, options) { debug('replaceGTE0', comp, options); return comp.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ''); }; // This function is passed to string.replace(re[t.HYPHENRANGE]) // M, m, patch, prerelease, build // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 // 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do // 1.2 - 3.4 => >=1.2.0 <3.5.0-0 var hyphenReplace = function hyphenReplace(incPr) { return function ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr, tb) { if (isX(fM)) { from = ''; } else if (isX(fm)) { from = ">=".concat(fM, ".0.0").concat(incPr ? '-0' : ''); } else if (isX(fp)) { from = ">=".concat(fM, ".").concat(fm, ".0").concat(incPr ? '-0' : ''); } else if (fpr) { from = ">=".concat(from); } else { from = ">=".concat(from).concat(incPr ? '-0' : ''); } if (isX(tM)) { to = ''; } else if (isX(tm)) { to = "<".concat(+tM + 1, ".0.0-0"); } else if (isX(tp)) { to = "<".concat(tM, ".").concat(+tm + 1, ".0-0"); } else if (tpr) { to = "<=".concat(tM, ".").concat(tm, ".").concat(tp, "-").concat(tpr); } else if (incPr) { to = "<".concat(tM, ".").concat(tm, ".").concat(+tp + 1, "-0"); } else { to = "<=".concat(to); } return "".concat(from, " ").concat(to).trim(); }; }; var testSet = function testSet(set, version, options) { for (var i = 0; i < set.length; i++) { if (!set[i].test(version)) { return false; } } if (version.prerelease.length && !options.includePrerelease) { // Find the set of versions that are allowed to have prereleases // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 // That should allow `1.2.3-pr.2` to pass. // However, `1.2.4-alpha.notready` should NOT be allowed, // even though it's within the range set by the comparators. for (var _i = 0; _i < set.length; _i++) { debug(set[_i].semver); if (set[_i].semver === Comparator.ANY) { continue; } if (set[_i].semver.prerelease.length > 0) { var allowed = set[_i].semver; if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) { return true; } } } // Version has a -pre, but it's not one of the ones we like. return false; } return true; };