You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
6.2 KiB
238 lines
6.2 KiB
'use strict';
|
|
var utils = require('./utils');
|
|
|
|
/**
|
|
* Get a range of download counts for the specified repository.
|
|
* This method returns a stream of raw data
|
|
* in the form of `{ day: '2016-01-10', downloads: 123456 }`.
|
|
*
|
|
* ```js
|
|
* var start = new Date('2016-01-09');
|
|
* var end = new Date('2016-01-10');
|
|
* stats.get(start, end, 'micromatch')
|
|
* .on('error', console.error)
|
|
* .on('data', function(data) {
|
|
* console.log(data);
|
|
* })
|
|
* .on('end', function() {
|
|
* console.log('done.');
|
|
* });
|
|
* // { day: '2016-01-09', downloads: 53331 }
|
|
* // { day: '2016-01-10', downloads: 47341 }
|
|
* ```
|
|
*
|
|
* @param {Date} `start` Start date of stream.
|
|
* @param {Date} `end` End date of stream.
|
|
* @param {String} `repo` Repository to get downloads for. If `repo` is not passed, then all npm downloads for the day will be returned.
|
|
* @return {Stream} Stream of download data.
|
|
* @api public
|
|
*/
|
|
|
|
function get(start, end, repo) {
|
|
start = utils.moment.utc(start);
|
|
end = utils.moment.utc(end);
|
|
var current = utils.moment.utc(start);
|
|
var stream = new utils.stream.Stream();
|
|
run();
|
|
return stream;
|
|
|
|
function run() {
|
|
process.nextTick(function() {
|
|
let period = utils.moment.utc(current).add(300, 'days');
|
|
if (period.format('YYYY-MM-DD') >= end.format('YYYY-MM-DD')) {
|
|
period = utils.moment.utc(end);
|
|
}
|
|
|
|
getPage(current, period, repo)
|
|
.on('error', stream.emit.bind(stream, 'error'))
|
|
.on('data', function(data) {
|
|
stream.emit('data', data);
|
|
})
|
|
.on('end', function() {
|
|
current.add(300, 'days');
|
|
if (current.format('YYYY-MM-DD') >= end.format('YYYY-MM-DD')) {
|
|
stream.emit('end');
|
|
return;
|
|
}
|
|
run();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
function getPage(start, end, repo) {
|
|
var stream = new utils.stream.Stream();
|
|
var url = 'https://api.npmjs.org/downloads/range/';
|
|
url += utils.format(start);
|
|
url += ':' + utils.format(end);
|
|
url += (repo ? '/' + repo : '');
|
|
|
|
var bulk = false;
|
|
if (repo && repo.indexOf(',') > -1) {
|
|
bulk = true;
|
|
}
|
|
|
|
process.nextTick(function() {
|
|
var req = utils.https.get(options(url), function(res) {
|
|
res.on('error', console.error)
|
|
.pipe(utils.JSONStream.parse(bulk ? '*' : 'downloads.*'))
|
|
.on('error', handleError)
|
|
.on('data', function(data) {
|
|
stream.emit('data', data);
|
|
})
|
|
.on('end', stream.emit.bind(stream, 'end'));
|
|
});
|
|
|
|
req.on('error', stream.emit.bind(stream, 'error'));
|
|
});
|
|
|
|
return stream;
|
|
|
|
function handleError(err) {
|
|
console.error('handling error', err);
|
|
if (err.message.indexOf('Invalid JSON') >= 0) {
|
|
handleInvalidJSON();
|
|
return;
|
|
}
|
|
stream.emit('error', err);
|
|
}
|
|
|
|
function handleInvalidJSON() {
|
|
var body = '';
|
|
utils.https.get(options(url), function(res) {
|
|
res
|
|
.on('error', stream.emit.bind('error'))
|
|
.on('data', function(data) {
|
|
body += data;
|
|
})
|
|
.on('end', function() {
|
|
stream.emit('error', new Error(body));
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a specific point (all-time, last-month, last-week, last-day)
|
|
*
|
|
* ```js
|
|
* stats.get.period('last-day', 'micromatch', function(err, results) {
|
|
* if (err) return console.error(err);
|
|
* console.log(results);
|
|
* });
|
|
* // { day: '2016-01-10', downloads: 47341 }
|
|
* ```
|
|
* @param {String} `period` Period to retrieve downloads for.
|
|
* @param {String} `repo` Repository to retrieve downloads for.
|
|
* @param {Function} `cb` Callback function to get results
|
|
* @api public
|
|
*/
|
|
|
|
get.point = function(period, repo, cb) {
|
|
var url = 'https://api.npmjs.org/downloads/point/';
|
|
url += period;
|
|
url += (repo ? '/' + repo : '');
|
|
|
|
var results;
|
|
var req = utils.https.get(options(url), function(res) {
|
|
res.once('error', console.error)
|
|
.pipe(utils.JSONStream.parse())
|
|
.once('error', cb)
|
|
.on('data', function(data) {
|
|
results = data;
|
|
})
|
|
.once('end', function() {
|
|
cb(null, results);
|
|
});
|
|
});
|
|
|
|
req.once('error', cb);
|
|
};
|
|
|
|
/**
|
|
* Get the all time total downloads for a repository.
|
|
*
|
|
* ```js
|
|
* stats.get.allTime('micromatch', function(err, results) {
|
|
* if (err) return console.error(err);
|
|
* console.log(results);
|
|
* });
|
|
* // { day: '2016-01-10', downloads: 47341 }
|
|
* ```
|
|
* @param {String} `repo` Repository to retrieve downloads for.
|
|
* @param {Function} `cb` Callback function to get results
|
|
* @api public
|
|
*/
|
|
|
|
get.allTime = function(repo, cb) {
|
|
return get.point('all-time', repo, cb);
|
|
};
|
|
|
|
/**
|
|
* Get the last month's total downloads for a repository.
|
|
*
|
|
* ```js
|
|
* stats.get.lastMonth('micromatch', function(err, results) {
|
|
* if (err) return console.error(err);
|
|
* console.log(results);
|
|
* });
|
|
* // { downloads: 7750788, start: '2016-10-10', end: '2016-11-08', package: 'micromatch' }
|
|
* ```
|
|
* @param {String} `repo` Repository to retrieve downloads for.
|
|
* @param {Function} `cb` Callback function to get results
|
|
* @api public
|
|
*/
|
|
|
|
get.lastMonth = function(repo, cb) {
|
|
return get.point('last-month', repo, cb);
|
|
};
|
|
|
|
/**
|
|
* Get the last week's total downloads for a repository.
|
|
*
|
|
* ```js
|
|
* stats.get.lastWeek('micromatch', function(err, results) {
|
|
* if (err) return console.error(err);
|
|
* console.log(results);
|
|
* });
|
|
* // { downloads: 1777065, start: '2016-11-02', end: '2016-11-08', package: 'micromatch' }
|
|
* ```
|
|
* @param {String} `repo` Repository to retrieve downloads for.
|
|
* @param {Function} `cb` Callback function to get results
|
|
* @api public
|
|
*/
|
|
|
|
get.lastWeek = function(repo, cb) {
|
|
return get.point('last-week', repo, cb);
|
|
};
|
|
|
|
/**
|
|
* Get the last day's total downloads for a repository.
|
|
*
|
|
* ```js
|
|
* stats.get.lastDay('micromatch', function(err, results) {
|
|
* if (err) return console.error(err);
|
|
* console.log(results);
|
|
* });
|
|
* // { downloads: 316004, start: '2016-11-08', end: '2016-11-08', package: 'micromatch' }
|
|
* ```
|
|
* @param {String} `repo` Repository to retrieve downloads for.
|
|
* @param {Function} `cb` Callback function to get results
|
|
* @api public
|
|
*/
|
|
|
|
get.lastDay = function(repo, cb) {
|
|
return get.point('last-day', repo, cb);
|
|
};
|
|
|
|
function options(url) {
|
|
var opts = utils.url.parse(url);
|
|
opts.headers = {'User-Agent': 'https://github.com/doowb/download-stats'};
|
|
return opts;
|
|
}
|
|
|
|
/**
|
|
* Expose `get`
|
|
*/
|
|
|
|
module.exports = get;
|
|
|