-
From {formatDate(since, 'MMM D')} to {formatDate(until, 'MMM D')} unpkg served {formatNumber(totals.requests.all)} requests and a total of {formatBytes(totals.bandwidth.all)} of data to {formatNumber(totals.uniques.all)} unique visitors, {formatPercent(totals.requests.cached / totals.requests.all, 0)}% of which were served from the cache.
+
+ From {formatDate(since, 'MMM D')} to{' '}
+ {formatDate(until, 'MMM D')} unpkg served{' '}
+ {formatNumber(totals.requests.all)} requests and a
+ total of {formatBytes(totals.bandwidth.all)} of data
+ to {formatNumber(totals.uniques.all)} unique
+ visitors,{' '}
+
+ {formatPercent(totals.requests.cached / totals.requests.all, 0)}%
+ {' '}
+ of which were served from the cache.
+
Packages
-
The table below shows the most popular packages served by unpkg from {formatDate(since, 'MMM D')} to {formatDate(until, 'MMM D')} . Only the top {Object.keys(totals.requests.package).length} packages are shown.
+
+ The table below shows the most popular packages served by unpkg from{' '}
+ {formatDate(since, 'MMM D')} to{' '}
+ {formatDate(until, 'MMM D')} . Only the top{' '}
+ {Object.keys(totals.requests.package).length} packages are shown.
+
-
Include only packages that received at least
+ Include only packages that received at least{' '}
+ this.setState({ minPackageRequests: parseInt(event.target.value, 10) })}
+ onChange={event =>
+ this.setState({
+ minPackageRequests: parseInt(event.target.value, 10)
+ })
+ }
>
0
1,000
@@ -147,7 +213,8 @@ class Stats extends React.Component {
100,000
1,000,000
10,000,000
- requests.
+ {' '}
+ requests.
@@ -158,28 +225,42 @@ class Stats extends React.Component {
Bandwidth (% of total)
-
- {packageRows}
-
+ {packageRows}
Regions
-
The table below breaks down requests to unpkg from {formatDate(since, 'MMM D')} to {formatDate(until, 'MMM D')} by geographic region.
+
+ The table below breaks down requests to unpkg from{' '}
+ {formatDate(since, 'MMM D')} to{' '}
+ {formatDate(until, 'MMM D')} by geographic region.
+
-
Include only countries that made at least
+ Include only countries that made at least{' '}
+ this.setState({ minCountryRequests: parseInt(event.target.value, 10) })}
+ onChange={event =>
+ this.setState({
+ minCountryRequests: parseInt(event.target.value, 10)
+ })
+ }
>
0
100,000
1,000,000
10,000,000
100,000,000
- requests.
+ {' '}
+ requests.
-
+
Region
@@ -187,14 +268,16 @@ class Stats extends React.Component {
Bandwidth (% of total)
-
- {regionRows}
-
+ {regionRows}
Protocols
- The table below breaks down requests to unpkg from {formatDate(since, 'MMM D')} to {formatDate(until, 'MMM D')} by HTTP protocol.
+
+ The table below breaks down requests to unpkg from{' '}
+ {formatDate(since, 'MMM D')} to{' '}
+ {formatDate(until, 'MMM D')} by HTTP protocol.
+
@@ -203,11 +286,8 @@ class Stats extends React.Component {
Requests (% of total)
-
- {protocolRows}
-
+ {protocolRows}
-
)
}
diff --git a/client/index.js b/client/index.js
index f66d1fc..fde0d67 100644
--- a/client/index.js
+++ b/client/index.js
@@ -3,7 +3,4 @@ import ReactDOM from 'react-dom'
import App from './App'
import './index.css'
-ReactDOM.render(
- ,
- document.getElementById('root')
-)
+ReactDOM.render( , document.getElementById('root'))
diff --git a/client/utils/formatNumber.js b/client/utils/formatNumber.js
index 6c69ad3..9b20345 100644
--- a/client/utils/formatNumber.js
+++ b/client/utils/formatNumber.js
@@ -1,9 +1,8 @@
-const formatNumber = (n) => {
+const formatNumber = n => {
const digits = String(n).split('')
const groups = []
- while (digits.length)
- groups.unshift(digits.splice(-3).join(''))
+ while (digits.length) groups.unshift(digits.splice(-3).join(''))
return groups.join(',')
}
diff --git a/client/utils/parseNumber.js b/client/utils/parseNumber.js
index 089bda7..fb0a9ea 100644
--- a/client/utils/parseNumber.js
+++ b/client/utils/parseNumber.js
@@ -1,4 +1,3 @@
-const parseNumber = (s) =>
- parseInt(s.replace(/,/g, ''), 10) || 0
+const parseNumber = s => parseInt(s.replace(/,/g, ''), 10) || 0
export default parseNumber
diff --git a/package.json b/package.json
index 5802734..e7e271b 100644
--- a/package.json
+++ b/package.json
@@ -114,5 +114,9 @@
},
"eslintConfig": {
"extends": "react-app"
+ },
+ "prettier": {
+ "semi": false,
+ "single-quote": true
}
}
diff --git a/server/CloudflareAPI.js b/server/CloudflareAPI.js
index d011922..8da56f9 100644
--- a/server/CloudflareAPI.js
+++ b/server/CloudflareAPI.js
@@ -7,15 +7,9 @@ const CloudflareAPIURL = 'https://api.cloudflare.com'
const CloudflareEmail = process.env.CLOUDFLARE_EMAIL
const CloudflareKey = process.env.CLOUDFLARE_KEY
-invariant(
- CloudflareEmail,
- 'Missing the $CLOUDFLARE_EMAIL environment variable'
-)
+invariant(CloudflareEmail, 'Missing the $CLOUDFLARE_EMAIL environment variable')
-invariant(
- CloudflareKey,
- 'Missing the $CLOUDFLARE_KEY environment variable'
-)
+invariant(CloudflareKey, 'Missing the $CLOUDFLARE_KEY environment variable')
function get(path, headers) {
return fetch(`${CloudflareAPIURL}/client/v4${path}`, {
@@ -27,26 +21,28 @@ function get(path, headers) {
}
function getJSON(path, headers) {
- return get(path, headers).then(function (res) {
- return res.json()
- }).then(function (data) {
- if (!data.success) {
- console.error(`CloudflareAPI.getJSON failed at ${path}`)
- console.error(data)
- throw new Error('Failed to getJSON from Cloudflare')
- }
+ return get(path, headers)
+ .then(function(res) {
+ return res.json()
+ })
+ .then(function(data) {
+ if (!data.success) {
+ console.error(`CloudflareAPI.getJSON failed at ${path}`)
+ console.error(data)
+ throw new Error('Failed to getJSON from Cloudflare')
+ }
- return data.result
- })
+ return data.result
+ })
}
function getZones(domains) {
return Promise.all(
- (Array.isArray(domains) ? domains : [ domains ]).map(function (domain) {
+ (Array.isArray(domains) ? domains : [domains]).map(function(domain) {
return getJSON(`/zones?name=${domain}`)
})
- ).then(function (results) {
- return results.reduce(function (memo, zones) {
+ ).then(function(results) {
+ return results.reduce(function(memo, zones) {
return memo.concat(zones)
})
})
@@ -68,26 +64,36 @@ function reduceResults(target, values) {
function getZoneAnalyticsDashboard(zones, since, until) {
return Promise.all(
- (Array.isArray(zones) ? zones : [ zones ]).map(function (zone) {
- return getJSON(`/zones/${zone.id}/analytics/dashboard?since=${since.toISOString()}&until=${until.toISOString()}`)
+ (Array.isArray(zones) ? zones : [zones]).map(function(zone) {
+ return getJSON(
+ `/zones/${
+ zone.id
+ }/analytics/dashboard?since=${since.toISOString()}&until=${until.toISOString()}`
+ )
})
- ).then(function (results) {
+ ).then(function(results) {
return results.reduce(reduceResults)
})
}
function getJSONStream(path, headers) {
- const acceptGzipHeaders = Object.assign({}, headers, { 'Accept-Encoding': 'gzip' })
-
- return get(path, acceptGzipHeaders).then(function (res) {
- return res.body.pipe(gunzip())
- }).then(function (stream) {
- return stream.pipe(ndjson.parse())
+ const acceptGzipHeaders = Object.assign({}, headers, {
+ 'Accept-Encoding': 'gzip'
})
+
+ return get(path, acceptGzipHeaders)
+ .then(function(res) {
+ return res.body.pipe(gunzip())
+ })
+ .then(function(stream) {
+ return stream.pipe(ndjson.parse())
+ })
}
function getLogs(zoneId, startTime, endTime) {
- return getJSONStream(`/zones/${zoneId}/logs/requests?start=${startTime}&end=${endTime}`)
+ return getJSONStream(
+ `/zones/${zoneId}/logs/requests?start=${startTime}&end=${endTime}`
+ )
}
module.exports = {
diff --git a/server/RedisClient.js b/server/RedisClient.js
index d725bd2..36a4d13 100644
--- a/server/RedisClient.js
+++ b/server/RedisClient.js
@@ -2,7 +2,8 @@ const redis = require('redis')
redis.debug_mode = process.env.DEBUG_REDIS != null
-const RedisURL = process.env.OPENREDIS_URL || process.env.REDIS_URL || 'redis://localhost:6379'
+const RedisURL =
+ process.env.OPENREDIS_URL || process.env.REDIS_URL || 'redis://localhost:6379'
const client = redis.createClient(RedisURL)
diff --git a/server/StatsServer.js b/server/StatsServer.js
index fbfb35d..2712a2c 100644
--- a/server/StatsServer.js
+++ b/server/StatsServer.js
@@ -4,7 +4,7 @@ const db = require('./RedisClient')
const PackageBlacklist = require('./PackageBlacklist').blacklist
function prunePackages(packagesMap) {
- PackageBlacklist.forEach(function (packageName) {
+ PackageBlacklist.forEach(function(packageName) {
delete packagesMap[packageName]
})
@@ -33,8 +33,8 @@ function createScoresMap(array) {
}
function getScoresMap(key, n = 100) {
- return new Promise(function (resolve, reject) {
- db.zrevrange(key, 0, n, 'withscores', function (error, value) {
+ return new Promise(function(resolve, reject) {
+ db.zrevrange(key, 0, n, 'withscores', function(error, value) {
if (error) {
reject(error)
} else {
@@ -45,11 +45,15 @@ function getScoresMap(key, n = 100) {
}
function getPackageRequests(date, n = 100) {
- return getScoresMap(`stats-packageRequests-${createDayKey(date)}`, n).then(prunePackages)
+ return getScoresMap(`stats-packageRequests-${createDayKey(date)}`, n).then(
+ prunePackages
+ )
}
function getPackageBandwidth(date, n = 100) {
- return getScoresMap(`stats-packageBytes-${createDayKey(date)}`, n).then(prunePackages)
+ return getScoresMap(`stats-packageBytes-${createDayKey(date)}`, n).then(
+ prunePackages
+ )
}
function getProtocolRequests(date) {
@@ -63,7 +67,7 @@ function addDailyMetricsToTimeseries(timeseries) {
getPackageRequests(since),
getPackageBandwidth(since),
getProtocolRequests(since)
- ]).then(function (results) {
+ ]).then(function(results) {
timeseries.requests.package = results[0]
timeseries.bandwidth.package = results[1]
timeseries.requests.protocol = results[2]
@@ -72,8 +76,8 @@ function addDailyMetricsToTimeseries(timeseries) {
}
function sumMaps(maps) {
- return maps.reduce(function (memo, map) {
- Object.keys(map).forEach(function (key) {
+ return maps.reduce(function(memo, map) {
+ Object.keys(map).forEach(function(key) {
memo[key] = (memo[key] || 0) + map[key]
})
@@ -82,29 +86,29 @@ function sumMaps(maps) {
}
function addDailyMetrics(result) {
- return Promise.all(
- result.timeseries.map(addDailyMetricsToTimeseries)
- ).then(function () {
- result.totals.requests.package = sumMaps(
- result.timeseries.map(function (timeseries) {
- return timeseries.requests.package
- })
- )
+ return Promise.all(result.timeseries.map(addDailyMetricsToTimeseries)).then(
+ function() {
+ result.totals.requests.package = sumMaps(
+ result.timeseries.map(function(timeseries) {
+ return timeseries.requests.package
+ })
+ )
- result.totals.bandwidth.package = sumMaps(
- result.timeseries.map(function (timeseries) {
- return timeseries.bandwidth.package
- })
- )
+ result.totals.bandwidth.package = sumMaps(
+ result.timeseries.map(function(timeseries) {
+ return timeseries.bandwidth.package
+ })
+ )
- result.totals.requests.protocol = sumMaps(
- result.timeseries.map(function (timeseries) {
- return timeseries.requests.protocol
- })
- )
+ result.totals.requests.protocol = sumMaps(
+ result.timeseries.map(function(timeseries) {
+ return timeseries.requests.protocol
+ })
+ )
- return result
- })
+ return result
+ }
+ )
}
function extractPublicInfo(data) {
@@ -136,19 +140,18 @@ function extractPublicInfo(data) {
}
}
-const DomainNames = [
- 'unpkg.com',
- 'npmcdn.com'
-]
+const DomainNames = ['unpkg.com', 'npmcdn.com']
function fetchStats(since, until) {
- return cf.getZones(DomainNames).then(function (zones) {
- return cf.getZoneAnalyticsDashboard(zones, since, until).then(function (dashboard) {
- return {
- timeseries: dashboard.timeseries.map(extractPublicInfo),
- totals: extractPublicInfo(dashboard.totals)
- }
- })
+ return cf.getZones(DomainNames).then(function(zones) {
+ return cf
+ .getZoneAnalyticsDashboard(zones, since, until)
+ .then(function(dashboard) {
+ return {
+ timeseries: dashboard.timeseries.map(extractPublicInfo),
+ totals: extractPublicInfo(dashboard.totals)
+ }
+ })
})
}
@@ -159,10 +162,9 @@ const oneDay = oneHour * 24
function getStats(since, until, callback) {
let promise = fetchStats(since, until)
- if ((until - since) > oneDay)
- promise = promise.then(addDailyMetrics)
+ if (until - since > oneDay) promise = promise.then(addDailyMetrics)
- promise.then(function (value) {
+ promise.then(function(value) {
callback(null, value)
}, callback)
}
diff --git a/server/createSearchServer.js b/server/createSearchServer.js
index 96edf66..458704f 100644
--- a/server/createSearchServer.js
+++ b/server/createSearchServer.js
@@ -4,18 +4,23 @@ const npmSearch = require('./npm/search')
function createSearchServer() {
const app = express()
- app.get('/', function (req, res) {
+ app.get('/', function(req, res) {
const { query, page = 0 } = req.query
if (!query)
return res.status(403).send({ error: 'Missing ?query parameter' })
- npmSearch(query, page).then(function (result) {
- res.send(result)
- }, function (error) {
- console.error(error)
- res.status(500).send({ error: 'There was an error executing the search' })
- })
+ npmSearch(query, page).then(
+ function(result) {
+ res.send(result)
+ },
+ function(error) {
+ console.error(error)
+ res
+ .status(500)
+ .send({ error: 'There was an error executing the search' })
+ }
+ )
})
return app
diff --git a/server/createServer.test.js b/server/createServer.test.js
index f565b85..bc25306 100644
--- a/server/createServer.test.js
+++ b/server/createServer.test.js
@@ -1,32 +1,38 @@
const request = require('supertest')
const createServer = require('./createServer')
-describe('The server app', function () {
+describe('The server app', function() {
let app
- beforeEach(function () {
+ beforeEach(function() {
app = createServer()
})
- it('rejects invalid package names', function (done) {
- request(app).get('/_invalid/index.js').then(function (res) {
- expect(res.statusCode).toBe(403)
- done()
- })
+ it('rejects invalid package names', function(done) {
+ request(app)
+ .get('/_invalid/index.js')
+ .then(function(res) {
+ expect(res.statusCode).toBe(403)
+ done()
+ })
})
- it('redirects invalid query params', function (done) {
- request(app).get('/react?main=index&invalid').then(function (res) {
- expect(res.statusCode).toBe(302)
- expect(res.headers.location).toBe('/react?main=index')
- done()
- })
+ it('redirects invalid query params', function(done) {
+ request(app)
+ .get('/react?main=index&invalid')
+ .then(function(res) {
+ expect(res.statusCode).toBe(302)
+ expect(res.headers.location).toBe('/react?main=index')
+ done()
+ })
})
- it('redirects /_meta to ?meta', function (done) {
- request(app).get('/_meta/react?main=index').then(function (res) {
- expect(res.statusCode).toBe(302)
- expect(res.headers.location).toBe('/react?main=index&meta')
- done()
- })
+ it('redirects /_meta to ?meta', function(done) {
+ request(app)
+ .get('/_meta/react?main=index')
+ .then(function(res) {
+ expect(res.statusCode).toBe(302)
+ expect(res.headers.location).toBe('/react?main=index&meta')
+ done()
+ })
})
})
diff --git a/server/createStatsServer.js b/server/createStatsServer.js
index c4a6df8..dc00a0e 100644
--- a/server/createStatsServer.js
+++ b/server/createStatsServer.js
@@ -5,7 +5,7 @@ const startOfSecond = require('date-fns/start_of_second')
const StatsServer = require('./StatsServer')
function serveArbitraryStats(req, res) {
- const now = startOfSecond(new Date)
+ const now = startOfSecond(new Date())
const since = req.query.since ? new Date(req.query.since) : subDays(now, 30)
const until = req.query.until ? new Date(req.query.until) : now
@@ -16,37 +16,43 @@ function serveArbitraryStats(req, res) {
return res.status(403).send({ error: '?until is not a valid date' })
if (until <= since)
- return res.status(403).send({ error: '?until date must come after ?since date' })
+ return res
+ .status(403)
+ .send({ error: '?until date must come after ?since date' })
if (until > now)
return res.status(403).send({ error: '?until must be a date in the past' })
- StatsServer.getStats(since, until, function (error, stats) {
+ StatsServer.getStats(since, until, function(error, stats) {
if (error) {
console.error(error)
res.status(500).send({ error: 'Unable to fetch stats' })
} else {
- res.set({
- 'Cache-Control': 'public, max-age=60',
- 'Cache-Tag': 'stats'
- }).send(stats)
+ res
+ .set({
+ 'Cache-Control': 'public, max-age=60',
+ 'Cache-Tag': 'stats'
+ })
+ .send(stats)
}
})
}
function servePastDaysStats(days, req, res) {
- const until = startOfDay(new Date)
+ const until = startOfDay(new Date())
const since = subDays(until, days)
- StatsServer.getStats(since, until, function (error, stats) {
+ StatsServer.getStats(since, until, function(error, stats) {
if (error) {
console.error(error)
res.status(500).send({ error: 'Unable to fetch stats' })
} else {
- res.set({
- 'Cache-Control': 'public, max-age=60',
- 'Cache-Tag': 'stats'
- }).send(stats)
+ res
+ .set({
+ 'Cache-Control': 'public, max-age=60',
+ 'Cache-Tag': 'stats'
+ })
+ .send(stats)
}
})
}
diff --git a/server/ingestLogs.js b/server/ingestLogs.js
index 600c5be..1697230 100644
--- a/server/ingestLogs.js
+++ b/server/ingestLogs.js
@@ -37,7 +37,7 @@ const oneMinute = oneSecond * 60
const oneHour = oneMinute * 60
function computeCounters(stream) {
- return new Promise(function (resolve, reject) {
+ return new Promise(function(resolve, reject) {
const counters = {}
const expireat = {}
@@ -49,7 +49,7 @@ function computeCounters(stream) {
stream
.on('error', reject)
- .on('data', function (entry) {
+ .on('data', function(entry) {
const date = new Date(Math.round(entry.timestamp / 1000000))
const nextDay = startOfDay(addDays(date, 1))
@@ -66,9 +66,22 @@ function computeCounters(stream) {
const url = parsePackageURL(parseURL(clientRequest.uri).pathname)
const packageName = url && url.packageName
- if (packageName && validateNPMPackageName(packageName).errors == null) {
- incr(`stats-packageRequests-${dayKey}`, packageName, 1, thirtyDaysLater)
- incr(`stats-packageBytes-${dayKey}`, packageName, edgeResponse.bytes, thirtyDaysLater)
+ if (
+ packageName &&
+ validateNPMPackageName(packageName).errors == null
+ ) {
+ incr(
+ `stats-packageRequests-${dayKey}`,
+ packageName,
+ 1,
+ thirtyDaysLater
+ )
+ incr(
+ `stats-packageBytes-${dayKey}`,
+ packageName,
+ edgeResponse.bytes,
+ thirtyDaysLater
+ )
}
}
@@ -85,32 +98,36 @@ function computeCounters(stream) {
if (hostname) {
incr(`stats-hostnameRequests-${dayKey}`, hostname, 1, sevenDaysLater)
- incr(`stats-hostnameBytes-${dayKey}`, hostname, edgeResponse.bytes, sevenDaysLater)
+ incr(
+ `stats-hostnameBytes-${dayKey}`,
+ hostname,
+ edgeResponse.bytes,
+ sevenDaysLater
+ )
}
})
- .on('end', function () {
+ .on('end', function() {
resolve({ counters, expireat })
})
})
}
function processLogs(stream) {
- return computeCounters(stream).then(function ({ counters, expireat }) {
- Object.keys(counters).forEach(function (key) {
+ return computeCounters(stream).then(function({ counters, expireat }) {
+ Object.keys(counters).forEach(function(key) {
const values = counters[key]
- Object.keys(values).forEach(function (member) {
+ Object.keys(values).forEach(function(member) {
db.zincrby(key, values[member], member)
})
- if (expireat[key])
- db.expireat(key, expireat[key])
+ if (expireat[key]) db.expireat(key, expireat[key])
})
})
}
function ingestLogs(zone, startSeconds, endSeconds) {
- return new Promise(function (resolve) {
+ return new Promise(function(resolve) {
console.log(
'info: Started ingesting logs for %s from %s to %s',
zone.name,
@@ -121,7 +138,7 @@ function ingestLogs(zone, startSeconds, endSeconds) {
const startFetchTime = Date.now()
resolve(
- cf.getLogs(zone.id, startSeconds, endSeconds).then(function (stream) {
+ cf.getLogs(zone.id, startSeconds, endSeconds).then(function(stream) {
const endFetchTime = Date.now()
console.log(
@@ -133,7 +150,7 @@ function ingestLogs(zone, startSeconds, endSeconds) {
const startProcessTime = Date.now()
- return processLogs(stream).then(function () {
+ return processLogs(stream).then(function() {
const endProcessTime = Date.now()
console.log(
@@ -149,10 +166,13 @@ function ingestLogs(zone, startSeconds, endSeconds) {
}
function startZone(zone) {
- const startSecondsKey = `ingestLogsWorker-nextStartSeconds-${zone.name.replace('.', '-')}`
+ const startSecondsKey = `ingestLogsWorker-nextStartSeconds-${zone.name.replace(
+ '.',
+ '-'
+ )}`
function takeATurn() {
- db.get(startSecondsKey, function (error, value) {
+ db.get(startSecondsKey, function(error, value) {
let startSeconds = value && parseInt(value, 10)
const now = Date.now()
@@ -182,18 +202,21 @@ function startZone(zone) {
// set of logs. This will help ensure that any congestion in the log
// pipeline has passed and a full set of logs can be ingested.
// https://support.cloudflare.com/hc/en-us/articles/216672448-Enterprise-Log-Share-REST-API
- const maxSeconds = toSeconds(now - (oneMinute * 30))
+ const maxSeconds = toSeconds(now - oneMinute * 30)
if (startSeconds < maxSeconds) {
const endSeconds = startSeconds + LogWindowSeconds
- ingestLogs(zone, startSeconds, endSeconds).then(function () {
- db.set(startSecondsKey, endSeconds)
- setTimeout(takeATurn)
- }, function (error) {
- console.error(error.stack)
- process.exit(1)
- })
+ ingestLogs(zone, startSeconds, endSeconds).then(
+ function() {
+ db.set(startSecondsKey, endSeconds)
+ setTimeout(takeATurn)
+ },
+ function(error) {
+ console.error(error.stack)
+ process.exit(1)
+ }
+ )
} else {
setTimeout(takeATurn, (startSeconds - maxSeconds) * 1000)
}
@@ -203,8 +226,8 @@ function startZone(zone) {
takeATurn()
}
-Promise.all(DomainNames.map(cf.getZones)).then(function (results) {
- const zones = results.reduce(function (memo, zones) {
+Promise.all(DomainNames.map(cf.getZones)).then(function(results) {
+ const zones = results.reduce(function(memo, zones) {
return memo.concat(zones)
})
diff --git a/server/middleware/checkBlacklist.js b/server/middleware/checkBlacklist.js
index 07b09a5..0f652ec 100644
--- a/server/middleware/checkBlacklist.js
+++ b/server/middleware/checkBlacklist.js
@@ -1,8 +1,11 @@
function checkBlacklist(blacklist) {
- return function (req, res, next) {
+ return function(req, res, next) {
// Do not allow packages that have been blacklisted.
if (blacklist.includes(req.packageName)) {
- res.status(403).type('text').send(`Package "${req.packageName}" is blacklisted`)
+ res
+ .status(403)
+ .type('text')
+ .send(`Package "${req.packageName}" is blacklisted`)
} else {
next()
}
diff --git a/server/middleware/components/DirectoryListing.js b/server/middleware/components/DirectoryListing.js
index 3e8be5f..6aa0bcc 100644
--- a/server/middleware/components/DirectoryListing.js
+++ b/server/middleware/components/DirectoryListing.js
@@ -4,27 +4,28 @@ const getFileContentType = require('../utils/getFileContentType')
const e = React.createElement
-const formatTime = (time) =>
- new Date(time).toISOString()
+const formatTime = time => new Date(time).toISOString()
const DirectoryListing = ({ dir, entries }) => {
const rows = entries.map(({ file, stats }, index) => {
const isDir = stats.isDirectory()
const href = file + (isDir ? '/' : '')
- return (
- e('tr', { key: file, className: index % 2 ? 'odd' : 'even' },
- e('td', null, e('a', { title: file, href }, file)),
- e('td', null, isDir ? '-' : getFileContentType(file)),
- e('td', null, isDir ? '-' : prettyBytes(stats.size)),
- e('td', null, isDir ? '-' : formatTime(stats.mtime))
- )
+ return e(
+ 'tr',
+ { key: file, className: index % 2 ? 'odd' : 'even' },
+ e('td', null, e('a', { title: file, href }, file)),
+ e('td', null, isDir ? '-' : getFileContentType(file)),
+ e('td', null, isDir ? '-' : prettyBytes(stats.size)),
+ e('td', null, isDir ? '-' : formatTime(stats.mtime))
)
})
if (dir !== '/')
rows.unshift(
- e('tr', { key: '..', className: 'odd' },
+ e(
+ 'tr',
+ { key: '..', className: 'odd' },
e('td', null, e('a', { title: 'Parent directory', href: '../' }, '..')),
e('td', null, '-'),
e('td', null, '-'),
@@ -32,18 +33,22 @@ const DirectoryListing = ({ dir, entries }) => {
)
)
- return (
- e('table', null,
- e('thead', null,
- e('tr', null,
- e('th', null, 'Name'),
- e('th', null, 'Type'),
- e('th', null, 'Size'),
- e('th', null, 'Last Modified')
- )
- ),
- e('tbody', null, rows)
- )
+ return e(
+ 'table',
+ null,
+ e(
+ 'thead',
+ null,
+ e(
+ 'tr',
+ null,
+ e('th', null, 'Name'),
+ e('th', null, 'Type'),
+ e('th', null, 'Size'),
+ e('th', null, 'Last Modified')
+ )
+ ),
+ e('tbody', null, rows)
)
}
diff --git a/server/middleware/components/IndexPage.js b/server/middleware/components/IndexPage.js
index b4e830e..4f5654b 100644
--- a/server/middleware/components/IndexPage.js
+++ b/server/middleware/components/IndexPage.js
@@ -13,34 +13,41 @@ s.onchange = function () {
}
`
-const byVersion = (a, b) =>
- semver.lt(a, b) ? -1 : (semver.gt(a, b) ? 1 : 0)
+const byVersion = (a, b) => (semver.lt(a, b) ? -1 : semver.gt(a, b) ? 1 : 0)
const IndexPage = ({ packageInfo, version, dir, entries }) => {
const versions = Object.keys(packageInfo.versions).sort(byVersion)
- const options = versions.map(v => (
+ const options = versions.map(v =>
e('option', { key: v, value: v }, `${packageInfo.name}@${v}`)
- ))
+ )
- return (
- e('html', null,
- e('head', null,
- e('meta', { charSet: 'utf-8' }),
- e('title', null, `Index of ${dir}`),
- e('style', { dangerouslySetInnerHTML: { __html: IndexPageStyle } })
- ),
- e('body', null,
- e('div', { className: 'content-wrapper' },
- e('div', { className: 'version-wrapper' },
- e('select', { id: 'version', defaultValue: version }, options)
- ),
- e('h1', null, `Index of ${dir}`),
- e('script', { dangerouslySetInnerHTML: { __html: IndexPageScript } }),
- e('hr'),
- e(DirectoryListing, { dir, entries }),
- e('hr'),
- e('address', null, `${packageInfo.name}@${version}`)
- )
+ return e(
+ 'html',
+ null,
+ e(
+ 'head',
+ null,
+ e('meta', { charSet: 'utf-8' }),
+ e('title', null, `Index of ${dir}`),
+ e('style', { dangerouslySetInnerHTML: { __html: IndexPageStyle } })
+ ),
+ e(
+ 'body',
+ null,
+ e(
+ 'div',
+ { className: 'content-wrapper' },
+ e(
+ 'div',
+ { className: 'version-wrapper' },
+ e('select', { id: 'version', defaultValue: version }, options)
+ ),
+ e('h1', null, `Index of ${dir}`),
+ e('script', { dangerouslySetInnerHTML: { __html: IndexPageScript } }),
+ e('hr'),
+ e(DirectoryListing, { dir, entries }),
+ e('hr'),
+ e('address', null, `${packageInfo.name}@${version}`)
)
)
)
diff --git a/server/middleware/fetchFile.js b/server/middleware/fetchFile.js
index 14e30f9..8077bff 100644
--- a/server/middleware/fetchFile.js
+++ b/server/middleware/fetchFile.js
@@ -13,18 +13,18 @@ function getBasename(file) {
/**
* File extensions to look for when automatically resolving.
*/
-const FindExtensions = [ '', '.js', '.json' ]
+const FindExtensions = ['', '.js', '.json']
/**
* Resolves a path like "lib/file" into "lib/file.js" or "lib/file.json"
* depending on which one is available, similar to require('lib/file').
*/
function findFile(base, useIndex, callback) {
- FindExtensions.reduceRight(function (next, ext) {
+ FindExtensions.reduceRight(function(next, ext) {
const file = base + ext
- return function () {
- fs.stat(file, function (error, stats) {
+ return function() {
+ fs.stat(file, function(error, stats) {
if (error) {
if (error.code === 'ENOENT' || error.code === 'ENOTDIR') {
next()
@@ -32,7 +32,11 @@ function findFile(base, useIndex, callback) {
callback(error)
}
} else if (useIndex && stats.isDirectory()) {
- findFile(path.join(file, 'index'), false, function (error, indexFile, indexStats) {
+ findFile(path.join(file, 'index'), false, function(
+ error,
+ indexFile,
+ indexStats
+ ) {
if (error) {
callback(error)
} else if (indexFile) {
@@ -55,14 +59,20 @@ function findFile(base, useIndex, callback) {
* trailing slash.
*/
function fetchFile(req, res, next) {
- getPackageInfo(req.packageName, function (error, packageInfo) {
+ getPackageInfo(req.packageName, function(error, packageInfo) {
if (error) {
console.error(error)
- return res.status(500).type('text').send(`Cannot get info for package "${req.packageName}"`)
+ return res
+ .status(500)
+ .type('text')
+ .send(`Cannot get info for package "${req.packageName}"`)
}
if (packageInfo == null || packageInfo.versions == null)
- return res.status(404).type('text').send(`Cannot find package "${req.packageName}"`)
+ return res
+ .status(404)
+ .type('text')
+ .send(`Cannot find package "${req.packageName}"`)
req.packageInfo = packageInfo
@@ -70,10 +80,13 @@ function fetchFile(req, res, next) {
// A valid request for a package we haven't downloaded yet.
req.packageConfig = req.packageInfo.versions[req.packageVersion]
- getPackage(req.packageConfig, function (error, outputDir) {
+ getPackage(req.packageConfig, function(error, outputDir) {
if (error) {
console.error(error)
- res.status(500).type('text').send(`Cannot fetch package ${req.packageSpec}`)
+ res
+ .status(500)
+ .type('text')
+ .send(`Cannot fetch package ${req.packageSpec}`)
} else {
req.packageDir = outputDir
@@ -84,12 +97,18 @@ function fetchFile(req, res, next) {
// They want an ES module. Try "module", "jsnext:main", and "/"
// https://github.com/rollup/rollup/wiki/pkg.module
if (!filename)
- filename = req.packageConfig.module || req.packageConfig['jsnext:main'] || '/'
+ filename =
+ req.packageConfig.module ||
+ req.packageConfig['jsnext:main'] ||
+ '/'
} else if (filename) {
// They are requesting an explicit filename. Only try to find an
// index file if they are NOT requesting an HTML directory listing.
useIndex = filename[filename.length - 1] !== '/'
- } else if (req.query.main && typeof req.packageConfig[req.query.main] === 'string') {
+ } else if (
+ req.query.main &&
+ typeof req.packageConfig[req.query.main] === 'string'
+ ) {
// They specified a custom ?main field.
filename = req.packageConfig[req.query.main]
} else if (typeof req.packageConfig.unpkg === 'string') {
@@ -104,23 +123,46 @@ function fetchFile(req, res, next) {
filename = req.packageConfig.main || '/'
}
- findFile(path.join(req.packageDir, filename), useIndex, function (error, file, stats) {
- if (error)
- console.error(error)
+ findFile(path.join(req.packageDir, filename), useIndex, function(
+ error,
+ file,
+ stats
+ ) {
+ if (error) console.error(error)
if (file == null)
- return res.status(404).type('text').send(`Cannot find module "${filename}" in package ${req.packageSpec}`)
+ return res
+ .status(404)
+ .type('text')
+ .send(
+ `Cannot find module "${filename}" in package ${
+ req.packageSpec
+ }`
+ )
filename = file.replace(req.packageDir, '')
- if (req.query.main != null || getBasename(req.filename) !== getBasename(filename)) {
+ if (
+ req.query.main != null ||
+ getBasename(req.filename) !== getBasename(filename)
+ ) {
// Need to redirect to the module file so relative imports resolve
// correctly. Cache module redirects for 1 minute.
delete req.query.main
- res.set({
- 'Cache-Control': 'public, max-age=60',
- 'Cache-Tag': 'redirect,module-redirect'
- }).redirect(302, createPackageURL(req.packageName, req.packageVersion, filename, createSearch(req.query)))
+ res
+ .set({
+ 'Cache-Control': 'public, max-age=60',
+ 'Cache-Tag': 'redirect,module-redirect'
+ })
+ .redirect(
+ 302,
+ createPackageURL(
+ req.packageName,
+ req.packageVersion,
+ filename,
+ createSearch(req.query)
+ )
+ )
} else {
req.filename = filename
req.stats = stats
@@ -131,21 +173,47 @@ function fetchFile(req, res, next) {
})
} else if (req.packageVersion in req.packageInfo['dist-tags']) {
// Cache tag redirects for 1 minute.
- res.set({
- 'Cache-Control': 'public, max-age=60',
- 'Cache-Tag': 'redirect,tag-redirect'
- }).redirect(302, createPackageURL(req.packageName, req.packageInfo['dist-tags'][req.packageVersion], req.filename, req.search))
+ res
+ .set({
+ 'Cache-Control': 'public, max-age=60',
+ 'Cache-Tag': 'redirect,tag-redirect'
+ })
+ .redirect(
+ 302,
+ createPackageURL(
+ req.packageName,
+ req.packageInfo['dist-tags'][req.packageVersion],
+ req.filename,
+ req.search
+ )
+ )
} else {
- const maxVersion = semver.maxSatisfying(Object.keys(req.packageInfo.versions), req.packageVersion)
+ const maxVersion = semver.maxSatisfying(
+ Object.keys(req.packageInfo.versions),
+ req.packageVersion
+ )
if (maxVersion) {
// Cache semver redirects for 1 minute.
- res.set({
- 'Cache-Control': 'public, max-age=60',
- 'Cache-Tag': 'redirect,semver-redirect'
- }).redirect(302, createPackageURL(req.packageName, maxVersion, req.filename, req.search))
+ res
+ .set({
+ 'Cache-Control': 'public, max-age=60',
+ 'Cache-Tag': 'redirect,semver-redirect'
+ })
+ .redirect(
+ 302,
+ createPackageURL(
+ req.packageName,
+ maxVersion,
+ req.filename,
+ req.search
+ )
+ )
} else {
- res.status(404).type('text').send(`Cannot find package ${req.packageSpec}`)
+ res
+ .status(404)
+ .type('text')
+ .send(`Cannot find package ${req.packageSpec}`)
}
}
})
diff --git a/server/middleware/packageURL.js b/server/middleware/packageURL.js
index ae8f191..1ee7e2f 100644
--- a/server/middleware/packageURL.js
+++ b/server/middleware/packageURL.js
@@ -19,9 +19,8 @@ function queryIsKnown(query) {
function sanitizeQuery(query) {
const saneQuery = {}
- Object.keys(query).forEach(function (param) {
- if (isKnownQueryParam(param))
- saneQuery[param] = query[param]
+ Object.keys(query).forEach(function(param) {
+ if (isKnownQueryParam(param)) saneQuery[param] = query[param]
})
return saneQuery
@@ -54,13 +53,21 @@ function packageURL(req, res, next) {
// Do not allow invalid URLs.
if (url == null)
- return res.status(403).type('text').send(`Invalid URL: ${req.url}`)
+ return res
+ .status(403)
+ .type('text')
+ .send(`Invalid URL: ${req.url}`)
const nameErrors = validateNPMPackageName(url.packageName).errors
// Do not allow invalid package names.
if (nameErrors)
- return res.status(403).type('text').send(`Invalid package name: ${url.packageName} (${nameErrors.join(', ')})`)
+ return res
+ .status(403)
+ .type('text')
+ .send(
+ `Invalid package name: ${url.packageName} (${nameErrors.join(', ')})`
+ )
req.packageName = url.packageName
req.packageVersion = url.packageVersion
diff --git a/server/middleware/serveFile.js b/server/middleware/serveFile.js
index 5333f59..39e476e 100644
--- a/server/middleware/serveFile.js
+++ b/server/middleware/serveFile.js
@@ -18,36 +18,43 @@ const AutoIndex = !process.env.DISABLE_INDEX
const MaximumDepth = 128
const FileTransforms = {
- expand: function (file, dependencies, callback) {
+ expand: function(file, dependencies, callback) {
const options = {
- plugins: [
- unpkgRewrite(dependencies)
- ]
+ plugins: [unpkgRewrite(dependencies)]
}
- babel.transformFile(file, options, function (error, result) {
+ babel.transformFile(file, options, function(error, result) {
callback(error, result && result.code)
})
}
}
-
/**
* Send the file, JSON metadata, or HTML directory listing.
*/
function serveFile(req, res, next) {
if (req.query.meta != null) {
// Serve JSON metadata.
- getMetadata(req.packageDir, req.filename, req.stats, MaximumDepth, function (error, metadata) {
+ getMetadata(req.packageDir, req.filename, req.stats, MaximumDepth, function(
+ error,
+ metadata
+ ) {
if (error) {
console.error(error)
- res.status(500).type('text').send(`Cannot generate metadata for ${req.packageSpec}${req.filename}`)
+ res
+ .status(500)
+ .type('text')
+ .send(
+ `Cannot generate metadata for ${req.packageSpec}${req.filename}`
+ )
} else {
// Cache metadata for 1 year.
- res.set({
- 'Cache-Control': 'public, max-age=31536000',
- 'Cache-Tag': 'meta'
- }).send(metadata)
+ res
+ .set({
+ 'Cache-Control': 'public, max-age=31536000',
+ 'Cache-Tag': 'meta'
+ })
+ .send(metadata)
}
})
} else if (req.stats.isFile()) {
@@ -56,39 +63,52 @@ function serveFile(req, res, next) {
let contentType = getFileContentType(file)
- if (contentType === 'text/html')
- contentType = 'text/plain' // We can't serve HTML because bad people :(
+ if (contentType === 'text/html') contentType = 'text/plain' // We can't serve HTML because bad people :(
if (contentType === 'application/javascript' && req.query.module != null) {
// Serve a JavaScript module.
- const dependencies = Object.assign({},
+ const dependencies = Object.assign(
+ {},
req.packageConfig.peerDependencies,
req.packageConfig.dependencies
)
- FileTransforms.expand(file, dependencies, function (error, code) {
+ FileTransforms.expand(file, dependencies, function(error, code) {
if (error) {
console.error(error)
- const debugInfo = error.constructor.name + ': ' + error.message.replace(/^.*?\/unpkg-.+?\//, `/${req.packageSpec}/`) + '\n\n' + error.codeFrame
- res.status(500).type('text').send(`Cannot generate module for ${req.packageSpec}${req.filename}\n\n${debugInfo}`)
+ const debugInfo =
+ error.constructor.name +
+ ': ' +
+ error.message.replace(/^.*?\/unpkg-.+?\//, `/${req.packageSpec}/`) +
+ '\n\n' +
+ error.codeFrame
+ res
+ .status(500)
+ .type('text')
+ .send(
+ `Cannot generate module for ${req.packageSpec}${
+ req.filename
+ }\n\n${debugInfo}`
+ )
} else {
// Cache modules for 1 year.
- res.set({
- 'Content-Type': contentType,
- 'Content-Length': Buffer.byteLength(code),
- 'Cache-Control': 'public, max-age=31536000',
- 'Cache-Tag': 'file,js-file,js-module'
- }).send(code)
+ res
+ .set({
+ 'Content-Type': contentType,
+ 'Content-Length': Buffer.byteLength(code),
+ 'Cache-Control': 'public, max-age=31536000',
+ 'Cache-Tag': 'file,js-file,js-module'
+ })
+ .send(code)
}
})
} else {
// Serve some other static file.
- const tags = [ 'file' ]
+ const tags = ['file']
const ext = path.extname(req.filename).substr(1)
- if (ext)
- tags.push(`${ext}-file`)
+ if (ext) tags.push(`${ext}-file`)
// Cache files for 1 year.
res.set({
@@ -96,13 +116,13 @@ function serveFile(req, res, next) {
'Content-Length': req.stats.size,
'Cache-Control': 'public, max-age=31536000',
'Last-Modified': req.stats.mtime.toUTCString(),
- 'ETag': etag(req.stats),
+ ETag: etag(req.stats),
'Cache-Tag': tags.join(',')
})
const stream = fs.createReadStream(file)
- stream.on('error', function (error) {
+ stream.on('error', function(error) {
console.error(`Cannot send file ${req.packageSpec}${req.filename}`)
console.error(error)
res.sendStatus(500)
@@ -112,20 +132,36 @@ function serveFile(req, res, next) {
}
} else if (AutoIndex && req.stats.isDirectory()) {
// Serve an HTML directory listing.
- getIndexHTML(req.packageInfo, req.packageVersion, req.packageDir, req.filename, function (error, html) {
- if (error) {
- console.error(error)
- res.status(500).type('text').send(`Cannot generate index page for ${req.packageSpec}${req.filename}`)
- } else {
- // Cache HTML directory listings for 1 minute.
- res.set({
- 'Cache-Control': 'public, max-age=60',
- 'Cache-Tag': 'index'
- }).send(html)
+ getIndexHTML(
+ req.packageInfo,
+ req.packageVersion,
+ req.packageDir,
+ req.filename,
+ function(error, html) {
+ if (error) {
+ console.error(error)
+ res
+ .status(500)
+ .type('text')
+ .send(
+ `Cannot generate index page for ${req.packageSpec}${req.filename}`
+ )
+ } else {
+ // Cache HTML directory listings for 1 minute.
+ res
+ .set({
+ 'Cache-Control': 'public, max-age=60',
+ 'Cache-Tag': 'index'
+ })
+ .send(html)
+ }
}
- })
+ )
} else {
- res.status(403).type('text').send(`Cannot serve ${req.packageSpec}${req.filename}; it's not a file`)
+ res
+ .status(403)
+ .type('text')
+ .send(`Cannot serve ${req.packageSpec}${req.filename}; it's not a file`)
}
}
diff --git a/server/middleware/utils/createCache.js b/server/middleware/utils/createCache.js
index e0106ae..73fab02 100644
--- a/server/middleware/utils/createCache.js
+++ b/server/middleware/utils/createCache.js
@@ -10,7 +10,7 @@ function createCache(keyPrefix) {
}
function get(key, callback) {
- db.get(createKey(key), function (error, value) {
+ db.get(createKey(key), function(error, value) {
callback(error, value && JSON.parse(value))
})
}
diff --git a/server/middleware/utils/createMutex.js b/server/middleware/utils/createMutex.js
index d635e4e..da5f666 100644
--- a/server/middleware/utils/createMutex.js
+++ b/server/middleware/utils/createMutex.js
@@ -1,16 +1,19 @@
function createMutex(doWork) {
const mutex = {}
- return function (key, payload, callback) {
+ return function(key, payload, callback) {
if (mutex[key]) {
mutex[key].push(callback)
} else {
- mutex[key] = [ function () {
- delete mutex[key]
- }, callback ]
+ mutex[key] = [
+ function() {
+ delete mutex[key]
+ },
+ callback
+ ]
- doWork(payload, function (error, value) {
- mutex[key].forEach(function (callback) {
+ doWork(payload, function(error, value) {
+ mutex[key].forEach(function(callback) {
callback(error, value)
})
})
diff --git a/server/middleware/utils/createSearch.js b/server/middleware/utils/createSearch.js
index a4fd805..65a4b17 100644
--- a/server/middleware/utils/createSearch.js
+++ b/server/middleware/utils/createSearch.js
@@ -1,7 +1,7 @@
function createSearch(query) {
const params = []
- Object.keys(query).forEach(function (param) {
+ Object.keys(query).forEach(function(param) {
if (query[param] === '') {
params.push(param) // Omit the trailing "=" from param=
} else {
diff --git a/server/middleware/utils/getIndexHTML.js b/server/middleware/utils/getIndexHTML.js
index c5d874e..651d1b1 100644
--- a/server/middleware/utils/getIndexHTML.js
+++ b/server/middleware/utils/getIndexHTML.js
@@ -8,16 +8,16 @@ const IndexPage = require('../components/IndexPage')
const e = React.createElement
function getEntries(dir) {
- return new Promise(function (resolve, reject) {
- fs.readdir(dir, function (error, files) {
+ return new Promise(function(resolve, reject) {
+ fs.readdir(dir, function(error, files) {
if (error) {
reject(error)
} else {
resolve(
Promise.all(
files.map(file => getFileStats(path.join(dir, file)))
- ).then(function (statsArray) {
- return statsArray.map(function (stats, index) {
+ ).then(function(statsArray) {
+ return statsArray.map(function(stats, index) {
return { file: files[index], stats }
})
})
diff --git a/server/middleware/utils/getMetadata.js b/server/middleware/utils/getMetadata.js
index 37fa390..7768e19 100644
--- a/server/middleware/utils/getMetadata.js
+++ b/server/middleware/utils/getMetadata.js
@@ -6,20 +6,27 @@ const getFileStats = require('./getFileStats')
const getFileType = require('./getFileType')
function getEntries(dir, file, maximumDepth) {
- return new Promise(function (resolve, reject) {
- fs.readdir(path.join(dir, file), function (error, files) {
+ return new Promise(function(resolve, reject) {
+ fs.readdir(path.join(dir, file), function(error, files) {
if (error) {
reject(error)
} else {
resolve(
Promise.all(
- files.map(function (f) {
+ files.map(function(f) {
return getFileStats(path.join(dir, file, f))
})
- ).then(function (statsArray) {
- return Promise.all(statsArray.map(function (stats, index) {
- return getMetadataRecursive(dir, path.join(file, files[index]), stats, maximumDepth - 1)
- }))
+ ).then(function(statsArray) {
+ return Promise.all(
+ statsArray.map(function(stats, index) {
+ return getMetadataRecursive(
+ dir,
+ path.join(file, files[index]),
+ stats,
+ maximumDepth - 1
+ )
+ })
+ )
})
)
}
@@ -32,12 +39,12 @@ function formatTime(time) {
}
function getIntegrity(file) {
- return new Promise(function (resolve, reject) {
- fs.readFile(file, function (error, data) {
+ return new Promise(function(resolve, reject) {
+ fs.readFile(file, function(error, data) {
if (error) {
reject(error)
} else {
- resolve(SRIToolbox.generate({ algorithms: [ 'sha384' ] }, data))
+ resolve(SRIToolbox.generate({ algorithms: ['sha384'] }, data))
}
})
})
@@ -53,7 +60,7 @@ function getMetadataRecursive(dir, file, stats, maximumDepth) {
}
if (stats.isFile()) {
- return getIntegrity(path.join(dir, file)).then(function (integrity) {
+ return getIntegrity(path.join(dir, file)).then(function(integrity) {
metadata.integrity = integrity
return metadata
})
@@ -62,16 +69,19 @@ function getMetadataRecursive(dir, file, stats, maximumDepth) {
if (!stats.isDirectory() || maximumDepth === 0)
return Promise.resolve(metadata)
- return getEntries(dir, file, maximumDepth).then(function (files) {
+ return getEntries(dir, file, maximumDepth).then(function(files) {
metadata.files = files
return metadata
})
}
function getMetadata(baseDir, path, stats, maximumDepth, callback) {
- getMetadataRecursive(baseDir, path, stats, maximumDepth).then(function (metadata) {
+ getMetadataRecursive(baseDir, path, stats, maximumDepth).then(function(
+ metadata
+ ) {
callback(null, metadata)
- }, callback)
+ },
+ callback)
}
module.exports = getMetadata
diff --git a/server/middleware/utils/getPackage.js b/server/middleware/utils/getPackage.js
index 5be1e76..85fc1fa 100644
--- a/server/middleware/utils/getPackage.js
+++ b/server/middleware/utils/getPackage.js
@@ -26,7 +26,7 @@ function ignoreSymlinks(file, headers) {
}
function extractResponse(response, outputDir) {
- return new Promise(function (resolve, reject) {
+ return new Promise(function(resolve, reject) {
const extract = tar.extract(outputDir, {
readable: true, // All dirs/files should be readable.
map: stripNamePrefix,
@@ -44,24 +44,24 @@ function extractResponse(response, outputDir) {
function fetchAndExtract(tarballURL, outputDir) {
console.log(`info: Fetching ${tarballURL} and extracting to ${outputDir}`)
- return fetch(tarballURL).then(function (response) {
+ return fetch(tarballURL).then(function(response) {
return extractResponse(response, outputDir)
})
}
-const fetchMutex = createMutex(function (payload, callback) {
+const fetchMutex = createMutex(function(payload, callback) {
const { tarballURL, outputDir } = payload
- fs.access(outputDir, function (error) {
+ fs.access(outputDir, function(error) {
if (error) {
if (error.code === 'ENOENT' || error.code === 'ENOTDIR') {
// ENOENT or ENOTDIR are to be expected when we haven't yet
// fetched a package for the first time. Carry on!
- mkdirp(outputDir, function (error) {
+ mkdirp(outputDir, function(error) {
if (error) {
callback(error)
} else {
- fetchAndExtract(tarballURL, outputDir).then(function () {
+ fetchAndExtract(tarballURL, outputDir).then(function() {
callback()
}, callback)
}
@@ -80,7 +80,7 @@ function getPackage(packageConfig, callback) {
const tarballURL = packageConfig.dist.tarball
const outputDir = createTempPath(packageConfig.name, packageConfig.version)
- fetchMutex(tarballURL, { tarballURL, outputDir }, function (error) {
+ fetchMutex(tarballURL, { tarballURL, outputDir }, function(error) {
callback(error, outputDir)
})
}
diff --git a/server/middleware/utils/getPackageInfo.js b/server/middleware/utils/getPackageInfo.js
index 34fd4a2..3cac869 100644
--- a/server/middleware/utils/getPackageInfo.js
+++ b/server/middleware/utils/getPackageInfo.js
@@ -20,9 +20,9 @@ function fetchPackageInfo(packageName) {
return fetch(url, {
headers: {
- 'Accept': 'application/json'
+ Accept: 'application/json'
}
- }).then(function (res) {
+ }).then(function(res) {
return res.status === 404 ? null : res.json()
})
}
@@ -31,32 +31,35 @@ const PackageNotFound = 'PackageNotFound'
// This mutex prevents multiple concurrent requests to
// the registry for the same package info.
-const fetchMutex = createMutex(function (packageName, callback) {
- fetchPackageInfo(packageName).then(function (value) {
- if (value == null) {
- // Cache 404s for 5 minutes. This prevents us from making
- // unnecessary requests to the registry for bad package names.
- // In the worst case, a brand new package's info will be
- // available within 5 minutes.
- PackageInfoCache.set(packageName, PackageNotFound, 300, function () {
- callback(null, value)
- })
- } else {
- // Cache valid package info for 1 minute.
- PackageInfoCache.set(packageName, value, 60, function () {
- callback(null, value)
+const fetchMutex = createMutex(function(packageName, callback) {
+ fetchPackageInfo(packageName).then(
+ function(value) {
+ if (value == null) {
+ // Cache 404s for 5 minutes. This prevents us from making
+ // unnecessary requests to the registry for bad package names.
+ // In the worst case, a brand new package's info will be
+ // available within 5 minutes.
+ PackageInfoCache.set(packageName, PackageNotFound, 300, function() {
+ callback(null, value)
+ })
+ } else {
+ // Cache valid package info for 1 minute.
+ PackageInfoCache.set(packageName, value, 60, function() {
+ callback(null, value)
+ })
+ }
+ },
+ function(error) {
+ // Do not cache errors.
+ PackageInfoCache.del(packageName, function() {
+ callback(error)
})
}
- }, function (error) {
- // Do not cache errors.
- PackageInfoCache.del(packageName, function () {
- callback(error)
- })
- })
+ )
})
function getPackageInfo(packageName, callback) {
- PackageInfoCache.get(packageName, function (error, value) {
+ PackageInfoCache.get(packageName, function(error, value) {
if (error || value != null) {
callback(error, value === PackageNotFound ? null : value)
} else {
diff --git a/server/npm/assetPathsIndex.js b/server/npm/assetPathsIndex.js
index 2400d68..ba5fe65 100644
--- a/server/npm/assetPathsIndex.js
+++ b/server/npm/assetPathsIndex.js
@@ -10,169 +10,96 @@
* The range `null` is a catch-all.
*/
module.exports = {
- 'angular': [
- [ '>=1.2.27', '/angular.min.js' ],
- [ null, '/lib/angular.min.js' ]
+ angular: [['>=1.2.27', '/angular.min.js'], [null, '/lib/angular.min.js']],
+
+ 'angular-animate': [[null, '/angular-animate.min.js']],
+
+ 'angular-cookies': [[null, '/angular-cookies.min.js']],
+
+ 'angular-resource': [[null, '/angular-resource.min.js']],
+
+ 'angular-sanitize': [[null, '/angular-sanitize.min.js']],
+
+ 'angular-ui-bootstrap': [[null, '/dist/ui-bootstrap.js']],
+
+ 'animate.css': [[null, '/animate.min.css']],
+
+ 'babel-standalone': [[null, '/babel.min.js']],
+
+ backbone: [[null, '/backbone-min.js']],
+
+ bootstrap: [
+ [null, '/dist/css/bootstrap.min.css', '/dist/js/bootstrap.min.js']
],
- 'angular-animate': [
- [ null, '/angular-animate.min.js' ]
- ],
+ 'bootstrap-sass': [[null, '/assets/javascripts/bootstrap.min.js']],
- 'angular-cookies': [
- [ null, '/angular-cookies.min.js' ]
- ],
+ bulma: [[null, '/css/bulma.css']],
- 'angular-resource': [
- [ null, '/angular-resource.min.js' ]
- ],
+ 'core.js': [[null, '/dist/core.min.js']],
- 'angular-sanitize': [
- [ null, '/angular-sanitize.min.js' ]
- ],
+ 'create-react-class': [[null, '/create-react-class.min.js']],
- 'angular-ui-bootstrap': [
- [ null, '/dist/ui-bootstrap.js' ]
- ],
+ d3: [[null, '/build/d3.min.js']],
- 'animate.css': [
- [ null, '/animate.min.css' ]
- ],
-
- 'babel-standalone': [
- [ null, '/babel.min.js' ]
- ],
-
- 'backbone': [
- [ null, '/backbone-min.js' ]
- ],
-
- 'bootstrap': [
- [ null, '/dist/css/bootstrap.min.css', '/dist/js/bootstrap.min.js' ]
- ],
-
- 'bootstrap-sass': [
- [ null, '/assets/javascripts/bootstrap.min.js' ]
- ],
-
- 'bulma': [
- [ null, '/css/bulma.css' ]
- ],
-
- 'core.js': [
- [ null, '/dist/core.min.js' ]
- ],
-
- 'create-react-class': [
- [ null, '/create-react-class.min.js' ]
- ],
-
- 'd3': [
- [ null, '/build/d3.min.js' ]
- ],
-
- 'ember-source': [
- [ null, '/dist/ember.min.js' ]
- ],
+ 'ember-source': [[null, '/dist/ember.min.js']],
'foundation-sites': [
- [ null, '/dist/css/foundation.min.css', '/dist/js/foundation.min.js' ]
+ [null, '/dist/css/foundation.min.css', '/dist/js/foundation.min.js']
],
- 'gsap': [
- [ null, '/TweenMax.js' ]
+ gsap: [[null, '/TweenMax.js']],
+
+ handlebars: [[null, '/dist/handlebars.min.js']],
+
+ jquery: [[null, '/dist/jquery.min.js']],
+
+ fastclick: [[null, '/lib/fastclick.js']],
+
+ lodash: [['<3', '/dist/lodash.min.js'], [null, '/lodash.min.js']],
+
+ 'masonry-layout': [[null, '/dist/masonry.pkgd.min.js']],
+
+ 'materialize-css': [[null, '/dist/css/materialize.min.css']],
+
+ 'ngx-bootstrap': [[null, '/bundles/ngx-bootstrap.umd.js']],
+
+ react: [
+ ['>=16.0.0-alpha.7', '/umd/react.production.min.js'],
+ [null, '/dist/react.min.js']
],
- 'handlebars': [
- [ null, '/dist/handlebars.min.js' ]
- ],
-
- 'jquery': [
- [ null, '/dist/jquery.min.js' ]
- ],
-
- 'fastclick': [
- [ null, '/lib/fastclick.js' ]
- ],
-
- 'lodash': [
- [ '<3', '/dist/lodash.min.js' ],
- [ null, '/lodash.min.js' ]
- ],
-
- 'masonry-layout': [
- [ null, '/dist/masonry.pkgd.min.js' ]
- ],
-
- 'materialize-css': [
- [ null, '/dist/css/materialize.min.css' ]
- ],
-
- 'ngx-bootstrap': [
- [ null, '/bundles/ngx-bootstrap.umd.js' ]
- ],
-
- 'react': [
- [ '>=16.0.0-alpha.7', '/umd/react.production.min.js' ],
- [ null, '/dist/react.min.js' ]
- ],
-
- 'react-bootstrap': [
- [ null, '/dist/react-bootstrap.min.js' ]
- ],
+ 'react-bootstrap': [[null, '/dist/react-bootstrap.min.js']],
'react-dom': [
- [ '>=16.0.0-alpha.7', '/umd/react-dom.production.min.js' ],
- [ null, '/dist/react-dom.min.js' ]
+ ['>=16.0.0-alpha.7', '/umd/react-dom.production.min.js'],
+ [null, '/dist/react-dom.min.js']
],
'react-router': [
- [ '>=4.0.0', '/umd/react-router.min.js' ],
- [ null, '/umd/ReactRouter.min.js' ]
+ ['>=4.0.0', '/umd/react-router.min.js'],
+ [null, '/umd/ReactRouter.min.js']
],
- 'redux': [
- [ null, '/dist/redux.min.js' ]
- ],
+ redux: [[null, '/dist/redux.min.js']],
- 'redux-saga': [
- [ null, '/dist/redux-saga.min.js' ]
- ],
+ 'redux-saga': [[null, '/dist/redux-saga.min.js']],
- 'redux-thunk': [
- [ null, '/dist/redux-thunk.min.js' ]
- ],
+ 'redux-thunk': [[null, '/dist/redux-thunk.min.js']],
- 'snapsvg': [
- [ null, '/snap.svg-min.js' ]
- ],
+ snapsvg: [[null, '/snap.svg-min.js']],
- 'systemjs': [
- [ null, '/dist/system.js' ]
- ],
+ systemjs: [[null, '/dist/system.js']],
- 'three': [
- [ '<=0.77.0', '/three.min.js' ],
- [ null, '/build/three.min.js' ]
- ],
+ three: [['<=0.77.0', '/three.min.js'], [null, '/build/three.min.js']],
- 'underscore': [
- [ null, '/underscore-min.js' ]
- ],
+ underscore: [[null, '/underscore-min.js']],
- 'vue': [
- [ null, '/dist/vue.min.js' ]
- ],
+ vue: [[null, '/dist/vue.min.js']],
- 'zepto': [
- [ null, '/dist/zepto.min.js' ]
- ],
+ zepto: [[null, '/dist/zepto.min.js']],
- 'zingchart': [
- [ null, '/client/zingchart.min.js' ]
- ],
+ zingchart: [[null, '/client/zingchart.min.js']],
- 'zone.js': [
- [ null, '/dist/zone.js' ]
- ]
+ 'zone.js': [[null, '/dist/zone.js']]
}
diff --git a/server/npm/getAssetPaths.js b/server/npm/getAssetPaths.js
index befa831..0ae9535 100644
--- a/server/npm/getAssetPaths.js
+++ b/server/npm/getAssetPaths.js
@@ -5,11 +5,10 @@ function getAssetPaths(packageName, version) {
const entries = assetPathsIndex[packageName]
if (entries) {
- const matchingEntry = entries.find(function (entry) {
+ const matchingEntry = entries.find(function(entry) {
const range = entry[0]
- if (range == null || semver.satisfies(version, range))
- return entry
+ if (range == null || semver.satisfies(version, range)) return entry
})
return matchingEntry.slice(1)
diff --git a/server/npm/search.js b/server/npm/search.js
index 35de1ae..1220d50 100644
--- a/server/npm/search.js
+++ b/server/npm/search.js
@@ -2,13 +2,13 @@ const searchIndex = require('./searchIndex')
const getAssetPaths = require('./getAssetPaths')
function enhanceHit(hit) {
- return new Promise(function (resolve, reject) {
+ return new Promise(function(resolve, reject) {
const assetPaths = getAssetPaths(hit.name, hit.version)
if (assetPaths) {
// TODO: Double check the package metadata to ensure the files
// haven't moved from the paths in the index?
- hit.assets = assetPaths.map(function (path) {
+ hit.assets = assetPaths.map(function(path) {
return `https://unpkg.com/${hit.name}@${hit.version}${path}`
})
@@ -16,9 +16,7 @@ function enhanceHit(hit) {
} else {
// We don't have any global paths for this package yet. Try
// using the "bare" URL.
- hit.assets = [
- `https://unpkg.com/${hit.name}@${hit.version}`
- ]
+ hit.assets = [`https://unpkg.com/${hit.name}@${hit.version}`]
resolve(hit)
}
@@ -32,13 +30,13 @@ function concat(string) {
}
function search(query, page) {
- return new Promise(function (resolve, reject) {
+ return new Promise(function(resolve, reject) {
const hitsPerPage = 10
const params = {
// typoTolerance: 'min',
// optionalFacetFilters: `concatenatedName:${concat(query)}`,
- facets: [ 'keywords' ],
+ facets: ['keywords'],
attributesToHighlight: null,
attributesToRetrieve: [
'description',
@@ -58,14 +56,12 @@ function search(query, page) {
page
}
- searchIndex.search(query, params, function (error, value) {
+ searchIndex.search(query, params, function(error, value) {
if (error) {
reject(error)
} else {
resolve(
- Promise.all(
- value.hits.map(enhanceHit)
- ).then(function (hits) {
+ Promise.all(value.hits.map(enhanceHit)).then(function(hits) {
const totalHits = value.nbHits
const totalPages = value.nbPages
diff --git a/server/npm/searchIndex.js b/server/npm/searchIndex.js
index 6278fc6..a80c872 100644
--- a/server/npm/searchIndex.js
+++ b/server/npm/searchIndex.js
@@ -14,9 +14,8 @@ invariant(
'Missing $ALGOLIA_NPM_SEARCH_API_KEY environment variable'
)
-const index = algolia(
- AlgoliaNpmSearchAppId,
- AlgoliaNpmSearchApiKey
-).initIndex('npm-search')
+const index = algolia(AlgoliaNpmSearchAppId, AlgoliaNpmSearchApiKey).initIndex(
+ 'npm-search'
+)
module.exports = index
diff --git a/server/utils/createPackageURL.js b/server/utils/createPackageURL.js
index 8456579..dbeef43 100644
--- a/server/utils/createPackageURL.js
+++ b/server/utils/createPackageURL.js
@@ -1,14 +1,11 @@
function createPackageURL(packageName, version, filename, search) {
let pathname = `/${packageName}`
- if (version != null)
- pathname += `@${version}`
+ if (version != null) pathname += `@${version}`
- if (filename)
- pathname += filename
+ if (filename) pathname += filename
- if (search)
- pathname += search
+ if (search) pathname += search
return pathname
}
diff --git a/server/utils/parsePackageURL.js b/server/utils/parsePackageURL.js
index 34324ea..f61c726 100644
--- a/server/utils/parsePackageURL.js
+++ b/server/utils/parsePackageURL.js
@@ -19,20 +19,20 @@ function parsePackageURL(packageURL) {
const match = URLFormat.exec(pathname)
- if (match == null)
- return null
+ if (match == null) return null
const packageName = match[1]
const packageVersion = decodeParam(match[2]) || 'latest'
const filename = decodeParam(match[3])
- return { // If the URL is /@scope/name@version/file.js?main=browser:
- pathname, // /@scope/name@version/path.js
- search, // ?main=browser
- query, // { main: 'browser' }
- packageName, // @scope/name
+ return {
+ // If the URL is /@scope/name@version/file.js?main=browser:
+ pathname, // /@scope/name@version/path.js
+ search, // ?main=browser
+ query, // { main: 'browser' }
+ packageName, // @scope/name
packageVersion, // version
- filename // /file.js
+ filename // /file.js
}
}