Use single quotes :P

This commit is contained in:
Michael Jackson 2018-12-17 09:38:05 -08:00
parent ada37035cd
commit 19b2e5574b
93 changed files with 792 additions and 791 deletions

View File

@ -1,3 +0,0 @@
{
"singleQuote": false
}

View File

@ -1,22 +1,22 @@
const crypto = require("crypto"); const crypto = require('crypto');
const jwt = require("jsonwebtoken"); const jwt = require('jsonwebtoken');
const db = require("./utils/data"); const db = require('./utils/data');
const secretKey = require("./secretKey"); const secretKey = require('./secretKey');
function getCurrentSeconds() { function getCurrentSeconds() {
return Math.floor(Date.now() / 1000); return Math.floor(Date.now() / 1000);
} }
function createTokenId() { function createTokenId() {
return crypto.randomBytes(16).toString("hex"); return crypto.randomBytes(16).toString('hex');
} }
function createToken(scopes = {}) { function createToken(scopes = {}) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const payload = { const payload = {
jti: createTokenId(), jti: createTokenId(),
iss: "https://unpkg.com", iss: 'https://unpkg.com',
iat: getCurrentSeconds(), iat: getCurrentSeconds(),
scopes scopes
}; };
@ -24,7 +24,7 @@ function createToken(scopes = {}) {
jwt.sign( jwt.sign(
payload, payload,
secretKey.private, secretKey.private,
{ algorithm: "RS256" }, { algorithm: 'RS256' },
(error, token) => { (error, token) => {
if (error) { if (error) {
reject(error); reject(error);
@ -36,11 +36,11 @@ function createToken(scopes = {}) {
}); });
} }
const revokedTokensSet = "revoked-tokens"; const revokedTokensSet = 'revoked-tokens';
function verifyToken(token) { function verifyToken(token) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const options = { algorithms: ["RS256"] }; const options = { algorithms: ['RS256'] };
jwt.verify(token, secretKey.public, options, (error, payload) => { jwt.verify(token, secretKey.public, options, (error, payload) => {
if (error) { if (error) {

View File

@ -1,6 +1,6 @@
const db = require("./utils/data"); const db = require('./utils/data');
const blacklistSet = "blacklisted-packages"; const blacklistSet = 'blacklisted-packages';
function addPackage(packageName) { function addPackage(packageName) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -1,24 +1,24 @@
require("isomorphic-fetch"); require('isomorphic-fetch');
const invariant = require("invariant"); const invariant = require('invariant');
const gunzip = require("gunzip-maybe"); const gunzip = require('gunzip-maybe');
const ndjson = require("ndjson"); const ndjson = require('ndjson');
const cloudflareURL = "https://api.cloudflare.com/client/v4"; const cloudflareURL = 'https://api.cloudflare.com/client/v4';
const cloudflareEmail = process.env.CLOUDFLARE_EMAIL; const cloudflareEmail = process.env.CLOUDFLARE_EMAIL;
const cloudflareKey = process.env.CLOUDFLARE_KEY; const cloudflareKey = process.env.CLOUDFLARE_KEY;
invariant( invariant(
cloudflareEmail, cloudflareEmail,
"Missing the $CLOUDFLARE_EMAIL environment variable" '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) { function get(path, headers) {
return fetch(`${cloudflareURL}${path}`, { return fetch(`${cloudflareURL}${path}`, {
headers: Object.assign({}, headers, { headers: Object.assign({}, headers, {
"X-Auth-Email": cloudflareEmail, 'X-Auth-Email': cloudflareEmail,
"X-Auth-Key": cloudflareKey 'X-Auth-Key': cloudflareKey
}) })
}); });
} }
@ -32,7 +32,7 @@ function getJSON(path, headers) {
if (!data.success) { if (!data.success) {
console.error(`CloudflareAPI.getJSON failed at ${path}`); console.error(`CloudflareAPI.getJSON failed at ${path}`);
console.error(data); console.error(data);
throw new Error("Failed to getJSON from Cloudflare"); throw new Error('Failed to getJSON from Cloudflare');
} }
return data.result; return data.result;
@ -51,9 +51,9 @@ function reduceResults(target, values) {
Object.keys(values).forEach(key => { Object.keys(values).forEach(key => {
const value = values[key]; const value = values[key];
if (typeof value === "object" && value) { if (typeof value === 'object' && value) {
target[key] = reduceResults(target[key] || {}, value); target[key] = reduceResults(target[key] || {}, value);
} else if (typeof value === "number") { } else if (typeof value === 'number') {
target[key] = (target[key] || 0) + values[key]; target[key] = (target[key] || 0) + values[key];
} }
}); });
@ -75,7 +75,7 @@ function getZoneAnalyticsDashboard(zones, since, until) {
function getJSONStream(path, headers) { function getJSONStream(path, headers) {
const gzipHeaders = Object.assign({}, headers, { const gzipHeaders = Object.assign({}, headers, {
"Accept-Encoding": "gzip" 'Accept-Encoding': 'gzip'
}); });
return get(path, gzipHeaders) return get(path, gzipHeaders)
@ -84,7 +84,7 @@ function getJSONStream(path, headers) {
} }
function getLogs(zoneId, startTime, endTime, fieldsArray) { function getLogs(zoneId, startTime, endTime, fieldsArray) {
const fields = fieldsArray.join(","); const fields = fieldsArray.join(',');
// console.log( // console.log(
// `https://api.cloudflare.com/client/v4/zones/${zoneId}/logs/received?start=${startTime}&end=${endTime}&fields=${fields}` // `https://api.cloudflare.com/client/v4/zones/${zoneId}/logs/received?start=${startTime}&end=${endTime}&fields=${fields}`

View File

@ -1,7 +1,7 @@
const db = require("./utils/data"); const db = require('./utils/data');
const CloudflareAPI = require("./CloudflareAPI"); const CloudflareAPI = require('./CloudflareAPI');
const BlacklistAPI = require("./BlacklistAPI"); const BlacklistAPI = require('./BlacklistAPI');
function prunePackages(packagesMap) { function prunePackages(packagesMap) {
return Promise.all( return Promise.all(
@ -39,7 +39,7 @@ function createScoresMap(array) {
function getScoresMap(key, n = 100) { function getScoresMap(key, n = 100) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
db.zrevrange(key, 0, n, "withscores", (error, value) => { db.zrevrange(key, 0, n, 'withscores', (error, value) => {
if (error) { if (error) {
reject(error); reject(error);
} else { } else {
@ -141,7 +141,7 @@ function extractPublicInfo(data) {
}; };
} }
const DomainNames = ["unpkg.com", "npmcdn.com"]; const DomainNames = ['unpkg.com', 'npmcdn.com'];
function fetchStats(since, until) { function fetchStats(since, until) {
return CloudflareAPI.getZones(DomainNames).then(zones => { return CloudflareAPI.getZones(DomainNames).then(zones => {

View File

@ -1,11 +1,11 @@
const AuthAPI = require("../AuthAPI"); const AuthAPI = require('../AuthAPI');
describe("Auth API", () => { describe('Auth API', () => {
beforeEach(done => { beforeEach(done => {
AuthAPI.removeAllRevokedTokens().then(() => done(), done); AuthAPI.removeAllRevokedTokens().then(() => done(), done);
}); });
it("creates tokens with the right scopes", done => { it('creates tokens with the right scopes', done => {
const scopes = { const scopes = {
blacklist: { blacklist: {
add: true, add: true,
@ -24,7 +24,7 @@ describe("Auth API", () => {
}); });
}); });
it("refuses to verify revoked tokens", done => { it('refuses to verify revoked tokens', done => {
const scopes = {}; const scopes = {};
AuthAPI.createToken(scopes).then(token => { AuthAPI.createToken(scopes).then(token => {

View File

@ -1,12 +1,12 @@
const BlacklistAPI = require("../BlacklistAPI"); const BlacklistAPI = require('../BlacklistAPI');
describe("Blacklist API", () => { describe('Blacklist API', () => {
beforeEach(done => { beforeEach(done => {
BlacklistAPI.removeAllPackages().then(() => done(), done); BlacklistAPI.removeAllPackages().then(() => done(), done);
}); });
it("adds and removes packages to/from the blacklist", done => { it('adds and removes packages to/from the blacklist', done => {
const packageName = "bad-package"; const packageName = 'bad-package';
BlacklistAPI.addPackage(packageName).then(() => { BlacklistAPI.addPackage(packageName).then(() => {
BlacklistAPI.getPackages().then(packageNames => { BlacklistAPI.getPackages().then(packageNames => {

View File

@ -1,46 +1,46 @@
const request = require("supertest"); const request = require('supertest');
const createServer = require("../createServer"); const createServer = require('../createServer');
const withRevokedToken = require("./utils/withRevokedToken"); const withRevokedToken = require('./utils/withRevokedToken');
const withToken = require("./utils/withToken"); const withToken = require('./utils/withToken');
describe("The /_auth endpoint", () => { describe('The /_auth endpoint', () => {
let server; let server;
beforeEach(() => { beforeEach(() => {
server = createServer(); server = createServer();
}); });
describe("POST /_auth", () => { describe('POST /_auth', () => {
it("creates a new auth token", done => { it('creates a new auth token', done => {
request(server) request(server)
.post("/_auth") .post('/_auth')
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("token"); expect(res.body).toHaveProperty('token');
done(); done();
}); });
}); });
}); });
describe("GET /_auth", () => { describe('GET /_auth', () => {
describe("with no auth", () => { describe('with no auth', () => {
it("echoes back null", done => { it('echoes back null', done => {
request(server) request(server)
.get("/_auth") .get('/_auth')
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("auth"); expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBe(null); expect(res.body.auth).toBe(null);
done(); done();
}); });
}); });
}); });
describe("with a revoked auth token", () => { describe('with a revoked auth token', () => {
it("echoes back null", done => { it('echoes back null', done => {
withRevokedToken({ some: { scope: true } }, token => { withRevokedToken({ some: { scope: true } }, token => {
request(server) request(server)
.get("/_auth?token=" + token) .get('/_auth?token=' + token)
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("auth"); expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBe(null); expect(res.body.auth).toBe(null);
done(); done();
}); });
@ -48,14 +48,14 @@ describe("The /_auth endpoint", () => {
}); });
}); });
describe("with a valid auth token", () => { describe('with a valid auth token', () => {
it("echoes back the auth payload", done => { it('echoes back the auth payload', done => {
withToken({ some: { scope: true } }, token => { withToken({ some: { scope: true } }, token => {
request(server) request(server)
.get("/_auth?token=" + token) .get('/_auth?token=' + token)
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("auth"); expect(res.body).toHaveProperty('auth');
expect(typeof res.body.auth).toBe("object"); expect(typeof res.body.auth).toBe('object');
done(); done();
}); });
}); });

View File

@ -1,22 +1,22 @@
const request = require("supertest"); const request = require('supertest');
const createServer = require("../createServer"); const createServer = require('../createServer');
const clearBlacklist = require("./utils/clearBlacklist"); const clearBlacklist = require('./utils/clearBlacklist');
const withToken = require("./utils/withToken"); const withToken = require('./utils/withToken');
describe("The /_blacklist endpoint", () => { describe('The /_blacklist endpoint', () => {
let server; let server;
beforeEach(() => { beforeEach(() => {
server = createServer(); server = createServer();
}); });
describe("POST /_blacklist", () => { describe('POST /_blacklist', () => {
afterEach(clearBlacklist); afterEach(clearBlacklist);
describe("with no auth", () => { describe('with no auth', () => {
it("is forbidden", done => { it('is forbidden', done => {
request(server) request(server)
.post("/_blacklist") .post('/_blacklist')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(403); expect(res.statusCode).toBe(403);
done(); done();
@ -25,11 +25,11 @@ describe("The /_blacklist endpoint", () => {
}); });
describe('with the "blacklist.add" scope', () => { describe('with the "blacklist.add" scope', () => {
it("can add to the blacklist", done => { it('can add to the blacklist', done => {
withToken({ blacklist: { add: true } }, token => { withToken({ blacklist: { add: true } }, token => {
request(server) request(server)
.post("/_blacklist") .post('/_blacklist')
.send({ token, packageName: "bad-package" }) .send({ token, packageName: 'bad-package' })
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(200); expect(res.statusCode).toBe(200);
expect(res.body.ok).toBe(true); expect(res.body.ok).toBe(true);
@ -40,11 +40,11 @@ describe("The /_blacklist endpoint", () => {
}); });
}); });
describe("GET /_blacklist", () => { describe('GET /_blacklist', () => {
describe("with no auth", () => { describe('with no auth', () => {
it("is forbidden", done => { it('is forbidden', done => {
request(server) request(server)
.get("/_blacklist") .get('/_blacklist')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(403); expect(res.statusCode).toBe(403);
done(); done();
@ -53,10 +53,10 @@ describe("The /_blacklist endpoint", () => {
}); });
describe('with the "blacklist.read" scope', () => { describe('with the "blacklist.read" scope', () => {
it("can read the blacklist", done => { it('can read the blacklist', done => {
withToken({ blacklist: { read: true } }, token => { withToken({ blacklist: { read: true } }, token => {
request(server) request(server)
.get("/_blacklist?token=" + token) .get('/_blacklist?token=' + token)
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(200); expect(res.statusCode).toBe(200);
done(); done();
@ -66,11 +66,11 @@ describe("The /_blacklist endpoint", () => {
}); });
}); });
describe("DELETE /_blacklist/:packageName", () => { describe('DELETE /_blacklist/:packageName', () => {
describe("with no auth", () => { describe('with no auth', () => {
it("is forbidden", done => { it('is forbidden', done => {
request(server) request(server)
.delete("/_blacklist/bad-package") .delete('/_blacklist/bad-package')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(403); expect(res.statusCode).toBe(403);
done(); done();
@ -79,10 +79,10 @@ describe("The /_blacklist endpoint", () => {
}); });
describe('with the "blacklist.remove" scope', () => { describe('with the "blacklist.remove" scope', () => {
it("can remove a package from the blacklist", done => { it('can remove a package from the blacklist', done => {
withToken({ blacklist: { remove: true } }, token => { withToken({ blacklist: { remove: true } }, token => {
request(server) request(server)
.delete("/_blacklist/bad-package") .delete('/_blacklist/bad-package')
.send({ token }) .send({ token })
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(200); expect(res.statusCode).toBe(200);
@ -92,10 +92,10 @@ describe("The /_blacklist endpoint", () => {
}); });
}); });
it("can remove a scoped package from the blacklist", done => { it('can remove a scoped package from the blacklist', done => {
withToken({ blacklist: { remove: true } }, token => { withToken({ blacklist: { remove: true } }, token => {
request(server) request(server)
.delete("/_blacklist/@scope/bad-package") .delete('/_blacklist/@scope/bad-package')
.send({ token }) .send({ token })
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(200); expect(res.statusCode).toBe(200);

View File

@ -1,17 +1,17 @@
const request = require("supertest"); const request = require('supertest');
const createServer = require("../createServer"); const createServer = require('../createServer');
describe("The /_publicKey endpoint", () => { describe('The /_publicKey endpoint', () => {
let server; let server;
beforeEach(() => { beforeEach(() => {
server = createServer(); server = createServer();
}); });
describe("GET /_publicKey", () => { describe('GET /_publicKey', () => {
it("echoes the public key", done => { it('echoes the public key', done => {
request(server) request(server)
.get("/_publicKey") .get('/_publicKey')
.end((err, res) => { .end((err, res) => {
expect(res.text).toMatch(/PUBLIC KEY/); expect(res.text).toMatch(/PUBLIC KEY/);
done(); done();

View File

@ -1,47 +1,47 @@
const request = require("supertest"); const request = require('supertest');
const createServer = require("../createServer"); const createServer = require('../createServer');
const withAuthHeader = require("./utils/withAuthHeader"); const withAuthHeader = require('./utils/withAuthHeader');
const withRevokedToken = require("./utils/withRevokedToken"); const withRevokedToken = require('./utils/withRevokedToken');
const withToken = require("./utils/withToken"); const withToken = require('./utils/withToken');
describe("The /api/auth endpoint", () => { describe('The /api/auth endpoint', () => {
let server; let server;
beforeEach(() => { beforeEach(() => {
server = createServer(); server = createServer();
}); });
describe("POST /api/auth", () => { describe('POST /api/auth', () => {
it("creates a new auth token", done => { it('creates a new auth token', done => {
request(server) request(server)
.post("/api/auth") .post('/api/auth')
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("token"); expect(res.body).toHaveProperty('token');
done(); done();
}); });
}); });
}); });
describe("GET /api/auth", () => { describe('GET /api/auth', () => {
describe("with no auth", () => { describe('with no auth', () => {
it("echoes back null", done => { it('echoes back null', done => {
request(server) request(server)
.get("/api/auth") .get('/api/auth')
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("auth"); expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBe(null); expect(res.body.auth).toBe(null);
done(); done();
}); });
}); });
}); });
describe("with a revoked auth token", () => { describe('with a revoked auth token', () => {
it("echoes back null", done => { it('echoes back null', done => {
withRevokedToken({ some: { scope: true } }, token => { withRevokedToken({ some: { scope: true } }, token => {
request(server) request(server)
.get("/api/auth?token=" + token) .get('/api/auth?token=' + token)
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("auth"); expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBe(null); expect(res.body.auth).toBe(null);
done(); done();
}); });
@ -49,16 +49,16 @@ describe("The /api/auth endpoint", () => {
}); });
}); });
describe("with a valid auth token", () => { describe('with a valid auth token', () => {
describe("in the query string", () => { describe('in the query string', () => {
it("echoes back the auth payload", done => { it('echoes back the auth payload', done => {
const scopes = { some: { scope: true } }; const scopes = { some: { scope: true } };
withToken(scopes, token => { withToken(scopes, token => {
request(server) request(server)
.get("/api/auth?token=" + token) .get('/api/auth?token=' + token)
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("auth"); expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBeDefined(); expect(res.body.auth).toBeDefined();
expect(res.body.auth.scopes).toMatchObject(scopes); expect(res.body.auth.scopes).toMatchObject(scopes);
done(); done();
@ -67,16 +67,16 @@ describe("The /api/auth endpoint", () => {
}); });
}); });
describe("in the Authorization header", () => { describe('in the Authorization header', () => {
it("echoes back the auth payload", done => { it('echoes back the auth payload', done => {
const scopes = { some: { scope: true } }; const scopes = { some: { scope: true } };
withAuthHeader(scopes, header => { withAuthHeader(scopes, header => {
request(server) request(server)
.get("/api/auth") .get('/api/auth')
.set({ Authorization: header }) .set({ Authorization: header })
.end((err, res) => { .end((err, res) => {
expect(res.body).toHaveProperty("auth"); expect(res.body).toHaveProperty('auth');
expect(res.body.auth).toBeDefined(); expect(res.body.auth).toBeDefined();
expect(res.body.auth.scopes).toMatchObject(scopes); expect(res.body.auth.scopes).toMatchObject(scopes);
done(); done();

View File

@ -1,22 +1,22 @@
const request = require("supertest"); const request = require('supertest');
const createServer = require("../createServer"); const createServer = require('../createServer');
const clearBlacklist = require("./utils/clearBlacklist"); const clearBlacklist = require('./utils/clearBlacklist');
const withToken = require("./utils/withToken"); const withToken = require('./utils/withToken');
describe("The /api/blacklist endpoint", () => { describe('The /api/blacklist endpoint', () => {
let server; let server;
beforeEach(() => { beforeEach(() => {
server = createServer(); server = createServer();
}); });
describe("POST /api/blacklist", () => { describe('POST /api/blacklist', () => {
afterEach(clearBlacklist); afterEach(clearBlacklist);
describe("with no auth", () => { describe('with no auth', () => {
it("is forbidden", done => { it('is forbidden', done => {
request(server) request(server)
.post("/api/blacklist") .post('/api/blacklist')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(403); expect(res.statusCode).toBe(403);
done(); done();
@ -25,11 +25,11 @@ describe("The /api/blacklist endpoint", () => {
}); });
describe('with the "blacklist.add" scope', () => { describe('with the "blacklist.add" scope', () => {
it("can add to the blacklist", done => { it('can add to the blacklist', done => {
withToken({ blacklist: { add: true } }, token => { withToken({ blacklist: { add: true } }, token => {
request(server) request(server)
.post("/api/blacklist") .post('/api/blacklist')
.send({ token, packageName: "bad-package" }) .send({ token, packageName: 'bad-package' })
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(200); expect(res.statusCode).toBe(200);
expect(res.body.ok).toBe(true); expect(res.body.ok).toBe(true);
@ -40,11 +40,11 @@ describe("The /api/blacklist endpoint", () => {
}); });
}); });
describe("GET /api/blacklist", () => { describe('GET /api/blacklist', () => {
describe("with no auth", () => { describe('with no auth', () => {
it("is forbidden", done => { it('is forbidden', done => {
request(server) request(server)
.get("/api/blacklist") .get('/api/blacklist')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(403); expect(res.statusCode).toBe(403);
done(); done();
@ -53,10 +53,10 @@ describe("The /api/blacklist endpoint", () => {
}); });
describe('with the "blacklist.read" scope', () => { describe('with the "blacklist.read" scope', () => {
it("can read the blacklist", done => { it('can read the blacklist', done => {
withToken({ blacklist: { read: true } }, token => { withToken({ blacklist: { read: true } }, token => {
request(server) request(server)
.get("/api/blacklist?token=" + token) .get('/api/blacklist?token=' + token)
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(200); expect(res.statusCode).toBe(200);
done(); done();
@ -66,11 +66,11 @@ describe("The /api/blacklist endpoint", () => {
}); });
}); });
describe("DELETE /api/blacklist", () => { describe('DELETE /api/blacklist', () => {
describe("with no auth", () => { describe('with no auth', () => {
it("is forbidden", done => { it('is forbidden', done => {
request(server) request(server)
.delete("/api/blacklist") .delete('/api/blacklist')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(403); expect(res.statusCode).toBe(403);
done(); done();
@ -79,11 +79,11 @@ describe("The /api/blacklist endpoint", () => {
}); });
describe('with the "blacklist.remove" scope', () => { describe('with the "blacklist.remove" scope', () => {
it("can remove a package from the blacklist", done => { it('can remove a package from the blacklist', done => {
withToken({ blacklist: { remove: true } }, token => { withToken({ blacklist: { remove: true } }, token => {
request(server) request(server)
.delete("/api/blacklist") .delete('/api/blacklist')
.send({ token, packageName: "bad-package" }) .send({ token, packageName: 'bad-package' })
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(200); expect(res.statusCode).toBe(200);
expect(res.body.ok).toBe(true); expect(res.body.ok).toBe(true);
@ -92,11 +92,11 @@ describe("The /api/blacklist endpoint", () => {
}); });
}); });
it("can remove a scoped package from the blacklist", done => { it('can remove a scoped package from the blacklist', done => {
withToken({ blacklist: { remove: true } }, token => { withToken({ blacklist: { remove: true } }, token => {
request(server) request(server)
.delete("/api/blacklist") .delete('/api/blacklist')
.send({ token, packageName: "@scope/bad-package" }) .send({ token, packageName: '@scope/bad-package' })
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(200); expect(res.statusCode).toBe(200);
expect(res.body.ok).toBe(true); expect(res.body.ok).toBe(true);

View File

@ -1,17 +1,17 @@
const request = require("supertest"); const request = require('supertest');
const createServer = require("../createServer"); const createServer = require('../createServer');
describe("The /api/publicKey endpoint", () => { describe('The /api/publicKey endpoint', () => {
let server; let server;
beforeEach(() => { beforeEach(() => {
server = createServer(); server = createServer();
}); });
describe("GET /api/publicKey", () => { describe('GET /api/publicKey', () => {
it("echoes the public key", done => { it('echoes the public key', done => {
request(server) request(server)
.get("/api/publicKey") .get('/api/publicKey')
.end((err, res) => { .end((err, res) => {
expect(res.text).toMatch(/PUBLIC KEY/); expect(res.text).toMatch(/PUBLIC KEY/);
done(); done();

View File

@ -1,62 +1,62 @@
const request = require("supertest"); const request = require('supertest');
const createServer = require("../createServer"); const createServer = require('../createServer');
const clearBlacklist = require("./utils/clearBlacklist"); const clearBlacklist = require('./utils/clearBlacklist');
const withBlacklist = require("./utils/withBlacklist"); const withBlacklist = require('./utils/withBlacklist');
describe("The server", () => { describe('The server', () => {
let server; let server;
beforeEach(() => { beforeEach(() => {
server = createServer(); server = createServer();
}); });
it("redirects /_meta to ?meta", done => { it('redirects /_meta to ?meta', done => {
request(server) request(server)
.get("/_meta/react") .get('/_meta/react')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(301); expect(res.statusCode).toBe(301);
expect(res.headers.location).toBe("/react?meta"); expect(res.headers.location).toBe('/react?meta');
done(); done();
}); });
}); });
it("redirects ?json to ?meta", done => { it('redirects ?json to ?meta', done => {
request(server) request(server)
.get("/react?json") .get('/react?json')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(301); expect(res.statusCode).toBe(301);
expect(res.headers.location).toBe("/react?meta"); expect(res.headers.location).toBe('/react?meta');
done(); done();
}); });
}); });
it("redirects invalid query params", done => { it('redirects invalid query params', done => {
request(server) request(server)
.get("/react?main=index&invalid") .get('/react?main=index&invalid')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(302); expect(res.statusCode).toBe(302);
expect(res.headers.location).toBe("/react?main=index"); expect(res.headers.location).toBe('/react?main=index');
done(); done();
}); });
}); });
it("rejects invalid package names", done => { it('rejects invalid package names', done => {
request(server) request(server)
.get("/_invalid/index.js") .get('/_invalid/index.js')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(403); expect(res.statusCode).toBe(403);
done(); done();
}); });
}); });
describe("blacklisted packages", () => { describe('blacklisted packages', () => {
afterEach(clearBlacklist); afterEach(clearBlacklist);
it("does not serve blacklisted packages", done => { it('does not serve blacklisted packages', done => {
withBlacklist(["bad-package"], () => { withBlacklist(['bad-package'], () => {
request(server) request(server)
.get("/bad-package/index.js") .get('/bad-package/index.js')
.end((err, res) => { .end((err, res) => {
expect(res.statusCode).toBe(403); expect(res.statusCode).toBe(403);
done(); done();

View File

@ -1,3 +1,3 @@
const closeDatabase = require("./utils/closeDatabase"); const closeDatabase = require('./utils/closeDatabase');
afterAll(closeDatabase); afterAll(closeDatabase);

View File

@ -1,4 +1,4 @@
const BlacklistAPI = require("../../BlacklistAPI"); const BlacklistAPI = require('../../BlacklistAPI');
function clearBlacklist(done) { function clearBlacklist(done) {
BlacklistAPI.removeAllPackages().then(done, done); BlacklistAPI.removeAllPackages().then(done, done);

View File

@ -1,7 +1,7 @@
const withToken = require("./withToken"); const withToken = require('./withToken');
function encodeBase64(token) { function encodeBase64(token) {
return Buffer.from(token).toString("base64"); return Buffer.from(token).toString('base64');
} }
function withAuthHeader(scopes, done) { function withAuthHeader(scopes, done) {

View File

@ -1,4 +1,4 @@
const BlacklistAPI = require("../../BlacklistAPI"); const BlacklistAPI = require('../../BlacklistAPI');
function withBlacklist(blacklist, done) { function withBlacklist(blacklist, done) {
Promise.all(blacklist.map(BlacklistAPI.addPackage)).then(done); Promise.all(blacklist.map(BlacklistAPI.addPackage)).then(done);

View File

@ -1,5 +1,5 @@
const withToken = require("./withToken"); const withToken = require('./withToken');
const AuthAPI = require("../../AuthAPI"); const AuthAPI = require('../../AuthAPI');
function withRevokedToken(scopes, done) { function withRevokedToken(scopes, done) {
withToken(scopes, token => { withToken(scopes, token => {

View File

@ -1,4 +1,4 @@
const AuthAPI = require("../../AuthAPI"); const AuthAPI = require('../../AuthAPI');
function withToken(scopes, done) { function withToken(scopes, done) {
AuthAPI.createToken(scopes).then(done); AuthAPI.createToken(scopes).then(done);

View File

@ -1,6 +1,6 @@
const validateNpmPackageName = require("validate-npm-package-name"); const validateNpmPackageName = require('validate-npm-package-name');
const BlacklistAPI = require("../BlacklistAPI"); const BlacklistAPI = require('../BlacklistAPI');
function addToBlacklist(req, res) { function addToBlacklist(req, res) {
const packageName = req.body.packageName; const packageName = req.body.packageName;
@ -15,7 +15,7 @@ function addToBlacklist(req, res) {
// Disallow invalid package names. // Disallow invalid package names.
if (nameErrors) { if (nameErrors) {
const reason = nameErrors.join(", "); const reason = nameErrors.join(', ');
return res.status(403).send({ return res.status(403).send({
error: `Invalid package name "${packageName}" (${reason})` error: `Invalid package name "${packageName}" (${reason})`
}); });
@ -33,7 +33,7 @@ function addToBlacklist(req, res) {
res.send({ res.send({
ok: true, ok: true,
message: `Package "${packageName}" was ${ message: `Package "${packageName}" was ${
added ? "added to" : "already in" added ? 'added to' : 'already in'
} the blacklist` } the blacklist`
}); });
}, },

View File

@ -1,4 +1,4 @@
const AuthAPI = require("../AuthAPI"); const AuthAPI = require('../AuthAPI');
const defaultScopes = { const defaultScopes = {
blacklist: { blacklist: {
@ -15,7 +15,7 @@ function createAuth(req, res) {
console.error(error); console.error(error);
res.status(500).send({ res.status(500).send({
error: "Unable to generate auth token" error: 'Unable to generate auth token'
}); });
} }
); );

View File

@ -1,6 +1,6 @@
const validateNpmPackageName = require("validate-npm-package-name"); const validateNpmPackageName = require('validate-npm-package-name');
const BlacklistAPI = require("../BlacklistAPI"); const BlacklistAPI = require('../BlacklistAPI');
function removeFromBlacklist(req, res) { function removeFromBlacklist(req, res) {
// TODO: Remove req.packageName when DELETE // TODO: Remove req.packageName when DELETE
@ -17,7 +17,7 @@ function removeFromBlacklist(req, res) {
// Disallow invalid package names. // Disallow invalid package names.
if (nameErrors) { if (nameErrors) {
const reason = nameErrors.join(", "); const reason = nameErrors.join(', ');
return res.status(403).send({ return res.status(403).send({
error: `Invalid package name "${packageName}" (${reason})` error: `Invalid package name "${packageName}" (${reason})`
}); });
@ -35,7 +35,7 @@ function removeFromBlacklist(req, res) {
res.send({ res.send({
ok: true, ok: true,
message: `Package "${packageName}" was ${ message: `Package "${packageName}" was ${
removed ? "removed from" : "not in" removed ? 'removed from' : 'not in'
} the blacklist` } the blacklist`
}); });
}, },

View File

@ -1,21 +1,21 @@
const React = require("react"); const React = require('react');
const ReactDOMServer = require("react-dom/server"); const ReactDOMServer = require('react-dom/server');
const semver = require("semver"); const semver = require('semver');
const MainPage = require("../client/MainPage"); const MainPage = require('../client/MainPage');
const AutoIndexApp = require("../client/autoIndex/App"); const AutoIndexApp = require('../client/autoIndex/App');
const createHTML = require("../client/utils/createHTML"); const createHTML = require('../client/utils/createHTML');
const renderPage = require("../utils/renderPage"); const renderPage = require('../utils/renderPage');
const globalScripts = const globalScripts =
process.env.NODE_ENV === "production" process.env.NODE_ENV === 'production'
? [ ? [
"/react@16.4.1/umd/react.production.min.js", '/react@16.4.1/umd/react.production.min.js',
"/react-dom@16.4.1/umd/react-dom.production.min.js" '/react-dom@16.4.1/umd/react-dom.production.min.js'
] ]
: [ : [
"/react@16.4.1/umd/react.development.js", '/react@16.4.1/umd/react.development.js',
"/react-dom@16.4.1/umd/react-dom.development.js" '/react-dom@16.4.1/umd/react-dom.development.js'
]; ];
function byVersion(a, b) { function byVersion(a, b) {
@ -23,8 +23,8 @@ function byVersion(a, b) {
} }
function serveAutoIndexPage(req, res) { function serveAutoIndexPage(req, res) {
const scripts = globalScripts.concat(req.assets.getScripts("autoIndex")); const scripts = globalScripts.concat(req.assets.getScripts('autoIndex'));
const styles = req.assets.getStyles("autoIndex"); const styles = req.assets.getStyles('autoIndex');
const props = { const props = {
packageName: req.packageName, packageName: req.packageName,
@ -49,8 +49,8 @@ function serveAutoIndexPage(req, res) {
res res
.set({ .set({
"Cache-Control": "public,max-age=60", // 1 minute 'Cache-Control': 'public,max-age=60', // 1 minute
"Cache-Tag": "auto-index" 'Cache-Tag': 'auto-index'
}) })
.send(html); .send(html);
} }

View File

@ -1,8 +1,8 @@
const serveAutoIndexPage = require("./serveAutoIndexPage"); const serveAutoIndexPage = require('./serveAutoIndexPage');
const serveHTMLModule = require("./serveHTMLModule"); const serveHTMLModule = require('./serveHTMLModule');
const serveJavaScriptModule = require("./serveJavaScriptModule"); const serveJavaScriptModule = require('./serveJavaScriptModule');
const serveStaticFile = require("./serveStaticFile"); const serveStaticFile = require('./serveStaticFile');
const serveMetadata = require("./serveMetadata"); const serveMetadata = require('./serveMetadata');
/** /**
* Send the file, JSON metadata, or HTML directory listing. * Send the file, JSON metadata, or HTML directory listing.
@ -12,23 +12,23 @@ function serveFile(req, res) {
return serveMetadata(req, res); return serveMetadata(req, res);
} }
if (req.entry.type === "directory") { if (req.entry.type === 'directory') {
return serveAutoIndexPage(req, res); return serveAutoIndexPage(req, res);
} }
if (req.query.module != null) { if (req.query.module != null) {
if (req.entry.contentType === "application/javascript") { if (req.entry.contentType === 'application/javascript') {
return serveJavaScriptModule(req, res); return serveJavaScriptModule(req, res);
} }
if (req.entry.contentType === "text/html") { if (req.entry.contentType === 'text/html') {
return serveHTMLModule(req, res); return serveHTMLModule(req, res);
} }
return res return res
.status(403) .status(403)
.type("text") .type('text')
.send("?module mode is available only for JavaScript and HTML files"); .send('?module mode is available only for JavaScript and HTML files');
} }
serveStaticFile(req, res); serveStaticFile(req, res);

View File

@ -1,14 +1,14 @@
const etag = require("etag"); const etag = require('etag');
const cheerio = require("cheerio"); const cheerio = require('cheerio');
const getContentTypeHeader = require("../utils/getContentTypeHeader"); const getContentTypeHeader = require('../utils/getContentTypeHeader');
const rewriteBareModuleIdentifiers = require("../utils/rewriteBareModuleIdentifiers"); const rewriteBareModuleIdentifiers = require('../utils/rewriteBareModuleIdentifiers');
function serveHTMLModule(req, res) { function serveHTMLModule(req, res) {
try { try {
const $ = cheerio.load(req.entry.content.toString("utf8")); const $ = cheerio.load(req.entry.content.toString('utf8'));
$("script[type=module]").each((index, element) => { $('script[type=module]').each((index, element) => {
$(element).html( $(element).html(
rewriteBareModuleIdentifiers($(element).html(), req.packageConfig) rewriteBareModuleIdentifiers($(element).html(), req.packageConfig)
); );
@ -18,11 +18,11 @@ function serveHTMLModule(req, res) {
res res
.set({ .set({
"Content-Length": Buffer.byteLength(code), 'Content-Length': Buffer.byteLength(code),
"Content-Type": getContentTypeHeader(req.entry.contentType), 'Content-Type': getContentTypeHeader(req.entry.contentType),
"Cache-Control": "public, max-age=31536000, immutable", // 1 year 'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
ETag: etag(code), ETag: etag(code),
"Cache-Tag": "file, html-file, html-module" 'Cache-Tag': 'file, html-file, html-module'
}) })
.send(code); .send(code);
} catch (error) { } catch (error) {
@ -38,7 +38,7 @@ function serveHTMLModule(req, res) {
res res
.status(500) .status(500)
.type("text") .type('text')
.send( .send(
`Cannot generate module for ${req.packageSpec}${ `Cannot generate module for ${req.packageSpec}${
req.filename req.filename

View File

@ -1,22 +1,22 @@
const etag = require("etag"); const etag = require('etag');
const getContentTypeHeader = require("../utils/getContentTypeHeader"); const getContentTypeHeader = require('../utils/getContentTypeHeader');
const rewriteBareModuleIdentifiers = require("../utils/rewriteBareModuleIdentifiers"); const rewriteBareModuleIdentifiers = require('../utils/rewriteBareModuleIdentifiers');
function serveJavaScriptModule(req, res) { function serveJavaScriptModule(req, res) {
try { try {
const code = rewriteBareModuleIdentifiers( const code = rewriteBareModuleIdentifiers(
req.entry.content.toString("utf8"), req.entry.content.toString('utf8'),
req.packageConfig req.packageConfig
); );
res res
.set({ .set({
"Content-Length": Buffer.byteLength(code), 'Content-Length': Buffer.byteLength(code),
"Content-Type": getContentTypeHeader(req.entry.contentType), 'Content-Type': getContentTypeHeader(req.entry.contentType),
"Cache-Control": "public, max-age=31536000, immutable", // 1 year 'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
ETag: etag(code), ETag: etag(code),
"Cache-Tag": "file,js-file,js-module" 'Cache-Tag': 'file,js-file,js-module'
}) })
.send(code); .send(code);
} catch (error) { } catch (error) {
@ -32,7 +32,7 @@ function serveJavaScriptModule(req, res) {
res res
.status(500) .status(500)
.type("text") .type('text')
.send( .send(
`Cannot generate module for ${req.packageSpec}${ `Cannot generate module for ${req.packageSpec}${
req.filename req.filename

View File

@ -1,9 +1,9 @@
const path = require("path"); const path = require('path');
const addLeadingSlash = require("../utils/addLeadingSlash"); const addLeadingSlash = require('../utils/addLeadingSlash');
function getMatchingEntries(entry, entries) { function getMatchingEntries(entry, entries) {
const dirname = entry.name || "."; const dirname = entry.name || '.';
return Object.keys(entries) return Object.keys(entries)
.filter(name => entry.name !== name && path.dirname(name) === dirname) .filter(name => entry.name !== name && path.dirname(name) === dirname)
@ -16,12 +16,12 @@ function getMetadata(entry, entries) {
type: entry.type type: entry.type
}; };
if (entry.type === "file") { if (entry.type === 'file') {
metadata.contentType = entry.contentType; metadata.contentType = entry.contentType;
metadata.integrity = entry.integrity; metadata.integrity = entry.integrity;
metadata.lastModified = entry.lastModified; metadata.lastModified = entry.lastModified;
metadata.size = entry.size; metadata.size = entry.size;
} else if (entry.type === "directory") { } else if (entry.type === 'directory') {
metadata.files = getMatchingEntries(entry, entries).map(e => metadata.files = getMatchingEntries(entry, entries).map(e =>
getMetadata(e, entries) getMetadata(e, entries)
); );
@ -35,8 +35,8 @@ function serveMetadata(req, res) {
res res
.set({ .set({
"Cache-Control": "public, max-age=31536000, immutable", // 1 year 'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
"Cache-Tag": "meta" 'Cache-Tag': 'meta'
}) })
.send(metadata); .send(metadata);
} }

View File

@ -1,22 +1,22 @@
const MainPage = require("../client/MainPage"); const MainPage = require('../client/MainPage');
const renderPage = require("../utils/renderPage"); const renderPage = require('../utils/renderPage');
const globalScripts = const globalScripts =
process.env.NODE_ENV === "production" process.env.NODE_ENV === 'production'
? [ ? [
"/react@16.4.1/umd/react.production.min.js", '/react@16.4.1/umd/react.production.min.js',
"/react-dom@16.4.1/umd/react-dom.production.min.js", '/react-dom@16.4.1/umd/react-dom.production.min.js',
"/react-router-dom@4.3.1/umd/react-router-dom.min.js" '/react-router-dom@4.3.1/umd/react-router-dom.min.js'
] ]
: [ : [
"/react@16.4.1/umd/react.development.js", '/react@16.4.1/umd/react.development.js',
"/react-dom@16.4.1/umd/react-dom.development.js", '/react-dom@16.4.1/umd/react-dom.development.js',
"/react-router-dom@4.3.1/umd/react-router-dom.js" '/react-router-dom@4.3.1/umd/react-router-dom.js'
]; ];
function serveRootPage(req, res) { function serveRootPage(req, res) {
const scripts = globalScripts.concat(req.assets.getScripts("main")); const scripts = globalScripts.concat(req.assets.getScripts('main'));
const styles = req.assets.getStyles("main"); const styles = req.assets.getStyles('main');
const html = renderPage(MainPage, { const html = renderPage(MainPage, {
scripts: scripts, scripts: scripts,

View File

@ -1,10 +1,10 @@
const path = require("path"); const path = require('path');
const etag = require("etag"); const etag = require('etag');
const getContentTypeHeader = require("../utils/getContentTypeHeader"); const getContentTypeHeader = require('../utils/getContentTypeHeader');
function serveStaticFile(req, res) { function serveStaticFile(req, res) {
const tags = ["file"]; const tags = ['file'];
const ext = path.extname(req.entry.name).substr(1); const ext = path.extname(req.entry.name).substr(1);
if (ext) { if (ext) {
@ -13,12 +13,12 @@ function serveStaticFile(req, res) {
res res
.set({ .set({
"Content-Length": req.entry.size, 'Content-Length': req.entry.size,
"Content-Type": getContentTypeHeader(req.entry.contentType), 'Content-Type': getContentTypeHeader(req.entry.contentType),
"Cache-Control": "public, max-age=31536000, immutable", // 1 year 'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
"Last-Modified": req.entry.lastModified, 'Last-Modified': req.entry.lastModified,
ETag: etag(req.entry.content), ETag: etag(req.entry.content),
"Cache-Tag": tags.join(",") 'Cache-Tag': tags.join(',')
}) })
.send(req.entry.content); .send(req.entry.content);
} }

View File

@ -1,4 +1,4 @@
const BlacklistAPI = require("../BlacklistAPI"); const BlacklistAPI = require('../BlacklistAPI');
function showBlacklist(req, res) { function showBlacklist(req, res) {
BlacklistAPI.getPackages().then( BlacklistAPI.getPackages().then(
@ -8,7 +8,7 @@ function showBlacklist(req, res) {
error => { error => {
console.error(error); console.error(error);
res.status(500).send({ res.status(500).send({
error: "Unable to fetch blacklist" error: 'Unable to fetch blacklist'
}); });
} }
); );

View File

@ -1,4 +1,4 @@
const secretKey = require("../secretKey"); const secretKey = require('../secretKey');
function showPublicKey(req, res) { function showPublicKey(req, res) {
res.send({ publicKey: secretKey.public }); res.send({ publicKey: secretKey.public });

View File

@ -1,21 +1,21 @@
const subDays = require("date-fns/sub_days"); const subDays = require('date-fns/sub_days');
const startOfDay = require("date-fns/start_of_day"); const startOfDay = require('date-fns/start_of_day');
const startOfSecond = require("date-fns/start_of_second"); const startOfSecond = require('date-fns/start_of_second');
const StatsAPI = require("../StatsAPI"); const StatsAPI = require('../StatsAPI');
function showStats(req, res) { function showStats(req, res) {
let since, until; let since, until;
switch (req.query.period) { switch (req.query.period) {
case "last-day": case 'last-day':
until = startOfDay(new Date()); until = startOfDay(new Date());
since = subDays(until, 1); since = subDays(until, 1);
break; break;
case "last-week": case 'last-week':
until = startOfDay(new Date()); until = startOfDay(new Date());
since = subDays(until, 7); since = subDays(until, 7);
break; break;
case "last-month": case 'last-month':
until = startOfDay(new Date()); until = startOfDay(new Date());
since = subDays(until, 30); since = subDays(until, 30);
break; break;
@ -27,35 +27,35 @@ function showStats(req, res) {
} }
if (isNaN(since.getTime())) { if (isNaN(since.getTime())) {
return res.status(403).send({ error: "?since is not a valid date" }); return res.status(403).send({ error: '?since is not a valid date' });
} }
if (isNaN(until.getTime())) { if (isNaN(until.getTime())) {
return res.status(403).send({ error: "?until is not a valid date" }); return res.status(403).send({ error: '?until is not a valid date' });
} }
if (until <= since) { if (until <= since) {
return res return res
.status(403) .status(403)
.send({ error: "?until date must come after ?since date" }); .send({ error: '?until date must come after ?since date' });
} }
if (until >= new Date()) { if (until >= new Date()) {
return res.status(403).send({ error: "?until must be a date in the past" }); return res.status(403).send({ error: '?until must be a date in the past' });
} }
StatsAPI.getStats(since, until).then( StatsAPI.getStats(since, until).then(
stats => { stats => {
res res
.set({ .set({
"Cache-Control": "public, max-age=60", 'Cache-Control': 'public, max-age=60',
"Cache-Tag": "stats" 'Cache-Tag': 'stats'
}) })
.send(stats); .send(stats);
}, },
error => { error => {
console.error(error); console.error(error);
res.status(500).send({ error: "Unable to fetch stats" }); res.status(500).send({ error: 'Unable to fetch stats' });
} }
); );
} }

View File

@ -1,8 +1,8 @@
const React = require("react"); const React = require('react');
const PropTypes = require("prop-types"); const PropTypes = require('prop-types');
const createHTML = require("./utils/createHTML"); const createHTML = require('./utils/createHTML');
const x = require("./utils/execScript"); const x = require('./utils/execScript');
function MainPage({ title, description, scripts, styles, data, content }) { function MainPage({ title, description, scripts, styles, data, content }) {
return ( return (
@ -17,19 +17,23 @@ function MainPage({ title, description, scripts, styles, data, content }) {
/> />
<meta name="timestamp" content={new Date().toISOString()} /> <meta name="timestamp" content={new Date().toISOString()} />
<link rel="shortcut icon" href="/favicon.ico" /> <link rel="shortcut icon" href="/favicon.ico" />
{styles.map(s => <link key={s} rel="stylesheet" href={s} />)} {styles.map(s => (
<link key={s} rel="stylesheet" href={s} />
))}
{x( {x(
"window.Promise || document.write('\\x3Cscript src=\"/_polyfills/es6-promise.min.js\">\\x3C/script>\\x3Cscript>ES6Promise.polyfill()\\x3C/script>')" 'window.Promise || document.write(\'\\x3Cscript src="/_polyfills/es6-promise.min.js">\\x3C/script>\\x3Cscript>ES6Promise.polyfill()\\x3C/script>\')'
)} )}
{x( {x(
"window.fetch || document.write('\\x3Cscript src=\"/_polyfills/fetch.min.js\">\\x3C/script>')" 'window.fetch || document.write(\'\\x3Cscript src="/_polyfills/fetch.min.js">\\x3C/script>\')'
)} )}
{x(`window.__DATA__ = ${JSON.stringify(data)}`)} {x(`window.__DATA__ = ${JSON.stringify(data)}`)}
<title>{title}</title> <title>{title}</title>
</head> </head>
<body> <body>
<div id="root" dangerouslySetInnerHTML={content} /> <div id="root" dangerouslySetInnerHTML={content} />
{scripts.map(s => <script key={s} src={s} />)} {scripts.map(s => (
<script key={s} src={s} />
))}
</body> </body>
</html> </html>
); );
@ -49,12 +53,12 @@ MainPage.propTypes = {
}; };
MainPage.defaultProps = { MainPage.defaultProps = {
title: "UNPKG", title: 'UNPKG',
description: "The CDN for everything on npm", description: 'The CDN for everything on npm',
scripts: [], scripts: [],
styles: [], styles: [],
data: {}, data: {},
content: createHTML("") content: createHTML('')
}; };
module.exports = MainPage; module.exports = MainPage;

View File

@ -1,10 +1,10 @@
require("./autoIndex.css"); require('./autoIndex.css');
const React = require("react"); const React = require('react');
const ReactDOM = require("react-dom"); const ReactDOM = require('react-dom');
const App = require("./autoIndex/App"); const App = require('./autoIndex/App');
const props = window.__DATA__ || {}; const props = window.__DATA__ || {};
ReactDOM.hydrate(<App {...props} />, document.getElementById("root")); ReactDOM.hydrate(<App {...props} />, document.getElementById('root'));

View File

@ -1,8 +1,8 @@
require("./App.css"); require('./App.css');
const React = require("react"); const React = require('react');
const DirectoryListing = require("./DirectoryListing"); const DirectoryListing = require('./DirectoryListing');
class App extends React.Component { class App extends React.Component {
static defaultProps = { static defaultProps = {
@ -11,8 +11,8 @@ class App extends React.Component {
handleChange = event => { handleChange = event => {
window.location.href = window.location.href.replace( window.location.href = window.location.href.replace(
"@" + this.props.packageVersion, '@' + this.props.packageVersion,
"@" + event.target.value '@' + event.target.value
); );
}; };
@ -26,7 +26,7 @@ class App extends React.Component {
</h1> </h1>
<div className="app-version-selector"> <div className="app-version-selector">
Version:{" "} Version:{' '}
<select <select
id="version" id="version"
defaultValue={this.props.packageVersion} defaultValue={this.props.packageVersion}
@ -59,8 +59,8 @@ class App extends React.Component {
} }
} }
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === 'development') {
const PropTypes = require("prop-types"); const PropTypes = require('prop-types');
const entryType = PropTypes.object; const entryType = PropTypes.object;

View File

@ -1,20 +1,20 @@
require("./DirectoryListing.css"); require('./DirectoryListing.css');
const React = require("react"); const React = require('react');
const formatBytes = require("pretty-bytes"); const formatBytes = require('pretty-bytes');
const sortBy = require("sort-by"); const sortBy = require('sort-by');
function getDirname(name) { function getDirname(name) {
return ( return (
name name
.split("/") .split('/')
.slice(0, -1) .slice(0, -1)
.join("/") || "." .join('/') || '.'
); );
} }
function getMatchingEntries(entry, entries) { function getMatchingEntries(entry, entries) {
const dirname = entry.name || "."; const dirname = entry.name || '.';
return Object.keys(entries) return Object.keys(entries)
.filter(name => entry.name !== name && getDirname(name) === dirname) .filter(name => entry.name !== name && getDirname(name) === dirname)
@ -28,7 +28,7 @@ function getRelativeName(base, name) {
function DirectoryListing({ filename, entry, entries }) { function DirectoryListing({ filename, entry, entries }) {
const rows = []; const rows = [];
if (filename !== "/") { if (filename !== '/') {
rows.push( rows.push(
<tr key=".."> <tr key="..">
<td> <td>
@ -46,11 +46,11 @@ function DirectoryListing({ filename, entry, entries }) {
const matchingEntries = getMatchingEntries(entry, entries); const matchingEntries = getMatchingEntries(entry, entries);
matchingEntries matchingEntries
.filter(({ type }) => type === "directory") .filter(({ type }) => type === 'directory')
.sort(sortBy("name")) .sort(sortBy('name'))
.forEach(({ name }) => { .forEach(({ name }) => {
const relName = getRelativeName(entry.name, name); const relName = getRelativeName(entry.name, name);
const href = relName + "/"; const href = relName + '/';
rows.push( rows.push(
<tr key={name}> <tr key={name}>
@ -67,8 +67,8 @@ function DirectoryListing({ filename, entry, entries }) {
}); });
matchingEntries matchingEntries
.filter(({ type }) => type === "file") .filter(({ type }) => type === 'file')
.sort(sortBy("name")) .sort(sortBy('name'))
.forEach(({ name, size, contentType, lastModified }) => { .forEach(({ name, size, contentType, lastModified }) => {
const relName = getRelativeName(entry.name, name); const relName = getRelativeName(entry.name, name);
@ -100,7 +100,7 @@ function DirectoryListing({ filename, entry, entries }) {
<tbody> <tbody>
{rows.map((row, index) => {rows.map((row, index) =>
React.cloneElement(row, { React.cloneElement(row, {
className: index % 2 ? "odd" : "even" className: index % 2 ? 'odd' : 'even'
}) })
)} )}
</tbody> </tbody>
@ -109,8 +109,8 @@ function DirectoryListing({ filename, entry, entries }) {
); );
} }
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === 'development') {
const PropTypes = require("prop-types"); const PropTypes = require('prop-types');
const entryType = PropTypes.shape({ const entryType = PropTypes.shape({
name: PropTypes.string.isRequired name: PropTypes.string.isRequired

View File

@ -1,8 +1,8 @@
require("./main.css"); require('./main.css');
const React = require("react"); const React = require('react');
const ReactDOM = require("react-dom"); const ReactDOM = require('react-dom');
const App = require("./main/App"); const App = require('./main/App');
ReactDOM.render(<App />, document.getElementById("root")); ReactDOM.render(<App />, document.getElementById('root'));

View File

@ -1,9 +1,9 @@
require("./About.css"); require('./About.css');
const React = require("react"); const React = require('react');
const h = require("../utils/createHTML"); const h = require('../utils/createHTML');
const markup = require("./About.md"); const markup = require('./About.md');
function About() { function About() {
return <div className="wrapper" dangerouslySetInnerHTML={h(markup)} />; return <div className="wrapper" dangerouslySetInnerHTML={h(markup)} />;

View File

@ -1,7 +1,7 @@
const React = require("react"); const React = require('react');
const { HashRouter } = require("react-router-dom"); const { HashRouter } = require('react-router-dom');
const Layout = require("./Layout"); const Layout = require('./Layout');
function App() { function App() {
return ( return (

View File

@ -1,9 +1,9 @@
require("./Home.css"); require('./Home.css');
const React = require("react"); const React = require('react');
const h = require("../utils/createHTML"); const h = require('../utils/createHTML');
const markup = require("./Home.md"); const markup = require('./Home.md');
function Home() { function Home() {
return <div className="wrapper" dangerouslySetInnerHTML={h(markup)} />; return <div className="wrapper" dangerouslySetInnerHTML={h(markup)} />;

View File

@ -1,14 +1,14 @@
require("./Layout.css"); require('./Layout.css');
const React = require("react"); const React = require('react');
const PropTypes = require("prop-types"); const PropTypes = require('prop-types');
const { Switch, Route, Link, withRouter } = require("react-router-dom"); const { Switch, Route, Link, withRouter } = require('react-router-dom');
const { Motion, spring } = require("react-motion"); const { Motion, spring } = require('react-motion');
const WindowSize = require("./WindowSize"); const WindowSize = require('./WindowSize');
const About = require("./About"); const About = require('./About');
const Stats = require("./Stats"); const Stats = require('./Stats');
const Home = require("./Home"); const Home = require('./Home');
class Layout extends React.Component { class Layout extends React.Component {
static propTypes = { static propTypes = {
@ -26,18 +26,18 @@ class Layout extends React.Component {
adjustUnderline = (useSpring = false) => { adjustUnderline = (useSpring = false) => {
let itemIndex; let itemIndex;
switch (this.props.location.pathname) { switch (this.props.location.pathname) {
case "/stats": case '/stats':
itemIndex = 1; itemIndex = 1;
break; break;
case "/about": case '/about':
itemIndex = 2; itemIndex = 2;
break; break;
case "/": case '/':
default: default:
itemIndex = 0; itemIndex = 0;
} }
const itemNodes = this.listNode.querySelectorAll("li"); const itemNodes = this.listNode.querySelectorAll('li');
const currentNode = itemNodes[itemIndex]; const currentNode = itemNodes[itemIndex];
this.setState({ this.setState({
@ -50,7 +50,7 @@ class Layout extends React.Component {
componentDidMount() { componentDidMount() {
this.adjustUnderline(); this.adjustUnderline();
fetch("/api/stats?period=last-month") fetch('/api/stats?period=last-month')
.then(res => res.json()) .then(res => res.json())
.then(stats => this.setState({ stats })); .then(stats => this.setState({ stats }));

View File

@ -1,14 +1,14 @@
require("./Stats.css"); require('./Stats.css');
const React = require("react"); const React = require('react');
const PropTypes = require("prop-types"); const PropTypes = require('prop-types');
const formatBytes = require("pretty-bytes"); const formatBytes = require('pretty-bytes');
const formatDate = require("date-fns/format"); const formatDate = require('date-fns/format');
const parseDate = require("date-fns/parse"); const parseDate = require('date-fns/parse');
const { continents, countries } = require("countries-list"); const { continents, countries } = require('countries-list');
const formatNumber = require("../utils/formatNumber"); const formatNumber = require('../utils/formatNumber');
const formatPercent = require("../utils/formatPercent"); const formatPercent = require('../utils/formatPercent');
function getCountriesByContinent(continent) { function getCountriesByContinent(continent) {
return Object.keys(countries).filter( return Object.keys(countries).filter(
@ -68,15 +68,15 @@ class Stats extends React.Component {
</a> </a>
</td> </td>
<td> <td>
{formatNumber(requests)} ({formatPercent( {formatNumber(requests)} (
requests / totals.requests.all {formatPercent(requests / totals.requests.all)}
)}%) %)
</td> </td>
{bandwidth ? ( {bandwidth ? (
<td> <td>
{formatBytes(bandwidth)} ({formatPercent( {formatBytes(bandwidth)} (
bandwidth / totals.bandwidth.all {formatPercent(bandwidth / totals.bandwidth.all)}
)}%) %)
</td> </td>
) : ( ) : (
<td>-</td> <td>-</td>
@ -120,16 +120,16 @@ class Stats extends React.Component {
</td> </td>
<td> <td>
<strong> <strong>
{formatNumber(continentData.requests)} ({formatPercent( {formatNumber(continentData.requests)} (
continentData.requests / totals.requests.all {formatPercent(continentData.requests / totals.requests.all)}
)}%) %)
</strong> </strong>
</td> </td>
<td> <td>
<strong> <strong>
{formatBytes(continentData.bandwidth)} ({formatPercent( {formatBytes(continentData.bandwidth)} (
continentData.bandwidth / totals.bandwidth.all {formatPercent(continentData.bandwidth / totals.bandwidth.all)}
)}%) %)
</strong> </strong>
</td> </td>
</tr> </tr>
@ -148,14 +148,14 @@ class Stats extends React.Component {
<tr key={continent + country} className="country-row"> <tr key={continent + country} className="country-row">
<td className="country-name">{countries[country].name}</td> <td className="country-name">{countries[country].name}</td>
<td> <td>
{formatNumber(countryRequests)} ({formatPercent( {formatNumber(countryRequests)} (
countryRequests / totals.requests.all {formatPercent(countryRequests / totals.requests.all)}
)}%) %)
</td> </td>
<td> <td>
{formatBytes(countryBandwidth)} ({formatPercent( {formatBytes(countryBandwidth)} (
countryBandwidth / totals.bandwidth.all {formatPercent(countryBandwidth / totals.bandwidth.all)}
)}%) %)
</td> </td>
</tr> </tr>
); );
@ -176,9 +176,9 @@ class Stats extends React.Component {
<tr key={protocol}> <tr key={protocol}>
<td>{protocol}</td> <td>{protocol}</td>
<td> <td>
{formatNumber(requests)} ({formatPercent( {formatNumber(requests)} (
requests / sumValues(totals.requests.protocol) {formatPercent(requests / sumValues(totals.requests.protocol))}
)}%) %)
</td> </td>
</tr> </tr>
); );
@ -187,29 +187,29 @@ class Stats extends React.Component {
return ( return (
<div className="wrapper"> <div className="wrapper">
<p> <p>
From <strong>{formatDate(since, "MMM D")}</strong> to{" "} From <strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, "MMM D")}</strong> unpkg served{" "} <strong>{formatDate(until, 'MMM D')}</strong> unpkg served{' '}
<strong>{formatNumber(totals.requests.all)}</strong> requests and a <strong>{formatNumber(totals.requests.all)}</strong> requests and a
total of <strong>{formatBytes(totals.bandwidth.all)}</strong> of data total of <strong>{formatBytes(totals.bandwidth.all)}</strong> of data
to <strong>{formatNumber(totals.uniques.all)}</strong> unique to <strong>{formatNumber(totals.uniques.all)}</strong> unique
visitors,{" "} visitors,{' '}
<strong> <strong>
{formatPercent(totals.requests.cached / totals.requests.all, 0)}% {formatPercent(totals.requests.cached / totals.requests.all, 0)}%
</strong>{" "} </strong>{' '}
of which were served from the cache. of which were served from the cache.
</p> </p>
<h3>Packages</h3> <h3>Packages</h3>
<p> <p>
The table below shows the most popular packages served by unpkg from{" "} The table below shows the most popular packages served by unpkg from{' '}
<strong>{formatDate(since, "MMM D")}</strong> to{" "} <strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, "MMM D")}</strong>. Only the top{" "} <strong>{formatDate(until, 'MMM D')}</strong>. Only the top{' '}
{Object.keys(totals.requests.package).length} packages are shown. {Object.keys(totals.requests.package).length} packages are shown.
</p> </p>
<p className="table-filter"> <p className="table-filter">
Include only packages that received at least{" "} Include only packages that received at least{' '}
<select <select
value={this.state.minPackageRequests} value={this.state.minPackageRequests}
onChange={event => onChange={event =>
@ -224,11 +224,11 @@ class Stats extends React.Component {
<option value="100000">100,000</option> <option value="100000">100,000</option>
<option value="1000000">1,000,000</option> <option value="1000000">1,000,000</option>
<option value="10000000">10,000,000</option> <option value="10000000">10,000,000</option>
</select>{" "} </select>{' '}
requests. requests.
</p> </p>
<table cellSpacing="0" cellPadding="0" style={{ width: "100%" }}> <table cellSpacing="0" cellPadding="0" style={{ width: '100%' }}>
<thead> <thead>
<tr> <tr>
<th> <th>
@ -248,13 +248,13 @@ class Stats extends React.Component {
<h3>Regions</h3> <h3>Regions</h3>
<p> <p>
The table below breaks down requests to unpkg from{" "} The table below breaks down requests to unpkg from{' '}
<strong>{formatDate(since, "MMM D")}</strong> to{" "} <strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, "MMM D")}</strong> by geographic region. <strong>{formatDate(until, 'MMM D')}</strong> by geographic region.
</p> </p>
<p className="table-filter"> <p className="table-filter">
Include only countries that made at least{" "} Include only countries that made at least{' '}
<select <select
value={this.state.minCountryRequests} value={this.state.minCountryRequests}
onChange={event => onChange={event =>
@ -268,14 +268,14 @@ class Stats extends React.Component {
<option value="1000000">1,000,000</option> <option value="1000000">1,000,000</option>
<option value="10000000">10,000,000</option> <option value="10000000">10,000,000</option>
<option value="100000000">100,000,000</option> <option value="100000000">100,000,000</option>
</select>{" "} </select>{' '}
requests. requests.
</p> </p>
<table <table
cellSpacing="0" cellSpacing="0"
cellPadding="0" cellPadding="0"
style={{ width: "100%" }} style={{ width: '100%' }}
className="regions-table" className="regions-table"
> >
<thead> <thead>
@ -297,12 +297,12 @@ class Stats extends React.Component {
<h3>Protocols</h3> <h3>Protocols</h3>
<p> <p>
The table below breaks down requests to unpkg from{" "} The table below breaks down requests to unpkg from{' '}
<strong>{formatDate(since, "MMM D")}</strong> to{" "} <strong>{formatDate(since, 'MMM D')}</strong> to{' '}
<strong>{formatDate(until, "MMM D")}</strong> by HTTP protocol. <strong>{formatDate(until, 'MMM D')}</strong> by HTTP protocol.
</p> </p>
<table cellSpacing="0" cellPadding="0" style={{ width: "100%" }}> <table cellSpacing="0" cellPadding="0" style={{ width: '100%' }}>
<thead> <thead>
<tr> <tr>
<th> <th>

View File

@ -1,10 +1,10 @@
const React = require("react"); const React = require('react');
const PropTypes = require("prop-types"); const PropTypes = require('prop-types');
const addEvent = require("../utils/addEvent"); const addEvent = require('../utils/addEvent');
const removeEvent = require("../utils/removeEvent"); const removeEvent = require('../utils/removeEvent');
const resizeEvent = "resize"; const resizeEvent = 'resize';
class WindowSize extends React.Component { class WindowSize extends React.Component {
static propTypes = { static propTypes = {

View File

@ -2,7 +2,7 @@ function addEvent(node, type, handler) {
if (node.addEventListener) { if (node.addEventListener) {
node.addEventListener(type, handler, false); node.addEventListener(type, handler, false);
} else if (node.attachEvent) { } else if (node.attachEvent) {
node.attachEvent("on" + type, handler); node.attachEvent('on' + type, handler);
} }
} }

View File

@ -1,6 +1,6 @@
const React = require("react"); const React = require('react');
const h = require("./createHTML"); const h = require('./createHTML');
function execScript(code) { function execScript(code) {
return <script dangerouslySetInnerHTML={h(code)} />; return <script dangerouslySetInnerHTML={h(code)} />;

View File

@ -1,12 +1,12 @@
function formatNumber(n) { function formatNumber(n) {
const digits = String(n).split(""); const digits = String(n).split('');
const groups = []; const groups = [];
while (digits.length) { while (digits.length) {
groups.unshift(digits.splice(-3).join("")); groups.unshift(digits.splice(-3).join(''));
} }
return groups.join(","); return groups.join(',');
} }
module.exports = formatNumber; module.exports = formatNumber;

View File

@ -1,5 +1,5 @@
function parseNumber(s) { function parseNumber(s) {
return parseInt(s.replace(/,/g, ""), 10) || 0; return parseInt(s.replace(/,/g, ''), 10) || 0;
} }
module.exports = parseNumber; module.exports = parseNumber;

View File

@ -2,7 +2,7 @@ function removeEvent(node, type, handler) {
if (node.removeEventListener) { if (node.removeEventListener) {
node.removeEventListener(type, handler, false); node.removeEventListener(type, handler, false);
} else if (node.detachEvent) { } else if (node.detachEvent) {
node.detachEvent("on" + type, handler); node.detachEvent('on' + type, handler);
} }
} }

View File

@ -1,9 +1,9 @@
// Use babel to compile JSX on the fly. // Use babel to compile JSX on the fly.
require("@babel/register")({ require('@babel/register')({
only: [/modules\/client/] only: [/modules\/client/]
}); });
// Ignore require("*.css") calls. // Ignore require("*.css") calls.
require.extensions[".css"] = function() { require.extensions['.css'] = function() {
return {}; return {};
}; };

View File

@ -1,11 +1,11 @@
const webpack = require("webpack"); const webpack = require('webpack');
/** /**
* Returns a modified copy of the given webpackEntry object with * Returns a modified copy of the given webpackEntry object with
* the moduleId in front of all other assets. * the moduleId in front of all other assets.
*/ */
function prependModuleId(webpackEntry, moduleId) { function prependModuleId(webpackEntry, moduleId) {
if (typeof webpackEntry === "string") { if (typeof webpackEntry === 'string') {
return [moduleId, webpackEntry]; return [moduleId, webpackEntry];
} }
@ -13,7 +13,7 @@ function prependModuleId(webpackEntry, moduleId) {
return [moduleId, ...webpackEntry]; return [moduleId, ...webpackEntry];
} }
if (webpackEntry && typeof webpackEntry === "object") { if (webpackEntry && typeof webpackEntry === 'object') {
const entry = { ...webpackEntry }; const entry = { ...webpackEntry };
for (const chunkName in entry) { for (const chunkName in entry) {
@ -25,7 +25,7 @@ function prependModuleId(webpackEntry, moduleId) {
return entry; return entry;
} }
throw new Error("Invalid webpack entry object"); throw new Error('Invalid webpack entry object');
} }
/** /**

View File

@ -1,11 +1,11 @@
const express = require("express"); const express = require('express');
const morgan = require("morgan"); const morgan = require('morgan');
const WebpackDevServer = require("webpack-dev-server"); const WebpackDevServer = require('webpack-dev-server');
const devErrorHandler = require("errorhandler"); const devErrorHandler = require('errorhandler');
const devAssets = require("./middleware/devAssets"); const devAssets = require('./middleware/devAssets');
const createDevCompiler = require("./createDevCompiler"); const createDevCompiler = require('./createDevCompiler');
const createRouter = require("./createRouter"); const createRouter = require('./createRouter');
function createDevServer(publicDir, webpackConfig, devOrigin) { function createDevServer(publicDir, webpackConfig, devOrigin) {
const compiler = createDevCompiler( const compiler = createDevCompiler(
@ -33,8 +33,8 @@ function createDevServer(publicDir, webpackConfig, devOrigin) {
disableHostCheck: true, disableHostCheck: true,
before(app) { before(app) {
// This runs before webpack-dev-middleware // This runs before webpack-dev-middleware
app.disable("x-powered-by"); app.disable('x-powered-by');
app.use(morgan("dev")); app.use(morgan('dev'));
} }
}); });

View File

@ -1,6 +1,6 @@
const express = require("express"); const express = require('express');
const bodyParser = require("body-parser"); const bodyParser = require('body-parser');
const cors = require("cors"); const cors = require('cors');
function route(setup) { function route(setup) {
const app = express.Router(); const app = express.Router();
@ -11,92 +11,92 @@ function route(setup) {
function createRouter() { function createRouter() {
const app = express.Router(); const app = express.Router();
app.get("/", require("./actions/serveRootPage")); app.get('/', require('./actions/serveRootPage'));
app.use(cors()); app.use(cors());
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(require("./middleware/userToken")); app.use(require('./middleware/userToken'));
app.use( app.use(
"/api", '/api',
route(app => { route(app => {
app.get("/publicKey", require("./actions/showPublicKey")); app.get('/publicKey', require('./actions/showPublicKey'));
app.post("/auth", require("./actions/createAuth")); app.post('/auth', require('./actions/createAuth'));
app.get("/auth", require("./actions/showAuth")); app.get('/auth', require('./actions/showAuth'));
app.post( app.post(
"/blacklist", '/blacklist',
require("./middleware/requireAuth")("blacklist.add"), require('./middleware/requireAuth')('blacklist.add'),
require("./actions/addToBlacklist") require('./actions/addToBlacklist')
); );
app.get( app.get(
"/blacklist", '/blacklist',
require("./middleware/requireAuth")("blacklist.read"), require('./middleware/requireAuth')('blacklist.read'),
require("./actions/showBlacklist") require('./actions/showBlacklist')
); );
app.delete( app.delete(
"/blacklist", '/blacklist',
require("./middleware/requireAuth")("blacklist.remove"), require('./middleware/requireAuth')('blacklist.remove'),
require("./actions/removeFromBlacklist") require('./actions/removeFromBlacklist')
); );
if (process.env.NODE_ENV !== "test") { if (process.env.NODE_ENV !== 'test') {
app.get("/stats", require("./actions/showStats")); app.get('/stats', require('./actions/showStats'));
} }
}) })
); );
// TODO: Remove // TODO: Remove
app.get("/_publicKey", require("./actions/showPublicKey")); app.get('/_publicKey', require('./actions/showPublicKey'));
// TODO: Remove // TODO: Remove
app.use( app.use(
"/_auth", '/_auth',
route(app => { route(app => {
app.post("/", require("./actions/createAuth")); app.post('/', require('./actions/createAuth'));
app.get("/", require("./actions/showAuth")); app.get('/', require('./actions/showAuth'));
}) })
); );
// TODO: Remove // TODO: Remove
app.use( app.use(
"/_blacklist", '/_blacklist',
route(app => { route(app => {
app.post( app.post(
"/", '/',
require("./middleware/requireAuth")("blacklist.add"), require('./middleware/requireAuth')('blacklist.add'),
require("./actions/addToBlacklist") require('./actions/addToBlacklist')
); );
app.get( app.get(
"/", '/',
require("./middleware/requireAuth")("blacklist.read"), require('./middleware/requireAuth')('blacklist.read'),
require("./actions/showBlacklist") require('./actions/showBlacklist')
); );
app.delete( app.delete(
"*", '*',
require("./middleware/requireAuth")("blacklist.remove"), require('./middleware/requireAuth')('blacklist.remove'),
require("./middleware/validatePackageURL"), require('./middleware/validatePackageURL'),
require("./actions/removeFromBlacklist") require('./actions/removeFromBlacklist')
); );
}) })
); );
// TODO: Remove // TODO: Remove
if (process.env.NODE_ENV !== "test") { if (process.env.NODE_ENV !== 'test') {
app.get("/_stats", require("./actions/showStats")); app.get('/_stats', require('./actions/showStats'));
} }
app.get( app.get(
"*", '*',
require("./middleware/redirectLegacyURLs"), require('./middleware/redirectLegacyURLs'),
require("./middleware/validatePackageURL"), require('./middleware/validatePackageURL'),
require("./middleware/validatePackageName"), require('./middleware/validatePackageName'),
require("./middleware/validateQuery"), require('./middleware/validateQuery'),
require("./middleware/checkBlacklist"), require('./middleware/checkBlacklist'),
require("./middleware/fetchPackage"), require('./middleware/fetchPackage'),
require("./middleware/findFile"), require('./middleware/findFile'),
require("./actions/serveFile") require('./actions/serveFile')
); );
return app; return app;

View File

@ -1,14 +1,14 @@
const http = require("http"); const http = require('http');
const express = require("express"); const express = require('express');
const morgan = require("morgan"); const morgan = require('morgan');
const raven = require("raven"); const raven = require('raven');
const staticAssets = require("./middleware/staticAssets"); const staticAssets = require('./middleware/staticAssets');
const createRouter = require("./createRouter"); const createRouter = require('./createRouter');
morgan.token("fwd", req => { morgan.token('fwd', req => {
const fwd = req.get("x-forwarded-for"); const fwd = req.get('x-forwarded-for');
return fwd ? fwd.replace(/\s/g, "") : "-"; return fwd ? fwd.replace(/\s/g, '') : '-';
}); });
if (process.env.SENTRY_DSN) { if (process.env.SENTRY_DSN) {
@ -34,13 +34,13 @@ if (process.env.SENTRY_DSN) {
function createServer(publicDir, statsFile) { function createServer(publicDir, statsFile) {
const app = express(); const app = express();
app.disable("x-powered-by"); app.disable('x-powered-by');
if (process.env.SENTRY_DSN) { if (process.env.SENTRY_DSN) {
app.use(raven.requestHandler()); app.use(raven.requestHandler());
} }
if (process.env.NODE_ENV !== "test") { if (process.env.NODE_ENV !== 'test') {
app.use( app.use(
morgan( morgan(
// Modified version of Heroku's log format // Modified version of Heroku's log format
@ -53,7 +53,7 @@ function createServer(publicDir, statsFile) {
// app.use(errorHandler); // app.use(errorHandler);
if (publicDir) { if (publicDir) {
app.use(express.static(publicDir, { maxAge: "365d" })); app.use(express.static(publicDir, { maxAge: '365d' }));
} }
if (statsFile) { if (statsFile) {
@ -76,14 +76,14 @@ function createServer(publicDir, statsFile) {
socket.end( socket.end(
[ [
"HTTP/1.1 503 Service Unavailable", 'HTTP/1.1 503 Service Unavailable',
"Date: " + new Date().toGMTString(), 'Date: ' + new Date().toGMTString(),
"Content-Length: " + Buffer.byteLength(message), 'Content-Length: ' + Buffer.byteLength(message),
"Content-Type: text/plain", 'Content-Type: text/plain',
"Connection: close", 'Connection: close',
"", '',
message message
].join("\r\n") ].join('\r\n')
); );
}); });

View File

@ -1,20 +1,20 @@
const parseURL = require("url").parse; const parseURL = require('url').parse;
const startOfDay = require("date-fns/start_of_day"); const startOfDay = require('date-fns/start_of_day');
const addDays = require("date-fns/add_days"); const addDays = require('date-fns/add_days');
const db = require("./utils/data"); const db = require('./utils/data');
const isValidPackageName = require("./utils/isValidPackageName"); const isValidPackageName = require('./utils/isValidPackageName');
const parsePackageURL = require("./utils/parsePackageURL"); const parsePackageURL = require('./utils/parsePackageURL');
const logging = require("./utils/logging"); const logging = require('./utils/logging');
const CloudflareAPI = require("./CloudflareAPI"); const CloudflareAPI = require('./CloudflareAPI');
const StatsAPI = require("./StatsAPI"); const StatsAPI = require('./StatsAPI');
/** /**
* Domains we want to analyze. * Domains we want to analyze.
*/ */
const domainNames = [ const domainNames = [
"unpkg.com" 'unpkg.com'
//"npmcdn.com" // We don't have log data on npmcdn.com yet :/ //"npmcdn.com" // We don't have log data on npmcdn.com yet :/
]; ];
@ -25,7 +25,7 @@ function getSeconds(date) {
} }
function stringifySeconds(seconds) { function stringifySeconds(seconds) {
return new Date(seconds * 1000).toISOString().replace(/\.0+Z$/, "Z"); return new Date(seconds * 1000).toISOString().replace(/\.0+Z$/, 'Z');
} }
function toSeconds(ms) { function toSeconds(ms) {
@ -45,8 +45,8 @@ function computeCounters(stream) {
} }
stream stream
.on("error", reject) .on('error', reject)
.on("data", entry => { .on('data', entry => {
totalEntries += 1; totalEntries += 1;
const date = new Date(Math.round(entry.EdgeStartTimestamp / 1000000)); const date = new Date(Math.round(entry.EdgeStartTimestamp / 1000000));
@ -105,7 +105,7 @@ function computeCounters(stream) {
); );
} }
}) })
.on("end", () => { .on('end', () => {
resolve({ counters, expireat, totalEntries }); resolve({ counters, expireat, totalEntries });
}); });
}); });
@ -137,12 +137,12 @@ function ingestLogsForZone(zone, startDate, endDate) {
const startFetchTime = Date.now(); const startFetchTime = Date.now();
const fields = [ const fields = [
"EdgeStartTimestamp", 'EdgeStartTimestamp',
"EdgeResponseStatus", 'EdgeResponseStatus',
"EdgeResponseBytes", 'EdgeResponseBytes',
"ClientRequestProtocol", 'ClientRequestProtocol',
"ClientRequestURI", 'ClientRequestURI',
"ClientRequestReferer" 'ClientRequestReferer'
]; ];
return CloudflareAPI.getLogs( return CloudflareAPI.getLogs(
@ -154,7 +154,7 @@ function ingestLogsForZone(zone, startDate, endDate) {
const endFetchTime = Date.now(); const endFetchTime = Date.now();
logging.info( logging.info(
"Fetched logs for %s from %s to %s (%dms)", 'Fetched logs for %s from %s to %s (%dms)',
zone.name, zone.name,
stringifySeconds(startSeconds), stringifySeconds(startSeconds),
stringifySeconds(endSeconds), stringifySeconds(endSeconds),
@ -167,7 +167,7 @@ function ingestLogsForZone(zone, startDate, endDate) {
const endProcessTime = Date.now(); const endProcessTime = Date.now();
logging.info( logging.info(
"Processed %d log entries for %s (%dms)", 'Processed %d log entries for %s (%dms)',
totalEntries, totalEntries,
zone.name, zone.name,
endProcessTime - startProcessTime endProcessTime - startProcessTime

View File

@ -1,7 +1,7 @@
const addMinutes = require("date-fns/add_minutes"); const addMinutes = require('date-fns/add_minutes');
const startOfMinute = require("date-fns/start_of_minute"); const startOfMinute = require('date-fns/start_of_minute');
const ingestLogs = require("./ingestLogs"); const ingestLogs = require('./ingestLogs');
const oneSecond = 1000; const oneSecond = 1000;
const oneMinute = oneSecond * 60; const oneMinute = oneSecond * 60;
@ -26,18 +26,18 @@ function work() {
} }
function shutdown() { function shutdown() {
console.log("Shutting down..."); console.log('Shutting down...');
clearInterval(timer); clearInterval(timer);
currentWorkload.then(() => { currentWorkload.then(() => {
console.log("Goodbye!"); console.log('Goodbye!');
process.exit(); process.exit();
}); });
} }
work(); work();
process.on("SIGINT", shutdown).on("SIGTERM", shutdown); process.on('SIGINT', shutdown).on('SIGTERM', shutdown);
timer = setInterval(work, oneMinute); timer = setInterval(work, oneMinute);

View File

@ -1,4 +1,4 @@
const BlacklistAPI = require("../BlacklistAPI"); const BlacklistAPI = require('../BlacklistAPI');
function checkBlacklist(req, res, next) { function checkBlacklist(req, res, next) {
BlacklistAPI.includesPackage(req.packageName).then( BlacklistAPI.includesPackage(req.packageName).then(
@ -7,14 +7,14 @@ function checkBlacklist(req, res, next) {
if (blacklisted) { if (blacklisted) {
res res
.status(403) .status(403)
.type("text") .type('text')
.send(`Package "${req.packageName}" is blacklisted`); .send(`Package "${req.packageName}" is blacklisted`);
} else { } else {
next(); next();
} }
}, },
error => { error => {
console.error("Unable to fetch the blacklist: %s", error); console.error('Unable to fetch the blacklist: %s', error);
// Continue anyway. // Continue anyway.
next(); next();

View File

@ -1,6 +1,6 @@
const invariant = require("invariant"); const invariant = require('invariant');
const createAssets = require("./utils/createAssets"); const createAssets = require('./utils/createAssets');
/** /**
* An express middleware that sets req.assets from the * An express middleware that sets req.assets from the
@ -9,15 +9,15 @@ const createAssets = require("./utils/createAssets");
*/ */
function devAssets(webpackCompiler) { function devAssets(webpackCompiler) {
let assets; let assets;
webpackCompiler.plugin("done", stats => { webpackCompiler.plugin('done', stats => {
assets = createAssets(stats.toJson()); assets = createAssets(stats.toJson());
}); });
return (req, res, next) => { return (req, res, next) => {
invariant( invariant(
assets != null, assets != null,
"devAssets middleware needs a running compiler; " + 'devAssets middleware needs a running compiler; ' +
"use webpack-dev-middleware in front of devAssets" 'use webpack-dev-middleware in front of devAssets'
); );
req.assets = assets; req.assets = assets;

View File

@ -1,19 +1,19 @@
const semver = require("semver"); const semver = require('semver');
const addLeadingSlash = require("../utils/addLeadingSlash"); const addLeadingSlash = require('../utils/addLeadingSlash');
const createPackageURL = require("../utils/createPackageURL"); const createPackageURL = require('../utils/createPackageURL');
const createSearch = require("../utils/createSearch"); const createSearch = require('../utils/createSearch');
const getNpmPackageInfo = require("../utils/getNpmPackageInfo"); const getNpmPackageInfo = require('../utils/getNpmPackageInfo');
const incrementCounter = require("../utils/incrementCounter"); const incrementCounter = require('../utils/incrementCounter');
function tagRedirect(req, res) { function tagRedirect(req, res) {
const version = req.packageInfo["dist-tags"][req.packageVersion]; const version = req.packageInfo['dist-tags'][req.packageVersion];
// Cache tag redirects for 1 minute. // Cache tag redirects for 1 minute.
res res
.set({ .set({
"Cache-Control": "public, max-age=60", 'Cache-Control': 'public, max-age=60',
"Cache-Tag": "redirect,tag-redirect" 'Cache-Tag': 'redirect,tag-redirect'
}) })
.redirect( .redirect(
302, 302,
@ -31,8 +31,8 @@ function semverRedirect(req, res) {
// Cache semver redirects for 1 minute. // Cache semver redirects for 1 minute.
res res
.set({ .set({
"Cache-Control": "public, max-age=60", 'Cache-Control': 'public, max-age=60',
"Cache-Tag": "redirect,semver-redirect" 'Cache-Tag': 'redirect,semver-redirect'
}) })
.redirect( .redirect(
302, 302,
@ -41,7 +41,7 @@ function semverRedirect(req, res) {
} else { } else {
res res
.status(404) .status(404)
.type("text") .type('text')
.send(`Cannot find package ${req.packageSpec}`); .send(`Cannot find package ${req.packageSpec}`);
} }
} }
@ -52,12 +52,12 @@ function filenameRedirect(req, res) {
// See https://github.com/rollup/rollup/wiki/pkg.module // See https://github.com/rollup/rollup/wiki/pkg.module
filename = filename =
req.packageConfig.module || req.packageConfig.module ||
req.packageConfig["jsnext:main"] || req.packageConfig['jsnext:main'] ||
"/index.js"; '/index.js';
} else if ( } else if (
req.query.main && req.query.main &&
req.packageConfig[req.query.main] && req.packageConfig[req.query.main] &&
typeof req.packageConfig[req.query.main] === "string" typeof req.packageConfig[req.query.main] === 'string'
) { ) {
// Deprecated, see #63 // Deprecated, see #63
filename = req.packageConfig[req.query.main]; filename = req.packageConfig[req.query.main];
@ -65,35 +65,35 @@ function filenameRedirect(req, res) {
// Count which packages are using this so we can warn them when we // Count which packages are using this so we can warn them when we
// remove this functionality. // remove this functionality.
incrementCounter( incrementCounter(
"package-json-custom-main", 'package-json-custom-main',
req.packageSpec + "?main=" + req.query.main, req.packageSpec + '?main=' + req.query.main,
1 1
); );
} else if ( } else if (
req.packageConfig.unpkg && req.packageConfig.unpkg &&
typeof req.packageConfig.unpkg === "string" typeof req.packageConfig.unpkg === 'string'
) { ) {
filename = req.packageConfig.unpkg; filename = req.packageConfig.unpkg;
} else if ( } else if (
req.packageConfig.browser && req.packageConfig.browser &&
typeof req.packageConfig.browser === "string" typeof req.packageConfig.browser === 'string'
) { ) {
// Deprecated, see #63 // Deprecated, see #63
filename = req.packageConfig.browser; filename = req.packageConfig.browser;
// Count which packages are using this so we can warn them when we // Count which packages are using this so we can warn them when we
// remove this functionality. // remove this functionality.
incrementCounter("package-json-browser-fallback", req.packageSpec, 1); incrementCounter('package-json-browser-fallback', req.packageSpec, 1);
} else { } else {
filename = req.packageConfig.main || "/index.js"; filename = req.packageConfig.main || '/index.js';
} }
// Redirect to the exact filename so relative imports // Redirect to the exact filename so relative imports
// and URLs resolve correctly. // and URLs resolve correctly.
res res
.set({ .set({
"Cache-Control": "public, max-age=31536000, immutable", // 1 year 'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
"Cache-Tag": "redirect, filename-redirect" 'Cache-Tag': 'redirect, filename-redirect'
}) })
.redirect( .redirect(
302, 302,
@ -117,7 +117,7 @@ function fetchPackage(req, res, next) {
if (packageInfo == null || packageInfo.versions == null) { if (packageInfo == null || packageInfo.versions == null) {
return res return res
.status(404) .status(404)
.type("text") .type('text')
.send(`Cannot find package "${req.packageName}"`); .send(`Cannot find package "${req.packageName}"`);
} }
@ -126,7 +126,7 @@ function fetchPackage(req, res, next) {
if (!req.packageConfig) { if (!req.packageConfig) {
// Redirect to a fully-resolved version. // Redirect to a fully-resolved version.
if (req.packageVersion in req.packageInfo["dist-tags"]) { if (req.packageVersion in req.packageInfo['dist-tags']) {
return tagRedirect(req, res); return tagRedirect(req, res);
} else { } else {
return semverRedirect(req, res); return semverRedirect(req, res);
@ -144,7 +144,7 @@ function fetchPackage(req, res, next) {
return res return res
.status(500) .status(500)
.type("text") .type('text')
.send(`Cannot get info for package "${req.packageName}"`); .send(`Cannot get info for package "${req.packageName}"`);
} }
); );

View File

@ -1,19 +1,19 @@
const path = require("path"); const path = require('path');
const addLeadingSlash = require("../utils/addLeadingSlash"); const addLeadingSlash = require('../utils/addLeadingSlash');
const createPackageURL = require("../utils/createPackageURL"); const createPackageURL = require('../utils/createPackageURL');
const createSearch = require("../utils/createSearch"); const createSearch = require('../utils/createSearch');
const fetchNpmPackage = require("../utils/fetchNpmPackage"); const fetchNpmPackage = require('../utils/fetchNpmPackage');
const getIntegrity = require("../utils/getIntegrity"); const getIntegrity = require('../utils/getIntegrity');
const getContentType = require("../utils/getContentType"); const getContentType = require('../utils/getContentType');
function indexRedirect(req, res, entry) { function indexRedirect(req, res, entry) {
// Redirect to the index file so relative imports // Redirect to the index file so relative imports
// resolve correctly. // resolve correctly.
res res
.set({ .set({
"Cache-Control": "public, max-age=31536000, immutable", // 1 year 'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
"Cache-Tag": "redirect, index-redirect" 'Cache-Tag': 'redirect, index-redirect'
}) })
.redirect( .redirect(
302, 302,
@ -27,7 +27,7 @@ function indexRedirect(req, res, entry) {
} }
function stripLeadingSegment(name) { function stripLeadingSegment(name) {
return name.replace(/^[^/]+\/?/, ""); return name.replace(/^[^/]+\/?/, '');
} }
function searchEntries(tarballStream, entryName, wantsIndex) { function searchEntries(tarballStream, entryName, wantsIndex) {
@ -35,14 +35,14 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
const entries = {}; const entries = {};
let foundEntry = null; let foundEntry = null;
if (entryName === "") { if (entryName === '') {
foundEntry = entries[""] = { name: "", type: "directory" }; foundEntry = entries[''] = { name: '', type: 'directory' };
} }
tarballStream tarballStream
.on("error", reject) .on('error', reject)
.on("finish", () => resolve({ entries, foundEntry })) .on('finish', () => resolve({ entries, foundEntry }))
.on("entry", (header, stream, next) => { .on('entry', (header, stream, next) => {
const entry = { const entry = {
// Most packages have header names that look like `package/index.js` // Most packages have header names that look like `package/index.js`
// so we shorten that to just `index.js` here. A few packages use a // so we shorten that to just `index.js` here. A few packages use a
@ -53,9 +53,9 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
}; };
// We are only interested in files that match the entryName. // We are only interested in files that match the entryName.
if (entry.type !== "file" || entry.name.indexOf(entryName) !== 0) { if (entry.type !== 'file' || entry.name.indexOf(entryName) !== 0) {
stream.resume(); stream.resume();
stream.on("end", next); stream.on('end', next);
return; return;
} }
@ -65,8 +65,8 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
// that are in this file's path. Some tarballs omit these entries // that are in this file's path. Some tarballs omit these entries
// for some reason, so this is the brute force method. // for some reason, so this is the brute force method.
let dirname = path.dirname(entry.name); let dirname = path.dirname(entry.name);
while (dirname !== ".") { while (dirname !== '.') {
const directoryEntry = { name: dirname, type: "directory" }; const directoryEntry = { name: dirname, type: 'directory' };
if (!entries[dirname]) { if (!entries[dirname]) {
entries[dirname] = directoryEntry; entries[dirname] = directoryEntry;
@ -94,7 +94,7 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
const chunks = []; const chunks = [];
stream.on("data", chunk => chunks.push(chunk)).on("end", () => { stream.on('data', chunk => chunks.push(chunk)).on('end', () => {
const content = Buffer.concat(chunks); const content = Buffer.concat(chunks);
// Set some extra properties for files that we will // Set some extra properties for files that we will
@ -126,8 +126,8 @@ const trailingSlash = /\/$/;
function findFile(req, res, next) { function findFile(req, res, next) {
fetchNpmPackage(req.packageConfig).then(tarballStream => { fetchNpmPackage(req.packageConfig).then(tarballStream => {
const entryName = req.filename const entryName = req.filename
.replace(trailingSlash, "") .replace(trailingSlash, '')
.replace(leadingSlash, ""); .replace(leadingSlash, '');
const wantsIndex = trailingSlash.test(req.filename); const wantsIndex = trailingSlash.test(req.filename);
searchEntries(tarballStream, entryName, wantsIndex).then( searchEntries(tarballStream, entryName, wantsIndex).then(
@ -135,7 +135,7 @@ function findFile(req, res, next) {
if (!foundEntry) { if (!foundEntry) {
return res return res
.status(404) .status(404)
.type("text") .type('text')
.send(`Cannot find "${req.filename}" in ${req.packageSpec}`); .send(`Cannot find "${req.filename}" in ${req.packageSpec}`);
} }
@ -144,17 +144,17 @@ function findFile(req, res, next) {
// inside that directory. This is so our URLs work in a similar way // inside that directory. This is so our URLs work in a similar way
// to require("lib") in node where it searches for `lib/index.js` // to require("lib") in node where it searches for `lib/index.js`
// and `lib/index.json` when `lib` is a directory. // and `lib/index.json` when `lib` is a directory.
if (foundEntry.type === "directory" && !wantsIndex) { if (foundEntry.type === 'directory' && !wantsIndex) {
const indexEntry = const indexEntry =
entries[path.join(entryName, "index.js")] || entries[path.join(entryName, 'index.js')] ||
entries[path.join(entryName, "index.json")]; entries[path.join(entryName, 'index.json')];
if (indexEntry && indexEntry.type === "file") { if (indexEntry && indexEntry.type === 'file') {
return indexRedirect(req, res, indexEntry); return indexRedirect(req, res, indexEntry);
} else { } else {
return res return res
.status(404) .status(404)
.type("text") .type('text')
.send( .send(
`Cannot find an index in "${req.filename}" in ${ `Cannot find an index in "${req.filename}" in ${
req.packageSpec req.packageSpec

View File

@ -1,4 +1,4 @@
const createSearch = require("../utils/createSearch"); const createSearch = require('../utils/createSearch');
/** /**
* Redirect old URLs that we no longer support. * Redirect old URLs that we no longer support.
@ -6,14 +6,14 @@ const createSearch = require("../utils/createSearch");
function redirectLegacyURLs(req, res, next) { function redirectLegacyURLs(req, res, next) {
// Permanently redirect /_meta/path to /path?meta. // Permanently redirect /_meta/path to /path?meta.
if (req.path.match(/^\/_meta\//)) { if (req.path.match(/^\/_meta\//)) {
req.query.meta = ""; req.query.meta = '';
return res.redirect(301, req.path.substr(6) + createSearch(req.query)); return res.redirect(301, req.path.substr(6) + createSearch(req.query));
} }
// Permanently redirect /path?json => /path?meta // Permanently redirect /path?json => /path?meta
if (req.query.json != null) { if (req.query.json != null) {
delete req.query.json; delete req.query.json;
req.query.meta = ""; req.query.meta = '';
return res.redirect(301, req.path + createSearch(req.query)); return res.redirect(301, req.path + createSearch(req.query));
} }

View File

@ -4,8 +4,8 @@
*/ */
function requireAuth(scope) { function requireAuth(scope) {
let checkScopes; let checkScopes;
if (scope.includes(".")) { if (scope.includes('.')) {
const parts = scope.split("."); const parts = scope.split('.');
checkScopes = scopes => checkScopes = scopes =>
parts.reduce((memo, part) => memo && memo[part], scopes) != null; parts.reduce((memo, part) => memo && memo[part], scopes) != null;
} else { } else {
@ -20,11 +20,11 @@ function requireAuth(scope) {
const user = req.user; const user = req.user;
if (!user) { if (!user) {
return res.status(403).send({ error: "Missing auth token" }); return res.status(403).send({ error: 'Missing auth token' });
} }
if (!user.scopes || !checkScopes(user.scopes)) { if (!user.scopes || !checkScopes(user.scopes)) {
return res.status(403).send({ error: "Insufficient scopes" }); return res.status(403).send({ error: 'Insufficient scopes' });
} }
if (req.auth) { if (req.auth) {

View File

@ -1,7 +1,7 @@
const fs = require("fs"); const fs = require('fs');
const invariant = require("invariant"); const invariant = require('invariant');
const createAssets = require("./utils/createAssets"); const createAssets = require('./utils/createAssets');
/** /**
* An express middleware that sets req.assets from the build * An express middleware that sets req.assets from the build
@ -10,12 +10,12 @@ const createAssets = require("./utils/createAssets");
function staticAssets(webpackStatsFile) { function staticAssets(webpackStatsFile) {
let stats; let stats;
try { try {
stats = JSON.parse(fs.readFileSync(webpackStatsFile, "utf8")); stats = JSON.parse(fs.readFileSync(webpackStatsFile, 'utf8'));
} catch (error) { } catch (error) {
invariant( invariant(
false, false,
"staticAssets middleware cannot read the build stats in %s; " + 'staticAssets middleware cannot read the build stats in %s; ' +
"run the `build` script before starting the server", 'run the `build` script before starting the server',
webpackStatsFile webpackStatsFile
); );
} }

View File

@ -1,9 +1,9 @@
const AuthAPI = require("../AuthAPI"); const AuthAPI = require('../AuthAPI');
const ReadMethods = { GET: true, HEAD: true }; const ReadMethods = { GET: true, HEAD: true };
function decodeBase64(string) { function decodeBase64(string) {
return Buffer.from(string, "base64").toString(); return Buffer.from(string, 'base64').toString();
} }
/** /**
@ -14,7 +14,7 @@ function userToken(req, res, next) {
return next(); return next();
} }
const auth = req.get("Authorization"); const auth = req.get('Authorization');
const token = auth const token = auth
? decodeBase64(auth) ? decodeBase64(auth)
: (ReadMethods[req.method] ? req.query : req.body).token; : (ReadMethods[req.method] ? req.query : req.body).token;
@ -30,7 +30,7 @@ function userToken(req, res, next) {
next(); next();
}, },
error => { error => {
if (error.name === "JsonWebTokenError") { if (error.name === 'JsonWebTokenError') {
res.status(403).send({ res.status(403).send({
error: `Bad auth token: ${error.message}` error: `Bad auth token: ${error.message}`
}); });
@ -38,7 +38,7 @@ function userToken(req, res, next) {
console.error(error); console.error(error);
res.status(500).send({ res.status(500).send({
error: "Unable to verify auth" error: 'Unable to verify auth'
}); });
} }
} }

View File

@ -12,7 +12,7 @@ function createAssets(webpackStats) {
/** /**
* Returns an array of URLs to all assets in the given chunks. * Returns an array of URLs to all assets in the given chunks.
*/ */
const getAll = (chunks = ["main"]) => const getAll = (chunks = ['main']) =>
(Array.isArray(chunks) ? chunks : [chunks]) (Array.isArray(chunks) ? chunks : [chunks])
.reduce((memo, chunk) => memo.concat(assetsByChunkName[chunk] || []), []) .reduce((memo, chunk) => memo.concat(assetsByChunkName[chunk] || []), [])
.map(createURL); .map(createURL);

View File

@ -1,4 +1,4 @@
const validateNpmPackageName = require("validate-npm-package-name"); const validateNpmPackageName = require('validate-npm-package-name');
const hexValue = /^[a-f0-9]+$/i; const hexValue = /^[a-f0-9]+$/i;
@ -13,18 +13,18 @@ function validatePackageName(req, res, next) {
if (isHash(req.packageName)) { if (isHash(req.packageName)) {
return res return res
.status(403) .status(403)
.type("text") .type('text')
.send(`Invalid package name "${req.packageName}" (cannot be a hash)`); .send(`Invalid package name "${req.packageName}" (cannot be a hash)`);
} }
const errors = validateNpmPackageName(req.packageName).errors; const errors = validateNpmPackageName(req.packageName).errors;
if (errors) { if (errors) {
const reason = errors.join(", "); const reason = errors.join(', ');
return res return res
.status(403) .status(403)
.type("text") .type('text')
.send(`Invalid package name "${req.packageName}" (${reason})`); .send(`Invalid package name "${req.packageName}" (${reason})`);
} }

View File

@ -1,4 +1,4 @@
const parsePackageURL = require("../utils/parsePackageURL"); const parsePackageURL = require('../utils/parsePackageURL');
/** /**
* Parse the URL and add various properties to the request object to * Parse the URL and add various properties to the request object to

View File

@ -1,4 +1,4 @@
const createSearch = require("../utils/createSearch"); const createSearch = require('../utils/createSearch');
const knownQueryParams = { const knownQueryParams = {
main: true, // Deprecated, see #63 main: true, // Deprecated, see #63

View File

@ -1,5 +1,5 @@
const babel = require("babel-core"); const babel = require('babel-core');
const unpkgRewrite = require("../unpkgRewrite"); const unpkgRewrite = require('../unpkgRewrite');
const testCases = [ const testCases = [
{ {
@ -66,13 +66,13 @@ const testCases = [
]; ];
const dependencies = { const dependencies = {
react: "15.6.1", react: '15.6.1',
"@angular/router": "4.3.5", '@angular/router': '4.3.5',
"lodash.map": "4.6.0", 'lodash.map': '4.6.0',
pn: "1.0.0" pn: '1.0.0'
}; };
describe("Rewriting imports/exports", () => { describe('Rewriting imports/exports', () => {
testCases.forEach(testCase => { testCases.forEach(testCase => {
it(`successfully rewrites '${testCase.before}'`, () => { it(`successfully rewrites '${testCase.before}'`, () => {
const result = babel.transform(testCase.before, { const result = babel.transform(testCase.before, {

View File

@ -1,7 +1,7 @@
const URL = require("whatwg-url"); const URL = require('whatwg-url');
const warning = require("warning"); const warning = require('warning');
const origin = require("../serverConfig").origin; const origin = require('../serverConfig').origin;
const bareIdentifierFormat = /^((?:@[^/]+\/)?[^/]+)(\/.*)?$/; const bareIdentifierFormat = /^((?:@[^/]+\/)?[^/]+)(\/.*)?$/;
@ -10,7 +10,7 @@ function isValidURL(value) {
} }
function isProbablyURLWithoutProtocol(value) { function isProbablyURLWithoutProtocol(value) {
return value.substr(0, 2) === "//"; return value.substr(0, 2) === '//';
} }
function isAbsoluteURL(value) { function isAbsoluteURL(value) {
@ -18,7 +18,7 @@ function isAbsoluteURL(value) {
} }
function isBareIdentifier(value) { function isBareIdentifier(value) {
return value.charAt(0) !== "." && value.charAt(0) !== "/"; return value.charAt(0) !== '.' && value.charAt(0) !== '/';
} }
function rewriteValue(/* StringLiteral */ node, dependencies) { function rewriteValue(/* StringLiteral */ node, dependencies) {
@ -30,7 +30,7 @@ function rewriteValue(/* StringLiteral */ node, dependencies) {
// "bare" identifier // "bare" identifier
const match = bareIdentifierFormat.exec(node.value); const match = bareIdentifierFormat.exec(node.value);
const packageName = match[1]; const packageName = match[1];
const file = match[2] || ""; const file = match[2] || '';
warning( warning(
dependencies[packageName], dependencies[packageName],
@ -38,7 +38,7 @@ function rewriteValue(/* StringLiteral */ node, dependencies) {
packageName packageName
); );
const version = dependencies[packageName] || "latest"; const version = dependencies[packageName] || 'latest';
node.value = `${origin}/${packageName}@${version}${file}?module`; node.value = `${origin}/${packageName}@${version}${file}?module`;
} else { } else {
@ -51,16 +51,16 @@ function unpkgRewrite(dependencies = {}) {
return { return {
manipulateOptions(opts, parserOpts) { manipulateOptions(opts, parserOpts) {
parserOpts.plugins.push( parserOpts.plugins.push(
"dynamicImport", 'dynamicImport',
"exportDefaultFrom", 'exportDefaultFrom',
"exportNamespaceFrom", 'exportNamespaceFrom',
"importMeta" 'importMeta'
); );
}, },
visitor: { visitor: {
CallExpression(path) { CallExpression(path) {
if (path.node.callee.type !== "Import") { if (path.node.callee.type !== 'Import') {
// Some other function call, not import(); // Some other function call, not import();
return; return;
} }

View File

@ -1,19 +1,19 @@
const fs = require("fs"); const fs = require('fs');
const path = require("path"); const path = require('path');
const forge = require("node-forge"); const forge = require('node-forge');
const invariant = require("invariant"); const invariant = require('invariant');
let secretKey; let secretKey;
if (process.env.NODE_ENV === "production") { if (process.env.NODE_ENV === 'production') {
invariant( invariant(
process.env.PRIVATE_KEY, process.env.PRIVATE_KEY,
"Missing $PRIVATE_KEY environment variable" 'Missing $PRIVATE_KEY environment variable'
); );
secretKey = { secretKey = {
public: fs.readFileSync( public: fs.readFileSync(
path.resolve(__dirname, "../secret_key.pub"), path.resolve(__dirname, '../secret_key.pub'),
"utf8" 'utf8'
), ),
private: process.env.PRIVATE_KEY private: process.env.PRIVATE_KEY
}; };

View File

@ -1,9 +1,9 @@
exports.port = parseInt(process.env.PORT, 10) || 5000; exports.port = parseInt(process.env.PORT, 10) || 5000;
exports.origin = exports.origin =
process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test" process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test'
? "https://unpkg.com" ? 'https://unpkg.com'
: `http://localhost:${exports.port}`; : `http://localhost:${exports.port}`;
exports.registryURL = exports.registryURL =
process.env.NPM_REGISTRY_URL || "https://registry.npmjs.org"; process.env.NPM_REGISTRY_URL || 'https://registry.npmjs.org';

View File

@ -1,15 +1,15 @@
const createSearch = require("../createSearch"); const createSearch = require('../createSearch');
describe("createSearch", () => { describe('createSearch', () => {
it("omits the trailing = for empty string values", () => { it('omits the trailing = for empty string values', () => {
expect(createSearch({ a: "a", b: "" })).toEqual("?a=a&b"); expect(createSearch({ a: 'a', b: '' })).toEqual('?a=a&b');
}); });
it("sorts keys", () => { it('sorts keys', () => {
expect(createSearch({ b: "b", a: "a", c: "c" })).toEqual("?a=a&b=b&c=c"); expect(createSearch({ b: 'b', a: 'a', c: 'c' })).toEqual('?a=a&b=b&c=c');
}); });
it("returns an empty string when there are no params", () => { it('returns an empty string when there are no params', () => {
expect(createSearch({})).toEqual(""); expect(createSearch({})).toEqual('');
}); });
}); });

View File

@ -1,39 +1,39 @@
const getContentType = require("../getContentType"); const getContentType = require('../getContentType');
it("gets a content type of text/plain for LICENSE|README|CHANGES|AUTHORS|Makefile", () => { it('gets a content type of text/plain for LICENSE|README|CHANGES|AUTHORS|Makefile', () => {
expect(getContentType("AUTHORS")).toBe("text/plain"); expect(getContentType('AUTHORS')).toBe('text/plain');
expect(getContentType("CHANGES")).toBe("text/plain"); expect(getContentType('CHANGES')).toBe('text/plain');
expect(getContentType("LICENSE")).toBe("text/plain"); expect(getContentType('LICENSE')).toBe('text/plain');
expect(getContentType("Makefile")).toBe("text/plain"); expect(getContentType('Makefile')).toBe('text/plain');
expect(getContentType("PATENTS")).toBe("text/plain"); expect(getContentType('PATENTS')).toBe('text/plain');
expect(getContentType("README")).toBe("text/plain"); expect(getContentType('README')).toBe('text/plain');
}); });
it("gets a content type of text/plain for .*rc files", () => { it('gets a content type of text/plain for .*rc files', () => {
expect(getContentType(".eslintrc")).toBe("text/plain"); expect(getContentType('.eslintrc')).toBe('text/plain');
expect(getContentType(".babelrc")).toBe("text/plain"); expect(getContentType('.babelrc')).toBe('text/plain');
expect(getContentType(".anythingrc")).toBe("text/plain"); expect(getContentType('.anythingrc')).toBe('text/plain');
}); });
it("gets a content type of text/plain for .git* files", () => { it('gets a content type of text/plain for .git* files', () => {
expect(getContentType(".gitignore")).toBe("text/plain"); expect(getContentType('.gitignore')).toBe('text/plain');
expect(getContentType(".gitanything")).toBe("text/plain"); expect(getContentType('.gitanything')).toBe('text/plain');
}); });
it("gets a content type of text/plain for .*ignore files", () => { it('gets a content type of text/plain for .*ignore files', () => {
expect(getContentType(".eslintignore")).toBe("text/plain"); expect(getContentType('.eslintignore')).toBe('text/plain');
expect(getContentType(".anythingignore")).toBe("text/plain"); expect(getContentType('.anythingignore')).toBe('text/plain');
}); });
it("gets a content type of text/plain for .ts files", () => { it('gets a content type of text/plain for .ts files', () => {
expect(getContentType("app.ts")).toBe("text/plain"); expect(getContentType('app.ts')).toBe('text/plain');
expect(getContentType("app.d.ts")).toBe("text/plain"); expect(getContentType('app.d.ts')).toBe('text/plain');
}); });
it("gets a content type of text/plain for .flow files", () => { it('gets a content type of text/plain for .flow files', () => {
expect(getContentType("app.js.flow")).toBe("text/plain"); expect(getContentType('app.js.flow')).toBe('text/plain');
}); });
it("gets a content type of text/plain for .lock files", () => { it('gets a content type of text/plain for .lock files', () => {
expect(getContentType("yarn.lock")).toBe("text/plain"); expect(getContentType('yarn.lock')).toBe('text/plain');
}); });

View File

@ -1,80 +1,80 @@
const parsePackageURL = require("../parsePackageURL"); const parsePackageURL = require('../parsePackageURL');
describe("parsePackageURL", () => { describe('parsePackageURL', () => {
it("parses plain packages", () => { it('parses plain packages', () => {
expect(parsePackageURL("/history@1.0.0/umd/history.min.js")).toEqual({ expect(parsePackageURL('/history@1.0.0/umd/history.min.js')).toEqual({
pathname: "/history@1.0.0/umd/history.min.js", pathname: '/history@1.0.0/umd/history.min.js',
search: "", search: '',
query: {}, query: {},
packageName: "history", packageName: 'history',
packageVersion: "1.0.0", packageVersion: '1.0.0',
filename: "/umd/history.min.js" filename: '/umd/history.min.js'
}); });
}); });
it("parses plain packages with a hyphen in the name", () => { it('parses plain packages with a hyphen in the name', () => {
expect(parsePackageURL("/query-string@5.0.0/index.js")).toEqual({ expect(parsePackageURL('/query-string@5.0.0/index.js')).toEqual({
pathname: "/query-string@5.0.0/index.js", pathname: '/query-string@5.0.0/index.js',
search: "", search: '',
query: {}, query: {},
packageName: "query-string", packageName: 'query-string',
packageVersion: "5.0.0", packageVersion: '5.0.0',
filename: "/index.js" filename: '/index.js'
}); });
}); });
it("parses plain packages with no version specified", () => { it('parses plain packages with no version specified', () => {
expect(parsePackageURL("/query-string/index.js")).toEqual({ expect(parsePackageURL('/query-string/index.js')).toEqual({
pathname: "/query-string/index.js", pathname: '/query-string/index.js',
search: "", search: '',
query: {}, query: {},
packageName: "query-string", packageName: 'query-string',
packageVersion: "latest", packageVersion: 'latest',
filename: "/index.js" filename: '/index.js'
}); });
}); });
it("parses plain packages with version spec", () => { it('parses plain packages with version spec', () => {
expect(parsePackageURL("/query-string@>=4.0.0/index.js")).toEqual({ expect(parsePackageURL('/query-string@>=4.0.0/index.js')).toEqual({
pathname: "/query-string@>=4.0.0/index.js", pathname: '/query-string@>=4.0.0/index.js',
search: "", search: '',
query: {}, query: {},
packageName: "query-string", packageName: 'query-string',
packageVersion: ">=4.0.0", packageVersion: '>=4.0.0',
filename: "/index.js" filename: '/index.js'
}); });
}); });
it("parses scoped packages", () => { it('parses scoped packages', () => {
expect(parsePackageURL("/@angular/router@4.3.3/src/index.d.ts")).toEqual({ expect(parsePackageURL('/@angular/router@4.3.3/src/index.d.ts')).toEqual({
pathname: "/@angular/router@4.3.3/src/index.d.ts", pathname: '/@angular/router@4.3.3/src/index.d.ts',
search: "", search: '',
query: {}, query: {},
packageName: "@angular/router", packageName: '@angular/router',
packageVersion: "4.3.3", packageVersion: '4.3.3',
filename: "/src/index.d.ts" filename: '/src/index.d.ts'
}); });
}); });
it("parses package names with a period in them", () => { it('parses package names with a period in them', () => {
expect(parsePackageURL("/index.js")).toEqual({ expect(parsePackageURL('/index.js')).toEqual({
pathname: "/index.js", pathname: '/index.js',
search: "", search: '',
query: {}, query: {},
packageName: "index.js", packageName: 'index.js',
packageVersion: "latest", packageVersion: 'latest',
filename: "" filename: ''
}); });
}); });
it("parses valid query parameters", () => { it('parses valid query parameters', () => {
expect(parsePackageURL("/history?main=browser")).toEqual({ expect(parsePackageURL('/history?main=browser')).toEqual({
pathname: "/history", pathname: '/history',
search: "?main=browser", search: '?main=browser',
query: { main: "browser" }, query: { main: 'browser' },
packageName: "history", packageName: 'history',
packageVersion: "latest", packageVersion: 'latest',
filename: "" filename: ''
}); });
}); });
}); });

View File

@ -1,5 +1,5 @@
function addLeadingSlash(name) { function addLeadingSlash(name) {
return name.charAt(0) === "/" ? name : "/" + name; return name.charAt(0) === '/' ? name : '/' + name;
} }
module.exports = addLeadingSlash; module.exports = addLeadingSlash;

View File

@ -3,9 +3,9 @@ function bufferStream(stream) {
const chunks = []; const chunks = [];
stream stream
.on("error", reject) .on('error', reject)
.on("data", chunk => chunks.push(chunk)) .on('data', chunk => chunks.push(chunk))
.on("end", () => resolve(Buffer.concat(chunks))); .on('end', () => resolve(Buffer.concat(chunks)));
}); });
} }

View File

@ -1,9 +1,9 @@
const redis = require("redis"); const redis = require('redis');
redis.debug_mode = process.env.DEBUG_REDIS != null; redis.debug_mode = process.env.DEBUG_REDIS != null;
const client = redis.createClient( const client = redis.createClient(
process.env.CACHE_URL || process.env.OPENREDIS_URL || "redis://localhost:6379" process.env.CACHE_URL || process.env.OPENREDIS_URL || 'redis://localhost:6379'
); );
module.exports = client; module.exports = client;

View File

@ -3,14 +3,14 @@ function createSearch(query) {
const params = keys.reduce( const params = keys.reduce(
(memo, key) => (memo, key) =>
memo.concat( memo.concat(
query[key] === "" query[key] === ''
? key // Omit the trailing "=" from key= ? key // Omit the trailing "=" from key=
: `${key}=${encodeURIComponent(query[key])}` : `${key}=${encodeURIComponent(query[key])}`
), ),
[] []
); );
return params.length ? `?${params.join("&")}` : ""; return params.length ? `?${params.join('&')}` : '';
} }
module.exports = createSearch; module.exports = createSearch;

View File

@ -1,9 +1,9 @@
const redis = require("redis"); const redis = require('redis');
redis.debug_mode = process.env.DEBUG_REDIS != null; redis.debug_mode = process.env.DEBUG_REDIS != null;
const client = redis.createClient( const client = redis.createClient(
process.env.DATA_URL || process.env.OPENREDIS_URL || "redis://localhost:6379" process.env.DATA_URL || process.env.OPENREDIS_URL || 'redis://localhost:6379'
); );
module.exports = client; module.exports = client;

View File

@ -1,18 +1,18 @@
const url = require("url"); const url = require('url');
const https = require("https"); const https = require('https');
const gunzip = require("gunzip-maybe"); const gunzip = require('gunzip-maybe');
const tar = require("tar-stream"); const tar = require('tar-stream');
const bufferStream = require("./bufferStream"); const bufferStream = require('./bufferStream');
const agent = require("./registryAgent"); const agent = require('./registryAgent');
const logging = require("./logging"); const logging = require('./logging');
function fetchNpmPackage(packageConfig) { function fetchNpmPackage(packageConfig) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const tarballURL = packageConfig.dist.tarball; const tarballURL = packageConfig.dist.tarball;
logging.debug( logging.debug(
"Fetching package for %s from %s", 'Fetching package for %s from %s',
packageConfig.name, packageConfig.name,
tarballURL tarballURL
); );
@ -31,7 +31,7 @@ function fetchNpmPackage(packageConfig) {
} else { } else {
bufferStream(res).then(data => { bufferStream(res).then(data => {
const spec = `${packageConfig.name}@${packageConfig.version}`; const spec = `${packageConfig.name}@${packageConfig.version}`;
const content = data.toString("utf-8"); const content = data.toString('utf-8');
const error = new Error( const error = new Error(
`Failed to fetch tarball for ${spec}\nstatus: ${ `Failed to fetch tarball for ${spec}\nstatus: ${
res.statusCode res.statusCode
@ -42,7 +42,7 @@ function fetchNpmPackage(packageConfig) {
}); });
} }
}) })
.on("error", reject); .on('error', reject);
}); });
} }

View File

@ -1,10 +1,10 @@
const url = require("url"); const url = require('url');
const https = require("https"); const https = require('https');
const serverConfig = require("../serverConfig"); const serverConfig = require('../serverConfig');
const bufferStream = require("./bufferStream"); const bufferStream = require('./bufferStream');
const agent = require("./registryAgent"); const agent = require('./registryAgent');
const logging = require("./logging"); const logging = require('./logging');
function parseJSON(res) { function parseJSON(res) {
return bufferStream(res).then(JSON.parse); return bufferStream(res).then(JSON.parse);
@ -13,13 +13,13 @@ function parseJSON(res) {
function fetchNpmPackageInfo(packageName) { function fetchNpmPackageInfo(packageName) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const encodedPackageName = const encodedPackageName =
packageName.charAt(0) === "@" packageName.charAt(0) === '@'
? `@${encodeURIComponent(packageName.substring(1))}` ? `@${encodeURIComponent(packageName.substring(1))}`
: encodeURIComponent(packageName); : encodeURIComponent(packageName);
const infoURL = `${serverConfig.registryURL}/${encodedPackageName}`; const infoURL = `${serverConfig.registryURL}/${encodedPackageName}`;
logging.debug("Fetching package info for %s from %s", packageName, infoURL); logging.debug('Fetching package info for %s from %s', packageName, infoURL);
const { hostname, pathname } = url.parse(infoURL); const { hostname, pathname } = url.parse(infoURL);
const options = { const options = {
@ -27,7 +27,7 @@ function fetchNpmPackageInfo(packageName) {
hostname: hostname, hostname: hostname,
path: pathname, path: pathname,
headers: { headers: {
Accept: "application/json" Accept: 'application/json'
} }
}; };
@ -39,7 +39,7 @@ function fetchNpmPackageInfo(packageName) {
resolve(null); resolve(null);
} else { } else {
bufferStream(res).then(data => { bufferStream(res).then(data => {
const content = data.toString("utf-8"); const content = data.toString('utf-8');
const error = new Error( const error = new Error(
`Failed to fetch info for ${packageName}\nstatus: ${ `Failed to fetch info for ${packageName}\nstatus: ${
res.statusCode res.statusCode
@ -50,7 +50,7 @@ function fetchNpmPackageInfo(packageName) {
}); });
} }
}) })
.on("error", reject); .on('error', reject);
}); });
} }

View File

@ -1,22 +1,22 @@
const mime = require("mime"); const mime = require('mime');
mime.define({ mime.define({
"text/plain": [ 'text/plain': [
"authors", 'authors',
"changes", 'changes',
"license", 'license',
"makefile", 'makefile',
"patents", 'patents',
"readme", 'readme',
"ts", 'ts',
"flow" 'flow'
] ]
}); });
const textFiles = /\/?(\.[a-z]*rc|\.git[a-z]*|\.[a-z]*ignore|\.lock)$/i; const textFiles = /\/?(\.[a-z]*rc|\.git[a-z]*|\.[a-z]*ignore|\.lock)$/i;
function getContentType(file) { function getContentType(file) {
return textFiles.test(file) ? "text/plain" : mime.lookup(file); return textFiles.test(file) ? 'text/plain' : mime.lookup(file);
} }
module.exports = getContentType; module.exports = getContentType;

View File

@ -1,5 +1,5 @@
function getContentTypeHeader(type) { function getContentTypeHeader(type) {
return type === "application/javascript" ? type + "; charset=utf-8" : type; return type === 'application/javascript' ? type + '; charset=utf-8' : type;
} }
module.exports = getContentTypeHeader; module.exports = getContentTypeHeader;

View File

@ -1,7 +1,7 @@
const SRIToolbox = require("sri-toolbox"); const SRIToolbox = require('sri-toolbox');
function getIntegrity(data) { function getIntegrity(data) {
return SRIToolbox.generate({ algorithms: ["sha384"] }, data); return SRIToolbox.generate({ algorithms: ['sha384'] }, data);
} }
module.exports = getIntegrity; module.exports = getIntegrity;

View File

@ -1,5 +1,5 @@
const cache = require("./cache"); const cache = require('./cache');
const fetchNpmPackageInfo = require("./fetchNpmPackageInfo"); const fetchNpmPackageInfo = require('./fetchNpmPackageInfo');
const notFound = 0; const notFound = 0;

View File

@ -1,4 +1,4 @@
const db = require("./data"); const db = require('./data');
function incrementCounter(counter, key, by = 1) { function incrementCounter(counter, key, by = 1) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -1,4 +1,4 @@
const validateNpmPackageName = require("validate-npm-package-name"); const validateNpmPackageName = require('validate-npm-package-name');
function isValidPackageName(packageName) { function isValidPackageName(packageName) {
return validateNpmPackageName(packageName).errors == null; return validateNpmPackageName(packageName).errors == null;

View File

@ -4,11 +4,11 @@ function noop() {}
let debug, info, warn; let debug, info, warn;
if (process.env.LOG_LEVEL === "none") { if (process.env.LOG_LEVEL === 'none') {
debug = info = warn = noop; debug = info = warn = noop;
} else if (process.env.LOG_LEVEL === "debug") { } else if (process.env.LOG_LEVEL === 'debug') {
debug = info = warn = log; debug = info = warn = log;
} else if (process.env.LOG_LEVEL === "warn") { } else if (process.env.LOG_LEVEL === 'warn') {
debug = info = noop; debug = info = noop;
warn = log; warn = log;
} else { } else {

View File

@ -1,4 +1,4 @@
const url = require("url"); const url = require('url');
const packageURLFormat = /^\/((?:@[^/@]+\/)?[^/@]+)(?:@([^/]+))?(\/.*)?$/; const packageURLFormat = /^\/((?:@[^/@]+\/)?[^/@]+)(?:@([^/]+))?(\/.*)?$/;
@ -11,7 +11,7 @@ function decodeParam(param) {
} }
} }
return ""; return '';
} }
function parsePackageURL(originalURL) { function parsePackageURL(originalURL) {
@ -24,13 +24,13 @@ function parsePackageURL(originalURL) {
} }
const packageName = match[1]; const packageName = match[1];
const packageVersion = decodeParam(match[2]) || "latest"; const packageVersion = decodeParam(match[2]) || 'latest';
const filename = decodeParam(match[3]); const filename = decodeParam(match[3]);
return { return {
// If the URL is /@scope/name@version/file.js?main=browser: // If the URL is /@scope/name@version/file.js?main=browser:
pathname, // /@scope/name@version/path.js pathname, // /@scope/name@version/path.js
search: search || "", // ?main=browser search: search || '', // ?main=browser
query, // { main: 'browser' } query, // { main: 'browser' }
packageName, // @scope/name packageName, // @scope/name
packageVersion, // version packageVersion, // version

View File

@ -1,4 +1,4 @@
const https = require("https"); const https = require('https');
const agent = new https.Agent({ const agent = new https.Agent({
keepAlive: true keepAlive: true

View File

@ -1,7 +1,7 @@
const React = require("react"); const React = require('react');
const ReactDOMServer = require("react-dom/server"); const ReactDOMServer = require('react-dom/server');
const doctype = "<!DOCTYPE html>"; const doctype = '<!DOCTYPE html>';
function renderPage(page, props) { function renderPage(page, props) {
const element = React.createElement(page, props); const element = React.createElement(page, props);

View File

@ -1,6 +1,6 @@
const babel = require("babel-core"); const babel = require('babel-core');
const unpkgRewrite = require("../plugins/unpkgRewrite"); const unpkgRewrite = require('../plugins/unpkgRewrite');
function rewriteBareModuleIdentifiers(code, packageConfig) { function rewriteBareModuleIdentifiers(code, packageConfig) {
const dependencies = Object.assign( const dependencies = Object.assign(