Skip to content

Commit

Permalink
Merge branch 'npm:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
mbtools authored Apr 9, 2024
2 parents 70bf371 + b236c3d commit 2f0db42
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 32 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ tap-testdir*/
!/.gitignore
!/.npmrc
!/.release-please-manifest.json
!/benchmarks
!/bin/
!/CHANGELOG*
!/classes/
Expand Down
75 changes: 44 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ semver.valid(semver.coerce('v2')) // '2.0.0'
semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7'
```

You can also just load the module for the function that you care about, if
You can also just load the module for the function that you care about if
you'd like to minimize your footprint.
```js
Expand Down Expand Up @@ -78,8 +78,8 @@ const semverOutside = require('semver/ranges/outside')
const semverGtr = require('semver/ranges/gtr')
const semverLtr = require('semver/ranges/ltr')
const semverIntersects = require('semver/ranges/intersects')
const simplifyRange = require('semver/ranges/simplify')
const rangeSubset = require('semver/ranges/subset')
const semverSimplifyRange = require('semver/ranges/simplify')
const semverRangeSubset = require('semver/ranges/subset')
```
As a command-line utility:
Expand Down Expand Up @@ -144,7 +144,7 @@ A leading `"="` or `"v"` character is stripped off and ignored.
## Ranges
A `version range` is a set of `comparators` which specify versions
A `version range` is a set of `comparators` that specify versions
that satisfy the range.
A `comparator` is composed of an `operator` and a `version`. The set
Expand All @@ -155,7 +155,7 @@ of primitive `operators` is:
* `>` Greater than
* `>=` Greater than or equal to
* `=` Equal. If no operator is specified, then equality is assumed,
so this operator is optional, but MAY be included.
so this operator is optional but MAY be included.
For example, the comparator `>=1.2.7` would match the versions
`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6`
Expand Down Expand Up @@ -189,26 +189,26 @@ For example, the range `>1.2.3-alpha.3` would be allowed to match the
version `1.2.3-alpha.7`, but it would *not* be satisfied by
`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater
than" `1.2.3-alpha.3` according to the SemVer sort rules. The version
range only accepts prerelease tags on the `1.2.3` version. The
version `3.4.5` *would* satisfy the range, because it does not have a
range only accepts prerelease tags on the `1.2.3` version.
Version `3.4.5` *would* satisfy the range because it does not have a
prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`.
The purpose for this behavior is twofold. First, prerelease versions
The purpose of this behavior is twofold. First, prerelease versions
frequently are updated very quickly, and contain many breaking changes
that are (by the author's design) not yet fit for public consumption.
Therefore, by default, they are excluded from range matching
Therefore, by default, they are excluded from range-matching
semantics.

Second, a user who has opted into using a prerelease version has
clearly indicated the intent to use *that specific* set of
indicated the intent to use *that specific* set of
alpha/beta/rc versions. By including a prerelease tag in the range,
the user is indicating that they are aware of the risk. However, it
is still not appropriate to assume that they have opted into taking a
similar risk on the *next* set of prerelease versions.

Note that this behavior can be suppressed (treating all prerelease
versions as if they were normal versions, for the purpose of range
matching) by setting the `includePrerelease` flag on the options
versions as if they were normal versions, for range-matching)
by setting the `includePrerelease` flag on the options
object to any
[functions](https://github.com/npm/node-semver#functions) that do
range matching.
Expand Down Expand Up @@ -401,12 +401,12 @@ All methods and classes take a final `options` object argument. All
options in this object are `false` by default. The options supported
are:

- `loose` Be more forgiving about not-quite-valid semver strings.
- `loose`: Be more forgiving about not-quite-valid semver strings.
(Any resulting output will always be 100% strict compliant, of
course.) For backwards compatibility reasons, if the `options`
argument is a boolean value instead of an object, it is interpreted
to be the `loose` param.
- `includePrerelease` Set to suppress the [default
- `includePrerelease`: Set to suppress the [default
behavior](https://github.com/npm/node-semver#prerelease-tags) of
excluding prerelease tagged versions from ranges unless they are
explicitly opted into.
Expand All @@ -415,16 +415,20 @@ Strict-mode Comparators and Ranges will be strict about the SemVer
strings that they parse.

* `valid(v)`: Return the parsed version, or null if it's not valid.
* `inc(v, release)`: Return the version incremented by the release
type (`major`, `premajor`, `minor`, `preminor`, `patch`,
* `inc(v, release, options, identifier, identifierBase)`:
Return the version incremented by the release
type (`major`, `premajor`, `minor`, `preminor`, `patch`,
`prepatch`, or `prerelease`), or null if it's not valid
* `premajor` in one call will bump the version up to the next major
version and down to a prerelease of that major version.
`preminor`, and `prepatch` work the same way.
* If called from a non-prerelease version, the `prerelease` will work the
same as `prepatch`. It increments the patch version, then makes a
* If called from a non-prerelease version, `prerelease` will work the
same as `prepatch`. It increments the patch version and then makes a
prerelease. If the input version is already a prerelease it simply
increments it.
* `identifier` can be used to prefix `premajor`, `preminor`,
`prepatch`, or `prerelease` version increments. `identifierBase`
is the base to be used for the `prerelease` identifier.
* `prerelease(v)`: Returns an array of prerelease components, or null
if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]`
* `major(v)`: Return the major version number.
Expand All @@ -442,7 +446,7 @@ strings that they parse.
* `lt(v1, v2)`: `v1 < v2`
* `lte(v1, v2)`: `v1 <= v2`
* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent,
even if they're not the exact same string. You already know how to
even if they're not the same string. You already know how to
compare strings.
* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`.
* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call
Expand All @@ -451,15 +455,22 @@ strings that they parse.
invalid comparison string is provided.
* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if
`v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions
* `rcompare(v1, v2)`: The reverse of `compare`. Sorts an array of versions
in descending order when passed to `Array.sort()`.
* `compareBuild(v1, v2)`: The same as `compare` but considers `build` when two versions
are equal. Sorts in ascending order if passed to `Array.sort()`.
`v2` is greater. Sorts in ascending order if passed to `Array.sort()`.
* `diff(v1, v2)`: Returns difference between two versions by the release type
* `compareLoose(v1, v2)`: Short for ``compare(v1, v2, { loose: true })`.
* `diff(v1, v2)`: Returns the difference between two versions by the release type
(`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`),
or null if the versions are the same.
### Sorting
* `sort(versions)`: Returns a sorted array of versions based on the `compareBuild`
function.
* `rsort(versions)`: The reverse of `sort`. Returns an array of versions based on
the `compareBuild` function in descending order.
### Comparators
* `intersects(comparator)`: Return true if the comparators intersect
Expand All @@ -473,19 +484,19 @@ strings that they parse.
that satisfies the range, or `null` if none of them do.
* `minSatisfying(versions, range)`: Return the lowest version in the list
that satisfies the range, or `null` if none of them do.
* `minVersion(range)`: Return the lowest version that can possibly match
* `minVersion(range)`: Return the lowest version that can match
the given range.
* `gtr(version, range)`: Return `true` if version is greater than all the
* `gtr(version, range)`: Return `true` if the version is greater than all the
versions possible in the range.
* `ltr(version, range)`: Return `true` if version is less than all the
* `ltr(version, range)`: Return `true` if the version is less than all the
versions possible in the range.
* `outside(version, range, hilo)`: Return true if the version is outside
the bounds of the range in either the high or low direction. The
`hilo` argument must be either the string `'>'` or `'<'`. (This is
the function called by `gtr` and `ltr`.)
* `intersects(range)`: Return true if any of the ranges comparators intersect
* `intersects(range)`: Return true if any of the range comparators intersect.
* `simplifyRange(versions, range)`: Return a "simplified" range that
matches the same items in `versions` list as the range specified. Note
matches the same items in the `versions` list as the range specified. Note
that it does *not* guarantee that it would match the same versions in all
cases, only for the set of versions provided. This is useful when
generating ranges by joining together multiple versions with `||`
Expand All @@ -498,7 +509,7 @@ strings that they parse.
Note that, since ranges may be non-contiguous, a version might not be
greater than a range, less than a range, *or* satisfy a range! For
example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9`
until `2.0.0`, so the version `1.2.10` would not be greater than the
until `2.0.0`, so version `1.2.10` would not be greater than the
range (because `2.0.1` satisfies, which is higher), nor less than the
range (since `1.2.8` satisfies, which is lower), and it also does not
satisfy the range.
Expand All @@ -511,13 +522,13 @@ range, use the `satisfies(version, range)` function.
* `coerce(version, options)`: Coerces a string to semver if possible

