semver.js 4.5 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. inc = argv.shift()
  50. break
  51. default:
  52. inc = 'patch'
  53. break
  54. }
  55. break
  56. case '--preid':
  57. identifier = argv.shift()
  58. break
  59. case '-r': case '--range':
  60. range.push(argv.shift())
  61. break
  62. case '-n':
  63. identifierBase = argv.shift()
  64. break
  65. case '-c': case '--coerce':
  66. coerce = true
  67. break
  68. case '--rtl':
  69. rtl = true
  70. break
  71. case '--ltr':
  72. rtl = false
  73. break
  74. case '-h': case '--help': case '-?':
  75. return help()
  76. default:
  77. versions.push(a)
  78. break
  79. }
  80. }
  81. options = parseOptions({ loose, includePrerelease, rtl })
  82. versions = versions.map((v) => {
  83. return coerce ? (semver.coerce(v, options) || { version: v }).version : v
  84. }).filter((v) => {
  85. return semver.valid(v)
  86. })
  87. if (!versions.length) {
  88. return fail()
  89. }
  90. if (inc && (versions.length !== 1 || range.length)) {
  91. return failInc()
  92. }
  93. for (let i = 0, l = range.length; i < l; i++) {
  94. versions = versions.filter((v) => {
  95. return semver.satisfies(v, range[i], options)
  96. })
  97. if (!versions.length) {
  98. return fail()
  99. }
  100. }
  101. return success(versions)
  102. }
  103. const failInc = () => {
  104. console.error('--inc can only be used on a single version with no range')
  105. fail()
  106. }
  107. const fail = () => process.exit(1)
  108. const success = () => {
  109. const compare = reverse ? 'rcompare' : 'compare'
  110. versions.sort((a, b) => {
  111. return semver[compare](a, b, options)
  112. }).map((v) => {
  113. return semver.clean(v, options)
  114. }).map((v) => {
  115. return inc ? semver.inc(v, inc, options, identifier, identifierBase) : v
  116. }).forEach((v, i, _) => {
  117. console.log(v)
  118. })
  119. }
  120. const help = () => console.log(
  121. `SemVer ${version}
  122. A JavaScript implementation of the https://semver.org/ specification
  123. Copyright Isaac Z. Schlueter
  124. Usage: semver [options] <version> [<version> [...]]
  125. Prints valid versions sorted by SemVer precedence
  126. Options:
  127. -r --range <range>
  128. Print versions that match the specified range.
  129. -i --increment [<level>]
  130. Increment a version by the specified level. Level can
  131. be one of: major, minor, patch, premajor, preminor,
  132. prepatch, or prerelease. Default level is 'patch'.
  133. Only one version may be specified.
  134. --preid <identifier>
  135. Identifier to be used to prefix premajor, preminor,
  136. prepatch or prerelease version increments.
  137. -l --loose
  138. Interpret versions and ranges loosely
  139. -p --include-prerelease
  140. Always include prerelease versions in range matching
  141. -c --coerce
  142. Coerce a string into SemVer if possible
  143. (does not imply --loose)
  144. --rtl
  145. Coerce version strings right to left
  146. --ltr
  147. Coerce version strings left to right (default)
  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()