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