2021-01-04 18:02:13 +08:00

258 lines
7.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var childProcess = require('child_process')
var colorette = require('colorette')
var escalade = require('escalade/sync')
var path = require('path')
var fs = require('fs')
var BrowserslistError = require('./error')
var red = colorette.red
var bold = colorette.bold
var green = colorette.green
var yellow = colorette.yellow
function detectLockfile () {
var packageDir = escalade('.', function (dir, names) {
return names.indexOf('package.json') !== -1 ? dir : ''
})
if (!packageDir) {
throw new BrowserslistError(
'Cannot find package.json. ' +
'Is it a right project to run npx browserslist --update-db?'
)
}
var lockfileNpm = path.join(packageDir, 'package-lock.json')
var lockfileYarn = path.join(packageDir, 'yarn.lock')
var lockfilePnpm = path.join(packageDir, 'pnpm-lock.yaml')
/* istanbul ignore next */
if (fs.existsSync(lockfilePnpm)) {
return { mode: 'pnpm', file: lockfilePnpm }
} else if (fs.existsSync(lockfileNpm)) {
return { mode: 'npm', file: lockfileNpm }
} else if (fs.existsSync(lockfileYarn)) {
return { mode: 'yarn', file: lockfileYarn }
} else {
throw new BrowserslistError(
'No lockfile found. Run "npm install", "yarn install" or "pnpm install"'
)
}
}
function getCurrentVersion (lock) {
var match
/* istanbul ignore if */
if (lock.mode === 'pnpm') {
match = /\/caniuse-lite\/([^:]+):/.exec(lock.content)
if (match[1]) return match[1]
} else if (lock.mode === 'npm') {
var dependencies = JSON.parse(lock.content).dependencies
if (dependencies && dependencies['caniuse-lite']) {
return dependencies['caniuse-lite'].version
}
} else if (lock.mode === 'yarn') {
match = /caniuse-lite@[^:]+:\r?\n\s+version\s+"([^"]+)"/.exec(lock.content)
if (match[1]) return match[1]
}
return null
}
function getLatestInfo (lock) {
if (lock.mode !== 'yarn') {
return JSON.parse(
childProcess.execSync('npm show caniuse-lite --json').toString()
)
} else {
return JSON.parse(
childProcess.execSync('yarn info caniuse-lite --json').toString()
).data
}
}
function getBrowsersList () {
return childProcess.execSync('npx browserslist').toString()
.trim()
.split('\n')
.map(function (line) {
return line.trim().split(' ')
})
.reduce(function (result, entry) {
if (!result[entry[0]]) {
result[entry[0]] = []
}
result[entry[0]].push(entry[1])
return result
}, {})
}
function diffBrowsersLists (old, current) {
var browsers = Object.keys(old).concat(
Object.keys(current).filter(function (browser) {
return old[browser] === undefined
})
)
return browsers.map(function (browser) {
var oldVersions = old[browser] || []
var currentVersions = current[browser] || []
var intersection = oldVersions.filter(function (version) {
return currentVersions.indexOf(version) !== -1
})
var addedVersions = currentVersions.filter(function (version) {
return intersection.indexOf(version) === -1
})
var removedVersions = oldVersions.filter(function (version) {
return intersection.indexOf(version) === -1
})
return removedVersions.map(function (version) {
return red('- ' + browser + ' ' + version)
}).concat(addedVersions.map(function (version) {
return green('+ ' + browser + ' ' + version)
}))
})
.reduce(function (result, array) {
return result.concat(array)
}, [])
.join('\n')
}
function updateLockfile (lock, latest) {
if (lock.mode === 'npm') {
var fixed = deletePackage(JSON.parse(lock.content))
return JSON.stringify(fixed, null, ' ')
} else {
var lines = lock.content.split('\n')
var i
/* istanbul ignore if */
if (lock.mode === 'pnpm') {
for (i = 0; i < lines.length; i++) {
if (lines[i].indexOf('caniuse-lite:') >= 0) {
lines[i] = lines[i].replace(/: .*$/, ': ' + latest.version)
} else if (lines[i].indexOf('/caniuse-lite') >= 0) {
lines[i] = lines[i].replace(/\/[^/:]+:/, '/' + latest.version + ':')
for (i = i + 1; i < lines.length; i++) {
if (lines[i].indexOf('integrity: ') !== -1) {
lines[i] = lines[i].replace(
/integrity: .+/, 'integrity: ' + latest.dist.integrity
)
} else if (lines[i].indexOf(' /') !== -1) {
break
}
}
}
}
} else if (lock.mode === 'yarn') {
for (i = 0; i < lines.length; i++) {
if (lines[i].indexOf('caniuse-lite@') !== -1) {
lines[i + 1] = lines[i + 1].replace(
/version "[^"]+"/, 'version "' + latest.version + '"'
)
lines[i + 2] = lines[i + 2].replace(
/resolved "[^"]+"/, 'resolved "' + latest.dist.tarball + '"'
)
lines[i + 3] = lines[i + 3].replace(
/integrity .+/, 'integrity ' + latest.dist.integrity
)
i += 4
}
}
}
return lines.join('\n')
}
}
function deletePackage (node) {
if (node.dependencies) {
delete node.dependencies['caniuse-lite']
for (var i in node.dependencies) {
node.dependencies[i] = deletePackage(node.dependencies[i])
}
}
return node
}
module.exports = function updateDB (print) {
var lock = detectLockfile()
lock.content = fs.readFileSync(lock.file).toString()
var current = getCurrentVersion(lock)
var latest = getLatestInfo(lock)
var browsersListRetrievalError
var oldBrowsersList
try {
oldBrowsersList = getBrowsersList()
} catch (e) {
browsersListRetrievalError = e
}
if (typeof current === 'string') {
print('Current version: ' + bold(red(current)) + '\n')
}
print(
'New version: ' + bold(green(latest.version)) + '\n' +
'Removing old caniuse-lite from lock file\n'
)
fs.writeFileSync(lock.file, updateLockfile(lock, latest))
var install = lock.mode === 'yarn' ? 'yarn add -W' : lock.mode + ' install'
print(
'Installing new caniuse-lite version\n' +
yellow('$ ' + install + ' caniuse-lite') + '\n'
)
try {
childProcess.execSync(install + ' caniuse-lite')
} catch (e) /* istanbul ignore next */ {
print(
red(
'\n' +
e.stack + '\n\n' +
'Problem with `' + install + ' caniuse-lite` call. ' +
'Run it manually.\n'
)
)
process.exit(1)
}
var del = lock.mode === 'yarn' ? 'yarn remove -W' : lock.mode + ' uninstall'
print(
'Cleaning package.json dependencies from caniuse-lite\n' +
yellow('$ ' + del + ' caniuse-lite') + '\n'
)
childProcess.execSync(del + ' caniuse-lite')
print('caniuse-lite has been successfully updated\n')
var currentBrowsersList
if (!browsersListRetrievalError) {
try {
currentBrowsersList = getBrowsersList()
} catch (e) /* istanbul ignore next */ {
browsersListRetrievalError = e
}
}
if (browsersListRetrievalError) {
print(
red(
'\n' +
browsersListRetrievalError.stack + '\n\n' +
'Problem with browsers list retrieval.\n' +
'Target browser changes wont be shown.\n'
)
)
} else {
var targetBrowserChanges = diffBrowsersLists(
oldBrowsersList,
currentBrowsersList
)
if (targetBrowserChanges) {
print('\nTarget browser changes:\n')
print(targetBrowserChanges + '\n')
} else {
print('\n' + green('No target browser changes') + '\n')
}
}
}