web 3d图形渲染器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
8.3 KiB

  1. var childProcess = require('child_process')
  2. var colorette = require('colorette')
  3. var escalade = require('escalade/sync')
  4. var path = require('path')
  5. var fs = require('fs')
  6. var BrowserslistError = require('./error')
  7. var red = colorette.red
  8. var bold = colorette.bold
  9. var green = colorette.green
  10. var yellow = colorette.yellow
  11. function detectLockfile () {
  12. var packageDir = escalade('.', function (dir, names) {
  13. return names.indexOf('package.json') !== -1 ? dir : ''
  14. })
  15. if (!packageDir) {
  16. throw new BrowserslistError(
  17. 'Cannot find package.json. ' +
  18. 'Is this the right directory to run `npx browserslist --update-db` in?'
  19. )
  20. }
  21. var lockfileNpm = path.join(packageDir, 'package-lock.json')
  22. var lockfileYarn = path.join(packageDir, 'yarn.lock')
  23. var lockfilePnpm = path.join(packageDir, 'pnpm-lock.yaml')
  24. if (fs.existsSync(lockfilePnpm)) {
  25. return { mode: 'pnpm', file: lockfilePnpm }
  26. } else if (fs.existsSync(lockfileNpm)) {
  27. return { mode: 'npm', file: lockfileNpm }
  28. } else if (fs.existsSync(lockfileYarn)) {
  29. return { mode: 'yarn', file: lockfileYarn }
  30. }
  31. throw new BrowserslistError(
  32. 'No lockfile found. Run "npm install", "yarn install" or "pnpm install"'
  33. )
  34. }
  35. function getLatestInfo (lock) {
  36. if (lock.mode === 'yarn') {
  37. return JSON.parse(
  38. childProcess.execSync('yarn info caniuse-lite --json').toString()
  39. ).data
  40. }
  41. return JSON.parse(
  42. childProcess.execSync('npm show caniuse-lite --json').toString()
  43. )
  44. }
  45. function getBrowsersList () {
  46. return childProcess.execSync('npx browserslist').toString()
  47. .trim()
  48. .split('\n')
  49. .map(function (line) {
  50. return line.trim().split(' ')
  51. })
  52. .reduce(function (result, entry) {
  53. if (!result[entry[0]]) {
  54. result[entry[0]] = []
  55. }
  56. result[entry[0]].push(entry[1])
  57. return result
  58. }, {})
  59. }
  60. function diffBrowsersLists (old, current) {
  61. var browsers = Object.keys(old).concat(
  62. Object.keys(current).filter(function (browser) {
  63. return old[browser] === undefined
  64. })
  65. )
  66. return browsers.map(function (browser) {
  67. var oldVersions = old[browser] || []
  68. var currentVersions = current[browser] || []
  69. var intersection = oldVersions.filter(function (version) {
  70. return currentVersions.indexOf(version) !== -1
  71. })
  72. var addedVersions = currentVersions.filter(function (version) {
  73. return intersection.indexOf(version) === -1
  74. })
  75. var removedVersions = oldVersions.filter(function (version) {
  76. return intersection.indexOf(version) === -1
  77. })
  78. return removedVersions.map(function (version) {
  79. return red('- ' + browser + ' ' + version)
  80. }).concat(addedVersions.map(function (version) {
  81. return green('+ ' + browser + ' ' + version)
  82. }))
  83. })
  84. .reduce(function (result, array) {
  85. return result.concat(array)
  86. }, [])
  87. .join('\n')
  88. }
  89. function updateNpmLockfile (lock, latest) {
  90. var metadata = { latest: latest, versions: [] }
  91. var content = deletePackage(JSON.parse(lock.content), metadata)
  92. metadata.content = JSON.stringify(content, null, ' ')
  93. return metadata
  94. }
  95. function deletePackage (node, metadata) {
  96. if (node.dependencies) {
  97. if (node.dependencies['caniuse-lite']) {
  98. var version = node.dependencies['caniuse-lite'].version
  99. metadata.versions[version] = true
  100. delete node.dependencies['caniuse-lite']
  101. }
  102. for (var i in node.dependencies) {
  103. node.dependencies[i] = deletePackage(node.dependencies[i], metadata)
  104. }
  105. }
  106. return node
  107. }
  108. var yarnVersionRe = new RegExp('version "(.*?)"')
  109. function updateYarnLockfile (lock, latest) {
  110. var blocks = lock.content.split(/(\n{2,})/).map(function (block) {
  111. return block.split('\n')
  112. })
  113. var versions = {}
  114. blocks.forEach(function (lines) {
  115. if (lines[0].indexOf('caniuse-lite@') !== -1) {
  116. var match = yarnVersionRe.exec(lines[1])
  117. versions[match[1]] = true
  118. if (match[1] !== latest.version) {
  119. lines[1] = lines[1].replace(
  120. /version "[^"]+"/, 'version "' + latest.version + '"'
  121. )
  122. lines[2] = lines[2].replace(
  123. /resolved "[^"]+"/, 'resolved "' + latest.dist.tarball + '"'
  124. )
  125. lines[3] = latest.dist.integrity ? lines[3].replace(
  126. /integrity .+/, 'integrity ' + latest.dist.integrity
  127. ) : ''
  128. }
  129. }
  130. })
  131. var content = blocks.map(function (lines) {
  132. return lines.join('\n')
  133. }).join('')
  134. return { content: content, versions: versions }
  135. }
  136. function updatePnpmLockfile (lock, latest) {
  137. var versions = {}
  138. var lines = lock.content.split('\n')
  139. var i
  140. var j
  141. var lineParts
  142. for (i = 0; i < lines.length; i++) {
  143. if (lines[i].indexOf('caniuse-lite:') >= 0) {
  144. lineParts = lines[i].split(/:\s?/, 2)
  145. versions[lineParts[1]] = true
  146. lines[i] = lineParts[0] + ': ' + latest.version
  147. } else if (lines[i].indexOf('/caniuse-lite') >= 0) {
  148. lineParts = lines[i].split(/([/:])/)
  149. for (j = 0; j < lineParts.length; j++) {
  150. if (lineParts[j].indexOf('caniuse-lite') >= 0) {
  151. versions[lineParts[j + 2]] = true
  152. lineParts[j + 2] = latest.version
  153. break
  154. }
  155. }
  156. lines[i] = lineParts.join('')
  157. for (i = i + 1; i < lines.length; i++) {
  158. if (lines[i].indexOf('integrity: ') !== -1) {
  159. lines[i] = lines[i].replace(
  160. /integrity: .+/, 'integrity: ' + latest.dist.integrity
  161. )
  162. } else if (lines[i].indexOf(' /') !== -1) {
  163. break
  164. }
  165. }
  166. }
  167. }
  168. return { content: lines.join('\n'), versions: versions }
  169. }
  170. function updateLockfile (lock, latest) {
  171. lock.content = fs.readFileSync(lock.file).toString()
  172. if (lock.mode === 'npm') {
  173. return updateNpmLockfile(lock, latest)
  174. } else if (lock.mode === 'yarn') {
  175. return updateYarnLockfile(lock, latest)
  176. }
  177. return updatePnpmLockfile(lock, latest)
  178. }
  179. module.exports = function updateDB (print) {
  180. var lock = detectLockfile()
  181. var latest = getLatestInfo(lock)
  182. var browsersListRetrievalError
  183. var oldBrowsersList
  184. try {
  185. oldBrowsersList = getBrowsersList()
  186. } catch (e) {
  187. browsersListRetrievalError = e
  188. }
  189. print(
  190. 'Latest version: ' + bold(green(latest.version)) + '\n'
  191. )
  192. var lockfileData = updateLockfile(lock, latest)
  193. var caniuseVersions = Object.keys(lockfileData.versions).sort()
  194. if (caniuseVersions.length === 1 &&
  195. caniuseVersions[0] === latest.version) {
  196. print(
  197. 'Installed version: ' + bold(green(latest.version)) + '\n' +
  198. bold(green('caniuse-lite is up to date')) + '\n'
  199. )
  200. return
  201. }
  202. if (caniuseVersions.length === 0) {
  203. caniuseVersions[0] = 'none'
  204. }
  205. print(
  206. 'Installed version' +
  207. (caniuseVersions.length === 1 ? ': ' : 's: ') +
  208. bold(red(caniuseVersions.join(', '))) +
  209. '\n' +
  210. 'Removing old caniuse-lite from lock file\n'
  211. )
  212. fs.writeFileSync(lock.file, lockfileData.content)
  213. var install = lock.mode === 'yarn' ? 'yarn add -W' : lock.mode + ' install'
  214. print(
  215. 'Installing new caniuse-lite version\n' +
  216. yellow('$ ' + install + ' caniuse-lite') + '\n'
  217. )
  218. try {
  219. childProcess.execSync(install + ' caniuse-lite')
  220. } catch (e) /* istanbul ignore next */ {
  221. print(
  222. red(
  223. '\n' +
  224. e.stack + '\n\n' +
  225. 'Problem with `' + install + ' caniuse-lite` call. ' +
  226. 'Run it manually.\n'
  227. )
  228. )
  229. process.exit(1)
  230. }
  231. var del = lock.mode === 'yarn' ? 'yarn remove -W' : lock.mode + ' uninstall'
  232. print(
  233. 'Cleaning package.json dependencies from caniuse-lite\n' +
  234. yellow('$ ' + del + ' caniuse-lite') + '\n'
  235. )
  236. childProcess.execSync(del + ' caniuse-lite')
  237. print('caniuse-lite has been successfully updated\n')
  238. var currentBrowsersList
  239. if (!browsersListRetrievalError) {
  240. try {
  241. currentBrowsersList = getBrowsersList()
  242. } catch (e) /* istanbul ignore next */ {
  243. browsersListRetrievalError = e
  244. }
  245. }
  246. if (browsersListRetrievalError) {
  247. print(
  248. red(
  249. '\n' +
  250. browsersListRetrievalError.stack + '\n\n' +
  251. 'Problem with browser list retrieval.\n' +
  252. 'Target browser changes won’t be shown.\n'
  253. )
  254. )
  255. } else {
  256. var targetBrowserChanges = diffBrowsersLists(
  257. oldBrowsersList,
  258. currentBrowsersList
  259. )
  260. if (targetBrowserChanges) {
  261. print('\nTarget browser changes:\n')
  262. print(targetBrowserChanges + '\n')
  263. } else {
  264. print('\n' + green('No target browser changes') + '\n')
  265. }
  266. }
  267. }