1exports = module.exports = SemVer 2 3var debug 4/* istanbul ignore next */ 5if (typeof process === 'object' && 6 process.env && 7 process.env.NODE_DEBUG && 8 /\bsemver\b/i.test(process.env.NODE_DEBUG)) { 9 debug = function () { 10 var args = Array.prototype.slice.call(arguments, 0) 11 args.unshift('SEMVER') 12 console.log.apply(console, args) 13 } 14} else { 15 debug = function () {} 16} 17 18// Note: this is the semver.org version of the spec that it implements 19// Not necessarily the package version of this code. 20exports.SEMVER_SPEC_VERSION = '2.0.0' 21 22var MAX_LENGTH = 256 23var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 24 /* istanbul ignore next */ 9007199254740991 25 26// Max safe segment length for coercion. 27var MAX_SAFE_COMPONENT_LENGTH = 16 28 29// The actual regexps go on exports.re 30var re = exports.re = [] 31var src = exports.src = [] 32var R = 0 33 34// The following Regular Expressions can be used for tokenizing, 35// validating, and parsing SemVer version strings. 36 37// ## Numeric Identifier 38// A single `0`, or a non-zero digit followed by zero or more digits. 39 40var NUMERICIDENTIFIER = R++ 41src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' 42var NUMERICIDENTIFIERLOOSE = R++ 43src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' 44 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. 48 49var NONNUMERICIDENTIFIER = R++ 50src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' 51 52// ## Main Version 53// Three dot-separated numeric identifiers. 54 55var MAINVERSION = R++ 56src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + 57 '(' + src[NUMERICIDENTIFIER] + ')\\.' + 58 '(' + src[NUMERICIDENTIFIER] + ')' 59 60var MAINVERSIONLOOSE = R++ 61src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + 62 '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + 63 '(' + src[NUMERICIDENTIFIERLOOSE] + ')' 64 65// ## Pre-release Version Identifier 66// A numeric identifier, or a non-numeric identifier. 67 68var PRERELEASEIDENTIFIER = R++ 69src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + 70 '|' + src[NONNUMERICIDENTIFIER] + ')' 71 72var PRERELEASEIDENTIFIERLOOSE = R++ 73src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + 74 '|' + src[NONNUMERICIDENTIFIER] + ')' 75 76// ## Pre-release Version 77// Hyphen, followed by one or more dot-separated pre-release version 78// identifiers. 79 80var PRERELEASE = R++ 81src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + 82 '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' 83 84var PRERELEASELOOSE = R++ 85src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + 86 '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' 87 88// ## Build Metadata Identifier 89// Any combination of digits, letters, or hyphens. 90 91var BUILDIDENTIFIER = R++ 92src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' 93 94// ## Build Metadata 95// Plus sign, followed by one or more period-separated build metadata 96// identifiers. 97 98var BUILD = R++ 99src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + 100 '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' 101 102// ## Full Version String 103// A main version, followed optionally by a pre-release version and 104// build metadata. 105 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 109// comparison. 110 111var FULL = R++ 112var FULLPLAIN = 'v?' + src[MAINVERSION] + 113 src[PRERELEASE] + '?' + 114 src[BUILD] + '?' 115 116src[FULL] = '^' + FULLPLAIN + '$' 117 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. 121var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + 122 src[PRERELEASELOOSE] + '?' + 123 src[BUILD] + '?' 124 125var LOOSE = R++ 126src[LOOSE] = '^' + LOOSEPLAIN + '$' 127 128var GTLT = R++ 129src[GTLT] = '((?:<|>)?=?)' 130 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. 134var XRANGEIDENTIFIERLOOSE = R++ 135src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' 136var XRANGEIDENTIFIER = R++ 137src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' 138 139var XRANGEPLAIN = R++ 140src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + 141 '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + 142 '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + 143 '(?:' + src[PRERELEASE] + ')?' + 144 src[BUILD] + '?' + 145 ')?)?' 146 147var XRANGEPLAINLOOSE = R++ 148src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + 149 '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + 150 '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + 151 '(?:' + src[PRERELEASELOOSE] + ')?' + 152 src[BUILD] + '?' + 153 ')?)?' 154 155var XRANGE = R++ 156src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' 157var XRANGELOOSE = R++ 158src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' 159 160// Coercion. 161// Extract anything that could conceivably be a part of a valid semver 162var COERCE = R++ 163src[COERCE] = '(?:^|[^\\d])' + 164 '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + 165 '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + 166 '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + 167 '(?:$|[^\\d])' 168 169// Tilde ranges. 170// Meaning is "reasonably at or greater than" 171var LONETILDE = R++ 172src[LONETILDE] = '(?:~>?)' 173 174var TILDETRIM = R++ 175src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' 176re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') 177var tildeTrimReplace = '$1~' 178 179var TILDE = R++ 180src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' 181var TILDELOOSE = R++ 182src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' 183 184// Caret ranges. 185// Meaning is "at least and backwards compatible with" 186var LONECARET = R++ 187src[LONECARET] = '(?:\\^)' 188 189var CARETTRIM = R++ 190src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' 191re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') 192var caretTrimReplace = '$1^' 193 194var CARET = R++ 195src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' 196var CARETLOOSE = R++ 197src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' 198 199// A simple gt/lt/eq thing, or just "" to indicate "any version" 200var COMPARATORLOOSE = R++ 201src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' 202var COMPARATOR = R++ 203src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' 204 205// An expression to strip any whitespace between the gtlt and the thing 206// it modifies, so that `> 1.2.3` ==> `>1.2.3` 207var COMPARATORTRIM = R++ 208src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + 209 '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' 210 211// this one has to use the /g flag 212re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') 213var comparatorTrimReplace = '$1$2$3' 214 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 218// later. 219var HYPHENRANGE = R++ 220src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + 221 '\\s+-\\s+' + 222 '(' + src[XRANGEPLAIN] + ')' + 223 '\\s*$' 224 225var HYPHENRANGELOOSE = R++ 226src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + 227 '\\s+-\\s+' + 228 '(' + src[XRANGEPLAINLOOSE] + ')' + 229 '\\s*$' 230 231// Star ranges basically just allow anything at all. 232var STAR = R++ 233src[STAR] = '(<|>)?=?\\s*\\*' 234 235// Compile to actual regexp objects. 236// All are flag-free, unless they were created above with a flag. 237for (var i = 0; i < R; i++) { 238 debug(i, src[i]) 239 if (!re[i]) { 240 re[i] = new RegExp(src[i]) 241 } 242} 243 244exports.parse = parse 245function parse (version, options) { 246 if (!options || typeof options !== 'object') { 247 options = { 248 loose: !!options, 249 includePrerelease: false 250 } 251 } 252 253 if (version instanceof SemVer) { 254 return version 255 } 256 257 if (typeof version !== 'string') { 258 return null 259 } 260 261 if (version.length > MAX_LENGTH) { 262 return null 263 } 264 265 var r = options.loose ? re[LOOSE] : re[FULL] 266 if (!r.test(version)) { 267 return null 268 } 269 270 try { 271 return new SemVer(version, options) 272 } catch (er) { 273 return null 274 } 275} 276 277exports.valid = valid 278function valid (version, options) { 279 var v = parse(version, options) 280 return v ? v.version : null 281} 282 283exports.clean = clean 284function clean (version, options) { 285 var s = parse(version.trim().replace(/^[=v]+/, ''), options) 286 return s ? s.version : null 287} 288 289exports.SemVer = SemVer 290 291function SemVer (version, options) { 292 if (!options || typeof options !== 'object') { 293 options = { 294 loose: !!options, 295 includePrerelease: false 296 } 297 } 298 if (version instanceof SemVer) { 299 if (version.loose === options.loose) { 300 return version 301 } else { 302 version = version.version 303 } 304 } else if (typeof version !== 'string') { 305 throw new TypeError('Invalid Version: ' + version) 306 } 307 308 if (version.length > MAX_LENGTH) { 309 throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') 310 } 311 312 if (!(this instanceof SemVer)) { 313 return new SemVer(version, options) 314 } 315 316 debug('SemVer', version, options) 317 this.options = options 318 this.loose = !!options.loose 319 320 var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) 321 322 if (!m) { 323 throw new TypeError('Invalid Version: ' + version) 324 } 325 326 this.raw = version 327 328 // these are actually numbers 329 this.major = +m[1] 330 this.minor = +m[2] 331 this.patch = +m[3] 332 333 if (this.major > MAX_SAFE_INTEGER || this.major < 0) { 334 throw new TypeError('Invalid major version') 335 } 336 337 if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { 338 throw new TypeError('Invalid minor version') 339 } 340 341 if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { 342 throw new TypeError('Invalid patch version') 343 } 344 345 // numberify any prerelease numeric ids 346 if (!m[4]) { 347 this.prerelease = [] 348 } else { 349 this.prerelease = m[4].split('.').map(function (id) { 350 if (/^[0-9]+$/.test(id)) { 351 var num = +id 352 if (num >= 0 && num < MAX_SAFE_INTEGER) { 353 return num 354 } 355 } 356 return id 357 }) 358 } 359 360 this.build = m[5] ? m[5].split('.') : [] 361 this.format() 362} 363 364SemVer.prototype.format = function () { 365 this.version = this.major + '.' + this.minor + '.' + this.patch 366 if (this.prerelease.length) { 367 this.version += '-' + this.prerelease.join('.') 368 } 369 return this.version 370} 371 372SemVer.prototype.toString = function () { 373 return this.version 374} 375 376SemVer.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) 380 } 381 382 return this.compareMain(other) || this.comparePre(other) 383} 384 385SemVer.prototype.compareMain = function (other) { 386 if (!(other instanceof SemVer)) { 387 other = new SemVer(other, this.options) 388 } 389 390 return compareIdentifiers(this.major, other.major) || 391 compareIdentifiers(this.minor, other.minor) || 392 compareIdentifiers(this.patch, other.patch) 393} 394 395SemVer.prototype.comparePre = function (other) { 396 if (!(other instanceof SemVer)) { 397 other = new SemVer(other, this.options) 398 } 399 400 // NOT having a prerelease is > having one 401 if (this.prerelease.length && !other.prerelease.length) { 402 return -1 403 } else if (!this.prerelease.length && other.prerelease.length) { 404 return 1 405 } else if (!this.prerelease.length && !other.prerelease.length) { 406 return 0 407 } 408 409 var i = 0 410 do { 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) { 415 return 0 416 } else if (b === undefined) { 417 return 1 418 } else if (a === undefined) { 419 return -1 420 } else if (a === b) { 421 continue 422 } else { 423 return compareIdentifiers(a, b) 424 } 425 } while (++i) 426} 427 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. 430SemVer.prototype.inc = function (release, identifier) { 431 switch (release) { 432 case 'premajor': 433 this.prerelease.length = 0 434 this.patch = 0 435 this.minor = 0 436 this.major++ 437 this.inc('pre', identifier) 438 break 439 case 'preminor': 440 this.prerelease.length = 0 441 this.patch = 0 442 this.minor++ 443 this.inc('pre', identifier) 444 break 445 case 'prepatch': 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) 452 break 453 // If the input is a non-prerelease version, this acts the same as 454 // prepatch. 455 case 'prerelease': 456 if (this.prerelease.length === 0) { 457 this.inc('patch', identifier) 458 } 459 this.inc('pre', identifier) 460 break 461 462 case 'major': 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 || 468 this.patch !== 0 || 469 this.prerelease.length === 0) { 470 this.major++ 471 } 472 this.minor = 0 473 this.patch = 0 474 this.prerelease = [] 475 break 476 case 'minor': 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) { 482 this.minor++ 483 } 484 this.patch = 0 485 this.prerelease = [] 486 break 487 case 'patch': 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) { 493 this.patch++ 494 } 495 this.prerelease = [] 496 break 497 // This probably shouldn't be used publicly. 498 // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. 499 case 'pre': 500 if (this.prerelease.length === 0) { 501 this.prerelease = [0] 502 } else { 503 var i = this.prerelease.length 504 while (--i >= 0) { 505 if (typeof this.prerelease[i] === 'number') { 506 this.prerelease[i]++ 507 i = -2 508 } 509 } 510 if (i === -1) { 511 // didn't increment anything 512 this.prerelease.push(0) 513 } 514 } 515 if (identifier) { 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] 521 } 522 } else { 523 this.prerelease = [identifier, 0] 524 } 525 } 526 break 527 528 default: 529 throw new Error('invalid increment argument: ' + release) 530 } 531 this.format() 532 this.raw = this.version 533 return this 534} 535 536exports.inc = inc 537function inc (version, release, loose, identifier) { 538 if (typeof (loose) === 'string') { 539 identifier = loose 540 loose = undefined 541 } 542 543 try { 544 return new SemVer(version, loose).inc(release, identifier).version 545 } catch (er) { 546 return null 547 } 548} 549 550exports.diff = diff 551function diff (version1, version2) { 552 if (eq(version1, version2)) { 553 return null 554 } else { 555 var v1 = parse(version1) 556 var v2 = parse(version2) 557 var prefix = '' 558 if (v1.prerelease.length || v2.prerelease.length) { 559 prefix = 'pre' 560 var defaultResult = 'prerelease' 561 } 562 for (var key in v1) { 563 if (key === 'major' || key === 'minor' || key === 'patch') { 564 if (v1[key] !== v2[key]) { 565 return prefix + key 566 } 567 } 568 } 569 return defaultResult // may be undefined 570 } 571} 572 573exports.compareIdentifiers = compareIdentifiers 574 575var numeric = /^[0-9]+$/ 576function compareIdentifiers (a, b) { 577 var anum = numeric.test(a) 578 var bnum = numeric.test(b) 579 580 if (anum && bnum) { 581 a = +a 582 b = +b 583 } 584 585 return a === b ? 0 586 : (anum && !bnum) ? -1 587 : (bnum && !anum) ? 1 588 : a < b ? -1 589 : 1 590} 591 592exports.rcompareIdentifiers = rcompareIdentifiers 593function rcompareIdentifiers (a, b) { 594 return compareIdentifiers(b, a) 595} 596 597exports.major = major 598function major (a, loose) { 599 return new SemVer(a, loose).major 600} 601 602exports.minor = minor 603function minor (a, loose) { 604 return new SemVer(a, loose).minor 605} 606 607exports.patch = patch 608function patch (a, loose) { 609 return new SemVer(a, loose).patch 610} 611 612exports.compare = compare 613function compare (a, b, loose) { 614 return new SemVer(a, loose).compare(new SemVer(b, loose)) 615} 616 617exports.compareLoose = compareLoose 618function compareLoose (a, b) { 619 return compare(a, b, true) 620} 621 622exports.rcompare = rcompare 623function rcompare (a, b, loose) { 624 return compare(b, a, loose) 625} 626 627exports.sort = sort 628function sort (list, loose) { 629 return list.sort(function (a, b) { 630 return exports.compare(a, b, loose) 631 }) 632} 633 634exports.rsort = rsort 635function rsort (list, loose) { 636 return list.sort(function (a, b) { 637 return exports.rcompare(a, b, loose) 638 }) 639} 640 641exports.gt = gt 642function gt (a, b, loose) { 643 return compare(a, b, loose) > 0 644} 645 646exports.lt = lt 647function lt (a, b, loose) { 648 return compare(a, b, loose) < 0 649} 650 651exports.eq = eq 652function eq (a, b, loose) { 653 return compare(a, b, loose) === 0 654} 655 656exports.neq = neq 657function neq (a, b, loose) { 658 return compare(a, b, loose) !== 0 659} 660 661exports.gte = gte 662function gte (a, b, loose) { 663 return compare(a, b, loose) >= 0 664} 665 666exports.lte = lte 667function lte (a, b, loose) { 668 return compare(a, b, loose) <= 0 669} 670 671exports.cmp = cmp 672function cmp (a, op, b, loose) { 673 switch (op) { 674 case '===': 675 if (typeof a === 'object') 676 a = a.version 677 if (typeof b === 'object') 678 b = b.version 679 return a === b 680 681 case '!==': 682 if (typeof a === 'object') 683 a = a.version 684 if (typeof b === 'object') 685 b = b.version 686 return a !== b 687 688 case '': 689 case '=': 690 case '==': 691 return eq(a, b, loose) 692 693 case '!=': 694 return neq(a, b, loose) 695 696 case '>': 697 return gt(a, b, loose) 698 699 case '>=': 700 return gte(a, b, loose) 701 702 case '<': 703 return lt(a, b, loose) 704 705 case '<=': 706 return lte(a, b, loose) 707 708 default: 709 throw new TypeError('Invalid operator: ' + op) 710 } 711} 712 713exports.Comparator = Comparator 714function Comparator (comp, options) { 715 if (!options || typeof options !== 'object') { 716 options = { 717 loose: !!options, 718 includePrerelease: false 719 } 720 } 721 722 if (comp instanceof Comparator) { 723 if (comp.loose === !!options.loose) { 724 return comp 725 } else { 726 comp = comp.value 727 } 728 } 729 730 if (!(this instanceof Comparator)) { 731 return new Comparator(comp, options) 732 } 733 734 debug('comparator', comp, options) 735 this.options = options 736 this.loose = !!options.loose 737 this.parse(comp) 738 739 if (this.semver === ANY) { 740 this.value = '' 741 } else { 742 this.value = this.operator + this.semver.version 743 } 744 745 debug('comp', this) 746} 747 748var ANY = {} 749Comparator.prototype.parse = function (comp) { 750 var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] 751 var m = comp.match(r) 752 753 if (!m) { 754 throw new TypeError('Invalid comparator: ' + comp) 755 } 756 757 this.operator = m[1] 758 if (this.operator === '=') { 759 this.operator = '' 760 } 761 762 // if it literally is just '>' or '' then allow anything. 763 if (!m[2]) { 764 this.semver = ANY 765 } else { 766 this.semver = new SemVer(m[2], this.options.loose) 767 } 768} 769 770Comparator.prototype.toString = function () { 771 return this.value 772} 773 774Comparator.prototype.test = function (version) { 775 debug('Comparator.test', version, this.options.loose) 776 777 if (this.semver === ANY) { 778 return true 779 } 780 781 if (typeof version === 'string') { 782 version = new SemVer(version, this.options) 783 } 784 785 return cmp(version, this.operator, this.semver, this.options) 786} 787 788Comparator.prototype.intersects = function (comp, options) { 789 if (!(comp instanceof Comparator)) { 790 throw new TypeError('a Comparator is required') 791 } 792 793 if (!options || typeof options !== 'object') { 794 options = { 795 loose: !!options, 796 includePrerelease: false 797 } 798 } 799 800 var rangeTmp 801 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) 808 } 809 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 === '>')) 828 829 return sameDirectionIncreasing || sameDirectionDecreasing || 830 (sameSemVer && differentDirectionsInclusive) || 831 oppositeDirectionsLessThan || oppositeDirectionsGreaterThan 832} 833 834exports.Range = Range 835function Range (range, options) { 836 if (!options || typeof options !== 'object') { 837 options = { 838 loose: !!options, 839 includePrerelease: false 840 } 841 } 842 843 if (range instanceof Range) { 844 if (range.loose === !!options.loose && 845 range.includePrerelease === !!options.includePrerelease) { 846 return range 847 } else { 848 return new Range(range.raw, options) 849 } 850 } 851 852 if (range instanceof Comparator) { 853 return new Range(range.value, options) 854 } 855 856 if (!(this instanceof Range)) { 857 return new Range(range, options) 858 } 859 860 this.options = options 861 this.loose = !!options.loose 862 this.includePrerelease = !!options.includePrerelease 863 864 // First, split based on boolean or || 865 this.raw = range 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 870 return c.length 871 }) 872 873 if (!this.set.length) { 874 throw new TypeError('Invalid SemVer Range: ' + range) 875 } 876 877 this.format() 878} 879 880Range.prototype.format = function () { 881 this.range = this.set.map(function (comps) { 882 return comps.join(' ').trim() 883 }).join('||').trim() 884 return this.range 885} 886 887Range.prototype.toString = function () { 888 return this.range 889} 890 891Range.prototype.parseRange = function (range) { 892 var loose = this.options.loose 893 range = range.trim() 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]) 901 902 // `~ 1.2.3` => `~1.2.3` 903 range = range.replace(re[TILDETRIM], tildeTrimReplace) 904 905 // `^ 1.2.3` => `^1.2.3` 906 range = range.replace(re[CARETTRIM], caretTrimReplace) 907 908 // normalize spaces 909 range = range.split(/\s+/).join(' ') 910 911 // At this point, the range is completely trimmed and 912 // ready to be split into comparators. 913 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) 922 }) 923 } 924 set = set.map(function (comp) { 925 return new Comparator(comp, this.options) 926 }, this) 927 928 return set 929} 930 931Range.prototype.intersects = function (range, options) { 932 if (!(range instanceof Range)) { 933 throw new TypeError('a Range is required') 934 } 935 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) 941 }) 942 }) 943 }) 944 }) 945} 946 947// Mostly just for testing and legacy API reasons 948exports.toComparators = toComparators 949function toComparators (range, options) { 950 return new Range(range, options).set.map(function (comp) { 951 return comp.map(function (c) { 952 return c.value 953 }).join(' ').trim().split(' ') 954 }) 955} 956 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. 960function parseComparator (comp, options) { 961 debug('comp', comp, options) 962 comp = replaceCarets(comp, options) 963 debug('caret', comp) 964 comp = replaceTildes(comp, options) 965 debug('tildes', comp) 966 comp = replaceXRanges(comp, options) 967 debug('xrange', comp) 968 comp = replaceStars(comp, options) 969 debug('stars', comp) 970 return comp 971} 972 973function isX (id) { 974 return !id || id.toLowerCase() === 'x' || id === '*' 975} 976 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 983function replaceTildes (comp, options) { 984 return comp.trim().split(/\s+/).map(function (comp) { 985 return replaceTilde(comp, options) 986 }).join(' ') 987} 988 989function 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) 993 var ret 994 995 if (isX(M)) { 996 ret = '' 997 } else if (isX(m)) { 998 ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' 999 } else if (isX(p)) { 1000 // ~1.2 == >=1.2.0 <1.3.0 1001 ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' 1002 } else if (pr) { 1003 debug('replaceTilde pr', pr) 1004 ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 1005 ' <' + M + '.' + (+m + 1) + '.0' 1006 } else { 1007 // ~1.2.3 == >=1.2.3 <1.3.0 1008 ret = '>=' + M + '.' + m + '.' + p + 1009 ' <' + M + '.' + (+m + 1) + '.0' 1010 } 1011 1012 debug('tilde return', ret) 1013 return ret 1014 }) 1015} 1016 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 1023function replaceCarets (comp, options) { 1024 return comp.trim().split(/\s+/).map(function (comp) { 1025 return replaceCaret(comp, options) 1026 }).join(' ') 1027} 1028 1029function 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) 1034 var ret 1035 1036 if (isX(M)) { 1037 ret = '' 1038 } else if (isX(m)) { 1039 ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' 1040 } else if (isX(p)) { 1041 if (M === '0') { 1042 ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' 1043 } else { 1044 ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' 1045 } 1046 } else if (pr) { 1047 debug('replaceCaret pr', pr) 1048 if (M === '0') { 1049 if (m === '0') { 1050 ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 1051 ' <' + M + '.' + m + '.' + (+p + 1) 1052 } else { 1053 ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 1054 ' <' + M + '.' + (+m + 1) + '.0' 1055 } 1056 } else { 1057 ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 1058 ' <' + (+M + 1) + '.0.0' 1059 } 1060 } else { 1061 debug('no pr') 1062 if (M === '0') { 1063 if (m === '0') { 1064 ret = '>=' + M + '.' + m + '.' + p + 1065 ' <' + M + '.' + m + '.' + (+p + 1) 1066 } else { 1067 ret = '>=' + M + '.' + m + '.' + p + 1068 ' <' + M + '.' + (+m + 1) + '.0' 1069 } 1070 } else { 1071 ret = '>=' + M + '.' + m + '.' + p + 1072 ' <' + (+M + 1) + '.0.0' 1073 } 1074 } 1075 1076 debug('caret return', ret) 1077 return ret 1078 }) 1079} 1080 1081function replaceXRanges (comp, options) { 1082 debug('replaceXRanges', comp, options) 1083 return comp.split(/\s+/).map(function (comp) { 1084 return replaceXRange(comp, options) 1085 }).join(' ') 1086} 1087 1088function replaceXRange (comp, options) { 1089 comp = comp.trim() 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) 1093 var xM = isX(M) 1094 var xm = xM || isX(m) 1095 var xp = xm || isX(p) 1096 var anyX = xp 1097 1098 if (gtlt === '=' && anyX) { 1099 gtlt = '' 1100 } 1101 1102 if (xM) { 1103 if (gtlt === '>' || gtlt === '<') { 1104 // nothing is allowed 1105 ret = '<0.0.0' 1106 } else { 1107 // nothing is forbidden 1108 ret = '*' 1109 } 1110 } else if (gtlt && anyX) { 1111 // we know patch is an x, because we have any x at all. 1112 // replace X with 0 1113 if (xm) { 1114 m = 0 1115 } 1116 p = 0 1117 1118 if (gtlt === '>') { 1119 // >1 => >=2.0.0 1120 // >1.2 => >=1.3.0 1121 // >1.2.3 => >= 1.2.4 1122 gtlt = '>=' 1123 if (xm) { 1124 M = +M + 1 1125 m = 0 1126 p = 0 1127 } else { 1128 m = +m + 1 1129 p = 0 1130 } 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. 1134 gtlt = '<' 1135 if (xm) { 1136 M = +M + 1 1137 } else { 1138 m = +m + 1 1139 } 1140 } 1141 1142 ret = gtlt + M + '.' + m + '.' + p 1143 } else if (xm) { 1144 ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' 1145 } else if (xp) { 1146 ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' 1147 } 1148 1149 debug('xRange return', ret) 1150 1151 return ret 1152 }) 1153} 1154 1155// Because * is AND-ed with everything else in the comparator, 1156// and '' means "any version", just remove the *s entirely. 1157function 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], '') 1161} 1162 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 1168function hyphenReplace ($0, 1169 from, fM, fm, fp, fpr, fb, 1170 to, tM, tm, tp, tpr, tb) { 1171 if (isX(fM)) { 1172 from = '' 1173 } else if (isX(fm)) { 1174 from = '>=' + fM + '.0.0' 1175 } else if (isX(fp)) { 1176 from = '>=' + fM + '.' + fm + '.0' 1177 } else { 1178 from = '>=' + from 1179 } 1180 1181 if (isX(tM)) { 1182 to = '' 1183 } else if (isX(tm)) { 1184 to = '<' + (+tM + 1) + '.0.0' 1185 } else if (isX(tp)) { 1186 to = '<' + tM + '.' + (+tm + 1) + '.0' 1187 } else if (tpr) { 1188 to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr 1189 } else { 1190 to = '<=' + to 1191 } 1192 1193 return (from + ' ' + to).trim() 1194} 1195 1196// if ANY of the sets match ALL of its comparators, then pass 1197Range.prototype.test = function (version) { 1198 if (!version) { 1199 return false 1200 } 1201 1202 if (typeof version === 'string') { 1203 version = new SemVer(version, this.options) 1204 } 1205 1206 for (var i = 0; i < this.set.length; i++) { 1207 if (testSet(this.set[i], version, this.options)) { 1208 return true 1209 } 1210 } 1211 return false 1212} 1213 1214function testSet (set, version, options) { 1215 for (var i = 0; i < set.length; i++) { 1216 if (!set[i].test(version)) { 1217 return false 1218 } 1219 } 1220 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) { 1230 continue 1231 } 1232 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) { 1238 return true 1239 } 1240 } 1241 } 1242 1243 // Version has a -pre, but it's not one of the ones we like. 1244 return false 1245 } 1246 1247 return true 1248} 1249 1250exports.satisfies = satisfies 1251function satisfies (version, range, options) { 1252 try { 1253 range = new Range(range, options) 1254 } catch (er) { 1255 return false 1256 } 1257 return range.test(version) 1258} 1259 1260exports.maxSatisfying = maxSatisfying 1261function maxSatisfying (versions, range, options) { 1262 var max = null 1263 var maxSV = null 1264 try { 1265 var rangeObj = new Range(range, options) 1266 } catch (er) { 1267 return null 1268 } 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) 1274 max = v 1275 maxSV = new SemVer(max, options) 1276 } 1277 } 1278 }) 1279 return max 1280} 1281 1282exports.minSatisfying = minSatisfying 1283function minSatisfying (versions, range, options) { 1284 var min = null 1285 var minSV = null 1286 try { 1287 var rangeObj = new Range(range, options) 1288 } catch (er) { 1289 return null 1290 } 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) 1296 min = v 1297 minSV = new SemVer(min, options) 1298 } 1299 } 1300 }) 1301 return min 1302} 1303 1304exports.minVersion = minVersion 1305function minVersion (range, loose) { 1306 range = new Range(range, loose) 1307 1308 var minver = new SemVer('0.0.0') 1309 if (range.test(minver)) { 1310 return minver 1311 } 1312 1313 minver = new SemVer('0.0.0-0') 1314 if (range.test(minver)) { 1315 return minver 1316 } 1317 1318 minver = null 1319 for (var i = 0; i < range.set.length; ++i) { 1320 var comparators = range.set[i] 1321 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) { 1326 case '>': 1327 if (compver.prerelease.length === 0) { 1328 compver.patch++ 1329 } else { 1330 compver.prerelease.push(0) 1331 } 1332 compver.raw = compver.format() 1333 /* fallthrough */ 1334 case '': 1335 case '>=': 1336 if (!minver || gt(minver, compver)) { 1337 minver = compver 1338 } 1339 break 1340 case '<': 1341 case '<=': 1342 /* Ignore maximum versions */ 1343 break 1344 /* istanbul ignore next */ 1345 default: 1346 throw new Error('Unexpected operation: ' + comparator.operator) 1347 } 1348 }) 1349 } 1350 1351 if (minver && range.test(minver)) { 1352 return minver 1353 } 1354 1355 return null 1356} 1357 1358exports.validRange = validRange 1359function validRange (range, options) { 1360 try { 1361 // Return '*' instead of '' so that truthiness works. 1362 // This will throw if it's invalid anyway 1363 return new Range(range, options).range || '*' 1364 } catch (er) { 1365 return null 1366 } 1367} 1368 1369// Determine if version is less than all the versions possible in the range 1370exports.ltr = ltr 1371function ltr (version, range, options) { 1372 return outside(version, range, '<', options) 1373} 1374 1375// Determine if version is greater than all the versions possible in the range. 1376exports.gtr = gtr 1377function gtr (version, range, options) { 1378 return outside(version, range, '>', options) 1379} 1380 1381exports.outside = outside 1382function outside (version, range, hilo, options) { 1383 version = new SemVer(version, options) 1384 range = new Range(range, options) 1385 1386 var gtfn, ltefn, ltfn, comp, ecomp 1387 switch (hilo) { 1388 case '>': 1389 gtfn = gt 1390 ltefn = lte 1391 ltfn = lt 1392 comp = '>' 1393 ecomp = '>=' 1394 break 1395 case '<': 1396 gtfn = lt 1397 ltefn = gte 1398 ltfn = gt 1399 comp = '<' 1400 ecomp = '<=' 1401 break 1402 default: 1403 throw new TypeError('Must provide a hilo val of "<" or ">"') 1404 } 1405 1406 // If it satisifes the range it is not outside 1407 if (satisfies(version, range, options)) { 1408 return false 1409 } 1410 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. 1413 1414 for (var i = 0; i < range.set.length; ++i) { 1415 var comparators = range.set[i] 1416 1417 var high = null 1418 var low = null 1419 1420 comparators.forEach(function (comparator) { 1421 if (comparator.semver === ANY) { 1422 comparator = new Comparator('>=0.0.0') 1423 } 1424 high = high || comparator 1425 low = low || comparator 1426 if (gtfn(comparator.semver, high.semver, options)) { 1427 high = comparator 1428 } else if (ltfn(comparator.semver, low.semver, options)) { 1429 low = comparator 1430 } 1431 }) 1432 1433 // If the edge version comparator has a operator then our version 1434 // isn't outside it 1435 if (high.operator === comp || high.operator === ecomp) { 1436 return false 1437 } 1438 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)) { 1443 return false 1444 } else if (low.operator === ecomp && ltfn(version, low.semver)) { 1445 return false 1446 } 1447 } 1448 return true 1449} 1450 1451exports.prerelease = prerelease 1452function prerelease (version, options) { 1453 var parsed = parse(version, options) 1454 return (parsed && parsed.prerelease.length) ? parsed.prerelease : null 1455} 1456 1457exports.intersects = intersects 1458function intersects (r1, r2, options) { 1459 r1 = new Range(r1, options) 1460 r2 = new Range(r2, options) 1461 return r1.intersects(r2) 1462} 1463 1464exports.coerce = coerce 1465function coerce (version) { 1466 if (version instanceof SemVer) { 1467 return version 1468 } 1469 1470 if (typeof version !== 'string') { 1471 return null 1472 } 1473 1474 var match = version.match(re[COERCE]) 1475 1476 if (match == null) { 1477 return null 1478 } 1479 1480 return parse(match[1] + 1481 '.' + (match[2] || '0') + 1482 '.' + (match[3] || '0')) 1483} 1484