semver.js 4.3 KB

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