semver.js 4.3 KB

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