1 exports = module.exports = SemVer
4 /* istanbul ignore next */
5 if (typeof process === 'object' &&
7 process.env.NODE_DEBUG &&
8 /\bsemver\b/i.test(process.env.NODE_DEBUG)) {
10 var args = Array.prototype.slice.call(arguments, 0)
11 args.unshift('SEMVER')
12 console.log.apply(console, args)
15 debug = function () {}
18 // Note: this is the semver.org version of the spec that it implements
19 // Not necessarily the package version of this code.
20 exports.SEMVER_SPEC_VERSION = '2.0.0'
23 var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
24 /* istanbul ignore next */ 9007199254740991
26 // Max safe segment length for coercion.
27 var MAX_SAFE_COMPONENT_LENGTH = 16
29 // The actual regexps go on exports.re
30 var re = exports.re = []
31 var src = exports.src = []
34 // The following Regular Expressions can be used for tokenizing,
35 // validating, and parsing SemVer version strings.
37 // ## Numeric Identifier
38 // A single `0`, or a non-zero digit followed by zero or more digits.
40 var NUMERICIDENTIFIER = R++
41 src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'
42 var NUMERICIDENTIFIERLOOSE = R++
43 src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'
45 // ## Non-numeric Identifier
46 // Zero or more digits, followed by a letter or hyphen, and then zero or
47 // more letters, digits, or hyphens.
49 var NONNUMERICIDENTIFIER = R++
50 src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'
53 // Three dot-separated numeric identifiers.
56 src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' +
57 '(' + src[NUMERICIDENTIFIER] + ')\\.' +
58 '(' + src[NUMERICIDENTIFIER] + ')'
60 var MAINVERSIONLOOSE = R++
61 src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
62 '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' +
63 '(' + src[NUMERICIDENTIFIERLOOSE] + ')'
65 // ## Pre-release Version Identifier
66 // A numeric identifier, or a non-numeric identifier.
68 var PRERELEASEIDENTIFIER = R++
69 src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] +
70 '|' + src[NONNUMERICIDENTIFIER] + ')'
72 var PRERELEASEIDENTIFIERLOOSE = R++
73 src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] +
74 '|' + src[NONNUMERICIDENTIFIER] + ')'
76 // ## Pre-release Version
77 // Hyphen, followed by one or more dot-separated pre-release version
81 src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] +
82 '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'
84 var PRERELEASELOOSE = R++
85 src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] +
86 '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'
88 // ## Build Metadata Identifier
89 // Any combination of digits, letters, or hyphens.
91 var BUILDIDENTIFIER = R++
92 src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'
95 // Plus sign, followed by one or more period-separated build metadata
99 src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] +
100 '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'
102 // ## Full Version String
103 // A main version, followed optionally by a pre-release version and
106 // Note that the only major, minor, patch, and pre-release sections of
107 // the version string are capturing groups. The build metadata is not a
108 // capturing group, because it should not ever be used in version
112 var FULLPLAIN = 'v?' + src[MAINVERSION] +
113 src[PRERELEASE] + '?' +
116 src[FULL] = '^' + FULLPLAIN + '$'
118 // like full, but allows v1.2.3 and =1.2.3, which people do sometimes.
119 // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty
120 // common in the npm registry.
121 var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] +
122 src[PRERELEASELOOSE] + '?' +
126 src[LOOSE] = '^' + LOOSEPLAIN + '$'
129 src[GTLT] = '((?:<|>)?=?)'
131 // Something like "2.*" or "1.2.x".
132 // Note that "x.x" is a valid xRange identifer, meaning "any version"
133 // Only the first item is strictly required.
134 var XRANGEIDENTIFIERLOOSE = R++
135 src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'
136 var XRANGEIDENTIFIER = R++
137 src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'
139 var XRANGEPLAIN = R++
140 src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' +
141 '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
142 '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' +
143 '(?:' + src[PRERELEASE] + ')?' +
147 var XRANGEPLAINLOOSE = R++
148 src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
149 '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
150 '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' +
151 '(?:' + src[PRERELEASELOOSE] + ')?' +
156 src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'
157 var XRANGELOOSE = R++
158 src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'
161 // Extract anything that could conceivably be a part of a valid semver
163 src[COERCE] = '(?:^|[^\\d])' +
164 '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' +
165 '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
166 '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' +
170 // Meaning is "reasonably at or greater than"
172 src[LONETILDE] = '(?:~>?)'
175 src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'
176 re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g')
177 var tildeTrimReplace = '$1~'
180 src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'
182 src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'
185 // Meaning is "at least and backwards compatible with"
187 src[LONECARET] = '(?:\\^)'
190 src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'
191 re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g')
192 var caretTrimReplace = '$1^'
195 src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'
197 src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'
199 // A simple gt/lt/eq thing, or just "" to indicate "any version"
200 var COMPARATORLOOSE = R++
201 src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'
203 src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'
205 // An expression to strip any whitespace between the gtlt and the thing
206 // it modifies, so that `> 1.2.3` ==> `>1.2.3`
207 var COMPARATORTRIM = R++
208 src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] +
209 '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'
211 // this one has to use the /g flag
212 re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g')
213 var comparatorTrimReplace = '$1$2$3'
215 // Something like `1.2.3 - 1.2.4`
216 // Note that these all use the loose form, because they'll be
217 // checked against either the strict or loose comparator form
219 var HYPHENRANGE = R++
220 src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' +
222 '(' + src[XRANGEPLAIN] + ')' +
225 var HYPHENRANGELOOSE = R++
226 src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' +
228 '(' + src[XRANGEPLAINLOOSE] + ')' +
231 // Star ranges basically just allow anything at all.
233 src[STAR] = '(<|>)?=?\\s*\\*'
235 // Compile to actual regexp objects.
236 // All are flag-free, unless they were created above with a flag.
237 for (var i = 0; i < R; i++) {
240 re[i] = new RegExp(src[i])
244 exports.parse = parse
245 function parse (version, options) {
246 if (!options || typeof options !== 'object') {
249 includePrerelease: false
253 if (version instanceof SemVer) {
257 if (typeof version !== 'string') {
261 if (version.length > MAX_LENGTH) {
265 var r = options.loose ? re[LOOSE] : re[FULL]
266 if (!r.test(version)) {
271 return new SemVer(version, options)
277 exports.valid = valid
278 function valid (version, options) {
279 var v = parse(version, options)
280 return v ? v.version : null
283 exports.clean = clean
284 function clean (version, options) {
285 var s = parse(version.trim().replace(/^[=v]+/, ''), options)
286 return s ? s.version : null
289 exports.SemVer = SemVer
291 function SemVer (version, options) {
292 if (!options || typeof options !== 'object') {
295 includePrerelease: false
298 if (version instanceof SemVer) {
299 if (version.loose === options.loose) {
302 version = version.version
304 } else if (typeof version !== 'string') {
305 throw new TypeError('Invalid Version: ' + version)
308 if (version.length > MAX_LENGTH) {
309 throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters')
312 if (!(this instanceof SemVer)) {
313 return new SemVer(version, options)
316 debug('SemVer', version, options)
317 this.options = options
318 this.loose = !!options.loose
320 var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL])
323 throw new TypeError('Invalid Version: ' + version)
328 // these are actually numbers
333 if (this.major > MAX_SAFE_INTEGER || this.major < 0) {
334 throw new TypeError('Invalid major version')
337 if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) {
338 throw new TypeError('Invalid minor version')
341 if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) {
342 throw new TypeError('Invalid patch version')
345 // numberify any prerelease numeric ids
349 this.prerelease = m[4].split('.').map(function (id) {
350 if (/^[0-9]+$/.test(id)) {
352 if (num >= 0 && num < MAX_SAFE_INTEGER) {
360 this.build = m[5] ? m[5].split('.') : []
364 SemVer.prototype.format = function () {
365 this.version = this.major + '.' + this.minor + '.' + this.patch
366 if (this.prerelease.length) {
367 this.version += '-' + this.prerelease.join('.')
372 SemVer.prototype.toString = function () {
376 SemVer.prototype.compare = function (other) {
377 debug('SemVer.compare', this.version, this.options, other)
378 if (!(other instanceof SemVer)) {
379 other = new SemVer(other, this.options)
382 return this.compareMain(other) || this.comparePre(other)
385 SemVer.prototype.compareMain = function (other) {
386 if (!(other instanceof SemVer)) {
387 other = new SemVer(other, this.options)
390 return compareIdentifiers(this.major, other.major) ||
391 compareIdentifiers(this.minor, other.minor) ||
392 compareIdentifiers(this.patch, other.patch)
395 SemVer.prototype.comparePre = function (other) {
396 if (!(other instanceof SemVer)) {
397 other = new SemVer(other, this.options)
400 // NOT having a prerelease is > having one
401 if (this.prerelease.length && !other.prerelease.length) {
403 } else if (!this.prerelease.length && other.prerelease.length) {
405 } else if (!this.prerelease.length && !other.prerelease.length) {
411 var a = this.prerelease[i]
412 var b = other.prerelease[i]
413 debug('prerelease compare', i, a, b)
414 if (a === undefined && b === undefined) {
416 } else if (b === undefined) {
418 } else if (a === undefined) {
420 } else if (a === b) {
423 return compareIdentifiers(a, b)
428 // preminor will bump the version up to the next minor release, and immediately
429 // down to pre-release. premajor and prepatch work the same way.
430 SemVer.prototype.inc = function (release, identifier) {
433 this.prerelease.length = 0
437 this.inc('pre', identifier)
440 this.prerelease.length = 0
443 this.inc('pre', identifier)
446 // If this is already a prerelease, it will bump to the next version
447 // drop any prereleases that might already exist, since they are not
448 // relevant at this point.
449 this.prerelease.length = 0
450 this.inc('patch', identifier)
451 this.inc('pre', identifier)
453 // If the input is a non-prerelease version, this acts the same as
456 if (this.prerelease.length === 0) {
457 this.inc('patch', identifier)
459 this.inc('pre', identifier)
463 // If this is a pre-major version, bump up to the same major version.
464 // Otherwise increment major.
465 // 1.0.0-5 bumps to 1.0.0
466 // 1.1.0 bumps to 2.0.0
467 if (this.minor !== 0 ||
469 this.prerelease.length === 0) {
477 // If this is a pre-minor version, bump up to the same minor version.
478 // Otherwise increment minor.
479 // 1.2.0-5 bumps to 1.2.0
480 // 1.2.1 bumps to 1.3.0
481 if (this.patch !== 0 || this.prerelease.length === 0) {
488 // If this is not a pre-release version, it will increment the patch.
489 // If it is a pre-release it will bump up to the same patch version.
490 // 1.2.0-5 patches to 1.2.0
491 // 1.2.0 patches to 1.2.1
492 if (this.prerelease.length === 0) {
497 // This probably shouldn't be used publicly.
498 // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction.
500 if (this.prerelease.length === 0) {
501 this.prerelease = [0]
503 var i = this.prerelease.length
505 if (typeof this.prerelease[i] === 'number') {
511 // didn't increment anything
512 this.prerelease.push(0)
516 // 1.2.0-beta.1 bumps to 1.2.0-beta.2,
517 // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
518 if (this.prerelease[0] === identifier) {
519 if (isNaN(this.prerelease[1])) {
520 this.prerelease = [identifier, 0]
523 this.prerelease = [identifier, 0]
529 throw new Error('invalid increment argument: ' + release)
532 this.raw = this.version
537 function inc (version, release, loose, identifier) {
538 if (typeof (loose) === 'string') {
544 return new SemVer(version, loose).inc(release, identifier).version
551 function diff (version1, version2) {
552 if (eq(version1, version2)) {
555 var v1 = parse(version1)
556 var v2 = parse(version2)
558 if (v1.prerelease.length || v2.prerelease.length) {
560 var defaultResult = 'prerelease'
562 for (var key in v1) {
563 if (key === 'major' || key === 'minor' || key === 'patch') {
564 if (v1[key] !== v2[key]) {
569 return defaultResult // may be undefined
573 exports.compareIdentifiers = compareIdentifiers
575 var numeric = /^[0-9]+$/
576 function compareIdentifiers (a, b) {
577 var anum = numeric.test(a)
578 var bnum = numeric.test(b)
586 : (anum && !bnum) ? -1
587 : (bnum && !anum) ? 1
592 exports.rcompareIdentifiers = rcompareIdentifiers
593 function rcompareIdentifiers (a, b) {
594 return compareIdentifiers(b, a)
597 exports.major = major
598 function major (a, loose) {
599 return new SemVer(a, loose).major
602 exports.minor = minor
603 function minor (a, loose) {
604 return new SemVer(a, loose).minor
607 exports.patch = patch
608 function patch (a, loose) {
609 return new SemVer(a, loose).patch
612 exports.compare = compare
613 function compare (a, b, loose) {
614 return new SemVer(a, loose).compare(new SemVer(b, loose))
617 exports.compareLoose = compareLoose
618 function compareLoose (a, b) {
619 return compare(a, b, true)
622 exports.rcompare = rcompare
623 function rcompare (a, b, loose) {
624 return compare(b, a, loose)
628 function sort (list, loose) {
629 return list.sort(function (a, b) {
630 return exports.compare(a, b, loose)
634 exports.rsort = rsort
635 function rsort (list, loose) {
636 return list.sort(function (a, b) {
637 return exports.rcompare(a, b, loose)
642 function gt (a, b, loose) {
643 return compare(a, b, loose) > 0
647 function lt (a, b, loose) {
648 return compare(a, b, loose) < 0
652 function eq (a, b, loose) {
653 return compare(a, b, loose) === 0
657 function neq (a, b, loose) {
658 return compare(a, b, loose) !== 0
662 function gte (a, b, loose) {
663 return compare(a, b, loose) >= 0
667 function lte (a, b, loose) {
668 return compare(a, b, loose) <= 0
672 function cmp (a, op, b, loose) {
675 if (typeof a === 'object')
677 if (typeof b === 'object')
682 if (typeof a === 'object')
684 if (typeof b === 'object')
691 return eq(a, b, loose)
694 return neq(a, b, loose)
697 return gt(a, b, loose)
700 return gte(a, b, loose)
703 return lt(a, b, loose)
706 return lte(a, b, loose)
709 throw new TypeError('Invalid operator: ' + op)
713 exports.Comparator = Comparator
714 function Comparator (comp, options) {
715 if (!options || typeof options !== 'object') {
718 includePrerelease: false
722 if (comp instanceof Comparator) {
723 if (comp.loose === !!options.loose) {
730 if (!(this instanceof Comparator)) {
731 return new Comparator(comp, options)
734 debug('comparator', comp, options)
735 this.options = options
736 this.loose = !!options.loose
739 if (this.semver === ANY) {
742 this.value = this.operator + this.semver.version
749 Comparator.prototype.parse = function (comp) {
750 var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]
751 var m = comp.match(r)
754 throw new TypeError('Invalid comparator: ' + comp)
758 if (this.operator === '=') {
762 // if it literally is just '>' or '' then allow anything.
766 this.semver = new SemVer(m[2], this.options.loose)
770 Comparator.prototype.toString = function () {
774 Comparator.prototype.test = function (version) {
775 debug('Comparator.test', version, this.options.loose)
777 if (this.semver === ANY) {
781 if (typeof version === 'string') {
782 version = new SemVer(version, this.options)
785 return cmp(version, this.operator, this.semver, this.options)
788 Comparator.prototype.intersects = function (comp, options) {
789 if (!(comp instanceof Comparator)) {
790 throw new TypeError('a Comparator is required')
793 if (!options || typeof options !== 'object') {
796 includePrerelease: false
802 if (this.operator === '') {
803 rangeTmp = new Range(comp.value, options)
804 return satisfies(this.value, rangeTmp, options)
805 } else if (comp.operator === '') {
806 rangeTmp = new Range(this.value, options)
807 return satisfies(comp.semver, rangeTmp, options)
810 var sameDirectionIncreasing =
811 (this.operator === '>=' || this.operator === '>') &&
812 (comp.operator === '>=' || comp.operator === '>')
813 var sameDirectionDecreasing =
814 (this.operator === '<=' || this.operator === '<') &&
815 (comp.operator === '<=' || comp.operator === '<')
816 var sameSemVer = this.semver.version === comp.semver.version
817 var differentDirectionsInclusive =
818 (this.operator === '>=' || this.operator === '<=') &&
819 (comp.operator === '>=' || comp.operator === '<=')
820 var oppositeDirectionsLessThan =
821 cmp(this.semver, '<', comp.semver, options) &&
822 ((this.operator === '>=' || this.operator === '>') &&
823 (comp.operator === '<=' || comp.operator === '<'))
824 var oppositeDirectionsGreaterThan =
825 cmp(this.semver, '>', comp.semver, options) &&
826 ((this.operator === '<=' || this.operator === '<') &&
827 (comp.operator === '>=' || comp.operator === '>'))
829 return sameDirectionIncreasing || sameDirectionDecreasing ||
830 (sameSemVer && differentDirectionsInclusive) ||
831 oppositeDirectionsLessThan || oppositeDirectionsGreaterThan
834 exports.Range = Range
835 function Range (range, options) {
836 if (!options || typeof options !== 'object') {
839 includePrerelease: false
843 if (range instanceof Range) {
844 if (range.loose === !!options.loose &&
845 range.includePrerelease === !!options.includePrerelease) {
848 return new Range(range.raw, options)
852 if (range instanceof Comparator) {
853 return new Range(range.value, options)
856 if (!(this instanceof Range)) {
857 return new Range(range, options)
860 this.options = options
861 this.loose = !!options.loose
862 this.includePrerelease = !!options.includePrerelease
864 // First, split based on boolean or ||
866 this.set = range.split(/\s*\|\|\s*/).map(function (range) {
867 return this.parseRange(range.trim())
868 }, this).filter(function (c) {
869 // throw out any that are not relevant for whatever reason
873 if (!this.set.length) {
874 throw new TypeError('Invalid SemVer Range: ' + range)
880 Range.prototype.format = function () {
881 this.range = this.set.map(function (comps) {
882 return comps.join(' ').trim()
887 Range.prototype.toString = function () {
891 Range.prototype.parseRange = function (range) {
892 var loose = this.options.loose
894 // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
895 var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]
896 range = range.replace(hr, hyphenReplace)
897 debug('hyphen replace', range)
898 // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
899 range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace)
900 debug('comparator trim', range, re[COMPARATORTRIM])
902 // `~ 1.2.3` => `~1.2.3`
903 range = range.replace(re[TILDETRIM], tildeTrimReplace)
905 // `^ 1.2.3` => `^1.2.3`
906 range = range.replace(re[CARETTRIM], caretTrimReplace)
909 range = range.split(/\s+/).join(' ')
911 // At this point, the range is completely trimmed and
912 // ready to be split into comparators.
914 var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]
915 var set = range.split(' ').map(function (comp) {
916 return parseComparator(comp, this.options)
917 }, this).join(' ').split(/\s+/)
918 if (this.options.loose) {
919 // in loose mode, throw out any that are not valid comparators
920 set = set.filter(function (comp) {
921 return !!comp.match(compRe)
924 set = set.map(function (comp) {
925 return new Comparator(comp, this.options)
931 Range.prototype.intersects = function (range, options) {
932 if (!(range instanceof Range)) {
933 throw new TypeError('a Range is required')
936 return this.set.some(function (thisComparators) {
937 return thisComparators.every(function (thisComparator) {
938 return range.set.some(function (rangeComparators) {
939 return rangeComparators.every(function (rangeComparator) {
940 return thisComparator.intersects(rangeComparator, options)
947 // Mostly just for testing and legacy API reasons
948 exports.toComparators = toComparators
949 function toComparators (range, options) {
950 return new Range(range, options).set.map(function (comp) {
951 return comp.map(function (c) {
953 }).join(' ').trim().split(' ')
957 // comprised of xranges, tildes, stars, and gtlt's at this point.
958 // already replaced the hyphen ranges
959 // turn into a set of JUST comparators.
960 function parseComparator (comp, options) {
961 debug('comp', comp, options)
962 comp = replaceCarets(comp, options)
964 comp = replaceTildes(comp, options)
965 debug('tildes', comp)
966 comp = replaceXRanges(comp, options)
967 debug('xrange', comp)
968 comp = replaceStars(comp, options)
974 return !id || id.toLowerCase() === 'x' || id === '*'
977 // ~, ~> --> * (any, kinda silly)
978 // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
979 // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
980 // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
981 // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
982 // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
983 function replaceTildes (comp, options) {
984 return comp.trim().split(/\s+/).map(function (comp) {
985 return replaceTilde(comp, options)
989 function replaceTilde (comp, options) {
990 var r = options.loose ? re[TILDELOOSE] : re[TILDE]
991 return comp.replace(r, function (_, M, m, p, pr) {
992 debug('tilde', comp, _, M, m, p, pr)
998 ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'
1000 // ~1.2 == >=1.2.0 <1.3.0
1001 ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'
1003 debug('replaceTilde pr', pr)
1004 ret = '>=' + M + '.' + m + '.' + p + '-' + pr +
1005 ' <' + M + '.' + (+m + 1) + '.0'
1007 // ~1.2.3 == >=1.2.3 <1.3.0
1008 ret = '>=' + M + '.' + m + '.' + p +
1009 ' <' + M + '.' + (+m + 1) + '.0'
1012 debug('tilde return', ret)
1017 // ^ --> * (any, kinda silly)
1018 // ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
1019 // ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
1020 // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
1021 // ^1.2.3 --> >=1.2.3 <2.0.0
1022 // ^1.2.0 --> >=1.2.0 <2.0.0
1023 function replaceCarets (comp, options) {
1024 return comp.trim().split(/\s+/).map(function (comp) {
1025 return replaceCaret(comp, options)
1029 function replaceCaret (comp, options) {
1030 debug('caret', comp, options)
1031 var r = options.loose ? re[CARETLOOSE] : re[CARET]
1032 return comp.replace(r, function (_, M, m, p, pr) {
1033 debug('caret', comp, _, M, m, p, pr)
1038 } else if (isX(m)) {
1039 ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'
1040 } else if (isX(p)) {
1042 ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'
1044 ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'
1047 debug('replaceCaret pr', pr)
1050 ret = '>=' + M + '.' + m + '.' + p + '-' + pr +
1051 ' <' + M + '.' + m + '.' + (+p + 1)
1053 ret = '>=' + M + '.' + m + '.' + p + '-' + pr +
1054 ' <' + M + '.' + (+m + 1) + '.0'
1057 ret = '>=' + M + '.' + m + '.' + p + '-' + pr +
1058 ' <' + (+M + 1) + '.0.0'
1064 ret = '>=' + M + '.' + m + '.' + p +
1065 ' <' + M + '.' + m + '.' + (+p + 1)
1067 ret = '>=' + M + '.' + m + '.' + p +
1068 ' <' + M + '.' + (+m + 1) + '.0'
1071 ret = '>=' + M + '.' + m + '.' + p +
1072 ' <' + (+M + 1) + '.0.0'
1076 debug('caret return', ret)
1081 function replaceXRanges (comp, options) {
1082 debug('replaceXRanges', comp, options)
1083 return comp.split(/\s+/).map(function (comp) {
1084 return replaceXRange(comp, options)
1088 function replaceXRange (comp, options) {
1090 var r = options.loose ? re[XRANGELOOSE] : re[XRANGE]
1091 return comp.replace(r, function (ret, gtlt, M, m, p, pr) {
1092 debug('xRange', comp, ret, gtlt, M, m, p, pr)
1094 var xm = xM || isX(m)
1095 var xp = xm || isX(p)
1098 if (gtlt === '=' && anyX) {
1103 if (gtlt === '>' || gtlt === '<') {
1104 // nothing is allowed
1107 // nothing is forbidden
1110 } else if (gtlt && anyX) {
1111 // we know patch is an x, because we have any x at all.
1121 // >1.2.3 => >= 1.2.4
1131 } else if (gtlt === '<=') {
1132 // <=0.7.x is actually <0.8.0, since any 0.7.x should
1133 // pass. Similarly, <=7.x is actually <8.0.0, etc.
1142 ret = gtlt + M + '.' + m + '.' + p
1144 ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'
1146 ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'
1149 debug('xRange return', ret)
1155 // Because * is AND-ed with everything else in the comparator,
1156 // and '' means "any version", just remove the *s entirely.
1157 function replaceStars (comp, options) {
1158 debug('replaceStars', comp, options)
1159 // Looseness is ignored here. star is always as loose as it gets!
1160 return comp.trim().replace(re[STAR], '')
1163 // This function is passed to string.replace(re[HYPHENRANGE])
1164 // M, m, patch, prerelease, build
1165 // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
1166 // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
1167 // 1.2 - 3.4 => >=1.2.0 <3.5.0
1168 function hyphenReplace ($0,
1169 from, fM, fm, fp, fpr, fb,
1170 to, tM, tm, tp, tpr, tb) {
1173 } else if (isX(fm)) {
1174 from = '>=' + fM + '.0.0'
1175 } else if (isX(fp)) {
1176 from = '>=' + fM + '.' + fm + '.0'
1183 } else if (isX(tm)) {
1184 to = '<' + (+tM + 1) + '.0.0'
1185 } else if (isX(tp)) {
1186 to = '<' + tM + '.' + (+tm + 1) + '.0'
1188 to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr
1193 return (from + ' ' + to).trim()
1196 // if ANY of the sets match ALL of its comparators, then pass
1197 Range.prototype.test = function (version) {
1202 if (typeof version === 'string') {
1203 version = new SemVer(version, this.options)
1206 for (var i = 0; i < this.set.length; i++) {
1207 if (testSet(this.set[i], version, this.options)) {
1214 function testSet (set, version, options) {
1215 for (var i = 0; i < set.length; i++) {
1216 if (!set[i].test(version)) {
1221 if (version.prerelease.length && !options.includePrerelease) {
1222 // Find the set of versions that are allowed to have prereleases
1223 // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0
1224 // That should allow `1.2.3-pr.2` to pass.
1225 // However, `1.2.4-alpha.notready` should NOT be allowed,
1226 // even though it's within the range set by the comparators.
1227 for (i = 0; i < set.length; i++) {
1228 debug(set[i].semver)
1229 if (set[i].semver === ANY) {
1233 if (set[i].semver.prerelease.length > 0) {
1234 var allowed = set[i].semver
1235 if (allowed.major === version.major &&
1236 allowed.minor === version.minor &&
1237 allowed.patch === version.patch) {
1243 // Version has a -pre, but it's not one of the ones we like.
1250 exports.satisfies = satisfies
1251 function satisfies (version, range, options) {
1253 range = new Range(range, options)
1257 return range.test(version)
1260 exports.maxSatisfying = maxSatisfying
1261 function maxSatisfying (versions, range, options) {
1265 var rangeObj = new Range(range, options)
1269 versions.forEach(function (v) {
1270 if (rangeObj.test(v)) {
1271 // satisfies(v, range, options)
1272 if (!max || maxSV.compare(v) === -1) {
1273 // compare(max, v, true)
1275 maxSV = new SemVer(max, options)
1282 exports.minSatisfying = minSatisfying
1283 function minSatisfying (versions, range, options) {
1287 var rangeObj = new Range(range, options)
1291 versions.forEach(function (v) {
1292 if (rangeObj.test(v)) {
1293 // satisfies(v, range, options)
1294 if (!min || minSV.compare(v) === 1) {
1295 // compare(min, v, true)
1297 minSV = new SemVer(min, options)
1304 exports.minVersion = minVersion
1305 function minVersion (range, loose) {
1306 range = new Range(range, loose)
1308 var minver = new SemVer('0.0.0')
1309 if (range.test(minver)) {
1313 minver = new SemVer('0.0.0-0')
1314 if (range.test(minver)) {
1319 for (var i = 0; i < range.set.length; ++i) {
1320 var comparators = range.set[i]
1322 comparators.forEach(function (comparator) {
1323 // Clone to avoid manipulating the comparator's semver object.
1324 var compver = new SemVer(comparator.semver.version)
1325 switch (comparator.operator) {
1327 if (compver.prerelease.length === 0) {
1330 compver.prerelease.push(0)
1332 compver.raw = compver.format()
1336 if (!minver || gt(minver, compver)) {
1342 /* Ignore maximum versions */
1344 /* istanbul ignore next */
1346 throw new Error('Unexpected operation: ' + comparator.operator)
1351 if (minver && range.test(minver)) {
1358 exports.validRange = validRange
1359 function validRange (range, options) {
1361 // Return '*' instead of '' so that truthiness works.
1362 // This will throw if it's invalid anyway
1363 return new Range(range, options).range || '*'
1369 // Determine if version is less than all the versions possible in the range
1371 function ltr (version, range, options) {
1372 return outside(version, range, '<', options)
1375 // Determine if version is greater than all the versions possible in the range.
1377 function gtr (version, range, options) {
1378 return outside(version, range, '>', options)
1381 exports.outside = outside
1382 function outside (version, range, hilo, options) {
1383 version = new SemVer(version, options)
1384 range = new Range(range, options)
1386 var gtfn, ltefn, ltfn, comp, ecomp
1403 throw new TypeError('Must provide a hilo val of "<" or ">"')
1406 // If it satisifes the range it is not outside
1407 if (satisfies(version, range, options)) {
1411 // From now on, variable terms are as if we're in "gtr" mode.
1412 // but note that everything is flipped for the "ltr" function.
1414 for (var i = 0; i < range.set.length; ++i) {
1415 var comparators = range.set[i]
1420 comparators.forEach(function (comparator) {
1421 if (comparator.semver === ANY) {
1422 comparator = new Comparator('>=0.0.0')
1424 high = high || comparator
1425 low = low || comparator
1426 if (gtfn(comparator.semver, high.semver, options)) {
1428 } else if (ltfn(comparator.semver, low.semver, options)) {
1433 // If the edge version comparator has a operator then our version
1435 if (high.operator === comp || high.operator === ecomp) {
1439 // If the lowest version comparator has an operator and our version
1440 // is less than it then it isn't higher than the range
1441 if ((!low.operator || low.operator === comp) &&
1442 ltefn(version, low.semver)) {
1444 } else if (low.operator === ecomp && ltfn(version, low.semver)) {
1451 exports.prerelease = prerelease
1452 function prerelease (version, options) {
1453 var parsed = parse(version, options)
1454 return (parsed && parsed.prerelease.length) ? parsed.prerelease : null
1457 exports.intersects = intersects
1458 function intersects (r1, r2, options) {
1459 r1 = new Range(r1, options)
1460 r2 = new Range(r2, options)
1461 return r1.intersects(r2)
1464 exports.coerce = coerce
1465 function coerce (version) {
1466 if (version instanceof SemVer) {
1470 if (typeof version !== 'string') {
1474 var match = version.match(re[COERCE])
1476 if (match == null) {
1480 return parse(match[1] +
1481 '.' + (match[2] || '0') +
1482 '.' + (match[3] || '0'))