semver 7.2.3 → 7.3.3
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/CHANGELOG.md +10 -0
- package/README.md +26 -23
- package/classes/comparator.js +2 -6
- package/classes/range.js +96 -39
- package/classes/semver.js +3 -6
- package/functions/parse.js +2 -6
- package/index.js +1 -0
- package/internal/parse-options.js +11 -0
- package/internal/re.js +3 -0
- package/package.json +5 -2
- package/ranges/min-version.js +5 -2
- package/ranges/outside.js +1 -1
- package/ranges/subset.js +162 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# changes log
|
|
2
2
|
|
|
3
|
+
## 7.3.0
|
|
4
|
+
|
|
5
|
+
* Add `subset(r1, r2)` method to determine if `r1` range is entirely
|
|
6
|
+
contained by `r2` range.
|
|
7
|
+
|
|
8
|
+
## 7.2.3
|
|
9
|
+
|
|
10
|
+
* Fix handling of `includePrelease` mode where version ranges like `1.0.0 -
|
|
11
|
+
2.0.0` would include `3.0.0-pre` and not `1.0.0-pre`.
|
|
12
|
+
|
|
3
13
|
## 7.2.2
|
|
4
14
|
|
|
5
15
|
* Fix bug where `2.0.0-pre` would be included in `^1.0.0` if
|
package/README.md
CHANGED
|
@@ -79,6 +79,7 @@ const semverGtr = require('semver/ranges/gtr')
|
|
|
79
79
|
const semverLtr = require('semver/ranges/ltr')
|
|
80
80
|
const semverIntersects = require('semver/ranges/intersects')
|
|
81
81
|
const simplifyRange = require('semver/ranges/simplify')
|
|
82
|
+
const rangeSubset = require('semver/ranges/subset')
|
|
82
83
|
```
|
|
83
84
|
|
|
84
85
|
As a command-line utility:
|
|
@@ -255,8 +256,8 @@ inclusive range, then all versions that start with the supplied parts
|
|
|
255
256
|
of the tuple are accepted, but nothing that would be greater than the
|
|
256
257
|
provided tuple parts.
|
|
257
258
|
|
|
258
|
-
* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0`
|
|
259
|
-
* `1.2.3 - 2` := `>=1.2.3 <3.0.0`
|
|
259
|
+
* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0-0`
|
|
260
|
+
* `1.2.3 - 2` := `>=1.2.3 <3.0.0-0`
|
|
260
261
|
|
|
261
262
|
#### X-Ranges `1.2.x` `1.X` `1.2.*` `*`
|
|
262
263
|
|
|
@@ -264,28 +265,28 @@ Any of `X`, `x`, or `*` may be used to "stand in" for one of the
|
|
|
264
265
|
numeric values in the `[major, minor, patch]` tuple.
|
|
265
266
|
|
|
266
267
|
* `*` := `>=0.0.0` (Any version satisfies)
|
|
267
|
-
* `1.x` := `>=1.0.0 <2.0.0` (Matching major version)
|
|
268
|
-
* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions)
|
|
268
|
+
* `1.x` := `>=1.0.0 <2.0.0-0` (Matching major version)
|
|
269
|
+
* `1.2.x` := `>=1.2.0 <1.3.0-0` (Matching major and minor versions)
|
|
269
270
|
|
|
270
271
|
A partial version range is treated as an X-Range, so the special
|
|
271
272
|
character is in fact optional.
|
|
272
273
|
|
|
273
274
|
* `""` (empty string) := `*` := `>=0.0.0`
|
|
274
|
-
* `1` := `1.x.x` := `>=1.0.0 <2.0.0`
|
|
275
|
-
* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0`
|
|
275
|
+
* `1` := `1.x.x` := `>=1.0.0 <2.0.0-0`
|
|
276
|
+
* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0-0`
|
|
276
277
|
|
|
277
278
|
#### Tilde Ranges `~1.2.3` `~1.2` `~1`
|
|
278
279
|
|
|
279
280
|
Allows patch-level changes if a minor version is specified on the
|
|
280
281
|
comparator. Allows minor-level changes if not.
|
|
281
282
|
|
|
282
|
-
* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0`
|
|
283
|
-
* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`)
|
|
284
|
-
* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`)
|
|
285
|
-
* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0`
|
|
286
|
-
* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`)
|
|
287
|
-
* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`)
|
|
288
|
-
* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in
|
|
283
|
+
* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0-0`
|
|
284
|
+
* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0-0` (Same as `1.2.x`)
|
|
285
|
+
* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0-0` (Same as `1.x`)
|
|
286
|
+
* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0-0`
|
|
287
|
+
* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0-0` (Same as `0.2.x`)
|
|
288
|
+
* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0-0` (Same as `0.x`)
|
|
289
|
+
* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0-0` Note that prereleases in
|
|
289
290
|
the `1.2.3` version will be allowed, if they are greater than or
|
|
290
291
|
equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
|
|
291
292
|
`1.2.4-beta.2` would not, because it is a prerelease of a
|
|
@@ -307,15 +308,15 @@ However, it presumes that there will *not* be breaking changes between
|
|
|
307
308
|
`0.2.4` and `0.2.5`. It allows for changes that are presumed to be
|
|
308
309
|
additive (but non-breaking), according to commonly observed practices.
|
|
309
310
|
|
|
310
|
-
* `^1.2.3` := `>=1.2.3 <2.0.0`
|
|
311
|
-
* `^0.2.3` := `>=0.2.3 <0.3.0`
|
|
312
|
-
* `^0.0.3` := `>=0.0.3 <0.0.4`
|
|
313
|
-
* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in
|
|
311
|
+
* `^1.2.3` := `>=1.2.3 <2.0.0-0`
|
|
312
|
+
* `^0.2.3` := `>=0.2.3 <0.3.0-0`
|
|
313
|
+
* `^0.0.3` := `>=0.0.3 <0.0.4-0`
|
|
314
|
+
* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0-0` Note that prereleases in
|
|
314
315
|
the `1.2.3` version will be allowed, if they are greater than or
|
|
315
316
|
equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but
|
|
316
317
|
`1.2.4-beta.2` would not, because it is a prerelease of a
|
|
317
318
|
different `[major, minor, patch]` tuple.
|
|
318
|
-
* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the
|
|
319
|
+
* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4-0` Note that prereleases in the
|
|
319
320
|
`0.0.3` version *only* will be allowed, if they are greater than or
|
|
320
321
|
equal to `beta`. So, `0.0.3-pr.2` would be allowed.
|
|
321
322
|
|
|
@@ -323,16 +324,16 @@ When parsing caret ranges, a missing `patch` value desugars to the
|
|
|
323
324
|
number `0`, but will allow flexibility within that value, even if the
|
|
324
325
|
major and minor versions are both `0`.
|
|
325
326
|
|
|
326
|
-
* `^1.2.x` := `>=1.2.0 <2.0.0`
|
|
327
|
-
* `^0.0.x` := `>=0.0.0 <0.1.0`
|
|
328
|
-
* `^0.0` := `>=0.0.0 <0.1.0`
|
|
327
|
+
* `^1.2.x` := `>=1.2.0 <2.0.0-0`
|
|
328
|
+
* `^0.0.x` := `>=0.0.0 <0.1.0-0`
|
|
329
|
+
* `^0.0` := `>=0.0.0 <0.1.0-0`
|
|
329
330
|
|
|
330
331
|
A missing `minor` and `patch` values will desugar to zero, but also
|
|
331
332
|
allow flexibility within those values, even if the major version is
|
|
332
333
|
zero.
|
|
333
334
|
|
|
334
|
-
* `^1.x` := `>=1.0.0 <2.0.0`
|
|
335
|
-
* `^0.x` := `>=0.0.0 <1.0.0`
|
|
335
|
+
* `^1.x` := `>=1.0.0 <2.0.0-0`
|
|
336
|
+
* `^0.x` := `>=0.0.0 <1.0.0-0`
|
|
336
337
|
|
|
337
338
|
### Range Grammar
|
|
338
339
|
|
|
@@ -455,6 +456,8 @@ strings that they parse.
|
|
|
455
456
|
programmatically, to provide the user with something a bit more
|
|
456
457
|
ergonomic. If the provided range is shorter in string-length than the
|
|
457
458
|
generated range, then that is returned.
|
|
459
|
+
* `subset(subRange, superRange)`: Return `true` if the `subRange` range is
|
|
460
|
+
entirely contained by the `superRange` range.
|
|
458
461
|
|
|
459
462
|
Note that, since ranges may be non-contiguous, a version might not be
|
|
460
463
|
greater than a range, less than a range, *or* satisfy a range! For
|
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,14 +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 *
|
|
118
|
+
.map(comp => replaceGTE0(comp, this.options))
|
|
95
119
|
// in loose mode, throw out any that are not valid comparators
|
|
96
120
|
.filter(this.options.loose ? comp => !!comp.match(compRe) : () => true)
|
|
97
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
|
|
98
139
|
}
|
|
99
140
|
|
|
100
141
|
intersects (range, options) {
|
|
@@ -143,6 +184,10 @@ class Range {
|
|
|
143
184
|
}
|
|
144
185
|
module.exports = Range
|
|
145
186
|
|
|
187
|
+
const LRU = require('lru-cache')
|
|
188
|
+
const cache = new LRU({ max: 1000 })
|
|
189
|
+
|
|
190
|
+
const parseOptions = require('../internal/parse-options')
|
|
146
191
|
const Comparator = require('./comparator')
|
|
147
192
|
const debug = require('../internal/debug')
|
|
148
193
|
const SemVer = require('./semver')
|
|
@@ -154,6 +199,9 @@ const {
|
|
|
154
199
|
caretTrimReplace
|
|
155
200
|
} = require('../internal/re')
|
|
156
201
|
|
|
202
|
+
const isNullSet = c => c.value === '<0.0.0-0'
|
|
203
|
+
const isAny = c => c.value === ''
|
|
204
|
+
|
|
157
205
|
// take a set of comparators and determine whether there
|
|
158
206
|
// exists a version which can satisfy it
|
|
159
207
|
const isSatisfiable = (comparators, options) => {
|
|
@@ -191,11 +239,11 @@ const parseComparator = (comp, options) => {
|
|
|
191
239
|
const isX = id => !id || id.toLowerCase() === 'x' || id === '*'
|
|
192
240
|
|
|
193
241
|
// ~, ~> --> * (any, kinda silly)
|
|
194
|
-
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0
|
|
195
|
-
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0
|
|
196
|
-
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0
|
|
197
|
-
// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0
|
|
198
|
-
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0
|
|
242
|
+
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0
|
|
243
|
+
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0
|
|
244
|
+
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0
|
|
245
|
+
// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0
|
|
246
|
+
// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0
|
|
199
247
|
const replaceTildes = (comp, options) =>
|
|
200
248
|
comp.trim().split(/\s+/).map((comp) => {
|
|
201
249
|
return replaceTilde(comp, options)
|
|
@@ -210,18 +258,18 @@ const replaceTilde = (comp, options) => {
|
|
|
210
258
|
if (isX(M)) {
|
|
211
259
|
ret = ''
|
|
212
260
|
} else if (isX(m)) {
|
|
213
|
-
ret = `>=${M}.0.0 <${+M + 1}.0.0`
|
|
261
|
+
ret = `>=${M}.0.0 <${+M + 1}.0.0-0`
|
|
214
262
|
} else if (isX(p)) {
|
|
215
|
-
// ~1.2 == >=1.2.0 <1.3.0
|
|
216
|
-
ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0`
|
|
263
|
+
// ~1.2 == >=1.2.0 <1.3.0-0
|
|
264
|
+
ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`
|
|
217
265
|
} else if (pr) {
|
|
218
266
|
debug('replaceTilde pr', pr)
|
|
219
267
|
ret = `>=${M}.${m}.${p}-${pr
|
|
220
|
-
} <${M}.${+m + 1}.0`
|
|
268
|
+
} <${M}.${+m + 1}.0-0`
|
|
221
269
|
} else {
|
|
222
|
-
// ~1.2.3 == >=1.2.3 <1.3.0
|
|
270
|
+
// ~1.2.3 == >=1.2.3 <1.3.0-0
|
|
223
271
|
ret = `>=${M}.${m}.${p
|
|
224
|
-
} <${M}.${+m + 1}.0`
|
|
272
|
+
} <${M}.${+m + 1}.0-0`
|
|
225
273
|
}
|
|
226
274
|
|
|
227
275
|
debug('tilde return', ret)
|
|
@@ -230,11 +278,11 @@ const replaceTilde = (comp, options) => {
|
|
|
230
278
|
}
|
|
231
279
|
|
|
232
280
|
// ^ --> * (any, kinda silly)
|
|
233
|
-
// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0
|
|
234
|
-
// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0
|
|
235
|
-
// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0
|
|
236
|
-
// ^1.2.3 --> >=1.2.3 <2.0.0
|
|
237
|
-
// ^1.2.0 --> >=1.2.0 <2.0.0
|
|
281
|
+
// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0
|
|
282
|
+
// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0
|
|
283
|
+
// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0
|
|
284
|
+
// ^1.2.3 --> >=1.2.3 <2.0.0-0
|
|
285
|
+
// ^1.2.0 --> >=1.2.0 <2.0.0-0
|
|
238
286
|
const replaceCarets = (comp, options) =>
|
|
239
287
|
comp.trim().split(/\s+/).map((comp) => {
|
|
240
288
|
return replaceCaret(comp, options)
|
|
@@ -251,40 +299,40 @@ const replaceCaret = (comp, options) => {
|
|
|
251
299
|
if (isX(M)) {
|
|
252
300
|
ret = ''
|
|
253
301
|
} else if (isX(m)) {
|
|
254
|
-
ret = `>=${M}.0.0${z} <${+M + 1}.0.0
|
|
302
|
+
ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`
|
|
255
303
|
} else if (isX(p)) {
|
|
256
304
|
if (M === '0') {
|
|
257
|
-
ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0
|
|
305
|
+
ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`
|
|
258
306
|
} else {
|
|
259
|
-
ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0
|
|
307
|
+
ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`
|
|
260
308
|
}
|
|
261
309
|
} else if (pr) {
|
|
262
310
|
debug('replaceCaret pr', pr)
|
|
263
311
|
if (M === '0') {
|
|
264
312
|
if (m === '0') {
|
|
265
313
|
ret = `>=${M}.${m}.${p}-${pr
|
|
266
|
-
} <${M}.${m}.${+p + 1}
|
|
314
|
+
} <${M}.${m}.${+p + 1}-0`
|
|
267
315
|
} else {
|
|
268
316
|
ret = `>=${M}.${m}.${p}-${pr
|
|
269
|
-
} <${M}.${+m + 1}.0
|
|
317
|
+
} <${M}.${+m + 1}.0-0`
|
|
270
318
|
}
|
|
271
319
|
} else {
|
|
272
320
|
ret = `>=${M}.${m}.${p}-${pr
|
|
273
|
-
} <${+M + 1}.0.0
|
|
321
|
+
} <${+M + 1}.0.0-0`
|
|
274
322
|
}
|
|
275
323
|
} else {
|
|
276
324
|
debug('no pr')
|
|
277
325
|
if (M === '0') {
|
|
278
326
|
if (m === '0') {
|
|
279
327
|
ret = `>=${M}.${m}.${p
|
|
280
|
-
}${z} <${M}.${m}.${+p + 1}
|
|
328
|
+
}${z} <${M}.${m}.${+p + 1}-0`
|
|
281
329
|
} else {
|
|
282
330
|
ret = `>=${M}.${m}.${p
|
|
283
|
-
}${z} <${M}.${+m + 1}.0
|
|
331
|
+
}${z} <${M}.${+m + 1}.0-0`
|
|
284
332
|
}
|
|
285
333
|
} else {
|
|
286
334
|
ret = `>=${M}.${m}.${p
|
|
287
|
-
} <${+M + 1}.0.0
|
|
335
|
+
} <${+M + 1}.0.0-0`
|
|
288
336
|
}
|
|
289
337
|
}
|
|
290
338
|
|
|
@@ -357,12 +405,15 @@ const replaceXRange = (comp, options) => {
|
|
|
357
405
|
}
|
|
358
406
|
}
|
|
359
407
|
|
|
408
|
+
if (gtlt === '<')
|
|
409
|
+
pr = '-0'
|
|
410
|
+
|
|
360
411
|
ret = `${gtlt + M}.${m}.${p}${pr}`
|
|
361
412
|
} else if (xm) {
|
|
362
|
-
ret = `>=${M}.0.0${pr} <${+M + 1}.0.0
|
|
413
|
+
ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`
|
|
363
414
|
} else if (xp) {
|
|
364
415
|
ret = `>=${M}.${m}.0${pr
|
|
365
|
-
} <${M}.${+m + 1}.0
|
|
416
|
+
} <${M}.${+m + 1}.0-0`
|
|
366
417
|
}
|
|
367
418
|
|
|
368
419
|
debug('xRange return', ret)
|
|
@@ -379,11 +430,17 @@ const replaceStars = (comp, options) => {
|
|
|
379
430
|
return comp.trim().replace(re[t.STAR], '')
|
|
380
431
|
}
|
|
381
432
|
|
|
433
|
+
const replaceGTE0 = (comp, options) => {
|
|
434
|
+
debug('replaceGTE0', comp, options)
|
|
435
|
+
return comp.trim()
|
|
436
|
+
.replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '')
|
|
437
|
+
}
|
|
438
|
+
|
|
382
439
|
// This function is passed to string.replace(re[t.HYPHENRANGE])
|
|
383
440
|
// M, m, patch, prerelease, build
|
|
384
441
|
// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5
|
|
385
|
-
// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do
|
|
386
|
-
// 1.2 - 3.4 => >=1.2.0 <3.5.0
|
|
442
|
+
// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do
|
|
443
|
+
// 1.2 - 3.4 => >=1.2.0 <3.5.0-0
|
|
387
444
|
const hyphenReplace = incPr => ($0,
|
|
388
445
|
from, fM, fm, fp, fpr, fb,
|
|
389
446
|
to, tM, tm, tp, tpr, tb) => {
|
|
@@ -402,9 +459,9 @@ const hyphenReplace = incPr => ($0,
|
|
|
402
459
|
if (isX(tM)) {
|
|
403
460
|
to = ''
|
|
404
461
|
} else if (isX(tm)) {
|
|
405
|
-
to = `<${+tM + 1}.0.0
|
|
462
|
+
to = `<${+tM + 1}.0.0-0`
|
|
406
463
|
} else if (isX(tp)) {
|
|
407
|
-
to = `<${tM}.${+tm + 1}.0
|
|
464
|
+
to = `<${tM}.${+tm + 1}.0-0`
|
|
408
465
|
} else if (tpr) {
|
|
409
466
|
to = `<=${tM}.${tm}.${tp}-${tpr}`
|
|
410
467
|
} else if (incPr) {
|
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
|
package/index.js
CHANGED
|
@@ -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/internal/re.js
CHANGED
|
@@ -177,3 +177,6 @@ createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
|
|
|
177
177
|
|
|
178
178
|
// Star ranges basically just allow anything at all.
|
|
179
179
|
createToken('STAR', '(<|>)?=?\\s*\\*')
|
|
180
|
+
// >=0.0.0 is like a star
|
|
181
|
+
createToken('GTE0', '^\\s*>=\\s*0\.0\.0\\s*$')
|
|
182
|
+
createToken('GTE0PRE', '^\\s*>=\\s*0\.0\.0-0\\s*$')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "semver",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.3",
|
|
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": "^4.1.5"
|
|
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
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
const Range = require('../classes/range.js')
|
|
2
|
+
const { ANY } = require('../classes/comparator.js')
|
|
3
|
+
const satisfies = require('../functions/satisfies.js')
|
|
4
|
+
const compare = require('../functions/compare.js')
|
|
5
|
+
|
|
6
|
+
// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff:
|
|
7
|
+
// - Every simple range `r1, r2, ...` is a subset of some `R1, R2, ...`
|
|
8
|
+
//
|
|
9
|
+
// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff:
|
|
10
|
+
// - If c is only the ANY comparator
|
|
11
|
+
// - If C is only the ANY comparator, return true
|
|
12
|
+
// - Else return false
|
|
13
|
+
// - Let EQ be the set of = comparators in c
|
|
14
|
+
// - If EQ is more than one, return true (null set)
|
|
15
|
+
// - Let GT be the highest > or >= comparator in c
|
|
16
|
+
// - Let LT be the lowest < or <= comparator in c
|
|
17
|
+
// - If GT and LT, and GT.semver > LT.semver, return true (null set)
|
|
18
|
+
// - If EQ
|
|
19
|
+
// - If GT, and EQ does not satisfy GT, return true (null set)
|
|
20
|
+
// - If LT, and EQ does not satisfy LT, return true (null set)
|
|
21
|
+
// - If EQ satisfies every C, return true
|
|
22
|
+
// - Else return false
|
|
23
|
+
// - If GT
|
|
24
|
+
// - If GT.semver is lower than any > or >= comp in C, return false
|
|
25
|
+
// - If GT is >=, and GT.semver does not satisfy every C, return false
|
|
26
|
+
// - If LT
|
|
27
|
+
// - If LT.semver is greater than any < or <= comp in C, return false
|
|
28
|
+
// - If LT is <=, and LT.semver does not satisfy every C, return false
|
|
29
|
+
// - If any C is a = range, and GT or LT are set, return false
|
|
30
|
+
// - Else return true
|
|
31
|
+
|
|
32
|
+
const subset = (sub, dom, options) => {
|
|
33
|
+
if (sub === dom)
|
|
34
|
+
return true
|
|
35
|
+
|
|
36
|
+
sub = new Range(sub, options)
|
|
37
|
+
dom = new Range(dom, options)
|
|
38
|
+
let sawNonNull = false
|
|
39
|
+
|
|
40
|
+
OUTER: for (const simpleSub of sub.set) {
|
|
41
|
+
for (const simpleDom of dom.set) {
|
|
42
|
+
const isSub = simpleSubset(simpleSub, simpleDom, options)
|
|
43
|
+
sawNonNull = sawNonNull || isSub !== null
|
|
44
|
+
if (isSub)
|
|
45
|
+
continue OUTER
|
|
46
|
+
}
|
|
47
|
+
// the null set is a subset of everything, but null simple ranges in
|
|
48
|
+
// a complex range should be ignored. so if we saw a non-null range,
|
|
49
|
+
// then we know this isn't a subset, but if EVERY simple range was null,
|
|
50
|
+
// then it is a subset.
|
|
51
|
+
if (sawNonNull)
|
|
52
|
+
return false
|
|
53
|
+
}
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const simpleSubset = (sub, dom, options) => {
|
|
58
|
+
if (sub === dom)
|
|
59
|
+
return true
|
|
60
|
+
|
|
61
|
+
if (sub.length === 1 && sub[0].semver === ANY)
|
|
62
|
+
return dom.length === 1 && dom[0].semver === ANY
|
|
63
|
+
|
|
64
|
+
const eqSet = new Set()
|
|
65
|
+
let gt, lt
|
|
66
|
+
for (const c of sub) {
|
|
67
|
+
if (c.operator === '>' || c.operator === '>=')
|
|
68
|
+
gt = higherGT(gt, c, options)
|
|
69
|
+
else if (c.operator === '<' || c.operator === '<=')
|
|
70
|
+
lt = lowerLT(lt, c, options)
|
|
71
|
+
else
|
|
72
|
+
eqSet.add(c.semver)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (eqSet.size > 1)
|
|
76
|
+
return null
|
|
77
|
+
|
|
78
|
+
let gtltComp
|
|
79
|
+
if (gt && lt) {
|
|
80
|
+
gtltComp = compare(gt.semver, lt.semver, options)
|
|
81
|
+
if (gtltComp > 0)
|
|
82
|
+
return null
|
|
83
|
+
else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<='))
|
|
84
|
+
return null
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// will iterate one or zero times
|
|
88
|
+
for (const eq of eqSet) {
|
|
89
|
+
if (gt && !satisfies(eq, String(gt), options))
|
|
90
|
+
return null
|
|
91
|
+
|
|
92
|
+
if (lt && !satisfies(eq, String(lt), options))
|
|
93
|
+
return null
|
|
94
|
+
|
|
95
|
+
for (const c of dom) {
|
|
96
|
+
if (!satisfies(eq, String(c), options))
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return true
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let higher, lower
|
|
104
|
+
let hasDomLT, hasDomGT
|
|
105
|
+
for (const c of dom) {
|
|
106
|
+
hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='
|
|
107
|
+
hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='
|
|
108
|
+
if (gt) {
|
|
109
|
+
if (c.operator === '>' || c.operator === '>=') {
|
|
110
|
+
higher = higherGT(gt, c, options)
|
|
111
|
+
if (higher === c && higher !== gt)
|
|
112
|
+
return false
|
|
113
|
+
} else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options))
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
if (lt) {
|
|
117
|
+
if (c.operator === '<' || c.operator === '<=') {
|
|
118
|
+
lower = lowerLT(lt, c, options)
|
|
119
|
+
if (lower === c && lower !== lt)
|
|
120
|
+
return false
|
|
121
|
+
} else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options))
|
|
122
|
+
return false
|
|
123
|
+
}
|
|
124
|
+
if (!c.operator && (lt || gt) && gtltComp !== 0)
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// if there was a < or >, and nothing in the dom, then must be false
|
|
129
|
+
// UNLESS it was limited by another range in the other direction.
|
|
130
|
+
// Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0
|
|
131
|
+
if (gt && hasDomLT && !lt && gtltComp !== 0)
|
|
132
|
+
return false
|
|
133
|
+
|
|
134
|
+
if (lt && hasDomGT && !gt && gtltComp !== 0)
|
|
135
|
+
return false
|
|
136
|
+
|
|
137
|
+
return true
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// >=1.2.3 is lower than >1.2.3
|
|
141
|
+
const higherGT = (a, b, options) => {
|
|
142
|
+
if (!a)
|
|
143
|
+
return b
|
|
144
|
+
const comp = compare(a.semver, b.semver, options)
|
|
145
|
+
return comp > 0 ? a
|
|
146
|
+
: comp < 0 ? b
|
|
147
|
+
: b.operator === '>' && a.operator === '>=' ? b
|
|
148
|
+
: a
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// <=1.2.3 is higher than <1.2.3
|
|
152
|
+
const lowerLT = (a, b, options) => {
|
|
153
|
+
if (!a)
|
|
154
|
+
return b
|
|
155
|
+
const comp = compare(a.semver, b.semver, options)
|
|
156
|
+
return comp < 0 ? a
|
|
157
|
+
: comp > 0 ? b
|
|
158
|
+
: b.operator === '<' && a.operator === '<=' ? b
|
|
159
|
+
: a
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
module.exports = subset
|