Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 200 lines (175 sloc) 5.642 kB
#!/usr/bin/env node
var fs = require('fs'),
path = require('path'),
colors = require('colors'),
winston = require('winston'),
argv = require('optimist').argv,
eyes = require('eyes'),
analyzer = require('../lib/require-analyzer');
var help = [
'usage: require-analyzer [options] [directory]',
'',
'Analyzes the node.js requirements for the target directory. If no directory',
'is supplied then the current directory is used',
'',
'options:',
' -d, --dir Directory to check for package.json',
' --update Update versions for existing dependencies',
' -f, --file File to check for instead of package.json.',
' --safe display existing dependencies but do change package.json',
' -h, --help You\'re staring at it'
].join('\n');
if (argv.h || argv.help) {
return console.log(help);
}
//
// Create an `eyes` inspector for pretty printing dependencies.
//
var inspect = eyes.inspector({ stream: null,
styles: { // Styles applied to stdout
all: null, // Overall style applied to everything
label: 'underline', // Inspection labels, like 'array' in `array: [1, 2, 3]`
other: 'inverted', // Objects which don't have a literal representation, such as functions
key: 'grey', // The keys in object literals, like 'a' in `{a: 1}`
special: 'grey', // null, undefined...
number: 'blue', // 1, 2, 3, etc
bool: 'magenta', // true false
regexp: 'green', // /\d+/
string: 'yellow'
}
});
//
// Configure winston to pretty print in a similar style
// to `jitsu`.
//
winston.cli();
//
// ### function listDependencies (pkg, msg)
// #### @pkg {Object} Valid package.json
// #### @msg {string} Message to print before listing
// Lists the dependencies in `pkg` using `eyes` for
// pretty printing the output consistently.
//
function listDependencies (pkg, msgs) {
pkg = pkg || {};
pkg.dependencies = pkg.dependencies || {};
var keys = Object.keys(pkg.dependencies),
list = inspect(pkg.dependencies);
if (keys.length === 0) {
return winston.warn(msgs.error);
}
else if (keys.length <= 2) {
list = list.replace(/\{\s/, '{ \n')
.replace(/\}/, '\n}')
.replace('\033[90m', ' \033[90m')
.replace(/, /ig, ',\n ');
}
else {
list = list.replace(/\n\s{4}/ig, '\n ');
}
winston.info(msgs.success);
list.split('\n').forEach(function (line) {
winston.data(line);
});
}
var dir = process.cwd(),
source = argv._[0],
pkgFile;
if (source) {
dir = source[0] === '/' ? source : path.join(argv.d || argv.dir || dir, source);
}
pkgFile = path.join(dir, argv.f || argv.file || 'package.json');
winston.info('require-analyzer starting in ' + dir.magenta);
fs.readFile(pkgFile, function (err, data) {
if (err) {
if (err.errno === 34 && err.code === 'ENOENT') {
data = "{}";
}
else {
winston.error('Error reading package.json');
winston.error(err.message.red);
return;
}
}
var pkg, updated, options = {
target: dir,
reduce: true
};
if (argv.f || argv.file) {
options.f = argv.f || argv.file;
}
//
// Attempt to parse the package.json from the current directory.
//
try {
pkg = JSON.parse(data.toString());
listDependencies(pkg, {
error: 'No dependencies found',
success: 'Found existing dependencies'
});
}
catch (ex) {
winston.error('Error parsing package.json');
winston.error(ex.message.red);
return;
}
//
// ### function mergeResults (results)
// #### @results {Object} Set of results returned from `npm`
// Formats the results according to the `version` of each package.
//
function mergeResults (results) {
var all = analyzer.extractVersions(results);
return analyzer.updates(pkg.dependencies, all);
}
winston.info('Analyzing dependencies...');
var emitter = analyzer.analyze(options, function (err, packages) {
if (err) {
winston.error('Error analyzing dependencies'.red);
err.message.split('\n').forEach(function (line) {
winston.error(line);
});
return;
}
});
emitter.on('dependencies', function (deps) {
winston.info('Done analyzing raw dependencies');
});
emitter.on('search', function (results) {
winston.info('Retrieved packages from npm');
updated = mergeResults(results).updated;
});
emitter.on('reduce', function (reduced) {
var added = mergeResults(reduced).added,
newpkg = {
dependencies: analyzer.merge({}, added)
};
if (argv.update) {
newpkg.dependencies = analyzer.merge({}, newpkg.dependencies, updated);
}
listDependencies(newpkg, {
error: 'No additional dependencies found',
success: 'Additional dependencies found'
});
//
// If require-analyzer found new dependencies then update the `package.json`
// file in the target `dir`.
//
if (argv.safe) {
winston.info('did not update package.json');
return;
}
if (Object.keys(newpkg.dependencies).length > 0) {
winston.info('Updating ' + pkgFile.magenta);
pkg.dependencies = analyzer.merge({}, pkg.dependencies, newpkg.dependencies);
fs.writeFile(pkgFile, JSON.stringify(pkg, null, 2), function (err) {
if (err) {
winston.error('Error writing package.json');
winston.error(err.message.red);
return;
}
winston.info('require-analyzer updated package.json dependencies');
});
}
});
});
Jump to Line
Something went wrong with that request. Please try again.