@devicefarmer/please-update-dependencies
Version:
It checks that currently installed dependencies satisfy the requirements set in your package.json file
140 lines (118 loc) • 3.47 kB
JavaScript
var fs = require('fs')
var path = require('path')
var url = require('url')
var util = require('util')
var chalk = require('chalk')
var semver = require('semver')
var ERROR = chalk.red('ERROR:')
var HINT = chalk.yellow('HINT:')
var BYPASS = 'ALLOW_OUTDATED_DEPENDENCIES'
function verify (mod) {
var ctx = path.parse(mod.filename)
var pkg = null
// The calling module might not be in the root folder of the package. Go
// through its parent folders until it's found.
do {
try {
pkg = mod.require(path.resolve(ctx.dir, './package.json'))
break
} catch (err) {
if (err.code !== 'MODULE_NOT_FOUND') {
throw err
}
ctx = path.parse(ctx.dir)
continue
}
} while (ctx.root !== ctx.dir)
// Or did we not find it at all? That's bad.
if (pkg === null) {
console.error(ERROR, util.format(
'No %s in any parent folder of %s',
chalk.cyan('package.json'),
chalk.inverse(mod.filename)
))
return false
}
function validateEngines (engines) {
var thisEngine = (process.release || {name: 'node'}).name
return Object.keys(engines).reduce(function (state, name) {
var wanted = engines[name]
if (name === thisEngine) {
if (!semver.satisfies(process.version, wanted)) {
console.error(ERROR, util.format(
'engine %s is currently %s but needs to be %s',
chalk.cyan(name),
chalk.red(process.version),
chalk.green(wanted)
))
return false
}
}
return state
}, true)
}
if (!validateEngines(pkg.engines || {})) {
console.error(HINT, 'Please update to a supported version.')
return false
}
function validateDeps (deps, type) {
return Object.keys(deps).reduce(function (state, name) {
var wanted = deps[name]
var depPkg = null
// Is it a full URL? Can't handle those.
var wantedUrl = url.parse(wanted)
if (wantedUrl.protocol) {
return state
}
// Or if it's a shorthand GitHub URL, we can't handle those either.
if (/[^@].*\//.test(wanted)) {
return state
}
try {
depPkg = mod.require(path.join(ctx.dir, './node_modules/', name, './package.json'))
} catch (err) {
console.error(ERROR, type, util.format(
'%s is not installed (%s)',
chalk.cyan(name),
chalk.red(err.code)
))
return false
}
if (!semver.satisfies(depPkg.version, wanted)) {
console.error(ERROR, type, util.format(
'%s is currently %s but needs to be %s',
chalk.cyan(name),
chalk.red(depPkg.version),
chalk.green(wanted)
))
return false
}
return state
}, true)
}
if (!validateDeps(pkg.dependencies || {}, 'dependency')) {
try {
fs.statSync(path.resolve(ctx.dir, 'yarn.lock'))
console.error(HINT,
'Please run `yarn`, `npm install` or equivalent before continuing.')
} catch (err) {
console.error(HINT,
'Please run `npm install` or equivalent before continuing.')
}
return false
}
return true
}
module.exports.verify = verify
module.exports = function (mod) {
if (process.env[BYPASS] === '1') {
return
}
if (!verify(mod)) {
console.error(HINT, util.format(
'You can also export %s=1 to bypass verification.',
BYPASS
))
process.exit(1)
}
}