Skip to content

Commit b99ae3b

Browse files
committed
Add semver.minVersion function.
1 parent 6086e5a commit b99ae3b

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ semver.clean(' =v1.2.3 ') // '1.2.3'
2020
semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true
2121
semver.gt('1.2.3', '9.8.7') // false
2222
semver.lt('1.2.3', '9.8.7') // true
23+
semver.minVersion('>=1.0.0') // '1.0.0'
2324
semver.valid(semver.coerce('v2')) // '2.0.0'
2425
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
2526
```
@@ -368,6 +369,8 @@ strings that they parse.
368369
that satisfies the range, or `null` if none of them do.
369370
* `minSatisfying(versions, range)`: Return the lowest version in the list
370371
that satisfies the range, or `null` if none of them do.
372+
* `minVersion(range)`: Return the lowest version that can possibly match
373+
the given range.
371374
* `gtr(version, range)`: Return `true` if version is greater than all the
372375
versions possible in the range.
373376
* `ltr(version, range)`: Return `true` if version is less than all the

semver.js

+54
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,60 @@ function minSatisfying (versions, range, options) {
11191119
return min
11201120
}
11211121

1122+
exports.minVersion = minVersion
1123+
function minVersion (range, loose) {
1124+
range = new Range(range, loose)
1125+
1126+
var minver = new SemVer('0.0.0')
1127+
if (range.test(minver)) {
1128+
return minver
1129+
}
1130+
1131+
minver = new SemVer('0.0.0-0')
1132+
if (range.test(minver)) {
1133+
return minver
1134+
}
1135+
1136+
minver = null
1137+
for (var i = 0; i < range.set.length; ++i) {
1138+
var comparators = range.set[i]
1139+
1140+
comparators.forEach(function (comparator) {
1141+
// Clone to avoid manipulating the comparator's semver object.
1142+
var compver = new SemVer(comparator.semver.version)
1143+
switch (comparator.operator) {
1144+
case '>':
1145+
if (compver.prerelease.length === 0) {
1146+
compver.patch++
1147+
} else {
1148+
compver.prerelease.push(0)
1149+
}
1150+
compver.raw = compver.format()
1151+
/* fallthrough */
1152+
case '':
1153+
case '>=':
1154+
if (!minver || gt(minver, compver)) {
1155+
minver = compver
1156+
}
1157+
break
1158+
case '<':
1159+
case '<=':
1160+
/* Ignore maximum versions */
1161+
break
1162+
/* istanbul ignore next */
1163+
default:
1164+
throw new Error('Unexpected operation: ' + comparator.operator)
1165+
}
1166+
})
1167+
}
1168+
1169+
if (minver && range.test(minver)) {
1170+
return minver
1171+
}
1172+
1173+
return null
1174+
}
1175+
11221176
exports.validRange = validRange
11231177
function validRange (range, options) {
11241178
try {

test/min-version.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
var tap = require('tap')
2+
var test = tap.test
3+
var semver = require('../semver.js')
4+
5+
test('\nminimum version in range tests', function (t) {
6+
// [range, minimum, loose]
7+
[
8+
// Stars
9+
['*', '0.0.0'],
10+
['* || >=2', '0.0.0'],
11+
['>=2 || *', '0.0.0'],
12+
['>2 || *', '0.0.0'],
13+
14+
// equal
15+
['1.0.0', '1.0.0'],
16+
['1.0', '1.0.0'],
17+
['1.0.x', '1.0.0'],
18+
['1.0.*', '1.0.0'],
19+
['1', '1.0.0'],
20+
['1.x.x', '1.0.0'],
21+
['1.x.x', '1.0.0'],
22+
['1.*.x', '1.0.0'],
23+
['1.x.*', '1.0.0'],
24+
['1.x', '1.0.0'],
25+
['1.*', '1.0.0'],
26+
['=1.0.0', '1.0.0'],
27+
28+
// Tilde
29+
['~1.1.1', '1.1.1'],
30+
['~1.1.1-beta', '1.1.1-beta'],
31+
['~1.1.1 || >=2', '1.1.1'],
32+
33+
// Carot
34+
['^1.1.1', '1.1.1'],
35+
['^1.1.1-beta', '1.1.1-beta'],
36+
['^1.1.1 || >=2', '1.1.1'],
37+
38+
// '-' operator
39+
['1.1.1 - 1.8.0', '1.1.1'],
40+
['1.1 - 1.8.0', '1.1.0'],
41+
42+
// Less / less or equal
43+
['<2', '0.0.0'],
44+
['<0.0.0-beta', '0.0.0-0'],
45+
['<0.0.1-beta', '0.0.0'],
46+
['<2 || >4', '0.0.0'],
47+
['>4 || <2', '0.0.0'],
48+
['<=2 || >=4', '0.0.0'],
49+
['>=4 || <=2', '0.0.0'],
50+
['<0.0.0-beta >0.0.0-alpha', '0.0.0-alpha.0'],
51+
['>0.0.0-alpha <0.0.0-beta', '0.0.0-alpha.0'],
52+
53+
// Greater than or equal
54+
['>=1.1.1 <2 || >=2.2.2 <2', '1.1.1'],
55+
['>=2.2.2 <2 || >=1.1.1 <2', '1.1.1'],
56+
57+
// Greater than but not equal
58+
['>1.0.0', '1.0.1'],
59+
['>1.0.0-0', '1.0.0-0.0'],
60+
['>1.0.0-beta', '1.0.0-beta.0'],
61+
['>2 || >1.0.0', '1.0.1'],
62+
['>2 || >1.0.0-0', '1.0.0-0.0'],
63+
['>2 || >1.0.0-beta', '1.0.0-beta.0'],
64+
65+
// Impossible range
66+
['>4 <3', null]
67+
].forEach(function (tuple) {
68+
var range = tuple[0]
69+
var version = tuple[1]
70+
var loose = tuple[2] || false
71+
var msg = 'minVersion(' + range + ', ' + loose + ') = ' + version
72+
var min = semver.minVersion(range, loose)
73+
t.ok(min === version || (min && min.version === version), msg)
74+
})
75+
t.end()
76+
})

0 commit comments

Comments
 (0)