This aims to provide a very forgiving translation of a non-semver string to
semver. It looks for the first digit in a string, and consumes all
semver. It looks for the first digit in a string and consumes all
remaining characters which satisfy at least a partial semver (e.g., `1`,
`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer
versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All
surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes
`3.4.0`). Only text which lacks digits will fail coercion (`version one`
is not valid). The maximum length for any semver component considered for
is not valid). The maximum length for any semver component considered for
coercion is 16 characters; longer components will be ignored
(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any
semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value
Expand Down Expand Up @@ -593,7 +604,7 @@ eg), and then pull the module name into the documentation for that specific
thing.
-->
You may pull in just the part of this semver utility that you need, if you
You may pull in just the part of this semver utility that you need if you
are sensitive to packing and tree-shaking concerns. The main
`require('semver')` export uses getter functions to lazily load the parts
of the API that are used.
Expand Down Expand Up @@ -636,6 +647,8 @@ The following modules are available:
* `require('semver/ranges/min-satisfying')`
* `require('semver/ranges/min-version')`
* `require('semver/ranges/outside')`
* `require('semver/ranges/simplify')`
* `require('semver/ranges/subset')`
* `require('semver/ranges/to-comparators')`
* `require('semver/ranges/valid')`
48 changes: 48 additions & 0 deletions benchmarks/bench-compare.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const Benchmark = require('benchmark')
const SemVer = require('../classes/semver')
const suite = new Benchmark.Suite()

const versions = ['1.0.3', '2.2.2', '2.3.0']
const versionToCompare = '1.0.2'
const option1 = { includePrelease: true }
const option2 = { includePrelease: true, loose: true }
const option3 = { includePrelease: true, loose: true, rtl: true }

for (const version of versions) {
suite.add(`compare ${version} to ${versionToCompare}`, function () {
const semver = new SemVer(version)
semver.compare(versionToCompare)
})
}

for (const version of versions) {
suite.add(
`compare ${version} to ${versionToCompare} with option (${JSON.stringify(option1)})`,
function () {
const semver = new SemVer(version, option1)
semver.compare(versionToCompare)
})
}

for (const version of versions) {
suite.add(`compare ${version} to ${versionToCompare} with option (${JSON.stringify(option2)})`,
function () {
const semver = new SemVer(version, option2)
semver.compare(versionToCompare)
})
}

for (const version of versions) {
suite.add(
`compare ${version} to ${versionToCompare} with option (${JSON.stringify(option3)})`,
function () {
const semver = new SemVer(version, option3)
semver.compare(versionToCompare)
})
}

suite
.on('cycle', function (event) {
console.log(String(event.target))
})
.run({ async: false })
21 changes: 21 additions & 0 deletions benchmarks/bench-diff.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const Benchmark = require('benchmark')
const diff = require('../functions/diff')
const suite = new Benchmark.Suite()

const cases = [
['0.0.1', '0.0.1-pre', 'patch'],
['0.0.1', '0.0.1-pre-2', 'patch'],
['1.1.0', '1.1.0-pre', 'minor'],
]

for (const [v1, v2] of cases) {
suite.add(`diff(${v1}, ${v2})`, function () {
diff(v1, v2)
})
}

suite
.on('cycle', function (event) {
console.log(String(event.target))
})
.run({ async: false })
33 changes: 33 additions & 0 deletions benchmarks/bench-parse-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const Benchmark = require('benchmark')
const parseOptions = require('../internal/parse-options')
const suite = new Benchmark.Suite()

const options1 = {
includePrerelease: true,
}

const options2 = {
includePrerelease: true,
loose: true,
}

const options3 = {
includePrerelease: true,
loose: true,
rtl: false,
}

suite
.add('includePrerelease', function () {
parseOptions(options1)
})
.add('includePrerelease + loose', function () {
parseOptions(options2)
})
.add('includePrerelease + loose + rtl', function () {
parseOptions(options3)
})
.on('cycle', function (event) {
console.log(String(event.target))
})
.run({ async: false })
25 changes: 25 additions & 0 deletions benchmarks/bench-parse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const Benchmark = require('benchmark')
const parse = require('../functions/parse')
const { MAX_SAFE_INTEGER } = require('../internal/constants')
const suite = new Benchmark.Suite()

const cases = ['1.2.1', '1.2.2-4', '1.2.3-pre']
const invalidCases = [`${MAX_SAFE_INTEGER}0.0.0`, 'hello, world', 'xyz']

for (const test of cases) {
suite.add(`parse(${test})`, function () {
parse(test)
})
}

for (const test of invalidCases) {
suite.add(`invalid parse(${test})`, function () {
parse(test)
})
}

suite
.on('cycle', function (event) {
console.log(String(event.target))
})
.run({ async: false })
39 changes: 39 additions & 0 deletions benchmarks/bench-satisfies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const Benchmark = require('benchmark')
const satisfies = require('../functions/satisfies')
const suite = new Benchmark.Suite()

const versions = ['1.0.3||^2.0.0', '2.2.2||~3.0.0', '2.3.0||<4.0.0']
const versionToCompare = '1.0.6'
const option1 = { includePrelease: true }
const option2 = { includePrelease: true, loose: true }
const option3 = { includePrelease: true, loose: true, rtl: true }

for (const version of versions) {
suite.add(`satisfies(${versionToCompare}, ${version})`, function () {
satisfies(versionToCompare, version)
})
}

for (const version of versions) {
suite.add(`satisfies(${versionToCompare}, ${version}, ${JSON.stringify(option1)})`, function () {
satisfies(versionToCompare, version, option1)
})
}

for (const version of versions) {
suite.add(`satisfies(${versionToCompare}, ${version}, ${JSON.stringify(option2)})`, function () {
satisfies(versionToCompare, version, option2)
})
}

for (const version of versions) {
suite.add(`satisfies(${versionToCompare}, ${version}, ${JSON.stringify(option3)})`, function () {
satisfies(versionToCompare, version, option3)
})
}

suite
.on('cycle', function (event) {
console.log(String(event.target))
})
.run({ async: false })
Loading

0 comments on commit 2f0db42

Please sign in to comment.