semver 7.7.4 → 7.8.1

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/README.md CHANGED
@@ -56,6 +56,7 @@ const semverCompareLoose = require('semver/functions/compare-loose')
56
56
  const semverCompareBuild = require('semver/functions/compare-build')
57
57
  const semverSort = require('semver/functions/sort')
58
58
  const semverRsort = require('semver/functions/rsort')
59
+ const semverTruncate = require('semver/functions/truncate')
59
60
 
60
61
  // low-level comparators between versions
61
62
  const semverGt = require('semver/functions/gt')
@@ -399,12 +400,19 @@ nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) *
399
400
  tilde ::= '~' partial
400
401
  caret ::= '^' partial
401
402
  qualifier ::= ( '-' pre )? ( '+' build )?
402
- pre ::= parts
403
- build ::= parts
404
- parts ::= part ( '.' part ) *
405
- part ::= nr | [-0-9A-Za-z]+
403
+ pre ::= prepart ( '.' prepart ) *
404
+ prepart ::= nr | alphanumid
405
+ build ::= buildid ( '.' buildid ) *
406
+ alphanumid ::= ( ['0'-'9'] ) * [-A-Za-z] [-0-9A-Za-z] *
407
+ buildid ::= [-0-9A-Za-z]+
406
408
  ```
407
409
 
410
+ Note: Prerelease identifiers (`pre`) use `nr` for numeric parts, which
411
+ disallows leading zeros (e.g., `1.2.3-00` is invalid). Build metadata
412
+ identifiers (`build`) allow any alphanumeric string including leading
413
+ zeros (e.g., `1.2.3+00` is valid). This matches the
414
+ [SemVer 2.0.0 specification](https://semver.org/#spec-item-9).
415
+
408
416
  ## Functions
409
417
 
410
418
  All methods and classes take a final `options` object argument. All
@@ -449,6 +457,12 @@ strings that they parse.
449
457
  or comparators intersect.
450
458
  * `parse(v)`: Attempt to parse a string as a semantic version, returning either
451
459
  a `SemVer` object or `null`.
460
+ * `truncate(v, releaseType)`: Return the version with components _lower_
461
+ than `releaseType` dropped off, e.g.:
462
+ * `major` removes build & prerelease info and sets minor & patch to 0.
463
+ * `minor` removes build & prerelease info, and sets patch to 0
464
+ * `patch` removes build & prerelease info
465
+ * All prerelease types remove build info only
452
466
 
453
467
  ### Comparison
454
468
 
@@ -650,6 +664,7 @@ The following modules are available:
650
664
  * `require('semver/functions/rsort')`
651
665
  * `require('semver/functions/satisfies')`
652
666
  * `require('semver/functions/sort')`
667
+ * `require('semver/functions/truncate')`
653
668
  * `require('semver/functions/valid')`
654
669
  * `require('semver/ranges/gtr')`
655
670
  * `require('semver/ranges/intersects')`
package/bin/semver.js CHANGED
@@ -46,6 +46,7 @@ const main = () => {
46
46
  a = a.slice(0, indexOfEqualSign)
47
47
  argv.unshift(value)
48
48
  }
49
+
49
50
  switch (a) {
50
51
  case '-rv': case '-rev': case '--rev': case '--reverse':
51
52
  reverse = true
@@ -60,15 +61,10 @@ const main = () => {
60
61
  versions.push(argv.shift())
61
62
  break
62
63
  case '-i': case '--inc': case '--increment':
63
- switch (argv[0]) {
64
- case 'major': case 'minor': case 'patch': case 'prerelease':
65
- case 'premajor': case 'preminor': case 'prepatch':
66
- case 'release':
67
- inc = argv.shift()
68
- break
69
- default:
70
- inc = 'patch'
71
- break
64
+ if (semver.RELEASE_TYPES.includes(argv[0]) || (argv[0] === 'release')) {
65
+ inc = { value: argv.shift(), maybeErrantValue: null, option: a }
66
+ } else {
67
+ inc = { value: 'patch', maybeErrantValue: argv[0], option: a }
72
68
  }
73
69
  break
74
70
  case '--preid':
@@ -102,6 +98,14 @@ const main = () => {
102
98
 
103
99
  options = parseOptions({ loose, includePrerelease, rtl })
104
100
 
101
+ if (
102
+ inc &&
103
+ versions.includes(inc.maybeErrantValue) &&
104
+ !semver.valid(inc.maybeErrantValue, options)
105
+ ) {
106
+ console.warn(`Invalid value for ${inc.option}; defaulting to 'patch'. This may become a failure in future major versions.`)
107
+ }
108
+
105
109
  versions = versions.map((v) => {
106
110
  return coerce ? (semver.coerce(v, options) || { version: v }).version : v
107
111
  }).filter((v) => {
@@ -125,7 +129,7 @@ const main = () => {
125
129
  versions
126
130
  .sort((a, b) => semver[reverse ? 'rcompare' : 'compare'](a, b, options))
127
131
  .map(v => semver.clean(v, options))
128
- .map(v => inc ? semver.inc(v, inc, options, identifier, identifierBase) : v)
132
+ .map(v => inc ? semver.inc(v, inc.value, options, identifier, identifierBase) : v)
129
133
  .forEach(v => console.log(v))
130
134
  }
131
135
 
package/classes/range.js CHANGED
@@ -98,6 +98,9 @@ class Range {
98
98
  }
99
99
 
100
100
  parseRange (range) {
101
+ // strip build metadata so it can't bleed into the version
102
+ range = range.replace(BUILDSTRIPRE, '')
103
+
101
104
  // memoize range parsing for performance.
102
105
  // this is a very hot path, and fully deterministic.
103
106
  const memoOpts =
@@ -223,6 +226,7 @@ const debug = require('../internal/debug')
223
226
  const SemVer = require('./semver')
224
227
  const {
225
228
  safeRe: re,
229
+ src,
226
230
  t,
227
231
  comparatorTrimReplace,
228
232
  tildeTrimReplace,
@@ -230,6 +234,9 @@ const {
230
234
  } = require('../internal/re')
231
235
  const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require('../internal/constants')
232
236
 
237
+ // unbounded global build-metadata stripper used by parseRange
238
+ const BUILDSTRIPRE = new RegExp(src[t.BUILD], 'g')
239
+
233
240
  const isNullSet = c => c.value === '<0.0.0-0'
234
241
  const isAny = c => c.value === ''
235
242
 
@@ -0,0 +1,48 @@
1
+ 'use strict'
2
+
3
+ const parse = require('./parse')
4
+ const constants = require('../internal/constants')
5
+ const SemVer = require('../classes/semver')
6
+
7
+ const truncate = (version, truncation, options) => {
8
+ if (!constants.RELEASE_TYPES.includes(truncation)) {
9
+ return null
10
+ }
11
+
12
+ const clonedVersion = cloneInputVersion(version, options)
13
+ return clonedVersion && doTruncation(clonedVersion, truncation)
14
+ }
15
+
16
+ const cloneInputVersion = (version, options) => {
17
+ const versionStringToParse = (
18
+ version instanceof SemVer ? version.version : version
19
+ )
20
+
21
+ return parse(versionStringToParse, options)
22
+ }
23
+
24
+ const doTruncation = (version, truncation) => {
25
+ if (isPrerelease(truncation)) {
26
+ return version.version
27
+ }
28
+
29
+ version.prerelease = []
30
+
31
+ switch (truncation) {
32
+ case 'major':
33
+ version.minor = 0
34
+ version.patch = 0
35
+ break
36
+ case 'minor':
37
+ version.patch = 0
38
+ break
39
+ }
40
+
41
+ return version.format()
42
+ }
43
+
44
+ const isPrerelease = (type) => {
45
+ return type.startsWith('pre')
46
+ }
47
+
48
+ module.exports = truncate
package/index.js CHANGED
@@ -28,6 +28,7 @@ const gte = require('./functions/gte')
28
28
  const lte = require('./functions/lte')
29
29
  const cmp = require('./functions/cmp')
30
30
  const coerce = require('./functions/coerce')
31
+ const truncate = require('./functions/truncate')
31
32
  const Comparator = require('./classes/comparator')
32
33
  const Range = require('./classes/range')
33
34
  const satisfies = require('./functions/satisfies')
@@ -66,6 +67,7 @@ module.exports = {
66
67
  lte,
67
68
  cmp,
68
69
  coerce,
70
+ truncate,
69
71
  Comparator,
70
72
  Range,
71
73
  satisfies,
package/internal/re.js CHANGED
@@ -136,7 +136,7 @@ createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`)
136
136
  createToken('GTLT', '((?:<|>)?=?)')
