Passed
Push — main ( 10dbfc...61a674 )
by LCS
05:39 queued 03:09
created

node_modules/semver/semver.js   F

Complexity

Total Complexity 258
Complexity/F 2.84

Size

Lines of Code 1525
Function Count 91

Duplication

Duplicated Lines 45
Ratio 2.95 %

Importance

Changes 0
Metric Value
eloc 931
dl 45
loc 1525
rs 1.669
c 0
b 0
f 0
wmc 258
mnd 167
bc 167
fnc 91
bpm 1.8351
cpm 2.8351
noi 34

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like node_modules/semver/semver.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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