semver 7.3.1 → 7.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/classes/comparator.js +2 -6
- package/classes/range.js +58 -8
- package/classes/semver.js +3 -6
- package/functions/parse.js +2 -6
- package/internal/parse-options.js +11 -0
- package/package.json +5 -2
- package/ranges/min-version.js +5 -2
- package/ranges/outside.js +1 -1
- package/ranges/subset.js +78 -11
package/classes/comparator.js
CHANGED
|
@@ -5,12 +5,7 @@ class Comparator {
|
|
|
5
5
|
return ANY
|
|
6
6
|
}
|
|
7
7
|
constructor (comp, options) {
|
|
8
|
-
|
|
9
|
-
options = {
|
|
10
|
-
loose: !!options,
|
|
11
|
-
includePrerelease: false
|
|
12
|
-
}
|
|
13
|
-
}
|
|
8
|
+
options = parseOptions(options)
|
|
14
9
|
|
|
15
10
|
if (comp instanceof Comparator) {
|
|
16
11
|
if (comp.loose === !!options.loose) {
|
|
@@ -132,6 +127,7 @@ class Comparator {
|
|
|
132
127
|
|
|
133
128
|
module.exports = Comparator
|
|
134
129
|
|
|
130
|
+
const parseOptions = require('../internal/parse-options')
|
|
135
131
|
const {re, t} = require('../internal/re')
|
|
136
132
|
const cmp = require('../functions/cmp')
|
|
137
133
|
const debug = require('../internal/debug')
|
package/classes/range.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
// hoisted class for cyclic dependency
|
|
2
2
|
class Range {
|
|
3
3
|
constructor (range, options) {
|
|
4
|
-
|
|
5
|
-
options = {
|
|
6
|
-
loose: !!options,
|
|
7
|
-
includePrerelease: false
|
|
8
|
-
}
|
|
9
|
-
}
|
|
4
|
+
options = parseOptions(options)
|
|
10
5
|
|
|
11
6
|
if (range instanceof Range) {
|
|
12
7
|
if (
|
|
@@ -46,6 +41,24 @@ class Range {
|
|
|
46
41
|
throw new TypeError(`Invalid SemVer Range: ${range}`)
|
|
47
42
|
}
|
|
48
43
|
|
|
44
|
+
// if we have any that are not the null set, throw out null sets.
|
|
45
|
+
if (this.set.length > 1) {
|
|
46
|
+
// keep the first one, in case they're all null sets
|
|
47
|
+
const first = this.set[0]
|
|
48
|
+
this.set = this.set.filter(c => !isNullSet(c[0]))
|
|
49
|
+
if (this.set.length === 0)
|
|
50
|
+
this.set = [first]
|
|
51
|
+
else if (this.set.length > 1) {
|
|
52
|
+
// if we have any that are *, then the range is just *
|
|
53
|
+
for (const c of this.set) {
|
|
54
|
+
if (c.length === 1 && isAny(c[0])) {
|
|
55
|
+
this.set = [c]
|
|
56
|
+
break
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
this.format()
|
|
50
63
|
}
|
|
51
64
|
|
|
@@ -64,8 +77,17 @@ class Range {
|
|
|
64
77
|
}
|
|
65
78
|
|
|
66
79
|
parseRange (range) {
|
|
67
|
-
const loose = this.options.loose
|
|
68
80
|
range = range.trim()
|
|
81
|
+
|
|
82
|
+
// memoize range parsing for performance.
|
|
83
|
+
// this is a very hot path, and fully deterministic.
|
|
84
|
+
const memoOpts = Object.keys(this.options).join(',')
|
|
85
|
+
const memoKey = `parseRange:${memoOpts}:${range}`
|
|
86
|
+
const cached = cache.get(memoKey)
|
|
87
|
+
if (cached)
|
|
88
|
+
return cached
|
|
89
|
+
|
|
90
|
+
const loose = this.options.loose
|
|
69
91
|
// `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
|
|
70
92
|
const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]
|
|
71
93
|
range = range.replace(hr, hyphenReplace(this.options.includePrerelease))
|
|
@@ -87,15 +109,33 @@ class Range {
|
|
|
87
109
|
// ready to be split into comparators.
|
|
88
110
|
|
|
89
111
|
const compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]
|
|
90
|
-
|
|
112
|
+
const rangeList = range
|
|
91
113
|
.split(' ')
|
|
92
114
|
.map(comp => parseComparator(comp, this.options))
|
|
93
115
|
.join(' ')
|
|
94
116
|
.split(/\s+/)
|
|
117
|
+
// >=0.0.0 is equivalent to *
|
|
95
118
|
.map(comp => replaceGTE0(comp, this.options))
|
|
96
119
|
// in loose mode, throw out any that are not valid comparators
|
|
97
120
|
.filter(this.options.loose ? comp => !!comp.match(compRe) : () => true)
|
|
98
121
|
.map(comp => new Comparator(comp, this.options))
|
|
122
|
+
|
|
123
|
+
// if any comparators are the null set, then replace with JUST null set
|
|
124
|
+
// if more than one comparator, remove any * comparators
|
|
125
|
+
// also, don't include the same comparator more than once
|
|
126
|
+
const l = rangeList.length
|
|
127
|
+
const rangeMap = new Map()
|
|
128
|
+
for (const comp of rangeList) {
|
|
129
|
+
if (isNullSet(comp))
|
|
130
|
+
return [comp]
|
|
131
|
+
rangeMap.set(comp.value, comp)
|
|
132
|
+
}
|
|
133
|
+
if (rangeMap.size > 1 && rangeMap.has(''))
|
|
134
|
+
rangeMap.delete('')
|
|
135
|
+
|
|
136
|
+
const result = [...rangeMap.values()]
|
|
137
|
+
cache.set(memoKey, result)
|
|
138
|
+
return result
|
|
99
139
|
}
|
|
100
140
|
|
|
101
141
|
intersects (range, options) {
|
|
@@ -144,6 +184,10 @@ class Range {
|
|
|
144
184
|
}
|
|
145
185
|
module.exports = Range
|
|
146
186
|
|
|
187
|
+
const LRU = require('lru-cache')
|
|
188
|
+
const cache = new LRU({ max: 1000 })
|
|
189
|
+
|
|
190
|
+
const parseOptions = require('../internal/parse-options')
|
|
147
191
|
const Comparator = require('./comparator')
|
|
148
192
|
const debug = require('../internal/debug')
|
|
149
193
|
const SemVer = require('./semver')
|
|
@@ -155,6 +199,9 @@ const {
|
|
|
155
199
|
caretTrimReplace
|
|
156
200
|
} = require('../internal/re')
|
|
157
201
|
|
|
202
|
+
const isNullSet = c => c.value === '<0.0.0-0'
|
|
203
|
+
const isAny = c => c.value === ''
|
|
204
|
+
|
|
158
205
|
// take a set of comparators and determine whether there
|
|
159
206
|
// exists a version which can satisfy it
|
|
160
207
|
const isSatisfiable = (comparators, options) => {
|
|
@@ -358,6 +405,9 @@ const replaceXRange = (comp, options) => {
|
|
|
358
405
|
}
|
|
359
406
|
}
|
|
360
407
|
|
|
408
|
+
if (gtlt === '<')
|
|
409
|
+
pr = '-0'
|
|
410
|
+
|
|
361
411
|
ret = `${gtlt + M}.${m}.${p}${pr}`
|
|
362
412
|
} else if (xm) {
|
|
363
413
|
ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`
|
package/classes/semver.js
CHANGED
|
@@ -2,15 +2,12 @@ const debug = require('../internal/debug')
|
|
|
2
2
|
const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants')
|
|
3
3
|
const { re, t } = require('../internal/re')
|
|
4
4
|
|
|
5
|
+
const parseOptions = require('../internal/parse-options')
|
|
5
6
|
const { compareIdentifiers } = require('../internal/identifiers')
|
|
6
7
|
class SemVer {
|
|
7
8
|
constructor (version, options) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
loose: !!options,
|
|
11
|
-
includePrerelease: false
|
|
12
|
-
}
|
|
13
|
-
}
|
|
9
|
+
options = parseOptions(options)
|
|
10
|
+
|
|
14
11
|
if (version instanceof SemVer) {
|
|
15
12
|
if (version.loose === !!options.loose &&
|
|
16
13
|
version.includePrerelease === !!options.includePrerelease) {
|
package/functions/parse.js
CHANGED
|
@@ -2,13 +2,9 @@ const {MAX_LENGTH} = require('../internal/constants')
|
|
|
2
2
|
const { re, t } = require('../internal/re')
|
|
3
3
|
const SemVer = require('../classes/semver')
|
|
4
4
|
|
|
5
|
+
const parseOptions = require('../internal/parse-options')
|
|
5
6
|
const parse = (version, options) => {
|
|
6
|
-
|
|
7
|
-
options = {
|
|
8
|
-
loose: !!options,
|
|
9
|
-
includePrerelease: false
|
|
10
|
-
}
|
|
11
|
-
}
|
|
7
|
+
options = parseOptions(options)
|
|
12
8
|
|
|
13
9
|
if (version instanceof SemVer) {
|
|
14
10
|
return version
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// parse out just the options we care about so we always get a consistent
|
|
2
|
+
// obj with keys in a consistent order.
|
|
3
|
+
const opts = ['includePrerelease', 'loose', 'rtl']
|
|
4
|
+
const parseOptions = options =>
|
|
5
|
+
!options ? {}
|
|
6
|
+
: typeof options !== 'object' ? { loose: true }
|
|
7
|
+
: opts.filter(k => options[k]).reduce((options, k) => {
|
|
8
|
+
options[k] = true
|
|
9
|
+
return options
|
|
10
|
+
}, {})
|
|
11
|
+
module.exports = parseOptions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "semver",
|
|
3
|
-
"version": "7.3.
|
|
3
|
+
"version": "7.3.5",
|
|
4
4
|
"description": "The semantic version parser used by npm.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"license": "ISC",
|
|
17
17
|
"repository": "https://github.com/npm/node-semver",
|
|
18
18
|
"bin": {
|
|
19
|
-
"semver": "
|
|
19
|
+
"semver": "bin/semver.js"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"bin/**/*.js",
|
|
@@ -34,5 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=10"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"lru-cache": "^6.0.0"
|
|
37
40
|
}
|
|
38
41
|
}
|
package/ranges/min-version.js
CHANGED
|
@@ -19,6 +19,7 @@ const minVersion = (range, loose) => {
|
|
|
19
19
|
for (let i = 0; i < range.set.length; ++i) {
|
|
20
20
|
const comparators = range.set[i]
|
|
21
21
|
|
|
22
|
+
let setMin = null
|
|
22
23
|
comparators.forEach((comparator) => {
|
|
23
24
|
// Clone to avoid manipulating the comparator's semver object.
|
|
24
25
|
const compver = new SemVer(comparator.semver.version)
|
|
@@ -33,8 +34,8 @@ const minVersion = (range, loose) => {
|
|
|
33
34
|
/* fallthrough */
|
|
34
35
|
case '':
|
|
35
36
|
case '>=':
|
|
36
|
-
if (!
|
|
37
|
-
|
|
37
|
+
if (!setMin || gt(compver, setMin)) {
|
|
38
|
+
setMin = compver
|
|
38
39
|
}
|
|
39
40
|
break
|
|
40
41
|
case '<':
|
|
@@ -46,6 +47,8 @@ const minVersion = (range, loose) => {
|
|
|
46
47
|
throw new Error(`Unexpected operation: ${comparator.operator}`)
|
|
47
48
|
}
|
|
48
49
|
})
|
|
50
|
+
if (setMin && (!minver || gt(minver, setMin)))
|
|
51
|
+
minver = setMin
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
if (minver && range.test(minver)) {
|
package/ranges/outside.js
CHANGED
|
@@ -32,7 +32,7 @@ const outside = (version, range, hilo, options) => {
|
|
|
32
32
|
throw new TypeError('Must provide a hilo val of "<" or ">"')
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// If it
|
|
35
|
+
// If it satisfies the range it is not outside
|
|
36
36
|
if (satisfies(version, range, options)) {
|
|
37
37
|
return false
|
|
38
38
|
}
|
package/ranges/subset.js
CHANGED
|
@@ -1,35 +1,49 @@
|
|
|
1
1
|
const Range = require('../classes/range.js')
|
|
2
|
-
const
|
|
2
|
+
const Comparator = require('../classes/comparator.js')
|
|
3
|
+
const { ANY } = Comparator
|
|
3
4
|
const satisfies = require('../functions/satisfies.js')
|
|
4
5
|
const compare = require('../functions/compare.js')
|
|
5
6
|
|
|
6
7
|
// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff:
|
|
7
|
-
// - Every simple range `r1, r2, ...` is a
|
|
8
|
+
// - Every simple range `r1, r2, ...` is a null set, OR
|
|
9
|
+
// - Every simple range `r1, r2, ...` which is not a null set is a subset of
|
|
10
|
+
// some `R1, R2, ...`
|
|
8
11
|
//
|
|
9
12
|
// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff:
|
|
10
13
|
// - If c is only the ANY comparator
|
|
11
14
|
// - If C is only the ANY comparator, return true
|
|
12
|
-
// - Else return false
|
|
15
|
+
// - Else if in prerelease mode, return false
|
|
16
|
+
// - else replace c with `[>=0.0.0]`
|
|
17
|
+
// - If C is only the ANY comparator
|
|
18
|
+
// - if in prerelease mode, return true
|
|
19
|
+
// - else replace C with `[>=0.0.0]`
|
|
13
20
|
// - Let EQ be the set of = comparators in c
|
|
14
21
|
// - If EQ is more than one, return true (null set)
|
|
15
22
|
// - Let GT be the highest > or >= comparator in c
|
|
16
23
|
// - Let LT be the lowest < or <= comparator in c
|
|
17
24
|
// - If GT and LT, and GT.semver > LT.semver, return true (null set)
|
|
25
|
+
// - If any C is a = range, and GT or LT are set, return false
|
|
18
26
|
// - If EQ
|
|
19
27
|
// - If GT, and EQ does not satisfy GT, return true (null set)
|
|
20
28
|
// - If LT, and EQ does not satisfy LT, return true (null set)
|
|
21
29
|
// - If EQ satisfies every C, return true
|
|
22
30
|
// - Else return false
|
|
23
31
|
// - If GT
|
|
24
|
-
// - If GT is lower than any > or >= comp in C, return false
|
|
32
|
+
// - If GT.semver is lower than any > or >= comp in C, return false
|
|
25
33
|
// - If GT is >=, and GT.semver does not satisfy every C, return false
|
|
34
|
+
// - If GT.semver has a prerelease, and not in prerelease mode
|
|
35
|
+
// - If no C has a prerelease and the GT.semver tuple, return false
|
|
26
36
|
// - If LT
|
|
27
|
-
// - If LT.semver is greater than
|
|
37
|
+
// - If LT.semver is greater than any < or <= comp in C, return false
|
|
28
38
|
// - If LT is <=, and LT.semver does not satisfy every C, return false
|
|
29
|
-
//
|
|
39
|
+
// - If GT.semver has a prerelease, and not in prerelease mode
|
|
40
|
+
// - If no C has a prerelease and the LT.semver tuple, return false
|
|
30
41
|
// - Else return true
|
|
31
42
|
|
|
32
|
-
const subset = (sub, dom, options) => {
|
|
43
|
+
const subset = (sub, dom, options = {}) => {
|
|
44
|
+
if (sub === dom)
|
|
45
|
+
return true
|
|
46
|
+
|
|
33
47
|
sub = new Range(sub, options)
|
|
34
48
|
dom = new Range(dom, options)
|
|
35
49
|
let sawNonNull = false
|
|
@@ -52,8 +66,24 @@ const subset = (sub, dom, options) => {
|
|
|
52
66
|
}
|
|
53
67
|
|
|
54
68
|
const simpleSubset = (sub, dom, options) => {
|
|
55
|
-
if (sub
|
|
56
|
-
return
|
|
69
|
+
if (sub === dom)
|
|
70
|
+
return true
|
|
71
|
+
|
|
72
|
+
if (sub.length === 1 && sub[0].semver === ANY) {
|
|
73
|
+
if (dom.length === 1 && dom[0].semver === ANY)
|
|
74
|
+
return true
|
|
75
|
+
else if (options.includePrerelease)
|
|
76
|
+
sub = [ new Comparator('>=0.0.0-0') ]
|
|
77
|
+
else
|
|
78
|
+
sub = [ new Comparator('>=0.0.0') ]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (dom.length === 1 && dom[0].semver === ANY) {
|
|
82
|
+
if (options.includePrerelease)
|
|
83
|
+
return true
|
|
84
|
+
else
|
|
85
|
+
dom = [ new Comparator('>=0.0.0') ]
|
|
86
|
+
}
|
|
57
87
|
|
|
58
88
|
const eqSet = new Set()
|
|
59
89
|
let gt, lt
|
|
@@ -90,26 +120,57 @@ const simpleSubset = (sub, dom, options) => {
|
|
|
90
120
|
if (!satisfies(eq, String(c), options))
|
|
91
121
|
return false
|
|
92
122
|
}
|
|
123
|
+
|
|
93
124
|
return true
|
|
94
125
|
}
|
|
95
126
|
|
|
96
127
|
let higher, lower
|
|
97
128
|
let hasDomLT, hasDomGT
|
|
129
|
+
// if the subset has a prerelease, we need a comparator in the superset
|
|
130
|
+
// with the same tuple and a prerelease, or it's not a subset
|
|
131
|
+
let needDomLTPre = lt &&
|
|
132
|
+
!options.includePrerelease &&
|
|
133
|
+
lt.semver.prerelease.length ? lt.semver : false
|
|
134
|
+
let needDomGTPre = gt &&
|
|
135
|
+
!options.includePrerelease &&
|
|
136
|
+
gt.semver.prerelease.length ? gt.semver : false
|
|
137
|
+
// exception: <1.2.3-0 is the same as <1.2.3
|
|
138
|
+
if (needDomLTPre && needDomLTPre.prerelease.length === 1 &&
|
|
139
|
+
lt.operator === '<' && needDomLTPre.prerelease[0] === 0) {
|
|
140
|
+
needDomLTPre = false
|
|
141
|
+
}
|
|
142
|
+
|
|
98
143
|
for (const c of dom) {
|
|
99
144
|
hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='
|
|
100
145
|
hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='
|
|
101
146
|
if (gt) {
|
|
147
|
+
if (needDomGTPre) {
|
|
148
|
+
if (c.semver.prerelease && c.semver.prerelease.length &&
|
|
149
|
+
c.semver.major === needDomGTPre.major &&
|
|
150
|
+
c.semver.minor === needDomGTPre.minor &&
|
|
151
|
+
c.semver.patch === needDomGTPre.patch) {
|
|
152
|
+
needDomGTPre = false
|
|
153
|
+
}
|
|
154
|
+
}
|
|
102
155
|
if (c.operator === '>' || c.operator === '>=') {
|
|
103
156
|
higher = higherGT(gt, c, options)
|
|
104
|
-
if (higher === c)
|
|
157
|
+
if (higher === c && higher !== gt)
|
|
105
158
|
return false
|
|
106
159
|
} else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options))
|
|
107
160
|
return false
|
|
108
161
|
}
|
|
109
162
|
if (lt) {
|
|
163
|
+
if (needDomLTPre) {
|
|
164
|
+
if (c.semver.prerelease && c.semver.prerelease.length &&
|
|
165
|
+
c.semver.major === needDomLTPre.major &&
|
|
166
|
+
c.semver.minor === needDomLTPre.minor &&
|
|
167
|
+
c.semver.patch === needDomLTPre.patch) {
|
|
168
|
+
needDomLTPre = false
|
|
169
|
+
}
|
|
170
|
+
}
|
|
110
171
|
if (c.operator === '<' || c.operator === '<=') {
|
|
111
172
|
lower = lowerLT(lt, c, options)
|
|
112
|
-
if (lower === c)
|
|
173
|
+
if (lower === c && lower !== lt)
|
|
113
174
|
return false
|
|
114
175
|
} else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options))
|
|
115
176
|
return false
|
|
@@ -127,6 +188,12 @@ const simpleSubset = (sub, dom, options) => {
|
|
|
127
188
|
if (lt && hasDomGT && !gt && gtltComp !== 0)
|
|
128
189
|
return false
|
|
129
190
|
|
|
191
|
+
// we needed a prerelease range in a specific tuple, but didn't get one
|
|
192
|
+
// then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0,
|
|
193
|
+
// because it includes prereleases in the 1.2.3 tuple
|
|
194
|
+
if (needDomGTPre || needDomLTPre)
|
|
195
|
+
return false
|
|
196
|
+
|
|
130
197
|
return true
|
|
131
198
|
}
|
|
132
199
|
|