semver.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #!/usr/bin/env node
  2. // Standalone semver comparison program.
  3. // Exits successfully and prints matching version(s) if
  4. // any supplied version is valid and passes all tests.
  5. const argv = process.argv.slice(2)
  6. let versions = []
  7. const range = []
  8. let inc = null
  9. const version = require('../package.json').version
  10. let loose = false
  11. let includePrerelease = false
  12. let coerce = false
  13. let rtl = false
  14. let identifier
  15. let identifierBase
  16. const semver = require('../')
  17. const parseOptions = require('../internal/parse-options')
  18. let reverse = false
  19. let options = {}
  20. const main = () => {
  21. if (!argv.length) {
  22. return help()
  23. }
  24. while (argv.length) {
  25. let a = argv.shift()
  26. const indexOfEqualSign = a.indexOf('=')
  27. if (indexOfEqualSign !== -1) {
  28. const value = a.slice(indexOfEqualSign + 1)
  29. a = a.slice(0, indexOfEqualSign)
  30. argv.unshift(value)
  31. }
  32. switch (a) {
  33. case '-rv': case '-rev': case '--rev': case '--reverse':
  34. reverse = true
  35. break
  36. case '-l': case '--loose':
  37. loose = true
  38. break
  39. case '-p': case '--include-prerelease':
  40. includePrerelease = true
  41. break
  42. case '-v': case '--version':
  43. versions.push(argv.shift())
  44. break
  45. case '-i': case '--inc': case '--increment':
  46. switch (argv[0]) {
  47. case 'major': case 'minor': case 'patch': case 'prerelease':
  48. case 'premajor': case 'preminor': case 'prepatch':
  49. case 'release':
  50. inc = argv.shift()
  51. break
  52. default:
  53. inc = 'patch'
  54. break
  55. }
  56. break
  57. case '--preid':
  58. identifier = argv.shift()
  59. break
  60. case '-r': case '--range':
  61. range.push(argv.shift())
  62. break
  63. case '-n':
  64. identifierBase = argv.shift()
  65. if (identifierBase === 'false') {
  66. identifierBase = false
  67. }
  68. break
  69. case '-c': case '--coerce':
  70. coerce = true
  71. break
  72. case '--rtl':
  73. rtl = true
  74. break
  75. case '--ltr':
  76. rtl = false
  77. break
  78. case '-h': case '--help': case '-?':
  79. return help()
  80. default:
  81. versions.push(a)
  82. break
  83. }
  84. }
  85. options = parseOptions({ loose, includePrerelease, rtl })
  86. versions = versions.map((v) => {
  87. return coerce ? (semver.coerce(v, options) || { version: v }).version : v
  88. }).filter((v) => {
  89. return semver.valid(v)
  90. })
  91. if (!versions.length) {
  92. return fail()
  93. }
  94. if (inc && (versions.length !== 1 || range.length)) {
  95. return failInc()
  96. }
  97. for (let i = 0, l = range.length; i < l; i++) {
  98. versions = versions.filter((v) => {
  99. return semver.satisfies(v, range[i], options)
  100. })
  101. if (!versions.length) {
  102. return fail()
  103. }
  104. }
  105. versions
  106. .sort((a, b) => semver[reverse ? 'rcompare' : 'compare'](a, b, options))
  107. .map(v => semver.clean(v, options))
  108. .map(v => inc ? semver.inc(v, inc, options, identifier, identifierBase) : v)
  109. .forEach(v => console.log(v))
  110. }
  111. const failInc = () => {
  112. console.error('--inc can only be used on a single version with no range')
  113. fail()
  114. }
  115. const fail = () => process.exit(1)
  116. const help = () => console.log(
  117. `SemVer ${version}
  118. A JavaScript implementation of the https://semver.org/ specification
  119. Copyright Isaac Z. Schlueter
  120. Usage: semver [options] <version> [<version> [...]]
  121. Prints valid versions sorted by SemVer precedence
  122. Options:
  123. -r --range <range>
  124. Print versions that match the specified range.
  125. -i --increment [<level>]
  126. Increment a version by the specified level. Level can
  127. be one of: major, minor, patch, premajor, preminor,
  128. prepatch, prerelease, or release. Default level is 'patch'.
  129. Only one version may be specified.
  130. --preid <identifier>
  131. Identifier to be used to prefix premajor, preminor,
  132. prepatch or prerelease version increments.
  133. -l --loose
  134. Interpret versions and ranges loosely
  135. -p --include-prerelease
  136. Always include prerelease versions in range matching
  137. -c --coerce
  138. Coerce a string into SemVer if possible
  139. (does not imply --loose)
  140. --rtl
  141. Coerce version strings right to left
  142. --ltr
  143. Coerce version strings left to right (default)
  144. -n <base>
  145. Base number to be used for the prerelease identifier.
  146. Can be either 0 or 1, or false to omit the number altogether.
  147. Defaults to 0.
  148. Program exits successfully if any valid version satisfies
  149. all supplied ranges, and prints all satisfying versions.
  150. If no satisfying versions are found, then exits failure.
  151. Versions are printed in ascending order, so supplying
  152. multiple versions to the utility will just sort them.`)
  153. main()