github.com/jfrog/frogbot@v1.1.1-0.20231221090046-821a26f50338/action/node_modules/semver/semver.js (about) 1 exports = module.exports = SemVer 2 3 var debug 4 /* istanbul ignore next */ 5 if (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. 20 exports.SEMVER_SPEC_VERSION = '2.0.0' 21 22 var MAX_LENGTH = 256 23 var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 24 /* istanbul ignore next */ 9007199254740991 25 26 // Max safe segment length for coercion. 27 var MAX_SAFE_COMPONENT_LENGTH = 16 28 29 var MAX_SAFE_BUILD_LENGTH = MAX_LENGTH - 6 30 31 // The actual regexps go on exports.re 32 var re = exports.re = [] 33 var safeRe = exports.safeRe = [] 34 var src = exports.src = [] 35 var t = exports.tokens = {} 36 var R = 0 37 38 function tok (n) { 39 t[n] = R++ 40 } 41 42 var LETTERDASHNUMBER = '[a-zA-Z0-9-]' 43 44 // Replace some greedy regex tokens to prevent regex dos issues. These regex are 45 // used internally via the safeRe object since all inputs in this library get 46 // normalized first to trim and collapse all extra whitespace. The original 47 // regexes are exported for userland consumption and lower level usage. A 48 // future breaking change could export the safer regex only with a note that 49 // all input should have extra whitespace removed. 50 var safeRegexReplacements = [ 51 ['\\s', 1], 52 ['\\d', MAX_LENGTH], 53 [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH], 54 ] 55 56 function makeSafeRe (value) { 57 for (var i = 0; i < safeRegexReplacements.length; i++) { 58 var token = safeRegexReplacements[i][0] 59 var max = safeRegexReplacements[i][1] 60 value = value 61 .split(token + '*').join(token + '{0,' + max + '}') 62 .split(token + '+').join(token + '{1,' + max + '}') 63 } 64 return value 65 } 66 67 // The following Regular Expressions can be used for tokenizing, 68 // validating, and parsing SemVer version strings. 69 70 // ## Numeric Identifier 71 // A single `0`, or a non-zero digit followed by zero or more digits. 72 73 tok('NUMERICIDENTIFIER') 74 src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*' 75 tok('NUMERICIDENTIFIERLOOSE') 76 src[t.NUMERICIDENTIFIERLOOSE] = '\\d+' 77 78 // ## Non-numeric Identifier 79 // Zero or more digits, followed by a letter or hyphen, and then zero or 80 // more letters, digits, or hyphens. 81 82 tok('NONNUMERICIDENTIFIER') 83 src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-]' + LETTERDASHNUMBER + '*' 84 85 // ## Main Version 86 // Three dot-separated numeric identifiers. 87 88 tok('MAINVERSION') 89 src[t.MAINVERSION] = '(' + src[t.NUMERICIDENTIFIER] + ')\\.' + 90 '(' + src[t.NUMERICIDENTIFIER] + ')\\.' + 91 '(' + src[t.NUMERICIDENTIFIER] + ')' 92 93 tok('MAINVERSIONLOOSE') 94 src[t.MAINVERSIONLOOSE] = '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' + 95 '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' + 96 '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')' 97 98 // ## Pre-release Version Identifier 99 // A numeric identifier, or a non-numeric identifier. 100 101 tok('PRERELEASEIDENTIFIER') 102 src[t.PRERELEASEIDENTIFIER] = '(?:' + src[t.NUMERICIDENTIFIER] + 103 '|' + src[t.NONNUMERICIDENTIFIER] + ')' 104 105 tok('PRERELEASEIDENTIFIERLOOSE') 106 src[t.PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[t.NUMERICIDENTIFIERLOOSE] + 107 '|' + src[t.NONNUMERICIDENTIFIER] + ')' 108 109 // ## Pre-release Version 110 // Hyphen, followed by one or more dot-separated pre-release version 111 // identifiers. 112 113 tok('PRERELEASE') 114 src[t.PRERELEASE] = '(?:-(' + src[t.PRERELEASEIDENTIFIER] + 115 '(?:\\.' + src[t.PRERELEASEIDENTIFIER] + ')*))' 116 117 tok('PRERELEASELOOSE') 118 src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] + 119 '(?:\\.' + src[t.PRERELEASEIDENTIFIERLOOSE] + ')*))' 120 121 // ## Build Metadata Identifier 122 // Any combination of digits, letters, or hyphens. 123 124 tok('BUILDIDENTIFIER') 125 src[t.BUILDIDENTIFIER] = LETTERDASHNUMBER + '+' 126 127 // ## Build Metadata 128 // Plus sign, followed by one or more period-separated build metadata 129 // identifiers. 130 131 tok('BUILD') 132 src[t.BUILD] = '(?:\\+(' + src[t.BUILDIDENTIFIER] + 133 '(?:\\.' + src[t.BUILDIDENTIFIER] + ')*))' 134 135 // ## Full Version String 136 // A main version, followed optionally by a pre-release version and 137 // build metadata. 138 139 // Note that the only major, minor, patch, and pre-release sections of 140 // the version string are capturing groups. The build metadata is not a 141 // capturing group, because it should not ever be used in version 142 // comparison. 143 144 tok('FULL') 145 tok('FULLPLAIN') 146 src[t.FULLPLAIN] = 'v?' + src[t.MAINVERSION] + 147 src[t.PRERELEASE] + '?' + 148 src[t.BUILD] + '?' 149 150 src[t.FULL] = '^' + src[t.FULLPLAIN] + '$' 151 152 // like full, but allows v1.2.3 and =1.2.3, which people do sometimes. 153 // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty 154 // common in the npm registry. 155 tok('LOOSEPLAIN') 156 src[t.LOOSEPLAIN] = '[v=\\s]*' + src[t.MAINVERSIONLOOSE] + 157 src[t.PRERELEASELOOSE] + '?' + 158 src[t.BUILD] + '?' 159 160 tok('LOOSE') 161 src[t.LOOSE] = '^' + src[t.LOOSEPLAIN] + '$' 162 163 tok('GTLT') 164 src[t.GTLT] = '((?:<|>)?=?)' 165 166 // Something like "2.*" or "1.2.x". 167 // Note that "x.x" is a valid xRange identifer, meaning "any version" 168 // Only the first item is strictly required. 169 tok('XRANGEIDENTIFIERLOOSE') 170 src[t.XRANGEIDENTIFIERLOOSE] = src[t.NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' 171 tok('XRANGEIDENTIFIER') 172 src[t.XRANGEIDENTIFIER] = src[t.NUMERICIDENTIFIER] + '|x|X|\\*' 173 174 tok('XRANGEPLAIN') 175 src[t.XRANGEPLAIN] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIER] + ')' + 176 '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' + 177 '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' + 178 '(?:' + src[t.PRERELEASE] + ')?' + 179 src[t.BUILD] + '?' + 180 ')?)?' 181 182 tok('XRANGEPLAINLOOSE') 183 src[t.XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + 184 '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + 185 '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + 186 '(?:' + src[t.PRERELEASELOOSE] + ')?' + 187 src[t.BUILD] + '?' + 188 ')?)?' 189 190 tok('XRANGE') 191 src[t.XRANGE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAIN] + '$' 192 tok('XRANGELOOSE') 193 src[t.XRANGELOOSE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAINLOOSE] + '$' 194 195 // Coercion. 196 // Extract anything that could conceivably be a part of a valid semver 197 tok('COERCE') 198 src[t.COERCE] = '(^|[^\\d])' + 199 '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + 200 '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + 201 '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + 202 '(?:$|[^\\d])' 203 tok('COERCERTL') 204 re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g') 205 safeRe[t.COERCERTL] = new RegExp(makeSafeRe(src[t.COERCE]), 'g') 206 207 // Tilde ranges. 208 // Meaning is "reasonably at or greater than" 209 tok('LONETILDE') 210 src[t.LONETILDE] = '(?:~>?)' 211 212 tok('TILDETRIM') 213 src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+' 214 re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g') 215 safeRe[t.TILDETRIM] = new RegExp(makeSafeRe(src[t.TILDETRIM]), 'g') 216 var tildeTrimReplace = '$1~' 217 218 tok('TILDE') 219 src[t.TILDE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAIN] + '$' 220 tok('TILDELOOSE') 221 src[t.TILDELOOSE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAINLOOSE] + '$' 222 223 // Caret ranges. 224 // Meaning is "at least and backwards compatible with" 225 tok('LONECARET') 226 src[t.LONECARET] = '(?:\\^)' 227 228 tok('CARETTRIM') 229 src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+' 230 re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g') 231 safeRe[t.CARETTRIM] = new RegExp(makeSafeRe(src[t.CARETTRIM]), 'g') 232 var caretTrimReplace = '$1^' 233 234 tok('CARET') 235 src[t.CARET] = '^' + src[t.LONECARET] + src[t.XRANGEPLAIN] + '$' 236 tok('CARETLOOSE') 237 src[t.CARETLOOSE] = '^' + src[t.LONECARET] + src[t.XRANGEPLAINLOOSE] + '$' 238 239 // A simple gt/lt/eq thing, or just "" to indicate "any version" 240 tok('COMPARATORLOOSE') 241 src[t.COMPARATORLOOSE] = '^' + src[t.GTLT] + '\\s*(' + src[t.LOOSEPLAIN] + ')$|^$' 242 tok('COMPARATOR') 243 src[t.COMPARATOR] = '^' + src[t.GTLT] + '\\s*(' + src[t.FULLPLAIN] + ')$|^$' 244 245 // An expression to strip any whitespace between the gtlt and the thing 246 // it modifies, so that `> 1.2.3` ==> `>1.2.3` 247 tok('COMPARATORTRIM') 248 src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] + 249 '\\s*(' + src[t.LOOSEPLAIN] + '|' + src[t.XRANGEPLAIN] + ')' 250 251 // this one has to use the /g flag 252 re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g') 253 safeRe[t.COMPARATORTRIM] = new RegExp(makeSafeRe(src[t.COMPARATORTRIM]), 'g') 254 var comparatorTrimReplace = '$1$2$3' 255 256 // Something like `1.2.3 - 1.2.4` 257 // Note that these all use the loose form, because they'll be 258 // checked against either the strict or loose comparator form 259 // later. 260 tok('HYPHENRANGE') 261 src[t.HYPHENRANGE] = '^\\s*(' + src[t.XRANGEPLAIN] + ')' + 262 '\\s+-\\s+' + 263 '(' + src[t.XRANGEPLAIN] + ')' + 264 '\\s*$' 265 266 tok('HYPHENRANGELOOSE') 267 src[t.HYPHENRANGELOOSE] = '^\\s*(' + src[t.XRANGEPLAINLOOSE] + ')' + 268 '\\s+-\\s+' + 269 '(' + src[t.XRANGEPLAINLOOSE] + ')' + 270 '\\s*$' 271 272 // Star ranges basically just allow anything at all. 273 tok('STAR') 274 src[t.STAR] = '(<|>)?=?\\s*\\*' 275 276 // Compile to actual regexp objects. 277 // All are flag-free, unless they were created above with a flag. 278 for (var i = 0; i < R; i++) { 279 debug(i, src[i]) 280 if (!re[i]) { 281 re[i] = new RegExp(src[i]) 282 283 // Replace all greedy whitespace to prevent regex dos issues. These regex are 284 // used internally via the safeRe object since all inputs in this library get 285 // normalized first to trim and collapse all extra whitespace. The original 286 // regexes are exported for userland consumption and lower level usage. A 287 // future breaking change could export the safer regex only with a note that 288 // all input should have extra whitespace removed. 289 safeRe[i] = new RegExp(makeSafeRe(src[i])) 290 } 291 } 292 293 exports.parse = parse 294 function parse (version, options) { 295 if (!options || typeof options !== 'object') { 296 options = { 297 loose: !!options, 298 includePrerelease: false 299 } 300 } 301 302 if (version instanceof SemVer) { 303 return version 304 } 305 306 if (typeof version !== 'string') { 307 return null 308 } 309 310 if (version.length > MAX_LENGTH) { 311 return null 312 } 313 314 var r = options.loose ? safeRe[t.LOOSE] : safeRe[t.FULL] 315 if (!r.test(version)) { 316 return null 317 } 318 319 try { 320 return new SemVer(version, options) 321 } catch (er) { 322 return null 323 } 324 } 325 326 exports.valid = valid 327 function valid (version, options) { 328 var v = parse(version, options) 329 return v ? v.version : null 330 } 331 332 exports.clean = clean 333 function clean (version, options) { 334 var s = parse(version.trim().replace(/^[=v]+/, ''), options) 335 return s ? s.version : null 336 } 337 338 exports.SemVer = SemVer 339 340 function SemVer (version, options) { 341 if (!options || typeof options !== 'object') { 342 options = { 343 loose: !!options, 344 includePrerelease: false 345 } 346 } 347 if (version instanceof SemVer) { 348 if (version.loose === options.loose) { 349 return version 350 } else { 351 version = version.version 352 } 353 } else if (typeof version !== 'string') { 354 throw new TypeError('Invalid Version: ' + version) 355 } 356 357 if (version.length > MAX_LENGTH) { 358 throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') 359 } 360 361 if (!(this instanceof SemVer)) { 362 return new SemVer(version, options) 363 } 364 365 debug('SemVer', version, options) 366 this.options = options 367 this.loose = !!options.loose 368 369 var m = version.trim().match(options.loose ? safeRe[t.LOOSE] : safeRe[t.FULL]) 370 371 if (!m) { 372 throw new TypeError('Invalid Version: ' + version) 373 } 374 375 this.raw = version 376 377 // these are actually numbers 378 this.major = +m[1] 379 this.minor = +m[2] 380 this.patch = +m[3] 381 382 if (this.major > MAX_SAFE_INTEGER || this.major < 0) { 383 throw new TypeError('Invalid major version') 384 } 385 386 if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { 387 throw new TypeError('Invalid minor version') 388 } 389 390 if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { 391 throw new TypeError('Invalid patch version') 392 } 393 394 // numberify any prerelease numeric ids 395 if (!m[4]) { 396 this.prerelease = [] 397 } else { 398 this.prerelease = m[4].split('.').map(function (id) { 399 if (/^[0-9]+$/.test(id)) { 400 var num = +id 401 if (num >= 0 && num < MAX_SAFE_INTEGER) { 402 return num 403 } 404 } 405 return id 406 }) 407 } 408 409 this.build = m[5] ? m[5].split('.') : [] 410 this.format() 411 } 412 413 SemVer.prototype.format = function () { 414 this.version = this.major + '.' + this.minor + '.' + this.patch 415 if (this.prerelease.length) { 416 this.version += '-' + this.prerelease.join('.') 417 } 418 return this.version 419 } 420 421 SemVer.prototype.toString = function () { 422 return this.version 423 } 424 425 SemVer.prototype.compare = function (other) { 426 debug('SemVer.compare', this.version, this.options, other) 427 if (!(other instanceof SemVer)) { 428 other = new SemVer(other, this.options) 429 } 430 431 return this.compareMain(other) || this.comparePre(other) 432 } 433 434 SemVer.prototype.compareMain = function (other) { 435 if (!(other instanceof SemVer)) { 436 other = new SemVer(other, this.options) 437 } 438 439 return compareIdentifiers(this.major, other.major) || 440 compareIdentifiers(this.minor, other.minor) || 441 compareIdentifiers(this.patch, other.patch) 442 } 443 444 SemVer.prototype.comparePre = function (other) { 445 if (!(other instanceof SemVer)) { 446 other = new SemVer(other, this.options) 447 } 448 449 // NOT having a prerelease is > having one 450 if (this.prerelease.length && !other.prerelease.length) { 451 return -1 452 } else if (!this.prerelease.length && other.prerelease.length) { 453 return 1 454 } else if (!this.prerelease.length && !other.prerelease.length) { 455 return 0 456 } 457 458 var i = 0 459 do { 460 var a = this.prerelease[i] 461 var b = other.prerelease[i] 462 debug('prerelease compare', i, a, b) 463 if (a === undefined && b === undefined) { 464 return 0 465 } else if (b === undefined) { 466 return 1 467 } else if (a === undefined) { 468 return -1 469 } else if (a === b) { 470 continue 471 } else { 472 return compareIdentifiers(a, b) 473 } 474 } while (++i) 475 } 476 477 SemVer.prototype.compareBuild = function (other) { 478 if (!(other instanceof SemVer)) { 479 other = new SemVer(other, this.options) 480 } 481 482 var i = 0 483 do { 484 var a = this.build[i] 485 var b = other.build[i] 486 debug('prerelease compare', i, a, b) 487 if (a === undefined && b === undefined) { 488 return 0 489 } else if (b === undefined) { 490 return 1 491 } else if (a === undefined) { 492 return -1 493 } else if (a === b) { 494 continue 495 } else { 496 return compareIdentifiers(a, b) 497 } 498 } while (++i) 499 } 500 501 // preminor will bump the version up to the next minor release, and immediately 502 // down to pre-release. premajor and prepatch work the same way. 503 SemVer.prototype.inc = function (release, identifier) { 504 switch (release) { 505 case 'premajor': 506 this.prerelease.length = 0 507 this.patch = 0 508 this.minor = 0 509 this.major++ 510 this.inc('pre', identifier) 511 break 512 case 'preminor': 513 this.prerelease.length = 0 514 this.patch = 0 515 this.minor++ 516 this.inc('pre', identifier) 517 break 518 case 'prepatch': 519 // If this is already a prerelease, it will bump to the next version 520 // drop any prereleases that might already exist, since they are not 521 // relevant at this point. 522 this.prerelease.length = 0 523 this.inc('patch', identifier) 524 this.inc('pre', identifier) 525 break 526 // If the input is a non-prerelease version, this acts the same as 527 // prepatch. 528 case 'prerelease': 529 if (this.prerelease.length === 0) { 530 this.inc('patch', identifier) 531 } 532 this.inc('pre', identifier) 533 break 534 535 case 'major': 536 // If this is a pre-major version, bump up to the same major version. 537 // Otherwise increment major. 538 // 1.0.0-5 bumps to 1.0.0 539 // 1.1.0 bumps to 2.0.0 540 if (this.minor !== 0 || 541 this.patch !== 0 || 542 this.prerelease.length === 0) { 543 this.major++ 544 } 545 this.minor = 0 546 this.patch = 0 547 this.prerelease = [] 548 break 549 case 'minor': 550 // If this is a pre-minor version, bump up to the same minor version. 551 // Otherwise increment minor. 552 // 1.2.0-5 bumps to 1.2.0 553 // 1.2.1 bumps to 1.3.0 554 if (this.patch !== 0 || this.prerelease.length === 0) { 555 this.minor++ 556 } 557 this.patch = 0 558 this.prerelease = [] 559 break 560 case 'patch': 561 // If this is not a pre-release version, it will increment the patch. 562 // If it is a pre-release it will bump up to the same patch version. 563 // 1.2.0-5 patches to 1.2.0 564 // 1.2.0 patches to 1.2.1 565 if (this.prerelease.length === 0) { 566 this.patch++ 567 } 568 this.prerelease = [] 569 break 570 // This probably shouldn't be used publicly. 571 // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. 572 case 'pre': 573 if (this.prerelease.length === 0) { 574 this.prerelease = [0] 575 } else { 576 var i = this.prerelease.length 577 while (--i >= 0) { 578 if (typeof this.prerelease[i] === 'number') { 579 this.prerelease[i]++ 580 i = -2 581 } 582 } 583 if (i === -1) { 584 // didn't increment anything 585 this.prerelease.push(0) 586 } 587 } 588 if (identifier) { 589 // 1.2.0-beta.1 bumps to 1.2.0-beta.2, 590 // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 591 if (this.prerelease[0] === identifier) { 592 if (isNaN(this.prerelease[1])) { 593 this.prerelease = [identifier, 0] 594 } 595 } else { 596 this.prerelease = [identifier, 0] 597 } 598 } 599 break 600 601 default: 602 throw new Error('invalid increment argument: ' + release) 603 } 604 this.format() 605 this.raw = this.version 606 return this 607 } 608 609 exports.inc = inc 610 function inc (version, release, loose, identifier) { 611 if (typeof (loose) === 'string') { 612 identifier = loose 613 loose = undefined 614 } 615 616 try { 617 return new SemVer(version, loose).inc(release, identifier).version 618 } catch (er) { 619 return null 620 } 621 } 622 623 exports.diff = diff 624 function diff (version1, version2) { 625 if (eq(version1, version2)) { 626 return null 627 } else { 628 var v1 = parse(version1) 629 var v2 = parse(version2) 630 var prefix = '' 631 if (v1.prerelease.length || v2.prerelease.length) { 632 prefix = 'pre' 633 var defaultResult = 'prerelease' 634 } 635 for (var key in v1) { 636 if (key === 'major' || key === 'minor' || key === 'patch') { 637 if (v1[key] !== v2[key]) { 638 return prefix + key 639 } 640 } 641 } 642 return defaultResult // may be undefined 643 } 644 } 645 646 exports.compareIdentifiers = compareIdentifiers 647 648 var numeric = /^[0-9]+$/ 649 function compareIdentifiers (a, b) { 650 var anum = numeric.test(a) 651 var bnum = numeric.test(b) 652 653 if (anum && bnum) { 654 a = +a 655 b = +b 656 } 657 658 return a === b ? 0 659 : (anum && !bnum) ? -1 660 : (bnum && !anum) ? 1 661 : a < b ? -1 662 : 1 663 } 664 665 exports.rcompareIdentifiers = rcompareIdentifiers 666 function rcompareIdentifiers (a, b) { 667 return compareIdentifiers(b, a) 668 } 669 670 exports.major = major 671 function major (a, loose) { 672 return new SemVer(a, loose).major 673 } 674 675 exports.minor = minor 676 function minor (a, loose) { 677 return new SemVer(a, loose).minor 678 } 679 680 exports.patch = patch 681 function patch (a, loose) { 682 return new SemVer(a, loose).patch 683 } 684 685 exports.compare = compare 686 function compare (a, b, loose) { 687 return new SemVer(a, loose).compare(new SemVer(b, loose)) 688 } 689 690 exports.compareLoose = compareLoose 691 function compareLoose (a, b) { 692 return compare(a, b, true) 693 } 694 695 exports.compareBuild = compareBuild 696 function compareBuild (a, b, loose) { 697 var versionA = new SemVer(a, loose) 698 var versionB = new SemVer(b, loose) 699 return versionA.compare(versionB) || versionA.compareBuild(versionB) 700 } 701 702 exports.rcompare = rcompare 703 function rcompare (a, b, loose) { 704 return compare(b, a, loose) 705 } 706 707 exports.sort = sort 708 function sort (list, loose) { 709 return list.sort(function (a, b) { 710 return exports.compareBuild(a, b, loose) 711 }) 712 } 713 714 exports.rsort = rsort 715 function rsort (list, loose) { 716 return list.sort(function (a, b) { 717 return exports.compareBuild(b, a, loose) 718 }) 719 } 720 721 exports.gt = gt 722 function gt (a, b, loose) { 723 return compare(a, b, loose) > 0 724 } 725 726 exports.lt = lt 727 function lt (a, b, loose) { 728 return compare(a, b, loose) < 0 729 } 730 731 exports.eq = eq 732 function eq (a, b, loose) { 733 return compare(a, b, loose) === 0 734 } 735 736 exports.neq = neq 737 function neq (a, b, loose) { 738 return compare(a, b, loose) !== 0 739 } 740 741 exports.gte = gte 742 function gte (a, b, loose) { 743 return compare(a, b, loose) >= 0 744 } 745 746 exports.lte = lte 747 function lte (a, b, loose) { 748 return compare(a, b, loose) <= 0 749 } 750 751 exports.cmp = cmp 752 function cmp (a, op, b, loose) { 753 switch (op) { 754 case '===': 755 if (typeof a === 'object') 756 a = a.version 757 if (typeof b === 'object') 758 b = b.version 759 return a === b 760 761 case '!==': 762 if (typeof a === 'object') 763 a = a.version 764 if (typeof b === 'object') 765 b = b.version 766 return a !== b 767 768 case '': 769 case '=': 770 case '==': 771 return eq(a, b, loose) 772 773 case '!=': 774 return neq(a, b, loose) 775 776 case '>': 777 return gt(a, b, loose) 778 779 case '>=': 780 return gte(a, b, loose) 781 782 case '<': 783 return lt(a, b, loose) 784 785 case '<=': 786 return lte(a, b, loose) 787 788 default: 789 throw new TypeError('Invalid operator: ' + op) 790 } 791 } 792 793 exports.Comparator = Comparator 794 function Comparator (comp, options) { 795 if (!options || typeof options !== 'object') { 796 options = { 797 loose: !!options, 798 includePrerelease: false 799 } 800 } 801 802 if (comp instanceof Comparator) { 803 if (comp.loose === !!options.loose) { 804 return comp 805 } else { 806 comp = comp.value 807 } 808 } 809 810 if (!(this instanceof Comparator)) { 811 return new Comparator(comp, options) 812 } 813 814 comp = comp.trim().split(/\s+/).join(' ') 815 debug('comparator', comp, options) 816 this.options = options 817 this.loose = !!options.loose 818 this.parse(comp) 819 820 if (this.semver === ANY) { 821 this.value = '' 822 } else { 823 this.value = this.operator + this.semver.version 824 } 825 826 debug('comp', this) 827 } 828 829 var ANY = {} 830 Comparator.prototype.parse = function (comp) { 831 var r = this.options.loose ? safeRe[t.COMPARATORLOOSE] : safeRe[t.COMPARATOR] 832 var m = comp.match(r) 833 834 if (!m) { 835 throw new TypeError('Invalid comparator: ' + comp) 836 } 837 838 this.operator = m[1] !== undefined ? m[1] : '' 839 if (this.operator === '=') { 840 this.operator = '' 841 } 842 843 // if it literally is just '>' or '' then allow anything. 844 if (!m[2]) { 845 this.semver = ANY 846 } else { 847 this.semver = new SemVer(m[2], this.options.loose) 848 } 849 } 850 851 Comparator.prototype.toString = function () { 852 return this.value 853 } 854 855 Comparator.prototype.test = function (version) { 856 debug('Comparator.test', version, this.options.loose) 857 858 if (this.semver === ANY || version === ANY) { 859 return true 860 } 861 862 if (typeof version === 'string') { 863 try { 864 version = new SemVer(version, this.options) 865 } catch (er) { 866 return false 867 } 868 } 869 870 return cmp(version, this.operator, this.semver, this.options) 871 } 872 873 Comparator.prototype.intersects = function (comp, options) { 874 if (!(comp instanceof Comparator)) { 875 throw new TypeError('a Comparator is required') 876 } 877 878 if (!options || typeof options !== 'object') { 879 options = { 880 loose: !!options, 881 includePrerelease: false 882 } 883 } 884 885 var rangeTmp 886 887 if (this.operator === '') { 888 if (this.value === '') { 889 return true 890 } 891 rangeTmp = new Range(comp.value, options) 892 return satisfies(this.value, rangeTmp, options) 893 } else if (comp.operator === '') { 894 if (comp.value === '') { 895 return true 896 } 897 rangeTmp = new Range(this.value, options) 898 return satisfies(comp.semver, rangeTmp, options) 899 } 900 901 var sameDirectionIncreasing = 902 (this.operator === '>=' || this.operator === '>') && 903 (comp.operator === '>=' || comp.operator === '>') 904 var sameDirectionDecreasing = 905 (this.operator === '<=' || this.operator === '<') && 906 (comp.operator === '<=' || comp.operator === '<') 907 var sameSemVer = this.semver.version === comp.semver.version 908 var differentDirectionsInclusive = 909 (this.operator === '>=' || this.operator === '<=') && 910 (comp.operator === '>=' || comp.operator === '<=') 911 var oppositeDirectionsLessThan = 912 cmp(this.semver, '<', comp.semver, options) && 913 ((this.operator === '>=' || this.operator === '>') && 914 (comp.operator === '<=' || comp.operator === '<')) 915 var oppositeDirectionsGreaterThan = 916 cmp(this.semver, '>', comp.semver, options) && 917 ((this.operator === '<=' || this.operator === '<') && 918 (comp.operator === '>=' || comp.operator === '>')) 919 920 return sameDirectionIncreasing || sameDirectionDecreasing || 921 (sameSemVer && differentDirectionsInclusive) || 922 oppositeDirectionsLessThan || oppositeDirectionsGreaterThan 923 } 924 925 exports.Range = Range 926 function Range (range, options) { 927 if (!options || typeof options !== 'object') { 928 options = { 929 loose: !!options, 930 includePrerelease: false 931 } 932 } 933 934 if (range instanceof Range) { 935 if (range.loose === !!options.loose && 936 range.includePrerelease === !!options.includePrerelease) { 937 return range 938 } else { 939 return new Range(range.raw, options) 940 } 941 } 942 943 if (range instanceof Comparator) { 944 return new Range(range.value, options) 945 } 946 947 if (!(this instanceof Range)) { 948 return new Range(range, options) 949 } 950 951 this.options = options 952 this.loose = !!options.loose 953 this.includePrerelease = !!options.includePrerelease 954 955 // First reduce all whitespace as much as possible so we do not have to rely 956 // on potentially slow regexes like \s*. This is then stored and used for 957 // future error messages as well. 958 this.raw = range 959 .trim() 960 .split(/\s+/) 961 .join(' ') 962 963 // First, split based on boolean or || 964 this.set = this.raw.split('||').map(function (range) { 965 return this.parseRange(range.trim()) 966 }, this).filter(function (c) { 967 // throw out any that are not relevant for whatever reason 968 return c.length 969 }) 970 971 if (!this.set.length) { 972 throw new TypeError('Invalid SemVer Range: ' + this.raw) 973 } 974 975 this.format() 976 } 977 978 Range.prototype.format = function () { 979 this.range = this.set.map(function (comps) { 980 return comps.join(' ').trim() 981 }).join('||').trim() 982 return this.range 983 } 984 985 Range.prototype.toString = function () { 986 return this.range 987 } 988 989 Range.prototype.parseRange = function (range) { 990 var loose = this.options.loose 991 // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` 992 var hr = loose ? safeRe[t.HYPHENRANGELOOSE] : safeRe[t.HYPHENRANGE] 993 range = range.replace(hr, hyphenReplace) 994 debug('hyphen replace', range) 995 // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` 996 range = range.replace(safeRe[t.COMPARATORTRIM], comparatorTrimReplace) 997 debug('comparator trim', range, safeRe[t.COMPARATORTRIM]) 998 999 // `~ 1.2.3` => `~1.2.3` 1000 range = range.replace(safeRe[t.TILDETRIM], tildeTrimReplace) 1001 1002 // `^ 1.2.3` => `^1.2.3` 1003 range = range.replace(safeRe[t.CARETTRIM], caretTrimReplace) 1004 1005 // normalize spaces 1006 range = range.split(/\s+/).join(' ') 1007 1008 // At this point, the range is completely trimmed and 1009 // ready to be split into comparators. 1010 1011 var compRe = loose ? safeRe[t.COMPARATORLOOSE] : safeRe[t.COMPARATOR] 1012 var set = range.split(' ').map(function (comp) { 1013 return parseComparator(comp, this.options) 1014 }, this).join(' ').split(/\s+/) 1015 if (this.options.loose) { 1016 // in loose mode, throw out any that are not valid comparators 1017 set = set.filter(function (comp) { 1018 return !!comp.match(compRe) 1019 }) 1020 } 1021 set = set.map(function (comp) { 1022 return new Comparator(comp, this.options) 1023 }, this) 1024 1025 return set 1026 } 1027 1028 Range.prototype.intersects = function (range, options) { 1029 if (!(range instanceof Range)) { 1030 throw new TypeError('a Range is required') 1031 } 1032 1033 return this.set.some(function (thisComparators) { 1034 return ( 1035 isSatisfiable(thisComparators, options) && 1036 range.set.some(function (rangeComparators) { 1037 return ( 1038 isSatisfiable(rangeComparators, options) && 1039 thisComparators.every(function (thisComparator) { 1040 return rangeComparators.every(function (rangeComparator) { 1041 return thisComparator.intersects(rangeComparator, options) 1042 }) 1043 }) 1044 ) 1045 }) 1046 ) 1047 }) 1048 } 1049 1050 // take a set of comparators and determine whether there 1051 // exists a version which can satisfy it 1052 function isSatisfiable (comparators, options) { 1053 var result = true 1054 var remainingComparators = comparators.slice() 1055 var testComparator = remainingComparators.pop() 1056 1057 while (result && remainingComparators.length) { 1058 result = remainingComparators.every(function (otherComparator) { 1059 return testComparator.intersects(otherComparator, options) 1060 }) 1061 1062 testComparator = remainingComparators.pop() 1063 } 1064 1065 return result 1066 } 1067 1068 // Mostly just for testing and legacy API reasons 1069 exports.toComparators = toComparators 1070 function toComparators (range, options) { 1071 return new Range(range, options).set.map(function (comp) { 1072 return comp.map(function (c) { 1073 return c.value 1074 }).join(' ').trim().split(' ') 1075 }) 1076 } 1077 1078 // comprised of xranges, tildes, stars, and gtlt's at this point. 1079 // already replaced the hyphen ranges 1080 // turn into a set of JUST comparators. 1081 function parseComparator (comp, options) { 1082 debug('comp', comp, options) 1083 comp = replaceCarets(comp, options) 1084 debug('caret', comp) 1085 comp = replaceTildes(comp, options) 1086 debug('tildes', comp) 1087 comp = replaceXRanges(comp, options) 1088 debug('xrange', comp) 1089 comp = replaceStars(comp, options) 1090 debug('stars', comp) 1091 return comp 1092 } 1093 1094 function isX (id) { 1095 return !id || id.toLowerCase() === 'x' || id === '*' 1096 } 1097 1098 // ~, ~> --> * (any, kinda silly) 1099 // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 1100 // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 1101 // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 1102 // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 1103 // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 1104 function replaceTildes (comp, options) { 1105 return comp.trim().split(/\s+/).map(function (comp) { 1106 return replaceTilde(comp, options) 1107 }).join(' ') 1108 } 1109 1110 function replaceTilde (comp, options) { 1111 var r = options.loose ? safeRe[t.TILDELOOSE] : safeRe[t.TILDE] 1112 return comp.replace(r, function (_, M, m, p, pr) { 1113 debug('tilde', comp, _, M, m, p, pr) 1114 var ret 1115 1116 if (isX(M)) { 1117 ret = '' 1118 } else if (isX(m)) { 1119 ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' 1120 } else if (isX(p)) { 1121 // ~1.2 == >=1.2.0 <1.3.0 1122 ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' 1123 } else if (pr) { 1124 debug('replaceTilde pr', pr) 1125 ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 1126 ' <' + M + '.' + (+m + 1) + '.0' 1127 } else { 1128 // ~1.2.3 == >=1.2.3 <1.3.0 1129 ret = '>=' + M + '.' + m + '.' + p + 1130 ' <' + M + '.' + (+m + 1) + '.0' 1131 } 1132 1133 debug('tilde return', ret) 1134 return ret 1135 }) 1136 } 1137 1138 // ^ --> * (any, kinda silly) 1139 // ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 1140 // ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 1141 // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 1142 // ^1.2.3 --> >=1.2.3 <2.0.0 1143 // ^1.2.0 --> >=1.2.0 <2.0.0 1144 function replaceCarets (comp, options) { 1145 return comp.trim().split(/\s+/).map(function (comp) { 1146 return replaceCaret(comp, options) 1147 }).join(' ') 1148 } 1149 1150 function replaceCaret (comp, options) { 1151 debug('caret', comp, options) 1152 var r = options.loose ? safeRe[t.CARETLOOSE] : safeRe[t.CARET] 1153 return comp.replace(r, function (_, M, m, p, pr) { 1154 debug('caret', comp, _, M, m, p, pr) 1155 var ret 1156 1157 if (isX(M)) { 1158 ret = '' 1159 } else if (isX(m)) { 1160 ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' 1161 } else if (isX(p)) { 1162 if (M === '0') { 1163 ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' 1164 } else { 1165 ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' 1166 } 1167 } else if (pr) { 1168 debug('replaceCaret pr', pr) 1169 if (M === '0') { 1170 if (m === '0') { 1171 ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 1172 ' <' + M + '.' + m + '.' + (+p + 1) 1173 } else { 1174 ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 1175 ' <' + M + '.' + (+m + 1) + '.0' 1176 } 1177 } else { 1178 ret = '>=' + M + '.' + m + '.' + p + '-' + pr + 1179 ' <' + (+M + 1) + '.0.0' 1180 } 1181 } else { 1182 debug('no pr') 1183 if (M === '0') { 1184 if (m === '0') { 1185 ret = '>=' + M + '.' + m + '.' + p + 1186 ' <' + M + '.' + m + '.' + (+p + 1) 1187 } else { 1188 ret = '>=' + M + '.' + m + '.' + p + 1189 ' <' + M + '.' + (+m + 1) + '.0' 1190 } 1191 } else { 1192 ret = '>=' + M + '.' + m + '.' + p + 1193 ' <' + (+M + 1) + '.0.0' 1194 } 1195 } 1196 1197 debug('caret return', ret) 1198 return ret 1199 }) 1200 } 1201 1202 function replaceXRanges (comp, options) { 1203 debug('replaceXRanges', comp, options) 1204 return comp.split(/\s+/).map(function (comp) { 1205 return replaceXRange(comp, options) 1206 }).join(' ') 1207 } 1208 1209 function replaceXRange (comp, options) { 1210 comp = comp.trim() 1211 var r = options.loose ? safeRe[t.XRANGELOOSE] : safeRe[t.XRANGE] 1212 return comp.replace(r, function (ret, gtlt, M, m, p, pr) { 1213 debug('xRange', comp, ret, gtlt, M, m, p, pr) 1214 var xM = isX(M) 1215 var xm = xM || isX(m) 1216 var xp = xm || isX(p) 1217 var anyX = xp 1218 1219 if (gtlt === '=' && anyX) { 1220 gtlt = '' 1221 } 1222 1223 // if we're including prereleases in the match, then we need 1224 // to fix this to -0, the lowest possible prerelease value 1225 pr = options.includePrerelease ? '-0' : '' 1226 1227 if (xM) { 1228 if (gtlt === '>' || gtlt === '<') { 1229 // nothing is allowed 1230 ret = '<0.0.0-0' 1231 } else { 1232 // nothing is forbidden 1233 ret = '*' 1234 } 1235 } else if (gtlt && anyX) { 1236 // we know patch is an x, because we have any x at all. 1237 // replace X with 0 1238 if (xm) { 1239 m = 0 1240 } 1241 p = 0 1242 1243 if (gtlt === '>') { 1244 // >1 => >=2.0.0 1245 // >1.2 => >=1.3.0 1246 // >1.2.3 => >= 1.2.4 1247 gtlt = '>=' 1248 if (xm) { 1249 M = +M + 1 1250 m = 0 1251 p = 0 1252 } else { 1253 m = +m + 1 1254 p = 0 1255 } 1256 } else if (gtlt === '<=') { 1257 // <=0.7.x is actually <0.8.0, since any 0.7.x should 1258 // pass. Similarly, <=7.x is actually <8.0.0, etc. 1259 gtlt = '<' 1260 if (xm) { 1261 M = +M + 1 1262 } else { 1263 m = +m + 1 1264 } 1265 } 1266 1267 ret = gtlt + M + '.' + m + '.' + p + pr 1268 } else if (xm) { 1269 ret = '>=' + M + '.0.0' + pr + ' <' + (+M + 1) + '.0.0' + pr 1270 } else if (xp) { 1271 ret = '>=' + M + '.' + m + '.0' + pr + 1272 ' <' + M + '.' + (+m + 1) + '.0' + pr 1273 } 1274 1275 debug('xRange return', ret) 1276 1277 return ret 1278 }) 1279 } 1280 1281 // Because * is AND-ed with everything else in the comparator, 1282 // and '' means "any version", just remove the *s entirely. 1283 function replaceStars (comp, options) { 1284 debug('replaceStars', comp, options) 1285 // Looseness is ignored here. star is always as loose as it gets! 1286 return comp.trim().replace(safeRe[t.STAR], '') 1287 } 1288 1289 // This function is passed to string.replace(re[t.HYPHENRANGE]) 1290 // M, m, patch, prerelease, build 1291 // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 1292 // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do 1293 // 1.2 - 3.4 => >=1.2.0 <3.5.0 1294 function hyphenReplace ($0, 1295 from, fM, fm, fp, fpr, fb, 1296 to, tM, tm, tp, tpr, tb) { 1297 if (isX(fM)) { 1298 from = '' 1299 } else if (isX(fm)) { 1300 from = '>=' + fM + '.0.0' 1301 } else if (isX(fp)) { 1302 from = '>=' + fM + '.' + fm + '.0' 1303 } else { 1304 from = '>=' + from 1305 } 1306 1307 if (isX(tM)) { 1308 to = '' 1309 } else if (isX(tm)) { 1310 to = '<' + (+tM + 1) + '.0.0' 1311 } else if (isX(tp)) { 1312 to = '<' + tM + '.' + (+tm + 1) + '.0' 1313 } else if (tpr) { 1314 to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr 1315 } else { 1316 to = '<=' + to 1317 } 1318 1319 return (from + ' ' + to).trim() 1320 } 1321 1322 // if ANY of the sets match ALL of its comparators, then pass 1323 Range.prototype.test = function (version) { 1324 if (!version) { 1325 return false 1326 } 1327 1328 if (typeof version === 'string') { 1329 try { 1330 version = new SemVer(version, this.options) 1331 } catch (er) { 1332 return false 1333 } 1334 } 1335 1336 for (var i = 0; i < this.set.length; i++) { 1337 if (testSet(this.set[i], version, this.options)) { 1338 return true 1339 } 1340 } 1341 return false 1342 } 1343 1344 function testSet (set, version, options) { 1345 for (var i = 0; i < set.length; i++) { 1346 if (!set[i].test(version)) { 1347 return false 1348 } 1349 } 1350 1351 if (version.prerelease.length && !options.includePrerelease) { 1352 // Find the set of versions that are allowed to have prereleases 1353 // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 1354 // That should allow `1.2.3-pr.2` to pass. 1355 // However, `1.2.4-alpha.notready` should NOT be allowed, 1356 // even though it's within the range set by the comparators. 1357 for (i = 0; i < set.length; i++) { 1358 debug(set[i].semver) 1359 if (set[i].semver === ANY) { 1360 continue 1361 } 1362 1363 if (set[i].semver.prerelease.length > 0) { 1364 var allowed = set[i].semver 1365 if (allowed.major === version.major && 1366 allowed.minor === version.minor && 1367 allowed.patch === version.patch) { 1368 return true 1369 } 1370 } 1371 } 1372 1373 // Version has a -pre, but it's not one of the ones we like. 1374 return false 1375 } 1376 1377 return true 1378 } 1379 1380 exports.satisfies = satisfies 1381 function satisfies (version, range, options) { 1382 try { 1383 range = new Range(range, options) 1384 } catch (er) { 1385 return false 1386 } 1387 return range.test(version) 1388 } 1389 1390 exports.maxSatisfying = maxSatisfying 1391 function maxSatisfying (versions, range, options) { 1392 var max = null 1393 var maxSV = null 1394 try { 1395 var rangeObj = new Range(range, options) 1396 } catch (er) { 1397 return null 1398 } 1399 versions.forEach(function (v) { 1400 if (rangeObj.test(v)) { 1401 // satisfies(v, range, options) 1402 if (!max || maxSV.compare(v) === -1) { 1403 // compare(max, v, true) 1404 max = v 1405 maxSV = new SemVer(max, options) 1406 } 1407 } 1408 }) 1409 return max 1410 } 1411 1412 exports.minSatisfying = minSatisfying 1413 function minSatisfying (versions, range, options) { 1414 var min = null 1415 var minSV = null 1416 try { 1417 var rangeObj = new Range(range, options) 1418 } catch (er) { 1419 return null 1420 } 1421 versions.forEach(function (v) { 1422 if (rangeObj.test(v)) { 1423 // satisfies(v, range, options) 1424 if (!min || minSV.compare(v) === 1) { 1425 // compare(min, v, true) 1426 min = v 1427 minSV = new SemVer(min, options) 1428 } 1429 } 1430 }) 1431 return min 1432 } 1433 1434 exports.minVersion = minVersion 1435 function minVersion (range, loose) { 1436 range = new Range(range, loose) 1437 1438 var minver = new SemVer('0.0.0') 1439 if (range.test(minver)) { 1440 return minver 1441 } 1442 1443 minver = new SemVer('0.0.0-0') 1444 if (range.test(minver)) { 1445 return minver 1446 } 1447 1448 minver = null 1449 for (var i = 0; i < range.set.length; ++i) { 1450 var comparators = range.set[i] 1451 1452 comparators.forEach(function (comparator) { 1453 // Clone to avoid manipulating the comparator's semver object. 1454 var compver = new SemVer(comparator.semver.version) 1455 switch (comparator.operator) { 1456 case '>': 1457 if (compver.prerelease.length === 0) { 1458 compver.patch++ 1459 } else { 1460 compver.prerelease.push(0) 1461 } 1462 compver.raw = compver.format() 1463 /* fallthrough */ 1464 case '': 1465 case '>=': 1466 if (!minver || gt(minver, compver)) { 1467 minver = compver 1468 } 1469 break 1470 case '<': 1471 case '<=': 1472 /* Ignore maximum versions */ 1473 break 1474 /* istanbul ignore next */ 1475 default: 1476 throw new Error('Unexpected operation: ' + comparator.operator) 1477 } 1478 }) 1479 } 1480 1481 if (minver && range.test(minver)) { 1482 return minver 1483 } 1484 1485 return null 1486 } 1487 1488 exports.validRange = validRange 1489 function validRange (range, options) { 1490 try { 1491 // Return '*' instead of '' so that truthiness works. 1492 // This will throw if it's invalid anyway 1493 return new Range(range, options).range || '*' 1494 } catch (er) { 1495 return null 1496 } 1497 } 1498 1499 // Determine if version is less than all the versions possible in the range 1500 exports.ltr = ltr 1501 function ltr (version, range, options) { 1502 return outside(version, range, '<', options) 1503 } 1504 1505 // Determine if version is greater than all the versions possible in the range. 1506 exports.gtr = gtr 1507 function gtr (version, range, options) { 1508 return outside(version, range, '>', options) 1509 } 1510 1511 exports.outside = outside 1512 function outside (version, range, hilo, options) { 1513 version = new SemVer(version, options) 1514 range = new Range(range, options) 1515 1516 var gtfn, ltefn, ltfn, comp, ecomp 1517 switch (hilo) { 1518 case '>': 1519 gtfn = gt 1520 ltefn = lte 1521 ltfn = lt 1522 comp = '>' 1523 ecomp = '>=' 1524 break 1525 case '<': 1526 gtfn = lt 1527 ltefn = gte 1528 ltfn = gt 1529 comp = '<' 1530 ecomp = '<=' 1531 break 1532 default: 1533 throw new TypeError('Must provide a hilo val of "<" or ">"') 1534 } 1535 1536 // If it satisifes the range it is not outside 1537 if (satisfies(version, range, options)) { 1538 return false 1539 } 1540 1541 // From now on, variable terms are as if we're in "gtr" mode. 1542 // but note that everything is flipped for the "ltr" function. 1543 1544 for (var i = 0; i < range.set.length; ++i) { 1545 var comparators = range.set[i] 1546 1547 var high = null 1548 var low = null 1549 1550 comparators.forEach(function (comparator) { 1551 if (comparator.semver === ANY) { 1552 comparator = new Comparator('>=0.0.0') 1553 } 1554 high = high || comparator 1555 low = low || comparator 1556 if (gtfn(comparator.semver, high.semver, options)) { 1557 high = comparator 1558 } else if (ltfn(comparator.semver, low.semver, options)) { 1559 low = comparator 1560 } 1561 }) 1562 1563 // If the edge version comparator has a operator then our version 1564 // isn't outside it 1565 if (high.operator === comp || high.operator === ecomp) { 1566 return false 1567 } 1568 1569 // If the lowest version comparator has an operator and our version 1570 // is less than it then it isn't higher than the range 1571 if ((!low.operator || low.operator === comp) && 1572 ltefn(version, low.semver)) { 1573 return false 1574 } else if (low.operator === ecomp && ltfn(version, low.semver)) { 1575 return false 1576 } 1577 } 1578 return true 1579 } 1580 1581 exports.prerelease = prerelease 1582 function prerelease (version, options) { 1583 var parsed = parse(version, options) 1584 return (parsed && parsed.prerelease.length) ? parsed.prerelease : null 1585 } 1586 1587 exports.intersects = intersects 1588 function intersects (r1, r2, options) { 1589 r1 = new Range(r1, options) 1590 r2 = new Range(r2, options) 1591 return r1.intersects(r2) 1592 } 1593 1594 exports.coerce = coerce 1595 function coerce (version, options) { 1596 if (version instanceof SemVer) { 1597 return version 1598 } 1599 1600 if (typeof version === 'number') { 1601 version = String(version) 1602 } 1603 1604 if (typeof version !== 'string') { 1605 return null 1606 } 1607 1608 options = options || {} 1609 1610 var match = null 1611 if (!options.rtl) { 1612 match = version.match(safeRe[t.COERCE]) 1613 } else { 1614 // Find the right-most coercible string that does not share 1615 // a terminus with a more left-ward coercible string. 1616 // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' 1617 // 1618 // Walk through the string checking with a /g regexp 1619 // Manually set the index so as to pick up overlapping matches. 1620 // Stop when we get a match that ends at the string end, since no 1621 // coercible string can be more right-ward without the same terminus. 1622 var next 1623 while ((next = safeRe[t.COERCERTL].exec(version)) && 1624 (!match || match.index + match[0].length !== version.length) 1625 ) { 1626 if (!match || 1627 next.index + next[0].length !== match.index + match[0].length) { 1628 match = next 1629 } 1630 safeRe[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length 1631 } 1632 // leave it in a clean state 1633 safeRe[t.COERCERTL].lastIndex = -1 1634 } 1635 1636 if (match === null) { 1637 return null 1638 } 1639 1640 return parse(match[2] + 1641 '.' + (match[3] || '0') + 1642 '.' + (match[4] || '0'), options) 1643 }