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