1 | const ANY = Symbol('SemVer ANY')
|
2 |
|
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 |
|
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')
|