| const ANY = Symbol('SemVer ANY') |
| // hoisted class for cyclic dependency |
| class Comparator { |
| static get ANY () { |
| return ANY |
| } |
| constructor (comp, options) { |
| if (!options || typeof options !== 'object') { |
| options = { |
| loose: !!options, |
| includePrerelease: false |
| } |
| } |
| |
| if (comp instanceof Comparator) { |
| if (comp.loose === !!options.loose) { |
| return comp |
| } else { |
| comp = comp.value |
| } |
| } |
| |
| debug('comparator', comp, options) |
| this.options = options |
| this.loose = !!options.loose |
| this.parse(comp) |
| |
| if (this.semver === ANY) { |
| this.value = '' |
| } else { |
| this.value = this.operator + this.semver.version |
| } |
| |
| debug('comp', this) |
| } |
| |
| parse (comp) { |
| const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] |
| const m = comp.match(r) |
| |
| if (!m) { |
| throw new TypeError(`Invalid comparator: ${comp}`) |
| } |
| |
| this.operator = m[1] !== undefined ? m[1] : '' |
| if (this.operator === '=') { |
| this.operator = '' |
| } |
| |
| // if it literally is just '>' or '' then allow anything. |
| if (!m[2]) { |
| this.semver = ANY |
| } else { |
| this.semver = new SemVer(m[2], this.options.loose) |
| } |
| } |
| |
| toString () { |
| return this.value |
| } |
| |
| test (version) { |
| debug('Comparator.test', version, this.options.loose) |
| |
| if (this.semver === ANY || version === ANY) { |
| return true |
| } |
| |
| if (typeof version === 'string') { |
| try { |
| version = new SemVer(version, this.options) |
| } catch (er) { |
| return false |
| } |
| } |
| |
| return cmp(version, this.operator, this.semver, this.options) |
| } |
| |
| intersects (comp, options) { |
| if (!(comp instanceof Comparator)) { |
| throw new TypeError('a Comparator is required') |
| } |
| |
| if (!options || typeof options !== 'object') { |
| options = { |
| loose: !!options, |
| includePrerelease: false |
| } |
| } |
| |
| if (this.operator === '') { |
| if (this.value === '') { |
| return true |
| } |
| return new Range(comp.value, options).test(this.value) |
| } else if (comp.operator === '') { |
| if (comp.value === '') { |
| return true |
| } |
| return new Range(this.value, options).test(comp.semver) |
| } |
| |
| const sameDirectionIncreasing = |
| (this.operator === '>=' || this.operator === '>') && |
| (comp.operator === '>=' || comp.operator === '>') |
| const sameDirectionDecreasing = |
| (this.operator === '<=' || this.operator === '<') && |
| (comp.operator === '<=' || comp.operator === '<') |
| const sameSemVer = this.semver.version === comp.semver.version |
| const differentDirectionsInclusive = |
| (this.operator === '>=' || this.operator === '<=') && |
| (comp.operator === '>=' || comp.operator === '<=') |
| const oppositeDirectionsLessThan = |
| cmp(this.semver, '<', comp.semver, options) && |
| (this.operator === '>=' || this.operator === '>') && |
| (comp.operator === '<=' || comp.operator === '<') |
| const oppositeDirectionsGreaterThan = |
| cmp(this.semver, '>', comp.semver, options) && |
| (this.operator === '<=' || this.operator === '<') && |
| (comp.operator === '>=' || comp.operator === '>') |
| |
| return ( |
| sameDirectionIncreasing || |
| sameDirectionDecreasing || |
| (sameSemVer && differentDirectionsInclusive) || |
| oppositeDirectionsLessThan || |
| oppositeDirectionsGreaterThan |
| ) |
| } |
| } |
| |
| module.exports = Comparator |
| |
| const {re, t} = require('../internal/re') |
| const cmp = require('../functions/cmp') |
| const debug = require('../internal/debug') |
| const SemVer = require('./semver') |
| const Range = require('./range') |