/ node_modules / semver / classes / comparator.js
comparator.js
  1  'use strict'
  2  
  3  const ANY = Symbol('SemVer ANY')
  4  // hoisted class for cyclic dependency
  5  class Comparator {
  6    static get ANY () {
  7      return ANY
  8    }
  9  
 10    constructor (comp, options) {
 11      options = parseOptions(options)
 12  
 13      if (comp instanceof Comparator) {
 14        if (comp.loose === !!options.loose) {
 15          return comp
 16        } else {
 17          comp = comp.value
 18        }
 19      }
 20  
 21      comp = comp.trim().split(/\s+/).join(' ')
 22      debug('comparator', comp, options)
 23      this.options = options
 24      this.loose = !!options.loose
 25      this.parse(comp)
 26  
 27      if (this.semver === ANY) {
 28        this.value = ''
 29      } else {
 30        this.value = this.operator + this.semver.version
 31      }
 32  
 33      debug('comp', this)
 34    }
 35  
 36    parse (comp) {
 37      const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
 38      const m = comp.match(r)
 39  
 40      if (!m) {
 41        throw new TypeError(`Invalid comparator: ${comp}`)
 42      }
 43  
 44      this.operator = m[1] !== undefined ? m[1] : ''
 45      if (this.operator === '=') {
 46        this.operator = ''
 47      }
 48  
 49      // if it literally is just '>' or '' then allow anything.
 50      if (!m[2]) {
 51        this.semver = ANY
 52      } else {
 53        this.semver = new SemVer(m[2], this.options.loose)
 54      }
 55    }
 56  
 57    toString () {
 58      return this.value
 59    }
 60  
 61    test (version) {
 62      debug('Comparator.test', version, this.options.loose)
 63  
 64      if (this.semver === ANY || version === ANY) {
 65        return true
 66      }
 67  
 68      if (typeof version === 'string') {
 69        try {
 70          version = new SemVer(version, this.options)
 71        } catch (er) {
 72          return false
 73        }
 74      }
 75  
 76      return cmp(version, this.operator, this.semver, this.options)
 77    }
 78  
 79    intersects (comp, options) {
 80      if (!(comp instanceof Comparator)) {
 81        throw new TypeError('a Comparator is required')
 82      }
 83  
 84      if (this.operator === '') {
 85        if (this.value === '') {
 86          return true
 87        }
 88        return new Range(comp.value, options).test(this.value)
 89      } else if (comp.operator === '') {
 90        if (comp.value === '') {
 91          return true
 92        }
 93        return new Range(this.value, options).test(comp.semver)
 94      }
 95  
 96      options = parseOptions(options)
 97  
 98      // Special cases where nothing can possibly be lower
 99      if (options.includePrerelease &&
100        (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) {
101        return false
102      }
103      if (!options.includePrerelease &&
104        (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) {
105        return false
106      }
107  
108      // Same direction increasing (> or >=)
109      if (this.operator.startsWith('>') && comp.operator.startsWith('>')) {
110        return true
111      }
112      // Same direction decreasing (< or <=)
113      if (this.operator.startsWith('<') && comp.operator.startsWith('<')) {
114        return true
115      }
116      // same SemVer and both sides are inclusive (<= or >=)
117      if (
118        (this.semver.version === comp.semver.version) &&
119        this.operator.includes('=') && comp.operator.includes('=')) {
120        return true
121      }
122      // opposite directions less than
123      if (cmp(this.semver, '<', comp.semver, options) &&
124        this.operator.startsWith('>') && comp.operator.startsWith('<')) {
125        return true
126      }
127      // opposite directions greater than
128      if (cmp(this.semver, '>', comp.semver, options) &&
129        this.operator.startsWith('<') && comp.operator.startsWith('>')) {
130        return true
131      }
132      return false
133    }
134  }
135  
136  module.exports = Comparator
137  
138  const parseOptions = require('../internal/parse-options')
139  const { safeRe: re, t } = require('../internal/re')
140  const cmp = require('../functions/cmp')
141  const debug = require('../internal/debug')
142  const SemVer = require('./semver')
143  const Range = require('./range')