top-dependents
Version:
Fetches the top dependents for the given NPM module
98 lines (82 loc) • 3.13 kB
JavaScript
var la = require('lazy-ass');
var check = require('check-more-types');
var _ = require('lodash');
var Q = require('q');
var Registry = require('npm-registry');
var npm = new Registry();
var downloads = {};
function isValidMetric(metric) {
la(check.unemptyString(metric), 'expected string metric name', metric);
return metric === 'downloads' || metric === 'starred';
}
function sortedByValue(o) {
la(check.object(o), 'expected an object', o);
la(check.arrayOf(check.number, _.values(o)),
'expected values to be numbers', o);
var list = _.pairs(o);
// [[name, n], [name, n], ...]
var sorted = _.sortBy(list, '1').reverse();
// sorts by number, largest first
var names = _.map(sorted, '0');
return names;
}
function topDownloads(name) {
la(check.unemptyString(name), 'invalid package name', name);
return Q.ninvoke(npm.downloads, 'totals', 'last-week', name)
.then(function statsToDownloads(stats) {
la(check.array(stats) && stats.length === 1, 'expected single stats', stats);
la(check.number(stats[0].downloads), 'invalid number of downloads', stats);
var n = stats[0].downloads;
downloads[name] = n;
console.log(name, 'has been downloaded', n, 'times');
return n;
});
}
function topStarred(name) {
la(check.unemptyString(name), 'invalid package name', name);
return Q.ninvoke(npm.packages, 'starred', name)
.then(function usersToStarred(users) {
la(check.array(users), 'expected list of users that starred', name, 'not', users);
var n = users.length;
downloads[name] = n;
console.log(name, 'has been starred', n, 'times');
return n;
});
}
function fetchDownloads(metric, name) {
la(isValidMetric(metric), 'invalid metric', metric);
la(check.unemptyString(name), 'invalid package name', name);
return metric === 'downloads' ? topDownloads(name) : topStarred(name);
}
function fetchInfoForEachDependent(metric, dependents) {
la(check.arrayOfStrings(dependents), 'invalid dependents', dependents);
var actions = dependents.map(function (name) {
return _.partial(fetchDownloads, metric, name);
});
console.log('preparing number of downloads for dependents', dependents.join(', '));
/* jshint -W064 */
/* eslint new-cap:0 */
var fetchSequence = actions.reduce(Q.when, Q());
return fetchSequence.then(function () {
return downloads;
});
}
function getTopDependents(name, n) {
la(check.unemptyString(name), 'missing package name');
la(check.positiveNumber(n), 'invalid top dependents to check', n);
console.log('fetching top', n, 'dependent projects for', name);
return Q.ninvoke(npm.packages, 'depended', name).then(function (dependents) {
la(check.array(dependents),
'expected modules dependent on', name, 'to be array', dependents);
console.log('module', name, 'has', dependents.length, 'dependents');
var names = _.pluck(dependents, 'name');
return names;
});
}
var api = {
topDependents: getTopDependents,
infoForDependents: fetchInfoForEachDependent,
sortedByValue: sortedByValue,
isValidMetric: isValidMetric
};
module.exports = api;