This should make it more difficult for people who are publishing malicious packages to npm to get them on the CDN.
54 lines
1.6 KiB
JavaScript
54 lines
1.6 KiB
JavaScript
const NPMAPI = require('./NPMAPI')
|
|
const createCache = require('./createCache')
|
|
const createMutex = require('./createMutex')
|
|
|
|
const NPMDownloadsCache = createCache('npmDownloads')
|
|
|
|
function fetchDailyDownloads(packageName) {
|
|
console.log(`info: Fetching downloads for ${packageName}`)
|
|
|
|
return NPMAPI.getJSON(`/downloads/point/last-week/${packageName}`).then(function (data) {
|
|
return data && Math.round(data.downloads / 7)
|
|
})
|
|
}
|
|
|
|
const PackageNotFound = 'PackageNotFound'
|
|
|
|
const fetchMutex = createMutex(function (packageName, callback) {
|
|
fetchDailyDownloads(packageName).then(function (value) {
|
|
if (value == null) {
|
|
// Cache 404s for 5 minutes. This prevents us from making
|
|
// unnecessary requests to the NPM API for bad package names.
|
|
// In the worst case, a brand new package's downloads will be
|
|
// available within 5 minutes.
|
|
NPMDownloadsCache.set(packageName, PackageNotFound, 300, function () {
|
|
callback(null, value)
|
|
})
|
|
} else {
|
|
// Cache downloads for 1 minute.
|
|
NPMDownloadsCache.set(packageName, value, 60, function () {
|
|
callback(null, value)
|
|
})
|
|
}
|
|
}, function (error) {
|
|
// Do not cache errors.
|
|
NPMDownloadsCache.del(packageName, function () {
|
|
callback(error)
|
|
})
|
|
})
|
|
})
|
|
|
|
function getDailyDownloads(packageName, callback) {
|
|
NPMDownloadsCache.get(packageName, function (error, value) {
|
|
if (error || value != null) {
|
|
callback(error, value === PackageNotFound ? null : value)
|
|
} else {
|
|
fetchMutex(packageName, packageName, callback)
|
|
}
|
|
})
|
|
}
|
|
|
|
module.exports = {
|
|
getDaily: getDailyDownloads
|
|
}
|