Badge for required node version from npm

Fixes #237.
This commit is contained in:
Thaddee Tyl 2014-09-09 21:11:10 +02:00
parent 0cacc19852
commit 2dd89e6c66
2 changed files with 84 additions and 1 deletions

View File

@ -524,7 +524,7 @@ cache(function(data, match, sendBadge) {
});
}));
// npm integration.
// npm download integration.
camp.route(/^\/npm\/dm\/(.*)\.(svg|png|gif|jpg)$/,
cache(function(data, match, sendBadge) {
var user = match[1]; // eg, `localeval`.
@ -619,6 +619,57 @@ cache(function(data, match, sendBadge) {
});
}));
// npm node version integration.
camp.route(/^\/node\/v\/(.*)\.(svg|png|gif|jpg)$/,
cache(function(data, match, sendBadge) {
var repo = match[1]; // eg, `localeval`.
var format = match[2];
var apiUrl = 'https://registry.npmjs.org/' + repo + '/latest';
var badgeData = getBadgeData('node', data);
// Using the Accept header because of this bug:
// <https://github.com/npm/npmjs.org/issues/163>
request(apiUrl, { headers: { 'Accept': '*/*' } }, function(err, res, buffer) {
if (err != null) {
badgeData.text[1] = 'inaccessible';
sendBadge(format, badgeData);
}
try {
var data = JSON.parse(buffer);
if (data.engines && data.engines.node) {
var versionRange = data.engines.node;
badgeData.text[1] = versionRange;
var AGE_OLD = 1, AGE_CURRENT = 2, AGE_BLEEDING = 3;
regularUpdate('http://nodejs.org/dist/latest/SHASUMS.txt',
(24 * 3600 * 1000),
function(shasums) {
var firstLine = shasums.slice(0, shasums.indexOf('\n'));
var version = firstLine.split(' ')[1].split('-')[1];
if (semver.satisfies(version, versionRange)) {
return AGE_CURRENT;
} else if (semver.gtr(version, versionRange)) {
return AGE_OLD;
} else { return AGE_BLEEDING; }
}, function(err, age) {
if (err != null) { sendBadge(format, badgeData); return; }
if (age === AGE_CURRENT) {
badgeData.colorscheme = 'brightgreen';
} else if (age === AGE_OLD) {
badgeData.colorscheme = 'yellow';
} else if (age === AGE_BLEEDING) {
badgeData.colorscheme = 'orange';
}
sendBadge(format, badgeData);
});
} else {
sendBadge(format, badgeData);
}
} catch(e) {
badgeData.text[1] = 'invalid';
sendBadge(format, badgeData);
}
});
}));
// Gem version integration.
camp.route(/^\/gem\/v\/(.*)\.(svg|png|gif|jpg)$/,
cache(function(data, match, sendBadge) {
@ -1904,6 +1955,34 @@ function streamFromString(str) {
return newStream;
}
// Map from URL to { timestamp: last fetch time, interval: in milliseconds,
// data: data }.
var regularUpdateCache = Object.create(null);
// url: a string, scraper: a function that takes string data at that URL.
// interval: number in milliseconds.
// cb: a callback function that takes an error and data returned by the scraper.
function regularUpdate(url, interval, scraper, cb) {
var timestamp = Date.now();
var cache = regularUpdateCache[url];
if (cache != null &&
(timestamp - cache.timestamp) < interval) {
cb(null, regularUpdateCache[url].data);
return;
}
request(url, function(err, res, buffer) {
if (err != null) { cb(err); return; }
if (regularUpdateCache[url] == null) {
regularUpdateCache[url] = { timestamp: 0, data: 0 };
}
try {
var data = scraper(buffer);
} catch(e) { cb(e); return; }
regularUpdateCache[url].timestamp = timestamp;
regularUpdateCache[url].data = data;
cb(null, data);
});
}
// Given a number, string with appropriate unit in the metric system, SI.
// Note: numbers beyond the peta- cannot be represented as integers in JS.
var metricPrefix = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];

View File

@ -282,6 +282,10 @@ I made the GitHub Badge Service.
<td><img src='/npm/v/npm.svg' alt=''/></td>
<td><code>http://img.shields.io/npm/v/npm.svg</code></td>
</tr>
<tr><th> node: </th>
<td><img src='/node/v/gh-badges.svg' alt=''/></td>
<td><code>http://img.shields.io/node/v/gh-badges.svg</code></td>
</tr>
<tr><th> PyPI: </th>
<td><img src='/pypi/v/nine.svg' alt=''/></td>
<td><code>http://img.shields.io/pypi/v/nine.svg</code></td>