env.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. const { execSync } = require('child_process')
  2. const fs = require('fs')
  3. const path = require('path')
  4. const LRU = require('lru-cache')
  5. const semver = require('semver')
  6. let _hasYarn
  7. const _yarnProjects = new LRU({
  8. max: 10,
  9. maxAge: 1000
  10. })
  11. let _hasGit
  12. const _gitProjects = new LRU({
  13. max: 10,
  14. maxAge: 1000
  15. })
  16. // env detection
  17. exports.hasYarn = () => {
  18. if (process.env.VUE_CLI_TEST) {
  19. return true
  20. }
  21. if (_hasYarn != null) {
  22. return _hasYarn
  23. }
  24. try {
  25. execSync('yarn --version', { stdio: 'ignore' })
  26. return (_hasYarn = true)
  27. } catch (e) {
  28. return (_hasYarn = false)
  29. }
  30. }
  31. exports.hasProjectYarn = (cwd) => {
  32. if (_yarnProjects.has(cwd)) {
  33. return checkYarn(_yarnProjects.get(cwd))
  34. }
  35. const lockFile = path.join(cwd, 'yarn.lock')
  36. const result = fs.existsSync(lockFile)
  37. _yarnProjects.set(cwd, result)
  38. return checkYarn(result)
  39. }
  40. function checkYarn (result) {
  41. if (result && !exports.hasYarn()) throw new Error(`The project seems to require yarn but it's not installed.`)
  42. return result
  43. }
  44. exports.hasGit = () => {
  45. if (process.env.VUE_CLI_TEST) {
  46. return true
  47. }
  48. if (_hasGit != null) {
  49. return _hasGit
  50. }
  51. try {
  52. execSync('git --version', { stdio: 'ignore' })
  53. return (_hasGit = true)
  54. } catch (e) {
  55. return (_hasGit = false)
  56. }
  57. }
  58. exports.hasProjectGit = (cwd) => {
  59. if (_gitProjects.has(cwd)) {
  60. return _gitProjects.get(cwd)
  61. }
  62. let result
  63. try {
  64. execSync('git status', { stdio: 'ignore', cwd })
  65. result = true
  66. } catch (e) {
  67. result = false
  68. }
  69. _gitProjects.set(cwd, result)
  70. return result
  71. }
  72. let _hasPnpm
  73. let _pnpmVersion
  74. const _pnpmProjects = new LRU({
  75. max: 10,
  76. maxAge: 1000
  77. })
  78. function getPnpmVersion () {
  79. if (_pnpmVersion != null) {
  80. return _pnpmVersion
  81. }
  82. try {
  83. _pnpmVersion = execSync('pnpm --version', {
  84. stdio: ['pipe', 'pipe', 'ignore']
  85. }).toString()
  86. // there's a critical bug in pnpm 2
  87. // https://github.com/pnpm/pnpm/issues/1678#issuecomment-469981972
  88. // so we only support pnpm >= 3.0.0
  89. _hasPnpm = true
  90. } catch (e) {}
  91. return _pnpmVersion || '0.0.0'
  92. }
  93. exports.hasPnpmVersionOrLater = (version) => {
  94. if (process.env.VUE_CLI_TEST) {
  95. return true
  96. }
  97. return semver.gte(getPnpmVersion(), version)
  98. }
  99. exports.hasPnpm3OrLater = () => {
  100. return this.hasPnpmVersionOrLater('3.0.0')
  101. }
  102. exports.hasProjectPnpm = (cwd) => {
  103. if (_pnpmProjects.has(cwd)) {
  104. return checkPnpm(_pnpmProjects.get(cwd))
  105. }
  106. const lockFile = path.join(cwd, 'pnpm-lock.yaml')
  107. const result = fs.existsSync(lockFile)
  108. _pnpmProjects.set(cwd, result)
  109. return checkPnpm(result)
  110. }
  111. function checkPnpm (result) {
  112. if (result && !exports.hasPnpm3OrLater()) {
  113. throw new Error(`The project seems to require pnpm${_hasPnpm ? ' >= 3' : ''} but it's not installed.`)
  114. }
  115. return result
  116. }
  117. const _npmProjects = new LRU({
  118. max: 10,
  119. maxAge: 1000
  120. })
  121. exports.hasProjectNpm = (cwd) => {
  122. if (_npmProjects.has(cwd)) {
  123. return _npmProjects.get(cwd)
  124. }
  125. const lockFile = path.join(cwd, 'package-lock.json')
  126. const result = fs.existsSync(lockFile)
  127. _npmProjects.set(cwd, result)
  128. return result
  129. }
  130. // OS
  131. exports.isWindows = process.platform === 'win32'
  132. exports.isMacintosh = process.platform === 'darwin'
  133. exports.isLinux = process.platform === 'linux'
  134. const browsers = {}
  135. let hasCheckedBrowsers = false
  136. function tryRun (cmd) {
  137. try {
  138. return execSync(cmd, {
  139. stdio: [0, 'pipe', 'ignore'],
  140. timeout: 10000
  141. }).toString().trim()
  142. } catch (e) {
  143. return ''
  144. }
  145. }
  146. function getLinuxAppVersion (binary) {
  147. return tryRun(`${binary} --version`).replace(/^.* ([^ ]*)/g, '$1')
  148. }
  149. function getMacAppVersion (bundleIdentifier) {
  150. const bundlePath = tryRun(`mdfind "kMDItemCFBundleIdentifier=='${bundleIdentifier}'"`)
  151. if (bundlePath) {
  152. return tryRun(`/usr/libexec/PlistBuddy -c Print:CFBundleShortVersionString ${
  153. bundlePath.replace(/(\s)/g, '\\ ')
  154. }/Contents/Info.plist`)
  155. }
  156. }
  157. exports.getInstalledBrowsers = () => {
  158. if (hasCheckedBrowsers) {
  159. return browsers
  160. }
  161. hasCheckedBrowsers = true
  162. if (exports.isLinux) {
  163. browsers.chrome = getLinuxAppVersion('google-chrome')
  164. browsers.firefox = getLinuxAppVersion('firefox')
  165. } else if (exports.isMacintosh) {
  166. browsers.chrome = getMacAppVersion('com.google.Chrome')
  167. browsers.firefox = getMacAppVersion('org.mozilla.firefox')
  168. } else if (exports.isWindows) {
  169. // get chrome stable version
  170. // https://stackoverflow.com/a/51773107/2302258
  171. const chromeQueryResult = tryRun(
  172. 'reg query "HKLM\\Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}" /v pv /reg:32'
  173. ) || tryRun(
  174. 'reg query "HKCU\\Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}" /v pv /reg:32'
  175. )
  176. if (chromeQueryResult) {
  177. const matched = chromeQueryResult.match(/REG_SZ\s+(\S*)$/)
  178. browsers.chrome = matched && matched[1]
  179. }
  180. // get firefox version
  181. // https://community.spiceworks.com/topic/111518-how-to-determine-version-of-installed-firefox-in-windows-batchscript
  182. const ffQueryResult = tryRun(
  183. 'reg query "HKLM\\Software\\Mozilla\\Mozilla Firefox" /v CurrentVersion'
  184. )
  185. if (ffQueryResult) {
  186. const matched = ffQueryResult.match(/REG_SZ\s+(\S*)$/)
  187. browsers.firefox = matched && matched[1]
  188. }
  189. }
  190. return browsers
  191. }