semver 7.2.2 → 7.3.2

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 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/range.js CHANGED
@@ -68,7 +68,7 @@ class Range {
68
68
  range = range.trim()
69
69
  // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4`
70
70
  const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]
71
- range = range.replace(hr, hyphenReplace)
71
+ range = range.replace(hr, hyphenReplace(this.options.includePrerelease))
72
72
  debug('hyphen replace', range)
73
73
  // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5`
74
74
  range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace)
@@ -92,6 +92,7 @@ class Range {
92
92
  .map(comp => parseComparator(comp, this.options))
93
93
  .join(' ')
94
94
  .split(/\s+/)
95
+ .map(comp => replaceGTE0(comp, this.options))
95
96
  // in loose mode, throw out any that are not valid comparators
96
97
  .filter(this.options.loose ? comp => !!comp.match(compRe) : () => true)
97
98
  .map(comp => new Comparator(comp, this.options))
@@ -191,11 +192,11 @@ const parseComparator = (comp, options) => {
191
192
  const isX = id => !id || id.toLowerCase() === 'x' || id === '*'
192
193
 
193
194
  // ~, ~> --> * (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
195
+ // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0
196
+ // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0
197
+ // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0
198
+ // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0
199
+ // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0
199
200
  const replaceTildes = (comp, options) =>
200
201
  comp.trim().split(/\s+/).map((comp) => {
201
202
  return replaceTilde(comp, options)
@@ -210,18 +211,18 @@ const replaceTilde = (comp, options) => {
210
211
  if (isX(M)) {
211
212
  ret = ''
212
213
  } else if (isX(m)) {
213
- ret = `>=${M}.0.0 <${+M + 1}.0.0`
214
+ ret = `>=${M}.0.0 <${+M + 1}.0.0-0`
214
215
  } else if (isX(p)) {
215
- // ~1.2 == >=1.2.0 <1.3.0
216
- ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0`
216
+ // ~1.2 == >=1.2.0 <1.3.0-0
217
+ ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`
217
218
  } else if (pr) {
218
219
  debug('replaceTilde pr', pr)
219
220
  ret = `>=${M}.${m}.${p}-${pr
220
- } <${M}.${+m + 1}.0`
221
+ } <${M}.${+m + 1}.0-0`
221
222
  } else {
222
- // ~1.2.3 == >=1.2.3 <1.3.0
223
+ // ~1.2.3 == >=1.2.3 <1.3.0-0
223
224
  ret = `>=${M}.${m}.${p
224
- } <${M}.${+m + 1}.0`
225
+ } <${M}.${+m + 1}.0-0`
225
226
  }
226
227
 
227
228
  debug('tilde return', ret)
@@ -230,11 +231,11 @@ const replaceTilde = (comp, options) => {
230
231
  }
231
232
 
232
233
  // ^ --> * (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
234
+ // ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0
235
+ // ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0
236
+ // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0
237
+ // ^1.2.3 --> >=1.2.3 <2.0.0-0
238
+ // ^1.2.0 --> >=1.2.0 <2.0.0-0
238
239
  const replaceCarets = (comp, options) =>
239
240
  comp.trim().split(/\s+/).map((comp) => {
240
241
  return replaceCaret(comp, options)
@@ -251,40 +252,40 @@ const replaceCaret = (comp, options) => {
251
252
  if (isX(M)) {
252
253
  ret = ''
253
254
  } else if (isX(m)) {
254
- ret = `>=${M}.0.0${z} <${+M + 1}.0.0${z}`
255
+ ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`
255
256
  } else if (isX(p)) {
256
257
  if (M === '0') {
257
- ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0${z}`
258
+ ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`
258
259
  } else {
259
- ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0${z}`
260
+ ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`
260
261
  }
261
262
  } else if (pr) {
262
263
  debug('replaceCaret pr', pr)
263
264
  if (M === '0') {
264
265
  if (m === '0') {
265
266
  ret = `>=${M}.${m}.${p}-${pr
266
- } <${M}.${m}.${+p + 1}${z}`
267
+ } <${M}.${m}.${+p + 1}-0`
267
268
  } else {
268
269
  ret = `>=${M}.${m}.${p}-${pr
269
- } <${M}.${+m + 1}.0${z}`
270
+ } <${M}.${+m + 1}.0-0`
270
271
  }
271
272
  } else {
272
273
  ret = `>=${M}.${m}.${p}-${pr
273
- } <${+M + 1}.0.0${z}`
274
+ } <${+M + 1}.0.0-0`
274
275
  }
275
276
  } else {
276
277
  debug('no pr')
277
278
  if (M === '0') {
278
279
  if (m === '0') {
279
280
  ret = `>=${M}.${m}.${p
280
- }${z} <${M}.${m}.${+p + 1}${z}`
281
+ }${z} <${M}.${m}.${+p + 1}-0`
281
282
  } else {
282
283
  ret = `>=${M}.${m}.${p
283
- }${z} <${M}.${+m + 1}.0${z}`
284
+ }${z} <${M}.${+m + 1}.0-0`
284
285
  }
285
286
  } else {
286
287
  ret = `>=${M}.${m}.${p
287
- } <${+M + 1}.0.0${z}`
288
+ } <${+M + 1}.0.0-0`
288
289
  }
289
290
  }
290
291
 
@@ -357,12 +358,15 @@ const replaceXRange = (comp, options) => {
357
358
  }
358
359
  }
359
360
 
361
+ if (gtlt === '<')
362
+ pr = '-0'
363
+
360
364
  ret = `${gtlt + M}.${m}.${p}${pr}`
361
365
  } else if (xm) {
362
- ret = `>=${M}.0.0${pr} <${+M + 1}.0.0${pr}`
366
+ ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`
363
367
  } else if (xp) {
364
368
  ret = `>=${M}.${m}.0${pr
365
- } <${M}.${+m + 1}.0${pr}`
369
+ } <${M}.${+m + 1}.0-0`
366
370
  }
367
371
 
368
372
  debug('xRange return', ret)
@@ -379,32 +383,42 @@ const replaceStars = (comp, options) => {
379
383
  return comp.trim().replace(re[t.STAR], '')
380
384
  }
381
385
 
386
+ const replaceGTE0 = (comp, options) => {
387
+ debug('replaceGTE0', comp, options)
388
+ return comp.trim()
389
+ .replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], '')
390
+ }
391
+
382
392
  // This function is passed to string.replace(re[t.HYPHENRANGE])
383
393
  // M, m, patch, prerelease, build
384
394
  // 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
387
- const hyphenReplace = ($0,
395
+ // 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do
396
+ // 1.2 - 3.4 => >=1.2.0 <3.5.0-0
397
+ const hyphenReplace = incPr => ($0,
388
398
  from, fM, fm, fp, fpr, fb,
389
399
  to, tM, tm, tp, tpr, tb) => {
390
400
  if (isX(fM)) {
391
401
  from = ''
392
402
  } else if (isX(fm)) {
393
- from = `>=${fM}.0.0`
403
+ from = `>=${fM}.0.0${incPr ? '-0' : ''}`
394
404
  } else if (isX(fp)) {
395
- from = `>=${fM}.${fm}.0`
396
- } else {
405
+ from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}`
406
+ } else if (fpr) {
397
407
  from = `>=${from}`
408
+ } else {
409
+ from = `>=${from}${incPr ? '-0' : ''}`
398
410
  }
399
411
 
400
412
  if (isX(tM)) {
401
413
  to = ''
402
414
  } else if (isX(tm)) {
403
- to = `<${+tM + 1}.0.0`
415
+ to = `<${+tM + 1}.0.0-0`
404
416
  } else if (isX(tp)) {
405
- to = `<${tM}.${+tm + 1}.0`
417
+ to = `<${tM}.${+tm + 1}.0-0`
406
418
  } else if (tpr) {
407
419
  to = `<=${tM}.${tm}.${tp}-${tpr}`
420
+ } else if (incPr) {
421
+ to = `<${tM}.${tm}.${+tp + 1}-0`
408
422
  } else {
409
423
  to = `<=${to}`
410
424
  }
package/index.js CHANGED
@@ -44,4 +44,5 @@ module.exports = {
44
44
  ltr: require('./ranges/ltr'),
45
45
  intersects: require('./ranges/intersects'),
46
46
  simplifyRange: require('./ranges/simplify'),
47
+ subset: require('./ranges/subset'),
47
48
  }
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.2.2",
3
+ "version": "7.3.2",
4
4
  "description": "The semantic version parser used by npm.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,7 +11,7 @@
11
11
  "postpublish": "git push origin --follow-tags"
12
12
  },
13
13
  "devDependencies": {
14
- "tap": "^14.10.2"
14
+ "tap": "^14.10.7"
15
15
  },
16
16
  "license": "ISC",
17
17
  "repository": "https://github.com/npm/node-semver",
@@ -0,0 +1,155 @@
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 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 that of any > 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
+ sub = new Range(sub, options)
34
+ dom = new Range(dom, options)
35
+ let sawNonNull = false
36
+
37
+ OUTER: for (const simpleSub of sub.set) {
38
+ for (const simpleDom of dom.set) {
39
+ const isSub = simpleSubset(simpleSub, simpleDom, options)
40
+ sawNonNull = sawNonNull || isSub !== null
41
+ if (isSub)
42
+ continue OUTER
43
+ }
44
+ // the null set is a subset of everything, but null simple ranges in
45
+ // a complex range should be ignored. so if we saw a non-null range,
46
+ // then we know this isn't a subset, but if EVERY simple range was null,
47
+ // then it is a subset.
48
+ if (sawNonNull)
49
+ return false
50
+ }
51
+ return true
52
+ }
53
+
54
+ const simpleSubset = (sub, dom, options) => {
55
+ if (sub.length === 1 && sub[0].semver === ANY)
56
+ return dom.length === 1 && dom[0].semver === ANY
57
+
58
+ const eqSet = new Set()
59
+ let gt, lt
60
+ for (const c of sub) {
61
+ if (c.operator === '>' || c.operator === '>=')
62
+ gt = higherGT(gt, c, options)
63
+ else if (c.operator === '<' || c.operator === '<=')
64
+ lt = lowerLT(lt, c, options)
65
+ else
66
+ eqSet.add(c.semver)
67
+ }
68
+
69
+ if (eqSet.size > 1)
70
+ return null
71
+
72
+ let gtltComp
73
+ if (gt && lt) {
74
+ gtltComp = compare(gt.semver, lt.semver, options)
75
+ if (gtltComp > 0)
76
+ return null
77
+ else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<='))
78
+ return null
79
+ }
80
+
81
+ // will iterate one or zero times
82
+ for (const eq of eqSet) {
83
+ if (gt && !satisfies(eq, String(gt), options))
84
+ return null
85
+
86
+ if (lt && !satisfies(eq, String(lt), options))
87
+ return null
88
+
89
+ for (const c of dom) {
90
+ if (!satisfies(eq, String(c), options))
91
+ return false
92
+ }
93
+ return true
94
+ }
95
+
96
+ let higher, lower
97
+ let hasDomLT, hasDomGT
98
+ for (const c of dom) {
99
+ hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='
100
+ hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='
101
+ if (gt) {
102
+ if (c.operator === '>' || c.operator === '>=') {
103
+ higher = higherGT(gt, c, options)
104
+ if (higher === c)
105
+ return false
106
+ } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options))
107
+ return false
108
+ }
109
+ if (lt) {
110
+ if (c.operator === '<' || c.operator === '<=') {
111
+ lower = lowerLT(lt, c, options)
112
+ if (lower === c)
113
+ return false
114
+ } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options))
115
+ return false
116
+ }
117
+ if (!c.operator && (lt || gt) && gtltComp !== 0)
118
+ return false
119
+ }
120
+
121
+ // if there was a < or >, and nothing in the dom, then must be false
122
+ // UNLESS it was limited by another range in the other direction.
123
+ // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0
124
+ if (gt && hasDomLT && !lt && gtltComp !== 0)
125
+ return false
126
+
127
+ if (lt && hasDomGT && !gt && gtltComp !== 0)
128
+ return false
129
+
130
+ return true
131
+ }
132
+
133
+ // >=1.2.3 is lower than >1.2.3
134
+ const higherGT = (a, b, options) => {
135
+ if (!a)
136
+ return b
137
+ const comp = compare(a.semver, b.semver, options)
138
+ return comp > 0 ? a
139
+ : comp < 0 ? b
140
+ : b.operator === '>' && a.operator === '>=' ? b
141
+ : a
142
+ }
143
+
144
+ // <=1.2.3 is higher than <1.2.3
145
+ const lowerLT = (a, b, options) => {
146
+ if (!a)
147
+ return b
148
+ const comp = compare(a.semver, b.semver, options)
149
+ return comp < 0 ? a
150
+ : comp > 0 ? b
151
+ : b.operator === '<' && a.operator === '<=' ? b
152
+ : a
153
+ }
154
+
155
+ module.exports = subset