137
137
 
138
138
  // Something like "2.*" or "1.2.x".
139
- // Note that "x.x" is a valid xRange identifer, meaning "any version"
139
+ // Note that "x.x" is a valid xRange identifier, meaning "any version"
140
140
  // Only the first item is strictly required.
141
141
  createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`)
142
142
  createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "semver",
3
- "version": "7.7.4",
3
+ "version": "7.8.1",
4
4
  "description": "The semantic version parser used by npm.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "devDependencies": {
17
17
  "@npmcli/eslint-config": "^6.0.0",
18
- "@npmcli/template-oss": "4.29.0",
18
+ "@npmcli/template-oss": "5.0.0",
19
19
  "benchmark": "^2.1.4",
20
20
  "tap": "^16.0.0"
21
21
  },
@@ -52,7 +52,7 @@
52
52
  "author": "GitHub Inc.",
53
53
  "templateOSS": {
54
54
  "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
55
- "version": "4.29.0",
55
+ "version": "5.0.0",
56
56
  "engines": ">=10",
57
57
  "distPaths": [
58
58
  "classes/",
package/range.bnf CHANGED
@@ -10,7 +10,8 @@ nr ::= '0' | [1-9] ( [0-9] ) *
10
10
  tilde ::= '~' partial
11
11
  caret ::= '^' partial
12
12
  qualifier ::= ( '-' pre )? ( '+' build )?
13
- pre ::= parts
14
- build ::= parts
15
- parts ::= part ( '.' part ) *
16
- part ::= nr | [-0-9A-Za-z]+
13
+ pre ::= prepart ( '.' prepart ) *
14
+ prepart ::= nr | alphanumid
15
+ build ::= buildid ( '.' buildid ) *
16
+ alphanumid ::= ( [0-9] ) * [A-Za-z-] [-0-9A-Za-z] *
17
+ buildid ::= [-0-9A-Za-z]+
package/ranges/subset.js CHANGED
@@ -174,7 +174,7 @@ const simpleSubset = (sub, dom, options) => {
174
174
  if (higher === c && higher !== gt) {
175
175
  return false
176
176
  }
177
- } else if (gt.operator === '>=' && !satisfies(gt.semver, String(c), options)) {
177
+ } else if (gt.operator === '>=' && !c.test(gt.semver)) {
178
178
  return false
179
179
  }
180
180
  }
@@ -192,7 +192,7 @@ const simpleSubset = (sub, dom, options) => {
192
192
  if (lower === c && lower !== lt) {
193
193
  return false
194
194
  }
195
- } else if (lt.operator === '<=' && !satisfies(lt.semver, String(c), options)) {
195
+ } else if (lt.operator === '<=' && !c.test(lt.semver)) {
196
196
  return false
197
197
  }
198
198
  }