npmcheck.js
This script parses a package.json
file and checks NPM for updates
to all dependencies.
javascript
#!/usr/bin/env node
const path = require('path');
const exec = require('child_process').exec;
const cwd = process.cwd();
let dir = process.argv[2];
if (!dir) {
dir = cwd;
}
if (!path.isAbsolute(dir)) {
dir = path.resolve(dir);
}
const pkg = require(path.join(dir, 'package.json'));
const deps = pkg.dependencies || {};
const devDeps = pkg.devDependencies || {};
const green = `\u001b[32m`;
const red = `\u001b[31m`;
const cyan = `\u001b[36m`;
const blue = `\u001b[34m`;
const bold = `\u001b[1m`;
const underline = `\u001b[4m`;
const reset = `\u001b[0m`;
const results = {
deps: {},
devDeps: {},
};
const pending = Object.keys(deps).map(name => ({ name, currentVersion: deps[name] }))
.concat(Object.keys(devDeps).map(name => ({name, currentVersion: devDeps[name]})));
const stats = {
inFlight: 0,
total: pending.length,
processed: 0,
failed: 0,
};
const printProgress = () => {
process.stdout.write('\r' + ' '.repeat(70));
process.stdout.write(`\r${bold}${stats.processed}/${stats.total}${reset} dependencies checked (${stats.inFlight} in flight)`);
};
const check = async (name, currentVersion) => {
stats.inFlight++;
printProgress();
return new Promise((resolve, reject) => {
exec(`npm info ${name} version`, (err, stdout) => {
stats.processed++;
stats.inFlight--;
if (err) {
stats.failed++;
}
printProgress();
const version = (stdout || '').trim() || '???';
if (deps[name]) {
results.deps[name] = {
current: currentVersion,
latest: version,
}
} else {
results.devDeps[name] = {
current: currentVersion,
latest: version,
}
}
resolve(runNext());
});
});
};
const runNext = () => {
const next = pending.shift();
if (next) {
return check(next.name, next.currentVersion);
}
return Promise.resolve();
};
const maxInFlight = 5;
const promises = [];
for (let i = 0; i < maxInFlight; i++) {
const next = pending.shift();
if (!next) {
break;
}
promises.push(check(next.name, next.currentVersion));
}
Promise.all(promises)
.then(() => {
console.log('\r' + ' '.repeat(70));
const maxLength = Object.keys(results.deps)
.concat(Object.keys(results.devDeps))
.reduce((max, name) => Math.max(max, name.length), 30);
const print = (deps) => {
Object.keys(deps).sort().forEach((name) => {
const value = deps[name];
const isCurrent = value.current === value.latest;
console.log(`${blue}${name}${reset} ` + '.'.repeat(maxLength - name.length + 5) + ' ' +
(isCurrent ? `${green}${value.current}${reset}` : `${red}${value.current}${reset} → ${bold}${cyan}${value.latest}${reset}`));
});
};
console.log(`${bold}${underline}Dependencies${reset}`);
print(results.deps);
console.log();
console.log(`${bold}${underline}Dev Dependencies${reset}`);
print(results.devDeps);
console.log();
process.exit();
})
.catch((err) => {
console.error(err);
process.exit(1);
});